driver: input: screentouch: support focaltech touch.

Signed-off-by: Jason Song <sxj@rock-chips.com>
Change-Id: Idd0d772225ed11a5080649d8e962e5cb4c2b89b7
This commit is contained in:
Jason Song
2020-10-28 18:41:37 +08:00
committed by Tao Huang
parent f701ad8fcf
commit 3161226167
26 changed files with 13949 additions and 0 deletions

View File

@@ -1380,4 +1380,12 @@ config TOUCHSCREEN_VTL_CT36X
config TOUCHSCREEN_GT1X
tristate "GT1X touchscreens support"
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.
endif

View File

@@ -124,3 +124,4 @@ obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023) += rohm_bu21023.o
obj-$(CONFIG_TOUCHSCREEN_VTL_CT36X) += vtl_ts/
obj-$(CONFIG_TOUCHSCREEN_GT1X) += gt1x/
obj-$(CONFIG_TOUCHSCREEN_HYN_CST2XX) += hyn_cst2xx/
obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_touch/

View File

@@ -0,0 +1,18 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the focaltech touchscreen drivers.
#
# Each configuration option enables a list of files.
obj-y += focaltech_core.o
obj-y += focaltech_ex_fun.o
obj-y += focaltech_ex_mode.o
obj-y += focaltech_flash.o
obj-y += focaltech_gesture.o
obj-y += focaltech_esdcheck.o
obj-y += focaltech_i2c.o
obj-y += focaltech_point_report_check.o
obj-y += focaltech_flash/
obj-y += focaltech_test/

View File

@@ -0,0 +1,159 @@
/*
*
* FocalTech fts TouchScreen driver.
*
* Copyright (c) 2012-2018, 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 V3.0a 20180929"
#define BYTE_OFF_0(x) (u8)((x) & 0xFF)
#define BYTE_OFF_8(x) (u8)((x >> 8) & 0xFF)
#define BYTE_OFF_16(x) (u8)((x >> 16) & 0xFF)
#define BYTE_OFF_24(x) (u8)((x >> 24) & 0xFF)
#define FLAGBIT(x) (0x00000001 << (x))
#define FLAGBITS(x, y) ((0xFFFFFFFF >> (32 - (y) - 1)) << (x))
#define FLAG_ICSERIALS_LEN 8
#define FLAG_HID_BIT 10
#define FLAG_IDC_BIT 11
#define IC_SERIALS (FTS_CHIP_TYPE & FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
#define IC_TO_SERIALS(x) ((x) & FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
#define FTS_CHIP_IDC ((FTS_CHIP_TYPE & FLAGBIT(FLAG_IDC_BIT)) == FLAGBIT(FLAG_IDC_BIT))
#define FTS_HID_SUPPORTTED ((FTS_CHIP_TYPE & FLAGBIT(FLAG_HID_BIT)) == FLAGBIT(FLAG_HID_BIT))
#define FTS_CHIP_TYPE_MAPPING {{0x10,0x82, 0x01, 0x80, 0x06, 0x80, 0xC6, 0x80, 0xB6}}
#define I2C_BUFFER_LENGTH_MAXINUM 256
#define FILE_NAME_LENGTH 128
#define ENABLE 1
#define DISABLE 0
#define VALID 1
#define INVALID 0
#define FTS_CMD_START1 0x55
#define FTS_CMD_START2 0xAA
#define FTS_CMD_START_DELAY 10
#define FTS_CMD_READ_ID 0x90
#define FTS_CMD_READ_ID_LEN 4
#define FTS_CMD_READ_ID_LEN_INCELL 1
/*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_ESDCHECK_DISABLE 0x8D
#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_FACE_DEC_MODE_STATUS 0x01
#define FTS_REG_IDE_PARA_VER_ID 0xB5
#define FTS_REG_IDE_PARA_STATUS 0xB6
#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_MODULE_ID 0xE3
#define FTS_REG_LIC_VER 0xE4
#define FTS_REG_ESD_SATURATE 0xED
#define FTS_SYSFS_ECHO_ON(buf) (buf[0] == '1')
#define FTS_SYSFS_ECHO_OFF(buf) (buf[0] == '0')
#define kfree_safe(pbuf) do {\
if (pbuf) {\
kfree(pbuf);\
pbuf = NULL;\
}\
} while(0)
/*****************************************************************************
* 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 0
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
struct ft_chip_t {
u64 type;
u8 chip_idh;
u8 chip_idl;
u8 rom_idh;
u8 rom_idl;
u8 pb_idh;
u8 pb_idl;
u8 bl_idh;
u8 bl_idl;
};
struct ts_ic_info {
bool is_incell;
bool hid_supported;
struct ft_chip_t ids;
};
/*****************************************************************************
* DEBUG function define here
*****************************************************************************/
#if FTS_DEBUG_EN
#define FTS_DEBUG_LEVEL 1
#if (FTS_DEBUG_LEVEL == 2)
#define FTS_DEBUG(fmt, args...) printk("[FTS][%s]"fmt"\n", __func__, ##args)
#else
#define FTS_DEBUG(fmt, args...) printk("[FTS]"fmt"\n", ##args)
#endif
#define FTS_FUNC_ENTER() printk("[FTS]%s: Enter\n", __func__)
#define FTS_FUNC_EXIT() printk("[FTS]%s: Exit(%d)\n", __func__, __LINE__)
#else /* #if FTS_DEBUG_EN*/
#define FTS_DEBUG(fmt, args...)
#define FTS_FUNC_ENTER()
#define FTS_FUNC_EXIT()
#endif
#define FTS_INFO(fmt, args...) printk(KERN_INFO "[FTS][Info]"fmt"\n", ##args)
#define FTS_ERROR(fmt, args...) printk(KERN_ERR "[FTS][Error]"fmt"\n", ##args)
#endif /* __LINUX_FOCALTECH_COMMON_H__ */

View File

@@ -0,0 +1,244 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2018, 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 _FT8006M 0x80060807
#define _FT7250 0x72500807
#define _FT8607 0x86070809
#define _FT8006U 0x8006D80B
#define _FT8006S 0x8006A80B
#define _FT8613 0x8613080C
#define _FT8719 0x8719080D
#define _FT8739 0x8739080E
#define _FT8615 0x8615080F
#define _FT8201 0x82010810
#define _FT8006P 0x86220811
#define _FT5416 0x54160402
#define _FT5426 0x54260402
#define _FT5435 0x54350402
#define _FT5436 0x54360402
#define _FT5526 0x55260402
#define _FT5526I 0x5526B402
#define _FT5446 0x54460402
#define _FT5346 0x53460402
#define _FT5446I 0x5446B402
#define _FT5346I 0x5346B402
#define _FT7661 0x76610402
#define _FT7511 0x75110402
#define _FT7421 0x74210402
#define _FT7681 0x76810402
#define _FT3C47U 0x3C47D402
#define _FT3417 0x34170402
#define _FT3517 0x35170402
#define _FT3327 0x33270402
#define _FT3427 0x34270402
#define _FT7311 0x73110402
#define _FT5626 0x56260401
#define _FT5726 0x57260401
#define _FT5826B 0x5826B401
#define _FT5826S 0x5826C401
#define _FT7811 0x78110401
#define _FT3D47 0x3D470401
#define _FT3617 0x36170401
#define _FT3717 0x37170401
#define _FT3817B 0x3817B401
#define _FT3517U 0x3517D401
#define _FT6236U 0x6236D003
#define _FT6336G 0x6336A003
#define _FT6336U 0x6336D003
#define _FT6436U 0x6436D003
#define _FT3267 0x32670004
#define _FT3367 0x33670004
#define _FT3327DQQ_XXX 0x3327D482
#define _FT5446DQS_XXX 0x5446D482
#define _FT3518 0x35180481
#define _FT3558 0x35580481
#define _FT3528 0x35280481
#define _FT5536 0x55360481
#define _FT5446U 0x5446D083
#define _FT5456U 0x5456D083
#define _FT3417U 0x3417D083
#define _FT5426U 0x5426D083
#define _FT3428 0x34280083
#define _FT3437U 0x3437D083
#define _FT7302 0x73020084
#define _FT7202 0x72020084
#define _FT3308 0x33080084
/*************************************************/
/*
* choose your ic chip type of focaltech
*/
#define FTS_CHIP_TYPE _FT8201
/******************* 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 1
/*
* Gesture function enable
* default: disable
*/
#define FTS_GESTURE_EN 0
/*
* ESD check & protection
* default: disable
*/
#define FTS_ESDCHECK_EN 0
/*
* 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 0
/*
* Charger enable
* 1: enable, 0:disable(default)
*/
#define FTS_CHARGER_EN 0
/*
* Nodes for tools, please keep enable
*/
#define FTS_SYSFS_NODE_EN 0
#define FTS_APK_NODE_EN 0
/*
* Pinctrl enable
* default: disable
*/
#define FTS_PINCTRL_EN 0
/*
* 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 0
/*
* auto upgrade for lcd cfg
*/
#define FTS_AUTO_LIC_UPGRADE_EN 1
/*
* Check vendor_id number
* 0:No check vendor_id (default)
* 1/2/3: Check vendor_id for vendor compatibility
*/
#define FTS_GET_VENDOR_ID_NUM 0
/*
* vendor_id(s) for vendor(s) to be compatible with.
* a confirmation of vendor_id(s) is recommended.
* FTS_VENDOR_ID = PANEL_ID << 8 + VENDOR_ID
* FTS_GET_VENDOR_ID_NUM == 0/1, no check vendor id, you may ignore them
* FTS_GET_VENDOR_ID_NUM > 1, compatible with FTS_VENDOR_ID
* FTS_GET_VENDOR_ID_NUM >= 2, compatible with FTS_VENDOR_ID2
* FTS_GET_VENDOR_ID_NUM >= 3, compatible with FTS_VENDOR_ID3
*/
#define FTS_VENDOR_ID 0x0000
#define FTS_VENDOR_ID2 0x0000
#define FTS_VENDOR_ID3 0x0000
/*
* FW.i file for auto upgrade, you must replace it with your own
* define your own fw_file, the sample one to be replaced is invalid
* NOTE: if FTS_GET_VENDOR_ID_NUM > 1, it's the fw corresponding with FTS_VENDOR_ID
*/
#define FTS_UPGRADE_FW_FILE "include/firmware/fw_sample.h"
/*
* if FTS_GET_VENDOR_ID_NUM >= 2, fw corrsponding with FTS_VENDOR_ID2
* define your own fw_file, the sample one is invalid
*/
#define FTS_UPGRADE_FW2_FILE "include/firmware/fw_sample.h"
/*
* if FTS_GET_VENDOR_ID_NUM >= 3, fw corrsponding with FTS_VENDOR_ID3
* define your own fw_file, the sample one is invalid
*/
#define FTS_UPGRADE_FW3_FILE "include/firmware/fw_sample.h"
/*********************************************************/
#endif /* _LINUX_FOCLATECH_CONFIG_H_ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,254 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2018, 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 <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/regulator/consumer.h>
#include <linux/firmware.h>
#include <linux/debugfs.h>
#include <linux/mutex.h>
#include <linux/wait.h>
#include <linux/time.h>
#include <linux/workqueue.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#include <linux/version.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/mount.h>
#include <linux/netdevice.h>
#include <linux/unistd.h>
#include <linux/ioctl.h>
#include <linux/vmalloc.h>
#include "focaltech_common.h"
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define FTS_MAX_POINTS_SUPPORT 10 /* constant value, can't be changed */
#define FTS_MAX_KEYS 4
#define FTS_KEY_WIDTH 50
#define FTS_ONE_TCH_LEN 6
#define FTS_MAX_ID 0x0A
#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_X_MIN_DISPLAY_DEFAULT 0
#define FTS_Y_MIN_DISPLAY_DEFAULT 0
#define FTS_X_MAX_DISPLAY_DEFAULT 1600
#define FTS_Y_MAX_DISPLAY_DEFAULT 2176
#define FTS_TOUCH_DOWN 0
#define FTS_TOUCH_UP 1
#define FTS_TOUCH_CONTACT 2
#define EVENT_DOWN(flag) ((FTS_TOUCH_DOWN == flag) || (FTS_TOUCH_CONTACT == flag))
#define EVENT_UP(flag) (FTS_TOUCH_UP == flag)
#define EVENT_NO_DOWN(data) (!data->point_num)
#define KEY_EN(data) (data->pdata->have_key)
#define TOUCH_IS_KEY(y, key_y) (y == key_y)
#define TOUCH_IN_RANGE(val, key_val, half) ((val > (key_val - half)) && (val < (key_val + half)))
#define TOUCH_IN_KEY(x, key_x) TOUCH_IN_RANGE(x, key_x, FTS_KEY_WIDTH)
#define FTX_MAX_COMPATIBLE_TYPE 4
/*****************************************************************************
* 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[FTS_MAX_KEYS];
u32 key_y_coord;
u32 key_x_coords[FTS_MAX_KEYS];
u32 x_max;
u32 y_max;
u32 x_min;
u32 y_min;
u32 max_touch_number;
};
struct ts_event {
int x; /*x coordinate */
int y; /*y coordinate */
int p; /* pressure */
int flag; /* touch event flag: 0 -- down; 1-- up; 2 -- contact */
int id; /*touch ID */
int area;
};
struct fts_ts_data {
struct i2c_client *client;
struct input_dev *input_dev;
struct fts_ts_platform_data *pdata;
struct ts_ic_info ic_info;
struct workqueue_struct *ts_workqueue;
struct work_struct fwupg_work;
struct delayed_work esdcheck_work;
struct delayed_work prc_work;
struct work_struct resume_work;
struct regulator *vdd;
struct regulator *vcc_i2c;
spinlock_t irq_lock;
struct mutex report_mutex;
int irq;
bool suspended;
bool fw_loading;
bool irq_disabled;
bool power_disabled;
/* multi-touch */
struct ts_event *events;
u8 *point_buf;
int pnt_buf_size;
int touchs;
bool key_down;
int touch_point;
int point_num;
struct proc_dir_entry *proc;
u8 proc_opmode;
#if FTS_PINCTRL_EN
struct pinctrl *pinctrl;
struct pinctrl_state *pins_active;
struct pinctrl_state *pins_suspend;
struct pinctrl_state *pins_release;
#endif
#if defined(CONFIG_FB)
struct notifier_block fb_notif;
#elif defined(CONFIG_HAS_EARLYSUSPEND)
struct early_suspend early_suspend;
#endif
};
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
extern struct fts_ts_data *fts_data;
/* 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);
void fts_i2c_hid2std(struct i2c_client *client);
int fts_i2c_init(void);
int fts_i2c_exit(void);
/* Gesture functions */
#if FTS_GESTURE_EN
int fts_gesture_init(struct fts_ts_data *ts_data);
int fts_gesture_exit(struct i2c_client *client);
void fts_gesture_recovery(struct i2c_client *client);
int fts_gesture_readdata(struct fts_ts_data *ts_data);
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 fts_ts_data *);
void fts_release_apk_debug_channel(struct fts_ts_data *);
#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(struct fts_ts_data *ts_data);
int fts_esdcheck_exit(struct fts_ts_data *ts_data);
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);
#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(struct fts_ts_data *ts_data);
int fts_point_report_check_exit(struct fts_ts_data *ts_data);
void fts_prc_queue_work(struct fts_ts_data *ts_data);
#endif
/* FW upgrade */
int fts_upgrade_bin(struct i2c_client *client, char *fw_name, bool force);
int fts_fwupg_init(struct fts_ts_data *ts_data);
int fts_fwupg_exit(struct fts_ts_data *ts_data);
/* Other */
int fts_reset_proc(int hdelayms);
int fts_wait_tp_to_valid(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);
#endif /* __LINUX_FOCALTECH_CORE_H__ */

View File

@@ -0,0 +1,552 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2018, 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: ESD check function
*
* Version: v1.0
*
* Revision History:
* v1.0:
* First release. By luougojin 2016-08-03
* v1.1: By luougojin 2017-02-15
* 1. Add LCD_ESD_PATCH to control idc_esdcheck_lcderror
*****************************************************************************/
/*****************************************************************************
* Included header files
*****************************************************************************/
#include "focaltech_core.h"
#if FTS_ESDCHECK_EN
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define ESDCHECK_WAIT_TIME 1000 /* ms */
#define LCD_ESD_PATCH 0
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
struct fts_esdcheck_st {
u8 mode : 1; /* 1- 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 fts_esdcheck_st fts_esdcheck_data;
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
/*****************************************************************************
* functions body
*****************************************************************************/
#if LCD_ESD_PATCH
/*****************************************************************************
* 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(struct fts_ts_data *ts_data)
{
int ret = 0;
u8 val = 0;
struct i2c_client *client = ts_data->client;
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(client);
}
ret = fts_i2c_read_reg(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;
}
#endif
/*****************************************************************************
* Name: fts_esdcheck_tp_reset
* Brief: esd check algorithm
* Input:
* Output:
* Return:
*****************************************************************************/
static int fts_esdcheck_tp_reset(struct fts_ts_data *ts_data)
{
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(ts_data->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(struct fts_ts_data *ts_data)
{
int ret = 0;
int i = 0;
u8 reg_value = 0;
u8 reg_addr = 0;
struct i2c_client *client = ts_data->client;
u8 chip_id = ts_data->ic_info.ids.chip_idh;
for (i = 0; i < 3; i++) {
reg_addr = FTS_REG_CHIP_ID;
ret = fts_i2c_read(client, &reg_addr, 1, &reg_value, 1);
if (ret < 0) {
FTS_ERROR("[ESD]: Read Reg 0xA3 failed ret = %d!!", ret);
fts_esdcheck_data.i2c_nack_cnt++;
} else {
if (reg_value == chip_id) {
break;
} else {
fts_esdcheck_data.i2c_dataerror_cnt++;
}
}
msleep(10);
}
/* 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(struct fts_ts_data *ts_data)
{
int ret = 0;
u8 reg_value = 0;
u8 reg_addr = 0;
struct i2c_client *client = ts_data->client;
reg_addr = FTS_REG_FLOW_WORK_CNT;
ret = fts_i2c_read(client, &reg_addr, 1, &reg_value, 1);
if (ret < 0) {
FTS_ERROR("[ESD]: Read Reg 0x91 failed ret = %d!!", ret);
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(struct fts_ts_data *ts_data)
{
int ret = 0;
u8 reg_value = 0;
u8 reg_addr = 0;
bool hardware_reset = 0;
struct i2c_client *client = ts_data->client;
/* 1. esdcheck is interrupt, then return */
if (fts_esdcheck_data.intr == 1) {
FTS_DEBUG("[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_DEBUG("[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
*/
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;
ret = fts_i2c_read(client, &reg_addr, 1, &reg_value, 1);
if ( ret < 0 ) {
fts_esdcheck_data.i2c_nack_cnt++;
} else if ( (reg_value & 0x70) != FTS_REG_WORKMODE_WORK_VALUE) {
FTS_DEBUG("[ESD]: not in work mode, no check esd, return immediately!!");
return 0;
}
/* 5. IDC esd check lcd default:close */
#if LCD_ESD_PATCH
idc_esdcheck_lcderror(ts_data);
#endif
/* 6. Get Chip ID */
hardware_reset = get_chip_id(ts_data);
/* 7. get Flow work cnt: 0x91 If no change for 5 times, then ESD and reset */
if (!hardware_reset) {
hardware_reset = get_flow_cnt(ts_data);
}
/* 8. If need hardware reset, then handle it here */
if ( hardware_reset == 1) {
fts_esdcheck_tp_reset(ts_data);
}
FTS_DEBUG("[ESD]: NoACK=%d, Error Data=%d, Hardware Reset=%d", 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)
{
u8 val = 0;
struct fts_ts_data *ts_data = container_of(work,
struct fts_ts_data, esdcheck_work.work);
FTS_FUNC_ENTER();
if (ENABLE == fts_esdcheck_data.mode) {
if (ts_data->ic_info.is_incell) {
fts_i2c_read_reg(ts_data->client, FTS_REG_ESDCHECK_DISABLE, &val);
if (0xA5 == val) {
fts_esdcheck_data.mode = DISABLE;
return;
}
}
esdcheck_algorithm(ts_data);
queue_delayed_work(ts_data->ts_workqueue, &ts_data->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.mode;
}
/*****************************************************************************
* 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)
{
struct fts_ts_data *ts_data = fts_data;
FTS_FUNC_ENTER();
if (fts_esdcheck_data.mode == ENABLE) {
if (enable) {
FTS_DEBUG("[ESD]: ESD check start!!");
fts_esdcheck_data.flow_work_hold_cnt = 0;
fts_esdcheck_data.flow_work_cnt_last = 0;
queue_delayed_work(ts_data->ts_workqueue, &ts_data->esdcheck_work,
msecs_to_jiffies(ESDCHECK_WAIT_TIME));
} else {
FTS_DEBUG("[ESD]: ESD check stop!!");
cancel_delayed_work(&ts_data->esdcheck_work);
}
} else {
FTS_DEBUG("[ESD]: ESD should disable!!");
cancel_delayed_work(&ts_data->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_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)
{
struct input_dev *input_dev = fts_data->input_dev;
mutex_lock(&input_dev->mutex);
if (FTS_SYSFS_ECHO_ON(buf)) {
FTS_DEBUG("enable esdcheck");
fts_esdcheck_data.mode = ENABLE;
fts_esdcheck_switch(ENABLE);
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
FTS_DEBUG("disable esdcheck");
fts_esdcheck_data.mode = DISABLE;
fts_esdcheck_switch(DISABLE);
}
mutex_unlock(&input_dev->mutex);
return count;
}
/************************************************************************
* 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;
struct input_dev *input_dev = fts_data->input_dev;
mutex_lock(&input_dev->mutex);
count = snprintf(buf, PAGE_SIZE, "Esd check: %s\n", fts_esdcheck_get_status() ? "On" : "Off");
mutex_unlock(&input_dev->mutex);
return count;
}
/* sysfs esd node
* read example: cat fts_esd_mode ---read esd mode
* write example:echo 01 > fts_esd_mode ---make esdcheck enable
*
*/
static DEVICE_ATTR (fts_esd_mode, S_IRUGO | S_IWUSR, fts_esdcheck_show, fts_esdcheck_store);
static struct attribute *fts_esd_mode_attrs[] = {
&dev_attr_fts_esd_mode.attr,
NULL,
};
static struct attribute_group fts_esd_group = {
.attrs = fts_esd_mode_attrs,
};
/*****************************************************************************
* Name: fts_create_gesture_sysfs
* Brief:
* Input:
* Output:
* Return: 0-success or others-error
*****************************************************************************/
int fts_create_esd_sysfs(struct i2c_client *client)
{
int ret = 0;
ret = sysfs_create_group(&client->dev.kobj, &fts_esd_group);
if ( ret != 0) {
FTS_ERROR("fts_create_esd_sysfs(sysfs) create failed!");
sysfs_remove_group(&client->dev.kobj, &fts_esd_group);
return ret;
}
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(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
if (ts_data->ts_workqueue) {
INIT_DELAYED_WORK(&ts_data->esdcheck_work, esdcheck_func);
} else {
FTS_ERROR("fts workqueue is NULL, can't run esd check function");
return -EINVAL;
}
memset((u8 *)&fts_esdcheck_data, 0, sizeof(struct fts_esdcheck_st));
fts_esdcheck_data.mode = ENABLE;
fts_esdcheck_switch(ENABLE);
fts_create_esd_sysfs(ts_data->client);
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(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
FTS_FUNC_EXIT();
return 0;
}
#endif /* FTS_ESDCHECK_EN */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,382 @@
/*
*
* FocalTech ftxxxx TouchScreen driver.
*
* Copyright (c) 2012-2018, 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: Focaltech Driver Team
*
* 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_enter_cover_mode(struct i2c_client *client, int mode );
int fts_enter_charger_mode(struct i2c_client *client, int mode );
/*****************************************************************************
* 6.Static function prototypes
*******************************************************************************/
#if FTS_GLOVE_EN
static ssize_t fts_touch_glove_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
u8 val;
struct input_dev *input_dev = fts_data->input_dev;
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
mutex_lock(&input_dev->mutex);
fts_i2c_read_reg(client, FTS_REG_GLOVE_MODE_EN, &val);
count = snprintf(buf, PAGE_SIZE, "Glove Mode: %s\n", g_fts_mode_flag.fts_glove_mode_flag ? "On" : "Off");
count += snprintf(buf + count, PAGE_SIZE, "Glove Reg(0xC0) = %d\n", val);
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_touch_glove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
struct fts_ts_data *ts_data = fts_data;
struct i2c_client *client;
client = ts_data->client;
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(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(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; /* glove control */
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)
{
int count;
u8 val;
struct input_dev *input_dev = fts_data->input_dev;
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
mutex_lock(&input_dev->mutex);
fts_i2c_read_reg(client, FTS_REG_COVER_MODE_EN, &val);
count = snprintf(buf, PAGE_SIZE, "Cover Mode: %s\n", g_fts_mode_flag.fts_cover_mode_flag ? "On" : "Off");
count += snprintf(buf + count, PAGE_SIZE, "Cover Reg(0xC1) = %d\n", val);
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_touch_cover_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
struct fts_ts_data *ts_data = fts_data;
struct i2c_client *client;
client = ts_data->client;
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(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(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; /* cover control */
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_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)
{
int count;
u8 val;
struct input_dev *input_dev = fts_data->input_dev;
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
mutex_lock(&input_dev->mutex);
fts_i2c_read_reg(client, FTS_REG_CHARGER_MODE_EN, &val);
count = snprintf(buf, PAGE_SIZE, "Charge Mode: %s\n", g_fts_mode_flag.fts_charger_mode_flag ? "On" : "Off");
count += snprintf(buf + count, PAGE_SIZE, "Charge Reg(0x8B) = %d\n", val);
mutex_unlock(&input_dev->mutex);
return count;
}
static ssize_t fts_touch_charger_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int ret;
struct fts_ts_data *ts_data = fts_data;
struct i2c_client *client;
client = ts_data->client;
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(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(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; /* charger control */
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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,182 @@
/*
*
* FocalTech ftxxxx TouchScreen driver.
*
* Copyright (c) 2012-2018, 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.
*
*/
#ifndef __LINUX_FOCALTECH_FLASH_H__
#define __LINUX_FOCALTECH_FLASH_H__
/*****************************************************************************
* 1.Included header files
*****************************************************************************/
#include "focaltech_core.h"
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define FTS_CMD_RESET 0x07
#define FTS_ROMBOOT_CMD_WRITE 0xAE
#define FTS_ROMBOOT_CMD_START_APP 0x08
#define FTS_DELAY_PRAMBOOT_START 10
#define FTS_ROMBOOT_CMD_ECC 0xCC
#define FTS_CMD_READ 0x03
#define FTS_CMD_READ_DELAY 1
#define FTS_CMD_READ_LEN 4
#define FTS_CMD_FLASH_TYPE 0x05
#define FTS_CMD_FLASH_MODE 0x09
#define FLASH_MODE_WRITE_FLASH_VALUE 0x0A
#define FLASH_MODE_UPGRADE_VALUE 0x0B
#define FLASH_MODE_LIC_VALUE 0x0C
#define FLASH_MODE_PARAM_VALUE 0x0D
#define FTS_CMD_ERASE_APP 0x61
#define FTS_REASE_APP_DELAY 1350
#define FTS_ERASE_SECTOR_DELAY 60
#define FTS_RETRIES_REASE 50
#define FTS_RETRIES_DELAY_REASE 200
#define FTS_CMD_FLASH_STATUS 0x6A
#define FTS_CMD_FLASH_STATUS_LEN 2
#define FTS_CMD_FLASH_STATUS_NOP 0x0000
#define FTS_CMD_FLASH_STATUS_ECC_OK 0xF055
#define FTS_CMD_FLASH_STATUS_ERASE_OK 0xF0AA
#define FTS_CMD_FLASH_STATUS_WRITE_OK 0x1000
#define FTS_CMD_ECC_INIT 0x64
#define FTS_CMD_ECC_CAL 0x65
#define FTS_CMD_ECC_CAL_LEN 6
#define FTS_RETRIES_ECC_CAL 10
#define FTS_RETRIES_DELAY_ECC_CAL 50
#define FTS_CMD_ECC_READ 0x66
#define FTS_CMD_DATA_LEN 0xB0
#define FTS_CMD_APP_DATA_LEN_INCELL 0x7A
#define FTS_CMD_DATA_LEN_LEN 4
#define FTS_CMD_WRITE 0xBF
#define FTS_RETRIES_WRITE 100
#define FTS_RETRIES_DELAY_WRITE 1
#define FTS_CMD_WRITE_LEN 6
#define FTS_DELAY_READ_ID 20
#define FTS_DELAY_UPGRADE_RESET 80
#define PRAMBOOT_MIN_SIZE 0x120
#define PRAMBOOT_MAX_SIZE (64*1024)
#define FTS_FLASH_PACKET_LENGTH 32 /* max=128 */
#define FTS_MAX_LEN_ECC_CALC 0xFFFE /* must be even */
#define FTS_MIN_LEN 0x120
#define FTS_MAX_LEN_FILE (128 * 1024)
#define FTS_MAX_LEN_APP (64 * 1024)
#define FTS_MAX_LEN_SECTOR (4 * 1024)
#define FTS_CONIFG_VENDORID_OFF 0x04
#define FTS_CONIFG_MODULEID_OFF 0x1E
#define FTS_CONIFG_PROJECTID_OFF 0x20
#define FTS_APPINFO_OFF 0x100
#define FTS_APPINFO_APPLEN_OFF 0x00
#define FTS_APPINFO_APPLEN2_OFF 0x12
#define FTS_REG_UPGRADE 0xFC
#define FTS_UPGRADE_AA 0xAA
#define FTS_UPGRADE_55 0x55
#define FTS_DELAY_FC_AA 10
#define FTS_UPGRADE_LOOP 30
#define FTS_HEADER_LEN 32
#define FTS_FW_BIN_FILEPATH "/sdcard/"
#define FTS_FW_IDE_SIG "IDE_"
#define FTS_FW_IDE_SIG_LEN 4
#define FTS_ROMBOOT_CMD_ECC_NEW_LEN 7
#define FTS_ROMBOOT_CMD_ECC_FINISH 0xCE
#define FTS_CMD_READ_ECC 0xCD
#define AL2_FCS_COEF ((1 << 15) + (1 << 10) + (1 << 3))
enum FW_STATUS {
FTS_RUN_IN_ERROR,
FTS_RUN_IN_APP,
FTS_RUN_IN_ROM,
FTS_RUN_IN_PRAM,
FTS_RUN_IN_BOOTLOADER,
};
enum FW_FLASH_MODE {
FLASH_MODE_APP,
FLASH_MODE_LIC,
FLASH_MODE_PARAM,
FLASH_MODE_ALL,
};
enum ECC_CHECK_MODE {
ECC_CHECK_MODE_XOR,
ECC_CHECK_MODE_CRC16,
};
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
/* IC info */
struct upgrade_func {
u64 ctype[FTX_MAX_COMPATIBLE_TYPE];
int newmode;
u32 fwveroff;
u32 fwcfgoff;
u32 appoff;
u32 licoff;
u32 paramcfgoff;
u32 paramcfgveroff;
u32 paramcfg2off;
int ecc_check_mode;
bool read_boot_id_need_reset;
bool hid_supported;
bool pramboot_supported;
u8 *pramboot;
u32 pb_length;
int (*init)(void);
int (*upgrade)(struct i2c_client *, u8 *, u32);
int (*get_hlic_ver)(u8 *);
int (*lic_upgrade)(struct i2c_client *, u8 *, u32);
int (*param_upgrade)(struct i2c_client *, u8 *, u32);
int (*force_upgrade)(struct i2c_client *, u8 *, u32);
};
struct fts_upgrade {
u8 *fw;
u32 fw_length;
u8 *lic;
u32 lic_length;
struct upgrade_func *func;
};
struct upgrade_fw {
u16 vendor_id;
u8 *fw_file;
u32 fw_len;
};
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
extern struct fts_upgrade *fwupgrade;
extern struct upgrade_func upgrade_func_ft8006m;
/*****************************************************************************
* Static function prototypes
*****************************************************************************/
bool fts_fwupg_check_fw_valid(struct i2c_client *client);
int fts_fwupg_get_boot_state(struct i2c_client *client, enum FW_STATUS *fw_sts);
bool fts_fwupg_check_state(struct i2c_client *client, enum FW_STATUS rstate);
int fts_fwupg_reset_in_boot(struct i2c_client *client);
int fts_fwupg_reset_to_boot(struct i2c_client *client);
int fts_fwupg_reset_to_romboot(struct i2c_client *client);
int fts_fwupg_enter_into_boot(struct i2c_client *client);
int fts_fwupg_erase(struct i2c_client *client, u32 delay);
int fts_fwupg_ecc_cal(struct i2c_client *client, u32 saddr, u32 len);
int fts_flash_write_buf(struct i2c_client *client, u32 saddr, u8 *buf, u32 len, u32 delay);
int fts_fwupg_upgrade(struct i2c_client *client, struct fts_upgrade *upg);
u16 fts_crc16_calc_host(u8 *pbuf, u16 length);
#endif

View File

@@ -0,0 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
# Makefile for the focaltech touchscreen drivers.
#
# Each configuration option enables a list of files.
obj-y += focaltech_upgrade_ft8201.o

View File

@@ -0,0 +1,597 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2018, 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 6
#define FTS_GESTRUE_POINTS_HEADER 2
/*****************************************************************************
* Private enumerations, structures and unions using typedef
*****************************************************************************/
/*
* header - byte0:gesture id
* byte1:pointnum
* byte2~7:reserved
* coordinate_x - All gesture point x coordinate
* coordinate_y - All gesture point y coordinate
* mode - 1:enable gesture function(default)
* - 0:disable
* active - 1:enter into gesture(suspend)
* 0:gesture disable or resume
*/
struct fts_gesture_st {
u8 header[FTS_GESTRUE_POINTS_HEADER];
u16 coordinate_x[FTS_GESTRUE_POINTS];
u16 coordinate_y[FTS_GESTRUE_POINTS];
u8 mode; /*host driver enable gesture flag*/
u8 active; /*gesture actutally work*/
};
/*****************************************************************************
* Static variables
*****************************************************************************/
static struct fts_gesture_st fts_gesture_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:
* Input: device, device attribute, char buf
* Output:
* Return:
***********************************************************************/
static ssize_t fts_gesture_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
u8 val;
struct input_dev *input_dev = fts_data->input_dev;
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
mutex_lock(&input_dev->mutex);
fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &val);
count = snprintf(buf, PAGE_SIZE, "Gesture Mode: %s\n", fts_gesture_data.mode ? "On" : "Off");
count += snprintf(buf + count, PAGE_SIZE, "Reg(0xD0) = %d\n", val);
mutex_unlock(&input_dev->mutex);
return count;
}
/************************************************************************
* Name: fts_gesture_store
* Brief:
* Input: device, device attribute, char buf, char count
* Output:
* Return:
***********************************************************************/
static ssize_t fts_gesture_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
struct input_dev *input_dev = fts_data->input_dev;
mutex_lock(&input_dev->mutex);
if (FTS_SYSFS_ECHO_ON(buf)) {
FTS_INFO("[GESTURE]enable gesture");
fts_gesture_data.mode = ENABLE;
} else if (FTS_SYSFS_ECHO_OFF(buf)) {
FTS_INFO("[GESTURE]disable gesture");
fts_gesture_data.mode = DISABLE;
}
mutex_unlock(&input_dev->mutex);
return count;
}
/************************************************************************
* Name: fts_gesture_buf_show
* Brief:
* Input: device, device attribute, char buf
* Output:
* Return:
***********************************************************************/
static ssize_t fts_gesture_buf_show(struct device *dev, struct device_attribute *attr, char *buf)
{
int count;
int i = 0;
struct input_dev *input_dev = fts_data->input_dev;
mutex_lock(&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(&input_dev->mutex);
return count;
}
/************************************************************************
* Name: fts_gesture_buf_store
* Brief:
* Input: device, device attribute, char buf, char count
* Output:
* 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:
* Return: 0-success or others-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_report
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
static void fts_gesture_report(struct input_dev *input_dev, int gesture_id)
{
int gesture;
FTS_FUNC_ENTER();
FTS_INFO("fts gesture_id==0x%x ", gesture_id);
switch (gesture_id) {
case GESTURE_LEFT:
gesture = KEY_GESTURE_LEFT;
break;
case GESTURE_RIGHT:
gesture = KEY_GESTURE_RIGHT;
break;
case GESTURE_UP:
gesture = KEY_GESTURE_UP;
break;
case GESTURE_DOWN:
gesture = KEY_GESTURE_DOWN;
break;
case GESTURE_DOUBLECLICK:
gesture = KEY_GESTURE_U;
break;
case GESTURE_O:
gesture = KEY_GESTURE_O;
break;
case GESTURE_W:
gesture = KEY_GESTURE_W;
break;
case GESTURE_M:
gesture = KEY_GESTURE_M;
break;
case GESTURE_E:
gesture = KEY_GESTURE_E;
break;
case GESTURE_L:
gesture = KEY_GESTURE_L;
break;
case GESTURE_S:
gesture = KEY_GESTURE_S;
break;
case GESTURE_V:
gesture = KEY_GESTURE_V;
break;
case GESTURE_Z:
gesture = KEY_GESTURE_Z;
break;
case GESTURE_C:
gesture = KEY_GESTURE_C;
break;
default:
gesture = -1;
break;
}
/* report event key */
if (gesture != -1) {
FTS_DEBUG("Gesture Code=%d", gesture);
input_report_key(input_dev, gesture, 1);
input_sync(input_dev);
input_report_key(input_dev, gesture, 0);
input_sync(input_dev);
}
FTS_FUNC_EXIT();
}
/************************************************************************
* Name: fts_gesture_read_buffer
* Brief: read data from TP register
* Input:
* Output:
* 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:
* Output:
* Return: return 0 if succuss, otherwise reture error code
***********************************************************************/
int fts_gesture_readdata(struct fts_ts_data *ts_data)
{
u8 buf[FTS_GESTRUE_POINTS * 4] = { 0 };
int ret = 0;
int i = 0;
int gestrue_id = 0;
int read_bytes = 0;
u8 pointnum;
u8 state;
struct i2c_client *client = ts_data->client;
struct input_dev *input_dev = ts_data->input_dev;
if (!ts_data->suspended) {
return -EINVAL;
}
ret = fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &state);
if ((ret < 0) || (state != ENABLE)) {
FTS_DEBUG("gesture not enable, don't process gesture");
return -EIO;
}
/* 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;
}
memcpy(fts_gesture_data.header, buf, FTS_GESTRUE_POINTS_HEADER);
gestrue_id = buf[0];
pointnum = buf[1];
read_bytes = ((int)pointnum) * 4 + FTS_GESTRUE_POINTS_HEADER;
buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
FTS_DEBUG("[GESTURE]PointNum=%d", pointnum);
if (pointnum > FTS_GESTRUE_POINTS) {
FTS_ERROR("[GESTURE]gesture point number(%d) fail");
return -EIO;
}
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_gesture_report(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);
}
return 0;
}
/*****************************************************************************
* Name: fts_gesture_recovery
* Brief: recovery gesture state when reset or power on
* Input:
* Output:
* Return:
*****************************************************************************/
void fts_gesture_recovery(struct i2c_client *client)
{
if ((ENABLE == fts_gesture_data.mode) && (ENABLE == fts_gesture_data.active)) {
FTS_INFO("enter fts_gesture_recovery");
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);
}
}
/*****************************************************************************
* Name: fts_gesture_suspend
* Brief:
* Input:
* Output:
* Return: return 0 if succuss, otherwise return error code
*****************************************************************************/
int fts_gesture_suspend(struct i2c_client *client)
{
int ret;
int i;
u8 state;
FTS_INFO("gesture suspend...");
/* gesture not enable, return immediately */
if (fts_gesture_data.mode == DISABLE) {
FTS_INFO("gesture is disabled");
return -EINVAL;
}
for (i = 0; i < 5; i++) {
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);
msleep(1);
fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &state);
if (state == ENABLE)
break;
}
if (i >= 5) {
FTS_ERROR("[GESTURE]Enter into gesture(suspend) failed!\n");
fts_gesture_data.active = DISABLE;
return -EIO;
}
ret = enable_irq_wake(fts_data->irq);
if (ret) {
FTS_INFO("enable_irq_wake(irq:%d) failed", fts_data->irq);
}
fts_gesture_data.active = ENABLE;
FTS_INFO("[GESTURE]Enter into gesture(suspend) successfully!");
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_gesture_resume
* Brief:
* Input:
* Output:
* Return: return 0 if succuss, otherwise return error code
*****************************************************************************/
int fts_gesture_resume(struct i2c_client *client)
{
int ret;
int i;
u8 state;
FTS_INFO("gesture resume...");
/* gesture not enable, return immediately */
if (fts_gesture_data.mode == DISABLE) {
FTS_DEBUG("gesture is disabled");
return -EINVAL;
}
if (fts_gesture_data.active == DISABLE) {
FTS_DEBUG("gesture in suspend is failed, no running fts_gesture_resume");
return -EINVAL;
}
fts_gesture_data.active = DISABLE;
for (i = 0; i < 5; i++) {
fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, DISABLE);
msleep(1);
fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &state);
if (state == DISABLE)
break;
}
if (i >= 5) {
FTS_ERROR("[GESTURE]Clear gesture(resume) failed!\n");
return -EIO;
}
ret = disable_irq_wake(fts_data->irq);
if (ret) {
FTS_INFO("disable_irq_wake(irq:%d) failed", fts_data->irq);
}
FTS_INFO("[GESTURE]resume from gesture successfully!");
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_gesture_init
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_gesture_init(struct fts_ts_data *ts_data)
{
struct i2c_client *client = ts_data->client;
struct input_dev *input_dev = ts_data->input_dev;
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 = ENABLE;
fts_gesture_data.active = DISABLE;
FTS_FUNC_EXIT();
return 0;
}
/************************************************************************
* Name: fts_gesture_exit
* Brief: call when driver removed
* Input:
* Output:
* Return:
***********************************************************************/
int fts_gesture_exit(struct i2c_client *client)
{
FTS_FUNC_ENTER();
sysfs_remove_group(&client->dev.kobj, &fts_gesture_group);
FTS_FUNC_EXIT();
return 0;
}
#endif

View File

@@ -0,0 +1,240 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2018, 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: Focaltech Driver Team
*
* Created: 2016-08-04
*
* Abstract: i2c communication with TP
*
* Version: v1.0
*
* Revision History:
*
************************************************************************/
/*****************************************************************************
* Included header files
*****************************************************************************/
#include "focaltech_core.h"
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define I2C_RETRY_NUMBER 3
/*****************************************************************************
* 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 = 0;
int i = 0;
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,
},
};
for (i = 0; i < I2C_RETRY_NUMBER; i++) {
ret = i2c_transfer(client->adapter, msgs, 2);
if (ret < 0) {
FTS_ERROR("[IIC]: i2c_transfer(write) error, ret=%d!!", ret);
} else
break;
}
} else {
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = I2C_M_RD,
.len = readlen,
.buf = readbuf,
},
};
for (i = 0; i < I2C_RETRY_NUMBER; i++) {
ret = i2c_transfer(client->adapter, msgs, 1);
if (ret < 0) {
FTS_ERROR("[IIC]: i2c_transfer(read) error, ret=%d!!", ret);
} else
break;
}
}
}
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;
int i = 0;
mutex_lock(&i2c_rw_access);
if (writelen > 0) {
struct i2c_msg msgs[] = {
{
.addr = client->addr,
.flags = 0,
.len = writelen,
.buf = writebuf,
},
};
for (i = 0; i < I2C_RETRY_NUMBER; i++) {
ret = i2c_transfer(client->adapter, msgs, 1);
if (ret < 0) {
FTS_ERROR("%s: i2c_transfer(write) error, ret=%d", __func__, ret);
} else
break;
}
}
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, &regaddr, 1, regvalue, 1);
}
/************************************************************************
* HID to standard I2C
***********************************************************************/
void fts_i2c_hid2std(struct i2c_client *client)
{
int ret = 0;
u8 buf[3] = {0xeb, 0xaa, 0x09};
ret = fts_i2c_write(client, buf, 3);
if (ret < 0)
FTS_ERROR("hid2std cmd write fail");
else {
msleep(10);
buf[0] = buf[1] = buf[2] = 0;
ret = fts_i2c_read(client, NULL, 0, buf, 3);
if (ret < 0)
FTS_ERROR("hid2std cmd read fail");
else if ((0xeb == buf[0]) && (0xaa == buf[1]) && (0x08 == buf[2])) {
FTS_DEBUG("hidi2c change to stdi2c successful");
} else {
FTS_ERROR("hidi2c change to stdi2c fail");
}
}
}
/************************************************************************
* 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;
}

View File

@@ -0,0 +1,135 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2018, 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: Focaltech Driver Team
*
* Created: 2016-11-16
*
* Abstract: point report check function
*
* Version: v1.0
*
* Revision History:
*
*****************************************************************************/
/*****************************************************************************
* 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 /* unit:ms */
/*****************************************************************************
* functions body
*****************************************************************************/
/*****************************************************************************
* Name: fts_prc_func
* Brief: fts point report check work func, report whole up of points
* Input:
* Output:
* Return:
*****************************************************************************/
static void fts_prc_func(struct work_struct *work)
{
struct fts_ts_data *ts_data = container_of(work,
struct fts_ts_data, prc_work.work);
struct input_dev *input_dev = ts_data->input_dev;
#if FTS_MT_PROTOCOL_B_EN
u32 finger_count = 0;
#endif
FTS_FUNC_ENTER();
mutex_lock(&ts_data->report_mutex);
#if FTS_MT_PROTOCOL_B_EN
for (finger_count = 0; finger_count < ts_data->pdata->max_touch_number; finger_count++) {
input_mt_slot(input_dev, finger_count);
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER, false);
}
#else
input_mt_sync(input_dev);
#endif
input_report_key(input_dev, BTN_TOUCH, 0);
input_sync(input_dev);
mutex_unlock(&ts_data->report_mutex);
FTS_FUNC_EXIT();
}
/*****************************************************************************
* Name: fts_prc_queue_work
* Brief: fts point report check queue work, call it when interrupt comes
* Input:
* Output:
* Return:
*****************************************************************************/
void fts_prc_queue_work(struct fts_ts_data *ts_data)
{
cancel_delayed_work(&ts_data->prc_work);
queue_delayed_work(ts_data->ts_workqueue, &ts_data->prc_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(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
if (ts_data->ts_workqueue) {
INIT_DELAYED_WORK(&ts_data->prc_work, fts_prc_func);
} else {
FTS_ERROR("fts workqueue is NULL, can't run point report check function");
return -EINVAL;
}
FTS_FUNC_EXIT();
return 0;
}
/*****************************************************************************
* Name: fts_point_report_check_exit
* Brief:
* Input:
* Output:
* Return:
*****************************************************************************/
int fts_point_report_check_exit(struct fts_ts_data *ts_data)
{
FTS_FUNC_ENTER();
FTS_FUNC_EXIT();
return 0;
}
#endif /* FTS_POINT_REPORT_CHECK_EN */

View File

@@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0
#
#Makefile for test module
#
obj-y += focaltech_test.o
obj-y += focaltech_test_ini.o
obj-y += supported_ic/

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,589 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2018, 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.
*
*/
#ifndef _TEST_LIB_H
#define _TEST_LIB_H
/*****************************************************************************
* Included header files
*****************************************************************************/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/debugfs.h>
#include <asm/uaccess.h>
#include <linux/i2c.h>//iic
#include <linux/delay.h>//msleep
#include <linux/string.h>
#include <asm/unistd.h>
#include <linux/vmalloc.h>
#include "../focaltech_core.h"
#include "focaltech_test_ini.h"
/*****************************************************************************
* Macro definitions using #define
*****************************************************************************/
#define FTS_INI_FILE_PATH "/mnt/sdcard/"
#define FTS_CSV_FILE_NAME "testdata.csv"
#define FTS_TXT_FILE_NAME "testresult.txt"
#define false 0
#define true 1
#define TEST_ICSERIES_LEN (8)
#define TEST_ICSERIES(x) ((x) >> TEST_ICSERIES_LEN)
#define TEST_OPEN_MAX_VALUE (255)
#define BYTES_PER_TIME (32) /* max:128 */
/* CSV & TXT */
#define CSV_LINE1_BUFFER_LEN (1024*1)
#define CSV_LINE2_BUFFER_LEN (1024*2)
#define CSV_DATA_BUFFER_LEN (1024*80)
#define CSV_BUFFER_LEN (CSV_LINE1_BUFFER_LEN + CSV_LINE2_BUFFER_LEN + CSV_DATA_BUFFER_LEN)
#define TXT_BUFFER_LEN (1024*80*5)
/*-----------------------------------------------------------
Test Status
-----------------------------------------------------------*/
#define RESULT_NULL 0
#define RESULT_PASS 1
#define RESULT_NG 2
#define TX_NUM_MAX 60
#define RX_NUM_MAX 60
#define NUM_MAX ((TX_NUM_MAX)*(RX_NUM_MAX))
#define NUM_MAX_SC (144)
#define KEY_NUM_MAX 6
#define TEST_ITEM_COUNT_MAX 32
#define TEST_SHORT_RES_MAX 0xFFFF
/*
* factory test registers
*/
#define ENTER_WORK_FACTORY_RETRIES 5
#define START_SCAN_RETRIES_INCELL 20
#define START_SCAN_RETRIES_DELAY_INCELL 16
#define FACTORY_TEST_RETRY 50
#define FACTORY_TEST_DELAY 18
#define FACTORY_TEST_RETRY_DELAY 100
#define DEVIDE_MODE_ADDR 0x00
#define REG_FW_CHIP_IDL 0x9F
#define REG_FW_IC_TYPE 0xA0
#define REG_FW_IC_VERSION 0xB1
#define REG_FW_CHIP_IDH 0xA3
#define REG_FW_VERSION 0xA6
#define REG_VA_TOUCH_THR 0x80
#define REG_VKEY_TOUCH_THR 0x82
#define FACTORY_REG_LINE_ADDR 0x01
#define FACTORY_REG_CHX_NUM 0x02
#define FACTORY_REG_CHY_NUM 0x03
#define FACTORY_REG_CLB 0x04
#define FACTORY_REG_DATA_SELECT 0x06
#define FACTORY_REG_RAWBUF_SELECT 0x09
#define FACTORY_REG_KEY_CBWIDTH 0x0B
#define FACTORY_REG_PARAM_UPDATE_STATE 0x0E
#define FACTORY_REG_SHORT_TEST_EN 0x0F
#define FACTORY_REG_SHORT_TEST_STATE 0x10
#define FACTORY_REG_LCD_NOISE_START 0x11
#define FACTORY_REG_LCD_NOISE_FRAME 0x12
#define FACTORY_REG_LCD_NOISE_NUMBER 0x13
#define FACTORY_REG_LCD_NOISE_TTHR 0x14
#define FACTORY_REG_OPEN_START 0x15
#define FACTORY_REG_OPEN_STATE 0x16
#define FACTORY_REG_CB_ADDR_H 0x18
#define FACTORY_REG_CB_ADDR_L 0x19
#define FACTORY_REG_LCD_NOISE_STATE 0x1E
#define FACTORY_REG_KEYSHORT_EN 0x2E
#define FACTORY_REG_KEYSHORT_STATE 0x2F
#define FACTORY_REG_LEFT_KEY 0x1E
#define FACTORY_REG_RIGHT_KEY 0x1F
#define FACTORY_REG_OPEN_REG20 0x20
#define FACTORY_REG_OPEN_REG21 0x21
#define FACTORY_REG_OPEN_REG22 0x22
#define FACTORY_REG_OPEN_REG23 0x23
#define FACTORY_REG_OPEN_REG86 0x86
#define FACTORY_REG_K1 0x31
#define FACTORY_REG_K2 0x32
#define FACTORY_REG_RAWDATA_ADDR 0x6A
#define FACTORY_REG_CB_ADDR 0x6E
#define FACTORY_REG_SHORT_ADDR 0x89
#define FACTORY_REG_RAWDATA_TEST_EN 0x9E
#define FACTORY_REG_CB_TEST_EN 0x9F
#define FACTORY_REG_OPEN_TEST_EN 0xA0
/* mc_sc */
#define FACTORY_REG_FRE_LIST 0x0A
#define FACTORY_REG_NORMALIZE 0x16
#define FACTORY_REG_RAWDATA_ADDR_MC_SC 0x36
#define FACTORY_REG_PATTERN 0x53
#define FACTORY_REG_NOMAPPING 0x54
#define FACTORY_REG_CHX_NUM_NOMAP 0x55
#define FACTORY_REG_CHY_NUM_NOMAP 0x56
#define FACTORY_REG_WC_SEL 0x09
#define FACTORY_REG_MC_SC_MODE 0x44
#define FACTORY_REG_MC_SC_CB_ADDR_OFF 0x45
#define FACTORY_REG_MC_SC_CB_ADDR 0x4E
#define FACTROY_REG_SHORT_TEST_EN 0x07
#define FACTROY_REG_SHORT_CA 0x01
#define FACTROY_REG_SHORT_CC 0x02
#define FACTROY_REG_SHORT_CG 0x03
#define FACTROY_REG_SHORT_OFFSET 0x04
#define FACTROY_REG_SHORT_AB_CH 0x58
#define FACTROY_REG_SHORT_DELAY 0x5A
#define FACTORY_REG_SHORT_ADDR_MC 0xF4
#define FACTORY_REG_FIR 0xFB
/* sc */
#define FACTORY_REG_SCAN_ADDR2 0x08
#define FACTORY_REG_CH_NUM_SC 0x0A
#define FACTORY_REG_KEY_NUM_SC 0x0B
#define FACTORY_REG_SC_CB_ADDR_OFF 0x33
#define FACTORY_REG_SC_CB_ADDR 0x39
#define FACTORY_REG_RAWDATA_SADDR_SC 0x34
#define FACTORY_REG_RAWDATA_ADDR_SC 0x35
#define FACTORY_REG_CB_SEL 0x41
#define FACTORY_REG_FMODE 0xAE
#define TEST_RETVAL_00 0x00
#define TEST_RETVAL_AA 0xAA
/*****************************************************************************
* enumerations, structures and unions
*****************************************************************************/
struct csv_format {
u8 *buffer;
int length;
u8 *line2_buffer;
int line2_len;
int start_line;
int item_count;
u8 *data_buffer;
int data_len;
};
/* incell */
struct incell_testitem {
u32 short_test : 1;
u32 open_test : 1;
u32 cb_test : 1;
u32 rawdata_test : 1;
u32 lcdnoise_test : 1;
u32 keyshort_test : 1;
};
struct incell_threshold_b {
int short_res_min;
int short_res_vk_min;
int open_cb_min;
int open_k1_check;
int open_k1_value;
int open_k2_check;
int open_k2_value;
int cb_min;
int cb_max;
int cb_vkey_check;
int cb_min_vk;
int cb_max_vk;
int rawdata_min;
int rawdata_max;
int rawdata_vkey_check;
int rawdata_min_vk;
int rawdata_max_vk;
int lcdnoise_frame;
int lcdnoise_coefficient;
int lcdnoise_coefficient_vkey;
int open_nmos;
int keyshort_k1;
int keyshort_cb_max;
int rawdata2_min;
int rawdata2_max;
};
struct incell_threshold {
struct incell_threshold_b basic;
int *rawdata_min;
int *rawdata_max;
int *rawdata2_min;
int *rawdata2_max;
int *cb_min;
int *cb_max;
};
struct incell_test {
struct incell_threshold thr;
union {
int tmp;
struct incell_testitem item;
} u;
};
/* mc_sc */
enum mapping_type {
MAPPING = 0,
NO_MAPPING = 1,
};
struct mc_sc_testitem {
u32 rawdata_test : 1;
u32 rawdata_uniformity_test : 1;
u32 scap_cb_test : 1;
u32 scap_rawdata_test : 1;
u32 short_test : 1;
u32 panel_differ_test : 1;
};
struct mc_sc_threshold_b {
int rawdata_h_min;
int rawdata_h_max;
int rawdata_set_hfreq;
int rawdata_l_min;
int rawdata_l_max;
int rawdata_set_lfreq;
int uniformity_check_tx;
int uniformity_check_rx;
int uniformity_check_min_max;
int uniformity_tx_hole;
int uniformity_rx_hole;
int uniformity_min_max_hole;
int scap_cb_off_min;
int scap_cb_off_max;
int scap_cb_wp_off_check;
int scap_cb_on_min;
int scap_cb_on_max;
int scap_cb_wp_on_check;
int scap_rawdata_off_min;
int scap_rawdata_off_max;
int scap_rawdata_wp_off_check;
int scap_rawdata_on_min;
int scap_rawdata_on_max;
int scap_rawdata_wp_on_check;
int short_cg;
int short_cc;
int panel_differ_min;
int panel_differ_max;
};
struct mc_sc_threshold {
struct mc_sc_threshold_b basic;
int *rawdata_h_min;
int *rawdata_h_max;
int *rawdata_l_min;
int *rawdata_l_max;
int *tx_linearity_max;
int *tx_linearity_min;
int *rx_linearity_max;
int *rx_linearity_min;
int *scap_cb_off_min;
int *scap_cb_off_max;
int *scap_cb_on_min;
int *scap_cb_on_max;
int *scap_rawdata_off_min;
int *scap_rawdata_off_max;
int *scap_rawdata_on_min;
int *scap_rawdata_on_max;
int *panel_differ_min;
int *panel_differ_max;
};
struct mc_sc_test {
struct mc_sc_threshold thr;
union {
u32 tmp;
struct mc_sc_testitem item;
} u;
};
/* sc */
struct sc_testitem {
u32 rawdata_test : 1;
u32 cb_test : 1;
u32 delta_cb_test : 1;
};
struct sc_threshold_b {
int rawdata_min;
int rawdata_max;
int cb_min;
int cb_max;
int dcb_base;
int dcb_differ_max;
int dcb_key_check;
int dcb_key_differ_max;
int dcb_ds1;
int dcb_ds2;
int dcb_ds3;
int dcb_ds4;
int dcb_ds5;
int dcb_ds6;
int dcb_critical_check;
int dcb_cs1;
int dcb_cs2;
int dcb_cs3;
int dcb_cs4;
int dcb_cs5;
int dcb_cs6;
};
struct sc_threshold {
struct sc_threshold_b basic;
int *rawdata_min;
int *rawdata_max;
int *cb_min;
int *cb_max;
int *dcb_sort;
int *dcb_base;
};
struct sc_test {
struct sc_threshold thr;
union {
u32 tmp;
struct sc_testitem item;
} u;
};
enum test_hw_type {
IC_HW_INCELL = 1,
IC_HW_MC_SC,
IC_HW_SC,
};
enum test_scan_mode {
SCAN_NORMAL = 0,
SCAN_SC,
};
struct fts_test_node {
int channel_num;
int tx_num;
int rx_num;
int node_num;
int key_num;
};
struct fts_test {
struct fts_ts_data *ts_data;
struct fts_test_node node;
struct fts_test_node sc_node;
u32 ic_ver;
u8 fw_ver;
u8 va_touch_thr;
u8 vk_touch_thr;
bool key_support;
bool v3_pattern;
u8 mapping;
u8 normalize;
int test_num;
int *buffer;
int buffer_length;
int *node_valid;
int *node_valid_sc;
int basic_thr_count;
int code1;
int code2;
int offset;
union {
struct incell_test incell;
struct mc_sc_test mc_sc;
struct sc_test sc;
} ic;
struct test_funcs *func;
struct csv_format csv;
char *testresult;
int testresult_len;
struct ini_data ini;
};
struct test_funcs {
u64 ctype[FTX_MAX_COMPATIBLE_TYPE];
enum test_hw_type hwtype;
int startscan_mode;
int key_num_total;
bool rawdata2_support;
bool force_touch;
int (*param_init)(void);
int (*init)(void);
int (*start_test)(void);
};
enum byte_mode {
DATA_ONE_BYTE,
DATA_TWO_BYTE,
};
/* mc_sc */
enum normalize_type {
NORMALIZE_OVERALL,
NORMALIZE_AUTO,
};
enum wp_type {
WATER_PROOF_OFF = 0,
WATER_PROOF_ON = 1,
WATER_PROOF_ON_TX,
WATER_PROOF_ON_RX,
WATER_PROOF_OFF_TX,
WATER_PROOF_OFF_RX,
};
/* mc end */
/* sc */
enum factory_mode {
FACTORY_NORMAL,
FACTORY_TESTMODE_1,
FACTORY_TESTMODE_2,
};
enum dcb_sort_num {
DCB_SORT_MIN = 1,
DCB_SORT_MAX = 6,
};
struct dcb_sort_d {
int ch_num;
int deviation;
int critical;
int min;
int max;
};
/* sc end */
enum csv_itemcode_incell {
CODE_ENTER_FACTORY_MODE = 0,
CODE_RAWDATA_TEST = 7,
CODE_CB_TEST = 12,
CODE_SHORT_TEST = 14,
CODE_OPEN_TEST = 15,
CODE_LCD_NOISE_TEST = 19,
};
enum csv_itemcode_mc_sc {
CODE_M_RAWDATA_TEST = 7,
CODE_M_SCAP_CB_TEST = 9,
CODE_M_SCAP_RAWDATA_TEST = 10,
CODE_M_WEAK_SHORT_CIRCUIT_TEST = 15,
CODE_M_PANELDIFFER_TEST = 20,
};
enum csv_itemcode_sc {
CODE_S_RAWDATA_TEST = 7,
CODE_S_CB_TEST = 13,
CODE_S_DCB_TEST = 14,
};
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
extern struct test_funcs test_func_ft8201;
extern struct fts_test *fts_ftest;
void sys_delay(int ms);
int focal_abs(int value);
void print_buffer(int *buffer, int length, int line_num);
int fts_test_read_reg(u8 addr, u8 *val);
int fts_test_write_reg(u8 addr, u8 val);
int fts_test_read(u8 addr, u8 *readbuf, int readlen);
int fts_test_write(u8 addr, u8 *writebuf, int writelen);
int enter_work_mode(void);
int enter_factory_mode(void);
int read_mass_data(u8 addr, int byte_num, int *buf);
int chip_clb(void);
int wait_state_update(u8 retval);
int get_cb_incell(u16 saddr, int byte_num, int *cb_buf);
int short_get_adcdata_incell(u8 retval, u8 ch_num, int byte_num, int *adc_buf);
int start_scan(void);
int get_rawdata(int *data);
int get_cb_sc(int byte_num, int *cb_buf, enum byte_mode mode);
bool compare_data(int *data, int min, int max, int min_vk, int max_vk, bool key);
bool compare_array(int *data, int *min, int *max, bool key);
void show_data(int *data, bool key);
void save_data_csv(int *data, char *name, u8 code, bool mc_sc, bool key);
/* mc_sc */
int mapping_switch(u8 mapping);
bool get_fw_wp(u8 wp_channel_select, enum wp_type water_proof_type);
int get_cb_mc_sc(u8 wp, int byte_num, int *cb_buf, enum byte_mode mode);
int get_rawdata_mc_sc(enum wp_type wp, int *data);
int get_rawdata_mc(u8 fre, u8 fir, int *rawdata);
void short_print_mc(int *r, int num);
int short_get_adc_data_mc(u8 retval, int byte_num, int *adc_buf, u8 mode);
bool compare_mc_sc(bool, bool, int *, int *, int *);
void show_data_mc_sc(int *data);
void *fts_malloc(size_t size);
void fts_free_proc(void *p);
int fts_test_init(struct i2c_client *client);
int fts_test_exit(struct i2c_client *client);
#define fts_malloc_r(p, size) do {\
if (NULL == p) {\
p = fts_malloc(size);\
if (NULL == p) {\
return -ENOMEM;\
}\
}\
} while(0)
#define fts_free(p) do {\
if (p) {\
fts_free_proc(p);\
p = NULL;\
}\
} while(0)
#define TEST_IC_VERSION(idh, idl, ver1, ver0) \
(((idh) << 24) | ((idl) << 16) | ((ver1) << 8) | (ver0))
#define CSV_SUPPORT 1
#define FOCAL_TEST_DEBUG_EN 1
#if (FOCAL_TEST_DEBUG_EN)
#define FTS_TEST_DBG(fmt, args...) do {printk("[FTS][TEST]%s. line: %d. "fmt"\n", __FUNCTION__, __LINE__, ##args);} while (0)
#define FTS_TEST_FUNC_ENTER() printk("[FTS][TEST]%s: Enter(%d)\n", __func__, __LINE__)
#define FTS_TEST_FUNC_EXIT() printk("[FTS][TEST]%s: Exit(%d)\n", __func__, __LINE__)
#else
#define FTS_TEST_DBG(fmt, args...) do{}while(0)
#define FTS_TEST_FUNC_ENTER()
#define FTS_TEST_FUNC_EXIT()
#endif
#define FTS_TEST_INFO(fmt, args...) do { printk(KERN_ERR "[FTS][TEST][Info]%s. line: %d. "fmt"\n", __FUNCTION__, __LINE__, ##args);} while (0)
#define FTS_TEST_ERROR(fmt, args...) do { printk(KERN_ERR "[FTS][TEST][Error]%s. line: %d. "fmt"\n", __FUNCTION__, __LINE__, ##args);} while (0)
#define FTS_TEST_SAVE_INFO(fmt, args...) do { \
if (fts_ftest->testresult) { \
fts_ftest->testresult_len += snprintf( \
fts_ftest->testresult + fts_ftest->testresult_len, \
TXT_BUFFER_LEN, \
fmt, ##args);\
} \
} while (0)
#define FTS_TEST_SAVE_ERR(fmt, args...) do { \
if (fts_ftest->testresult) { \
fts_ftest->testresult_len += snprintf( \
fts_ftest->testresult + fts_ftest->testresult_len, \
TXT_BUFFER_LEN, \
fmt, ##args);\
} \
printk(KERN_ERR "[FTS][TEST][Error]%s. line: %d. "fmt"", __FUNCTION__, __LINE__, ##args);\
} while (0)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,144 @@
/*
*
* FocalTech TouchScreen driver.
*
* Copyright (c) 2012-2018, 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.
*
*/
#ifndef _INI_H
#define _INI_H
/*****************************************************************************
* Private constant and macro definitions using #define
*****************************************************************************/
#define MAX_KEYWORD_NUM (500)
#define MAX_KEYWORD_NAME_LEN (50)
#define MAX_KEYWORD_VALUE_LEN (512)
#define MAX_KEYWORD_VALUE_ONE_LEN (16)
#define MAX_INI_LINE_LEN (MAX_KEYWORD_NAME_LEN + MAX_KEYWORD_VALUE_LEN)
#define MAX_INI_SECTION_NUM (20)
#define MAX_IC_NAME_LEN (512) //The original value is 32
#define MAX_TEST_ITEM (20)
#define IC_CODE_OFFSET (16)
/*****************************************************************************
* enumerations, structures and unions
*****************************************************************************/
struct ini_ic_type {
char ic_name[MAX_IC_NAME_LEN];
u32 ic_type;
};
enum line_type {
LINE_SECTION = 1,
LINE_KEYWORD = 2 ,
LINE_OTHER = 3,
};
struct ini_keyword {
char name[MAX_KEYWORD_NAME_LEN];
char value[MAX_KEYWORD_VALUE_LEN];
};
struct ini_section {
char name[MAX_KEYWORD_NAME_LEN];
int keyword_num;
/* point to ini.tmp, don't need free */
struct ini_keyword *keyword;
};
struct ini_data {
char *data;
int length;
int keyword_num_total;
int section_num;
struct ini_section section[MAX_INI_SECTION_NUM];
struct ini_keyword *tmp;
char ic_name[MAX_IC_NAME_LEN];
u32 ic_code;
};
#define TEST_ITEM_INCELL { \
"SHORT_CIRCUIT_TEST", \
"OPEN_TEST", \
"CB_TEST", \
"RAWDATA_TEST", \
"LCD_NOISE_TEST", \
"KEY_SHORT_TEST", \
}
#define BASIC_THRESHOLD_INCELL { \
"ShortCircuit_ResMin", "ShortCircuit_VkResMin", \
"OpenTest_CBMin", "OpenTest_Check_K1", "OpenTest_K1Threshold", "OpenTest_Check_K2", "OpenTest_K2Threshold", \
"CBTest_Min", "CBTest_Max", \
"CBTest_VKey_Check", "CBTest_Min_Vkey", "CBTest_Max_Vkey", \
"RawDataTest_Min", "RawDataTest_Max", \
"RawDataTest_VKey_Check", "RawDataTest_Min_VKey", "RawDataTest_Max_VKey", \
"LCD_NoiseTest_Frame", "LCD_NoiseTest_Coefficient", "LCD_NoiseTest_Coefficient_key", \
}
#define TEST_ITEM_MC_SC { \
"RAWDATA_TEST", \
"UNIFORMITY_TEST", \
"SCAP_CB_TEST", \
"SCAP_RAWDATA_TEST", \
"WEAK_SHORT_CIRCUIT_TEST", \
"PANEL_DIFFER_TEST", \
}
#define BASIC_THRESHOLD_MC_SC { \
"RawDataTest_High_Min", "RawDataTest_High_Max", "RawDataTest_HighFreq", \
"RawDataTest_Low_Min", "RawDataTest_Low_Max", "RawDataTest_LowFreq", \
"UniformityTest_Check_Tx", "UniformityTest_Check_Rx","UniformityTest_Check_MinMax", \
"UniformityTest_Tx_Hole", "UniformityTest_Rx_Hole", "UniformityTest_MinMax_Hole", \
"SCapCbTest_OFF_Min", "SCapCbTest_OFF_Max", "ScapCBTest_SetWaterproof_OFF", \
"SCapCbTest_ON_Min", "SCapCbTest_ON_Max", "ScapCBTest_SetWaterproof_ON", \
"SCapRawDataTest_OFF_Min", "SCapRawDataTest_OFF_Max", "SCapRawDataTest_SetWaterproof_OFF", \
"SCapRawDataTest_ON_Min", "SCapRawDataTest_ON_Max", "SCapRawDataTest_SetWaterproof_ON", \
"WeakShortTest_CG", "WeakShortTest_CC", \
"PanelDifferTest_Min", "PanelDifferTest_Max", \
}
#define TEST_ITEM_SC { \
"CB_TEST", \
"DELTA_CB_TEST", \
"RAWDATA_TEST", \
}
#define BASIC_THRESHOLD_SC { \
"RawDataTest_Min", "RawDataTest_Max", \
"CbTest_Min", "CbTest_Max", \
"DeltaCbTest_Base", "DeltaCbTest_Differ_Max", \
"DeltaCbTest_Include_Key_Test", "DeltaCbTest_Key_Differ_Max", \
"DeltaCbTest_Deviation_S1", "DeltaCbTest_Deviation_S2", "DeltaCbTest_Deviation_S3", \
"DeltaCbTest_Deviation_S4", "DeltaCbTest_Deviation_S5", "DeltaCbTest_Deviation_S6", \
"DeltaCbTest_Set_Critical", "DeltaCbTest_Critical_S1", "DeltaCbTest_Critical_S2", \
"DeltaCbTest_Critical_S3", "DeltaCbTest_Critical_S4", \
"DeltaCbTest_Critical_S5", "DeltaCbTest_Critical_S6", \
}
/*****************************************************************************
* Global variable or extern global variabls/functions
*****************************************************************************/
int fts_test_get_testparam_from_ini(char *config_name);
int get_keyword_value(char *section, char *name, int *value);
#define get_value_interface(name, value) \
get_keyword_value("Interface", name, value)
#define get_value_basic(name, value) \
get_keyword_value("Basic_Threshold", name, value)
#define get_value_detail(name, value) \
get_keyword_value("SpecialSet", name, value)
#define get_value_testitem(name, value) \
get_keyword_value("TestItem", name, value)
#endif /* _INI_H */

View File

@@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for test module
#
# Linux driver folder
obj-y += focaltech_test_ft8201.o

View File

@@ -0,0 +1,299 @@
0x60,0x00,0x00,0x00,0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,
0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,
0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,
0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,
0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,
0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,0x98,0x06,0x00,0x00,
0x00,0x3c,0x60,0xe0,0x60,0xe0,0x02,0xcc,0x00,0xea,0x10,0x3c,0x3f,0xe0,0x03,0xc8,
0x00,0xfa,0x7c,0xc8,0x00,0xf0,0x82,0xcf,0x00,0xe0,0x80,0xcf,0x60,0xe0,0x00,0x14,
0x00,0xea,0x17,0x3c,0x00,0xe0,0x02,0xcc,0x24,0xe0,0x00,0xcc,0x79,0x3c,0x9c,0x14,
0x00,0xea,0x08,0x01,0x01,0xe0,0x02,0xcd,0x28,0x3d,0x0c,0xcd,0x42,0xd8,0x00,0xe0,
0x6c,0x14,0x0c,0xe0,0x00,0x00,0x02,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x57,0xed,0xa8,0x12,0x2c,0x49,0xd3,0xb6,0xa6,0x29,0x59,0xd6,0xfe,0x01,0x72,0x8d,
0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xfe,0x01,0x00,0x00,0xc6,0x80,0x00,0x00,
0xff,0x00,0x8f,0x70,0xa3,0x08,0x72,0x8d,0xa9,0x02,0x63,0x48,0xfe,0x01,0x8d,0x72,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0x01,0xff,0xff,
0x38,0x53,0x54,0x46,0x50,0x36,0x30,0x30,0x00,0x31,0x30,0x30,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x00,0x31,0x30,0x30,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0x30,0x38,0x54,0x46,0x50,0x5f,0x36,0x30,0x62,0x6d,0x61,0x72,0x5f,0x74,0x6f,0x6f,
0x36,0x2e,0x31,0x56,0x72,0x70,0x41,0x5f,0x20,0x36,0x32,0x20,0x38,0x31,0x30,0x32,
0xef,0x17,0x7c,0xc0,0x02,0xe8,0x87,0x6f,0x00,0xe2,0x9c,0x4f,0x30,0x01,0xea,0xcf,
0x00,0xe2,0x94,0x02,0x25,0x01,0x85,0xcf,0xe6,0xcf,0x00,0xe2,0x00,0xe2,0x26,0x01,
0x87,0x01,0x83,0xcf,0xaa,0x67,0x02,0xe8,0x01,0xe0,0x1f,0x3c,0x07,0x6c,0x08,0x8c,
0x6f,0x3c,0x87,0x4f,0x82,0x38,0x04,0xc0,0xb3,0xcf,0x01,0xe2,0x01,0xe2,0x74,0x01,
0x13,0x01,0xcc,0xcf,0x90,0xcf,0x01,0xe2,0x05,0x2c,0xf4,0x01,0xd4,0x4f,0x00,0xe8,
0xef,0x00,0x87,0x6f,0x01,0xcc,0x00,0xe2,0x00,0xe8,0xec,0x01,0xf9,0x00,0xd5,0x4f,
0x00,0xe8,0x68,0x2c,0xf5,0x00,0xc6,0x4f,0xa0,0x4f,0x02,0xe8,0x05,0x2c,0xf2,0x00,
0x88,0x5f,0x01,0xe8,0xed,0x00,0xc8,0x37,0x01,0xcc,0x00,0xe2,0x01,0xe8,0xda,0x01,
0xe7,0x00,0x88,0x5f,0x02,0xe8,0x00,0x17,0x02,0xe8,0x1e,0x6f,0x00,0xe2,0x9c,0x4f,
0x02,0xe0,0xe5,0xcf,0xb2,0x02,0x4f,0x01,0x89,0xcf,0x00,0xe2,0x3b,0x01,0x02,0xe0,
0x00,0xe2,0x96,0x02,0x01,0xe0,0x83,0xcf,0x88,0x02,0x5f,0x01,0x81,0xcf,0x00,0xe2,
0x01,0x17,0x8d,0x01,0x1e,0x6f,0x02,0xe8,0x00,0xe2,0x89,0x00,0x02,0xe0,0x85,0xcf,
0x00,0xe2,0x0c,0x01,0x02,0xe0,0x87,0xcf,0x82,0x38,0x12,0x01,0xd5,0xcf,0x00,0xe2,
0x87,0x02,0x27,0x01,0x90,0xcf,0x00,0xe2,0x02,0xe8,0xf9,0x01,0xf6,0x00,0x92,0x6c,
0xe1,0xcf,0x00,0xe2,0x4b,0x01,0x02,0xe0,0xe4,0xcf,0x00,0xe2,0x02,0xe8,0xef,0x01,
0x80,0x17,0x20,0x6f,0xc0,0x7f,0x00,0xe8,0x01,0xe2,0xe9,0x00,0x00,0xe0,0xb0,0xcf,
0x91,0x02,0x43,0x01,0xea,0xcf,0x00,0xe2,0x84,0x02,0x55,0x01,0xe6,0xcf,0x00,0xe2,
0x01,0xe2,0xd0,0x00,0x29,0x01,0x90,0xcf,0xaa,0xcf,0x01,0xe2,0x02,0xe8,0xd7,0x01,
0xd4,0x00,0x20,0x6f,0xb3,0xcf,0x01,0xe2,0x1e,0x01,0x01,0xe0,0x01,0xe2,0x97,0x02,
0xcc,0x01,0xb2,0xcf,0x05,0xcc,0x00,0xe2,0xe6,0x02,0x00,0xe0,0x8e,0x7f,0x06,0xea,
0xfe,0xc7,0xff,0xe9,0x1f,0x3c,0x21,0x34,0x1f,0x3c,0x08,0x94,0x7c,0xff,0x02,0x3c,
0x4c,0x01,0x2a,0x01,0x98,0x00,0x8a,0x00,0x01,0xe2,0xa4,0x00,0x6b,0x01,0xbf,0xcf,
0xcc,0xcf,0x01,0xe2,0xa6,0x00,0xff,0xe7,0x03,0xcc,0x00,0xe2,0xaf,0x02,0xff,0xe7,
0x90,0x1f,0x00,0xe0,0x20,0x6f,0x02,0xe8,0x8f,0xac,0x98,0x3f,0x1b,0x24,0xff,0xe7,
0xa5,0x00,0xff,0xe7,0x03,0xcc,0x00,0xe2,0xa1,0x02,0xff,0xe7,0xdc,0x7f,0x06,0xea,
0xfe,0xc7,0xff,0xe9,0x08,0x8c,0x1f,0x3c,0x02,0x3c,0x1f,0x3c,0x26,0x16,0x04,0x04,
0x01,0xe8,0x80,0x17,0x01,0xe8,0x87,0x77,0x02,0xe8,0x86,0x77,0xff,0xe7,0xa0,0x6f,
0x01,0xe8,0x8e,0x00,0xa8,0x34,0x87,0x5f,0x01,0xe8,0x9f,0x3c,0xff,0xe7,0x87,0x74,
0x01,0xe8,0x86,0x00,0x00,0x17,0x87,0x5f,0x86,0x17,0x9f,0x3c,0x87,0x74,0x01,0xe8,
0xc2,0x7f,0x00,0xe8,0xa5,0x00,0xff,0xe7,0x2a,0x67,0x02,0xe8,0x9f,0x3c,0x8e,0xa7,
0xfe,0xe7,0x8e,0xbc,0x02,0xe8,0xf4,0x00,0xa8,0x34,0xaa,0x67,0xfe,0xe7,0xaf,0xb4,
0x02,0xe8,0xee,0x00,0x2f,0x9f,0xaa,0x67,0xaf,0xb4,0x9e,0x3c,0x3f,0xb7,0x00,0x17,
0xe5,0x00,0xfe,0xe7,0x9c,0x4f,0x02,0xe8,0xb2,0xcf,0x01,0xe2,0x02,0xe8,0x87,0x01,
0x0f,0xe2,0xa0,0x4f,0x02,0xe8,0xcf,0x3c,0x02,0xe8,0xa0,0x6f,0x3f,0x9f,0xaa,0x67,
0x81,0xc6,0xee,0x3e,0x1f,0x3f,0xbf,0xb6,0x8e,0xac,0x01,0xe0,0xaf,0x9e,0x3f,0x9f,
0xfe,0xe7,0xfe,0x3e,0x09,0xe8,0xcc,0x02,0x00,0x17,0xa6,0x4e,0x0d,0x3f,0x2e,0xe0,
0x26,0x6f,0x09,0xe8,0xa6,0x7f,0x02,0xe8,0x00,0xe8,0x82,0x17,0x02,0xe8,0xc2,0x7f,
0x01,0xe2,0x9c,0x4f,0xfe,0xe7,0xb2,0xcf,0x07,0x17,0xba,0x01,0x42,0x7f,0x00,0xe8,
0xb5,0x00,0xfe,0xe7,0x02,0xcc,0x00,0xe2,0x00,0xe2,0x19,0x01,0x1c,0x01,0x03,0xcc,
0x01,0xcc,0x00,0xe2,0xab,0x01,0xfe,0xe7,0xa6,0x4f,0x09,0xe8,0x00,0xe0,0x8c,0x27,
0x02,0xe8,0x8c,0x1f,0x09,0xe4,0xaa,0x7f,0x02,0xe8,0xa0,0x34,0x8f,0xbc,0xaa,0x67,
0x9d,0x00,0xfe,0xe7,0x8b,0x1f,0x00,0xe0,0x02,0xe8,0xf5,0x00,0x0f,0xa7,0xaa,0x67,
0x9e,0x3c,0xa8,0x34,0x02,0xe8,0xf5,0x00,0x0f,0xa7,0xaa,0x67,0x8f,0xbc,0x9e,0x3c,
0x02,0xe8,0x01,0x17,0x81,0x17,0xa6,0x7f,0x9e,0x6f,0x02,0xe8,0x42,0x7f,0x00,0xe8,
0x9c,0x4f,0x02,0xe8,0xb3,0xcf,0x01,0xe2,0x81,0x01,0xfe,0xe7,0x00,0xe8,0x88,0x17,
0xfd,0xe7,0xc2,0x7f,0x00,0xe2,0xfc,0x00,0x81,0x17,0x02,0xcc,0x02,0xe8,0x83,0x01,
0x02,0xe8,0x94,0x6f,0xfd,0xe7,0x9e,0x6f,0x02,0xe0,0xf2,0x00,0x0f,0xaf,0x84,0x17,
0x0f,0xaf,0x81,0xc7,0x86,0x17,0x02,0xe0,0x81,0xc7,0x0f,0xaf,0x00,0x17,0x0f,0xaf,
0x9d,0x67,0x00,0xe8,0x1f,0xb7,0x03,0xe0,0x02,0xe8,0x81,0x17,0xfd,0xe7,0x95,0x6f,
0x00,0xe2,0xde,0x00,0x85,0x01,0x01,0xcc,0xc7,0x6c,0x00,0xe8,0xd7,0x00,0xfd,0xe7,
0x02,0xcc,0x00,0xe2,0xd3,0x01,0xfd,0xe7,0x93,0x6c,0x02,0xe8,0xcf,0x00,0xfd,0xe7,
0x00,0xe2,0x7f,0xc4,0xfd,0xe7,0x04,0xcc,0x0a,0xea,0xca,0x02,0xff,0xe9,0x90,0x7f,
0x21,0x34,0xfe,0xc7,0x08,0x94,0x1f,0x3c,0x02,0xe8,0x1f,0x3c,0x02,0x3c,0xaa,0x67,
0x4e,0xff,0x0a,0x00,0x18,0x00,0x12,0x00,0x09,0xe4,0x1e,0x00,0xff,0xe7,0xa0,0x34,
0x0f,0xa7,0x98,0x00,0x9f,0x00,0xff,0xe7,0xfe,0xe7,0xa8,0x34,0x2f,0x9f,0xc1,0x00,
0xaf,0xb4,0x9e,0x3c,0xfe,0xe7,0x03,0x17,0x84,0x17,0xf3,0x00,0xc2,0x7f,0x00,0xe8,
0x20,0x6f,0x02,0xe8,0x00,0xe8,0x00,0x17,0xfd,0xe7,0x40,0x7f,0xb2,0x08,0xa0,0x00,
0x37,0x0c,0x00,0xe8,0x80,0x17,0x7c,0xc0,0x81,0x17,0x87,0x6f,0x1b,0x61,0x00,0xe8,
0xc8,0x6f,0x00,0xe8,0x00,0xe2,0x82,0xa7,0x9e,0x27,0x81,0xc7,0x7e,0x17,0x82,0xa7,
0x82,0xbf,0xde,0x3f,0x87,0x6f,0xf2,0x8f,0x9d,0x4f,0x02,0xe8,0x87,0x4f,0x84,0x2f,
0x9c,0x6f,0x02,0xe8,0x9d,0x4f,0x02,0xe8,0x6f,0x3c,0x07,0x4f,0x5b,0xde,0xee,0x3c,
0x9d,0x4f,0x02,0xe8,0x02,0xe8,0x81,0xc7,0x02,0xe8,0x9d,0x6f,0x84,0x27,0x9e,0x4f,
0x0f,0xde,0x00,0x14,0x82,0xa7,0x72,0xac,0x00,0xe2,0xc1,0x37,0x8f,0x27,0x81,0xc7,
0x7d,0x17,0x82,0xa7,0x82,0xbf,0xde,0x3f,0x9d,0x4f,0x02,0xe8,0x02,0xe8,0x81,0xc7,
0x02,0xe8,0x9d,0x6f,0x6f,0x3c,0x9d,0x4f,0x72,0xac,0xfc,0xdd,0x61,0xe0,0x88,0x17,
0x04,0xc0,0x91,0x3f,0xa8,0x0b,0x00,0xf0,0x00,0x38,0x21,0x09,0x00,0xe8,0xbf,0x0e,
0xfe,0x16,0x1b,0x67,0xdd,0x3f,0xbe,0xa7,0x80,0x17,0xbe,0xbf,0x9d,0x6f,0x02,0xe8,
0x61,0xe0,0x90,0x17,0xad,0x0f,0x91,0x3f,0xb6,0x08,0x00,0x38,0x00,0xc0,0xff,0xe1,
0x84,0x4f,0x02,0xe8,0xe9,0x39,0x68,0x3a,0x8a,0x27,0xea,0x3a,0x8e,0x1c,0x00,0xe0,
0xa2,0xe0,0x20,0x15,0x06,0xd3,0x00,0x14,0x02,0xe8,0x80,0x17,0x01,0xe0,0x84,0x6f,
0xa1,0x00,0x00,0x13,0x01,0xe2,0x63,0x39,0x82,0x05,0x00,0xc9,0xff,0xe3,0x66,0x39,
0x64,0x3c,0x7f,0xc1,0x00,0xe2,0x62,0x3d,0xe6,0xd2,0x84,0x7c,0x85,0x8f,0xa2,0x39,
0xff,0xc1,0xff,0xe3,0x00,0xe2,0x12,0x3a,0x00,0x17,0x84,0x7e,0x80,0xe1,0x01,0xc7,
0xff,0xe3,0x1d,0x8e,0x7e,0x39,0x7f,0xc7,0xcc,0x3f,0x0f,0xe2,0xff,0xc7,0x01,0xe2,
0x85,0xaf,0xf6,0x01,0x01,0xe0,0xe0,0x29,0x61,0x0b,0x00,0xc0,0x02,0xcc,0x00,0xea,
0x00,0xcc,0x02,0xe0,0x00,0xea,0x80,0x14,0x0b,0xe0,0x02,0xcd,0x28,0x3d,0x20,0xcd,
0x00,0xea,0x88,0xd5,0x00,0xe0,0x00,0xcc,0x02,0x24,0x00,0xcc,0x00,0x14,0x01,0x3c,
0xf1,0xd3,0x80,0x14,0x00,0x00,0x80,0x3a,0xb1,0x08,0x80,0x3a,0x60,0xe0,0xb3,0xd5,
0x00,0xe0,0x87,0x3f,0x01,0xe0,0x08,0x1f,0x00,0xe0,0x3f,0xbf,0x01,0xe0,0x0f,0x1f,
0x00,0xe0,0x4f,0xbf,0x02,0xe0,0x06,0x1f,0xe1,0x08,0x4f,0xbf,0xa0,0x1f,0x00,0xe0,
0x5f,0xb7,0x7f,0x17,0x03,0x17,0x1e,0xe0,0x00,0xe8,0x3f,0xb7,0x13,0x27,0x56,0x4f,
0x14,0x17,0xa0,0xe0,0x20,0xe0,0x7f,0xb7,0x01,0xe0,0x04,0x17,0x00,0xeb,0x1f,0xb7,
0x2f,0xa7,0x80,0xcf,0x5d,0x3f,0xf8,0x16,0x1f,0xa7,0x2f,0xbf,0x49,0xcf,0xc0,0xe0,
0x82,0x38,0x1f,0xbf,0x7f,0xb7,0x04,0x17,0x00,0xe0,0xf1,0x00,0x02,0xe0,0xa0,0x1e,
0x02,0xe2,0x9d,0x9f,0x95,0x27,0x80,0xc7,0x9d,0x9f,0x02,0xe0,0x7f,0x16,0xfb,0xe7,
0x6f,0x3f,0xc9,0x37,0x01,0xc7,0x00,0xe2,0x56,0x6f,0x00,0xe8,0x8f,0x3f,0x41,0xe0,
0x00,0xe2,0x0d,0xa7,0xa9,0x37,0x81,0xc7,0xce,0x3f,0x5c,0x3f,0x82,0x38,0x8d,0xbf,
0x00,0xe8,0x83,0x17,0xfc,0x00,0xd6,0x6f,0x18,0x8c,0x88,0x8f,0x01,0xe0,0x98,0x3f,
0x28,0xe0,0x7f,0x14,0x82,0x38,0x88,0x3f,0x00,0xe0,0xb4,0x08,0x68,0x39,0x83,0x19,
0x63,0x3c,0x98,0x39,0xf1,0xdf,0x69,0x3a,0x83,0x8f,0x04,0x24,0x61,0x0a,0x84,0xaf,
0x87,0x1f,0x00,0xe0,0x62,0x3c,0x1f,0x39,0x7a,0x24,0xe8,0xdf,0xf7,0x00,0x82,0x8f,
0xd6,0x4f,0x00,0xe8,0xb1,0x08,0x93,0x27,0x83,0x1c,0x00,0xe0,0x1f,0xe0,0x0e,0x15,
0x42,0xd2,0x00,0x14,0x87,0x1c,0x00,0xe0,0x22,0xe0,0x0e,0x15,0x3c,0xd2,0x20,0x14,
0xd9,0x7c,0x00,0xea,0xa1,0x08,0x00,0x14,0x82,0x38,0xd8,0x00,0xd6,0x4f,0x00,0xe8,
0x00,0xe0,0xfe,0x16,0x91,0x2f,0x21,0x1f,0xd8,0x4f,0x00,0xe8,0x01,0xe0,0xdd,0x3f,
0x61,0xe0,0xbe,0xaf,0x88,0xcf,0x82,0x3f,0x92,0x3f,0x61,0xe0,0x82,0x3f,0x61,0xe0,
0x61,0xe0,0x90,0xcf,0x82,0x38,0x92,0x3f,0xd9,0x4f,0x00,0xe8,0xbf,0x0e,0xf0,0x00,
0xc9,0x67,0x00,0xe8,0x00,0xe8,0x81,0xc7,0x00,0xe8,0xc9,0x7f,0x81,0xc7,0xca,0x67,
0xca,0x7f,0x00,0xe8,0xca,0x67,0x00,0xe8,0x84,0xcf,0x00,0xe2,0x84,0x17,0x84,0x05,
0xca,0x7f,0x00,0xe8,0x00,0xe0,0xdf,0x16,0xbe,0xa7,0x22,0x1f,0xbe,0xbf,0xdd,0x3f,
0x80,0x17,0x20,0xe0,0x91,0x3f,0x61,0xe0,0x00,0x38,0xad,0x0f,0x22,0x1f,0x00,0xe0,
0xbe,0xbf,0x91,0x17,0xae,0xa7,0xfc,0x16,0x82,0xcf,0xdd,0x3f,0x0a,0xe0,0xae,0xbf,
0x9e,0xb7,0x80,0x17,0x80,0x17,0x20,0xe0,0x91,0x3f,0x61,0xe0,0x82,0x3f,0x61,0xe0,
0x80,0xcf,0x20,0xe0,0x92,0x3f,0x61,0xe0,0x7c,0xc0,0x82,0x38,0x80,0x17,0xa0,0xe0,
0x00,0xe0,0x81,0x7f,0x01,0xe0,0xa0,0x1f,0xff,0xe3,0x1f,0x9f,0x01,0xe0,0x7b,0xc7,
0xff,0x16,0x1f,0xb7,0x9e,0x3e,0x01,0x67,0x7c,0x2f,0x81,0x7e,0x1f,0x9f,0x01,0xe0,
0x01,0xe0,0x04,0xcf,0x04,0xc0,0x1f,0xb7,0xff,0xe1,0x82,0x38,0x7f,0xc4,0xff,0x17,
0x7f,0xc4,0xff,0xe3,0x0a,0x01,0x7f,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x38,0xf3,0x00,0x00,0xe0,0xb3,0x08,
0x00,0x17,0x8a,0x1f,0x6f,0x3d,0x01,0x16,0x9e,0x3f,0x0d,0xe0,0x00,0xe2,0x01,0xc7,
0x0d,0xae,0x10,0xcf,0x03,0x17,0xfa,0x01,0x81,0x10,0x3f,0xaf,0x02,0x17,0x4f,0xaf,
0x00,0x17,0x6f,0xaf,0x8d,0x1d,0x00,0xe0,0x7f,0xaf,0x01,0xe0,0x6b,0x3c,0x80,0x17,
0x0d,0xe0,0xef,0x3c,0x0e,0xe0,0xa2,0x37,0x8e,0xbc,0x9d,0x3d,0x1f,0x3d,0x02,0xe0,
0x00,0x17,0x98,0x3e,0x1e,0x3d,0x0c,0xe0,0x82,0x89,0x0c,0x8e,0x86,0x03,0xfc,0x39,
0x0c,0xe0,0x8d,0xa1,0x43,0x3e,0xbe,0x30,0x01,0xc7,0x0d,0xbe,0x10,0xcf,0x00,0xe2,
0x81,0xc7,0xf2,0x01,0x90,0xcf,0x00,0xe2,0x00,0xe0,0xe5,0x01,0x00,0x17,0x89,0x1f,
0x0f,0xaf,0x06,0xe0,0x00,0xe0,0xe1,0x09,0x0f,0xe0,0x8d,0x1e,0x9f,0x3e,0x22,0x34,
0xb3,0x27,0x8d,0xa7,0x00,0xe0,0x83,0x3f,0x06,0xe0,0x89,0x1f,0x60,0xe0,0x0f,0x8f,
0x24,0x37,0x09,0x3e,0x0e,0xbe,0x1f,0x3f,0x0f,0x8f,0x06,0xe0,0x0a,0x3e,0x60,0xe0,
0x1f,0x3f,0x24,0x37,0x06,0xe0,0x1e,0xbe,0x60,0xe0,0x0f,0x8f,0x24,0x37,0x08,0x3e,
0x2e,0xbe,0x1f,0x3f,0x0f,0x8f,0x06,0xe0,0x02,0x3e,0x61,0xe0,0x1f,0x3f,0x24,0x37,
0x06,0xe0,0x3e,0xbe,0x01,0xc7,0x0f,0x8f,0x0f,0xaf,0x06,0xe0,0x61,0xe0,0x8d,0xa7,
0x81,0x17,0x92,0x3f,0xb8,0x37,0x08,0xe0,0x11,0x3c,0x61,0xe0,0x80,0x3f,0x60,0xe0,
0x60,0xe0,0x82,0xcf,0x00,0x3b,0x90,0x3f,0x00,0xe0,0x82,0x38,0x0e,0xe0,0x8d,0x1f,
0x9e,0x3f,0x22,0x34,0xa7,0x27,0x8f,0xa7,0x00,0xe0,0x83,0x3f,0x06,0xe0,0x89,0x1f,
0x7f,0xc7,0x0f,0x8f,0x0f,0xaf,0x06,0xe0,0x0f,0x8f,0x06,0xe0,0x1f,0x3f,0x24,0x37,
0x60,0xe0,0x0e,0xa7,0x06,0xe0,0x19,0x3f,0x24,0x37,0x0f,0x8f,0x1e,0xa7,0x1f,0x3f,
0x1a,0x3f,0x60,0xe0,0x0f,0x8f,0x06,0xe0,0x1f,0x3f,0x24,0x37,0x60,0xe0,0x2e,0xa7,
0x06,0xe0,0x18,0x3f,0x24,0x37,0x0f,0x8f,0xbf,0xa7,0x9e,0x3f,0x92,0x3f,0x61,0xe0,
0x82,0x38,0x00,0x3b,0x08,0xe0,0x81,0x17,0x61,0xe0,0xb8,0x37,0xfa,0x00,0x11,0x3c,
0x19,0x67,0x00,0xe8,0x8e,0xa7,0x7e,0xac,0x00,0xe2,0xce,0x37,0xfc,0x27,0x81,0xc7,
0x7f,0xe7,0x8e,0xa7,0xdd,0x3f,0xff,0x16,0x8e,0xbf,0x01,0x14,0x00,0xe8,0x82,0x38,
0x00,0x17,0x99,0x67,0x0f,0xa7,0x7f,0xaf,0x00,0xe2,0x4e,0x37,0x7c,0x27,0x01,0xc7,
0x7f,0xe7,0x0f,0xa7,0x5d,0x3f,0xff,0x16,0xff,0x8f,0x0f,0xbf,0x82,0x38,0x6f,0x3c,
0x99,0x67,0x00,0xe8,0x80,0x16,0x98,0x3c,0x7f,0x16,0x7f,0xe7,0x82,0x01,0x79,0x3c,
0xff,0xae,0x82,0x38,0x4e,0x37,0x0f,0xa7,0x01,0xc7,0x00,0xe2,0x0f,0xa7,0x7c,0x27,
0x0f,0xbf,0x5c,0x3f,0x80,0xe1,0x7f,0x8f,0xf1,0x00,0x18,0xaf,0x00,0xe8,0xb2,0x08,
0x7b,0x17,0x19,0x61,0x00,0xe2,0x82,0xa7,0xde,0x3f,0x01,0xcc,0x87,0x01,0x82,0xbf,
0xbf,0xdf,0x06,0x14,0x84,0xcf,0x82,0xa7,0x61,0x09,0x82,0xbf,0xfa,0x00,0x04,0x14,
0x00,0xe8,0xb2,0x08,0x7b,0x17,0x19,0x61,0x05,0x14,0x82,0xa7,0x82,0xbf,0xde,0x3f,
0xbe,0xdf,0xb0,0xdf,0x00,0xe2,0x82,0xa7,0x84,0xcf,0x01,0xc4,0x61,0x09,0x82,0xbf,
0x01,0x14,0xb2,0x08,0x00,0xe8,0xdc,0xdf,0x7b,0x17,0x19,0x61,0x01,0xe0,0x82,0xa7,
0xde,0x3f,0x10,0x14,0x9d,0xdf,0x82,0xbf,0x82,0xa7,0xab,0xdf,0x82,0xbf,0x84,0xcf,
0xb4,0x08,0x61,0x09,0xcb,0xdf,0x01,0x14,0x19,0x61,0x00,0xe8,0x02,0xa7,0xfb,0x11,
0x53,0x3f,0x05,0x14,0x8d,0xdf,0x02,0xbf,0x02,0xa7,0x9b,0xdf,0x04,0xcf,0x68,0x3a,
0x01,0x14,0x02,0xbf,0x82,0xa7,0xbc,0xdf,0xd3,0x3f,0x01,0x14,0x81,0xdf,0x82,0xbf,
0x01,0xe2,0x64,0x3c,0x7d,0xdf,0x03,0xc4,0x84,0xcf,0x82,0xa7,0xc1,0xdf,0x82,0xbf,
0x61,0x0a,0x7f,0x2c,0x1e,0x67,0x00,0xe8,0x81,0xcf,0x9e,0xa7,0x00,0xe8,0x9e,0xbf,
0x3f,0x9f,0x9d,0x67,0x00,0xcf,0x1e,0xe0,0x01,0xe0,0x3f,0xb7,0x80,0xe0,0x1f,0x9f,
0x01,0xe0,0x00,0xcf,0x61,0xe0,0x1f,0xb7,0xef,0xe7,0x82,0x3f,0xde,0x3f,0x7f,0x17,
0x92,0x3f,0x61,0xe0,0x99,0x67,0x00,0xe8,0x06,0x17,0x26,0xe0,0xc2,0x00,0x0f,0xbf,
0x00,0xe8,0xb2,0x08,0xfb,0x16,0x19,0x67,0x69,0x39,0x8e,0xa7,0x8e,0xbf,0xdd,0x3f,
0x08,0xe4,0x50,0xdf,0x01,0xe2,0x40,0x31,0x4b,0xdf,0x7f,0xc4,0x48,0x31,0x08,0xe0,
0x7f,0xc4,0x01,0xe2,0x62,0x3c,0x46,0xdf,0x7f,0xc4,0x01,0xe2,0xfe,0xe7,0x21,0x09,
0xb4,0x08,0xc1,0x00,0x01,0x14,0x68,0x3a,0xea,0x39,0x69,0x39,0xe4,0x3c,0x70,0xdf,
0xdf,0xdf,0x02,0x14,0x00,0xe8,0xe2,0x3c,0xff,0xc4,0x99,0x67,0x7f,0xe7,0x00,0x17,
0x73,0x3f,0x7f,0x16,0x0f,0xa7,0x95,0x01,0x0f,0xbf,0x04,0xcf,0x06,0x24,0x72,0xdf,
0xc9,0x67,0x00,0xe8,0xb2,0xcf,0x00,0xe2,0x00,0xe8,0xfa,0x05,0x00,0xe2,0xc9,0x67,
0x95,0x05,0xb2,0xcf,0x08,0x14,0x27,0xe0,0xfc,0xe7,0x21,0x0a,0x80,0xe0,0xe0,0x00,
0xff,0xae,0x99,0x8e,0xce,0x36,0x8f,0xa6,0x81,0xc6,0x00,0xe2,0x8f,0xa6,0xfc,0x26,
0xdc,0x3e,0x01,0xc7,0x7f,0xc7,0xff,0xe3,0xdc,0x00,0x8f,0xbe,0xb2,0x08,0x61,0x0a,
0x19,0x67,0x00,0xe8,0x8e,0xa7,0xfb,0x16,0xdd,0x3f,0x68,0x39,0x0b,0x14,0x8e,0xbf,
0x08,0xe4,0x00,0xdf,0x01,0xe2,0x40,0x31,0xfb,0xde,0x7f,0xc4,0x48,0x31,0x08,0xe0,
0x7f,0xc4,0x01,0xe2,0x62,0x3c,0xf6,0xde,0x7f,0xc4,0x01,0xe2,0x00,0x14,0xf2,0xde,
0xfd,0xe7,0x21,0x09,0xb3,0x08,0xef,0x00,0xea,0x39,0x69,0x39,0x62,0x3c,0xe1,0xdf,
0x07,0xdf,0xe3,0x3c,0x19,0x67,0x00,0xe8,0x8e,0xa7,0x01,0x14,0x8e,0xbf,0x84,0xcf,
0xb7,0x08,0xe1,0x09,0x38,0x0c,0x00,0xf8,0x00,0xe2,0xe8,0x39,0x01,0xe0,0xff,0xc1,
0x03,0xe0,0x80,0x13,0xff,0xe3,0xa3,0x3b,0xfa,0x39,0xff,0xc1,0x92,0xdf,0x83,0x04,
0x6a,0x39,0xa1,0x00,0x68,0x3a,0xe9,0x3a,0x13,0x3a,0x23,0x39,0xff,0xe3,0x63,0x3d,
0x95,0x39,0x7f,0xc1,0xe2,0x3a,0x87,0xdf,0x18,0xe0,0x64,0x3b,0x00,0xe2,0xa4,0x39,
0x09,0xf0,0xff,0xca,0x92,0x02,0x16,0x3c,0x47,0x31,0x0a,0xe0,0x27,0x35,0x09,0xe0,
0x00,0xc5,0xff,0xe5,0x19,0x3a,0x08,0xe0,0xff,0xe3,0x12,0x3d,0x93,0x3c,0x7f,0xc5,
0x01,0x14,0x5f,0x2d,0x28,0x0c,0x00,0xf8,0x66,0x3c,0xe1,0x0b,0xff,0xe1,0x67,0x3d,
0x68,0xdf,0x80,0xc2,0xff,0xc2,0xff,0xe3,0x00,0xc3,0x01,0xe0,0xb2,0x08,0xe1,0x00,
0x01,0x14,0x68,0x39,0x09,0xe0,0xd4,0xde,0x20,0x14,0x2c,0x31,0x00,0xe8,0x42,0xdf,
0x8e,0xa7,0x19,0x67,0x8e,0xbf,0x84,0xcf,0x06,0x24,0xdc,0xde,0xc9,0x67,0x00,0xe8,
0xf4,0xcf,0x03,0xe2,0x00,0xe8,0xfa,0x05,0x03,0xe2,0xc9,0x67,0x86,0x05,0xf4,0xcf,
0x08,0x14,0x27,0xe0,0xfb,0xe7,0x21,0x09,0x61,0x09,0xca,0x00,0x68,0x39,0xb2,0x08,
0xb5,0xde,0x01,0x14,0x20,0x31,0x09,0xe4,0x58,0x14,0x01,0xe0,0x00,0xe8,0x22,0xdf,
0x8e,0xa7,0x19,0x67,0x8e,0xbf,0x84,0xcf,0x06,0x24,0xbc,0xde,0xc9,0x67,0x00,0xe8,
0xdc,0xcf,0x0b,0xe2,0x00,0xe8,0xfa,0x05,0x0b,0xe2,0xc9,0x67,0x86,0x05,0xdc,0xcf,
0x08,0x14,0x27,0xe0,0xfb,0xe7,0x21,0x09,0x61,0x09,0xaa,0x00,0x01,0x14,0xb2,0x08,
0x00,0xe8,0x96,0xde,0x7b,0x17,0x19,0x61,0x00,0xe0,0x82,0xa7,0xde,0x3f,0x60,0x14,
0x57,0xde,0x82,0xbf,0x84,0xcf,0x82,0xa7,0x9b,0xde,0x82,0xbf,0x61,0x09,0x7f,0x2c,
0xc7,0x4f,0x00,0xe8,0x8a,0xcf,0x00,0xe2,0x00,0xe8,0x28,0x01,0x02,0xe0,0xc7,0x4f,
0x9f,0xe3,0x80,0x17,0x7e,0x3c,0x7f,0x17,0xb4,0x08,0xa3,0x02,0x40,0x67,0x00,0xe8,
0xfe,0x3f,0x6a,0x39,0x68,0x3a,0xe9,0x39,0x00,0xe0,0x8d,0x01,0x20,0x15,0x0e,0x1c,
0x20,0x15,0xd8,0xd1,0xff,0x14,0x01,0xe0,0x0b,0xd2,0x63,0x3c,0x02,0xe8,0x81,0x17,
0x05,0x21,0x84,0x6f,0xe3,0x3c,0x62,0x3d,0x4c,0xdf,0x64,0x3c,0x40,0x65,0x00,0xe8,
0x00,0xe8,0x1a,0x39,0x61,0x0a,0x40,0x79,0x80,0x17,0xa2,0xe0,0x82,0x38,0xdb,0x00,
0x85,0x1f,0x00,0xe0,0x84,0x1e,0x00,0xe0,0x7f,0x16,0x6f,0x3f,0x1f,0xae,0x80,0xe1,
0xfd,0x01,0xfd,0x3f,0x87,0x5f,0x01,0xe8,0x85,0x1c,0x00,0xe0,0xc8,0x37,0x0d,0xe0,
0xef,0x3e,0x8e,0xae,0x80,0xcf,0xfe,0xe5,0xae,0xaf,0xc8,0x37,0xff,0xc6,0x01,0xe2,
0xa0,0x4f,0x02,0xe8,0x20,0x15,0x9e,0xae,0x41,0xe0,0xce,0xaf,0x02,0xe8,0x8d,0x3e,
0xa0,0xe3,0xa0,0x4f,0x41,0xe0,0x00,0x14,0xbe,0xae,0x8f,0x3f,0xfe,0xe7,0xde,0xaf,
0xa0,0xe3,0x9a,0x00,0x1f,0x3c,0xa0,0x17,0xff,0x17,0x9f,0xe3,0xa8,0x05,0x7f,0x3c,
0x18,0x3d,0x0d,0xe0,0x80,0x17,0xc0,0xe3,0xa2,0x02,0xff,0x3e,0x87,0x5e,0x01,0xe8,
0xe0,0xce,0x1f,0xe2,0x01,0xe8,0x9d,0x02,0x9a,0x3f,0x86,0x5f,0xff,0xc7,0xff,0xe3,
0x86,0x77,0x01,0xe8,0xff,0x3e,0x0f,0x25,0xb1,0x08,0x8d,0x04,0x01,0xe8,0xfb,0xde,
0x01,0xe8,0x06,0x5f,0x7f,0x3f,0x87,0x5f,0xa1,0x08,0x84,0x01,0xb2,0x00,0xff,0xe7,
0x01,0xe8,0xe1,0x08,0x01,0xe8,0x06,0x5f,0x7f,0x3f,0x87,0x5f,0x82,0x38,0x78,0x01,
0xf0,0x17,0xff,0xe2,0x0f,0xbf,0x00,0x17,0xb1,0x08,0x82,0x38,0x2f,0xdc,0x4f,0xdc,
0xf0,0x17,0xff,0xe2,0x0f,0xbf,0x00,0x17,0x83,0xdc,0x46,0xde,0x16,0xdc,0x98,0xdc,
0xe1,0x08,0x00,0x3b,0x00,0xf8,0xb7,0x08,0xe1,0xe7,0x3c,0x0c,0xee,0xdf,0xaa,0x11,
0x80,0x13,0xff,0xe7,0x55,0x14,0xe0,0xf7,0x80,0x14,0xa0,0xf3,0x00,0x12,0x02,0xe0,
0x9b,0x62,0x00,0xe8,0x40,0xf0,0x00,0x11,0x01,0x13,0x65,0x3d,0x7c,0x4c,0x00,0xe8,
0x00,0xf8,0x04,0x2c,0xe1,0x0b,0x28,0x0e,0xc2,0x67,0x00,0xe8,0x00,0xe2,0xff,0xc7,
0xb9,0x02,0x87,0xcf,0x46,0x7f,0x1d,0xea,0x7e,0xc7,0xff,0xe9,0x9e,0x3f,0xa1,0x37,
0x9e,0x3f,0x8f,0x9f,0xa4,0x00,0x82,0x3f,0xf6,0x00,0x10,0x00,0x5e,0x00,0x16,0x01,
0x82,0x00,0x10,0x02,0x00,0xe8,0xc8,0x00,0x00,0xe8,0x42,0x79,0x01,0xe8,0xfd,0x4f,
0x84,0x27,0x08,0x71,0x00,0xe8,0xab,0xdc,0x00,0xe8,0x7d,0x69,0x6f,0x3f,0xc7,0x4f,
0xa6,0x67,0x02,0xe8,0x0b,0xcf,0x00,0xe2,0x88,0xc4,0xef,0x3c,0x00,0xe8,0x06,0x01,
0x00,0xe2,0x47,0x4f,0x9d,0x01,0x0a,0xcf,0x2f,0x9d,0x0f,0xa4,0x02,0xe8,0x1a,0xdf,
0x00,0xe8,0xa6,0x67,0x0f,0xa4,0x7d,0x6b,0xe4,0xd0,0xaf,0x9c,0x00,0xc4,0x20,0xe0,
0x08,0x74,0x01,0xe8,0x95,0x4f,0x02,0xe8,0xba,0x27,0xff,0xe7,0x08,0x14,0x27,0xe0,
0x00,0xe8,0x9d,0xdc,0x7f,0x17,0x9d,0x67,0x3f,0xaf,0x07,0xe0,0xaa,0x00,0xff,0xe7,
0x2f,0x9d,0x0f,0xa4,0xe4,0x00,0x6f,0xde,0x42,0x79,0x00,0xe8,0xfd,0x4f,0x00,0xe8,
0x08,0x71,0x01,0xe8,0x72,0xdc,0x84,0x27,0x7d,0x69,0x00,0xe8,0xa6,0x64,0x02,0xe8,
0x29,0x9d,0x09,0xa4,0x46,0xdf,0x88,0xc4,0x02,0xe8,0xd3,0x00,0x00,0xe8,0xa6,0x64,
0x64,0x3d,0x42,0x79,0x29,0xa4,0x80,0xe1,0x00,0xe8,0x47,0xde,0xd3,0x27,0xc8,0x4f,
0xa6,0x67,0x02,0xe8,0x8f,0x8f,0x01,0xe0,0xfa,0xaf,0x00,0xe8,0x02,0xe8,0xcc,0x00,
0x00,0xe8,0xa6,0x64,0x64,0x3d,0x42,0x79,0x0f,0xe8,0x89,0xa7,0x89,0xbf,0x99,0x3f,
0x29,0xa4,0x80,0xe1,0x00,0xe8,0x31,0xde,0xff,0xe7,0xc8,0x4f,0x02,0xe8,0xbd,0x27,
0x01,0xe0,0xa6,0x67,0xf5,0xaf,0x8f,0x8f,0xb6,0x00,0xff,0xe7,0x42,0x79,0x00,0xe8,
0x20,0x7d,0x02,0xea,0xa6,0x67,0x02,0xe8,0x08,0x71,0x01,0xe8,0xaf,0x9c,0x0f,0xa4,
0x34,0xdc,0x15,0xdb,0x08,0x74,0x01,0xf8,0xa6,0x00,0xff,0xe7,0x42,0x79,0x00,0xe8,
0x08,0x71,0x01,0xe8,0xc7,0x4f,0x00,0xe8,0x8a,0xcf,0x00,0xe2,0x00,0xe8,0x9e,0x01,
0x01,0xe2,0xc6,0x4f,0x97,0x01,0x80,0xcf,0x71,0xde,0x62,0x3c,0x90,0x15,0x00,0xf0,
0x6b,0x3c,0x40,0xe8,0x40,0xe8,0x4d,0xde,0x81,0xc7,0xeb,0x3f,0xef,0x3d,0x40,0xf0,
0xff,0xc5,0x01,0xf2,0x9d,0xcd,0x00,0xf2,0x10,0xdc,0xf4,0x01,0x88,0x71,0x01,0xe8,
0x82,0x00,0xff,0xe7,0xfa,0x00,0x7c,0xde,0xc7,0x4f,0x00,0xe8,0x8b,0xcf,0x00,0xe2,
0x00,0xe8,0xa6,0x01,0x01,0xe2,0xc6,0x4f,0x91,0x01,0x80,0xcf,0x85,0x15,0x00,0xf0,
0x6b,0x3c,0x40,0xe8,0x40,0xe8,0x2d,0xde,0x81,0xc7,0xeb,0x3f,0xef,0x3d,0x40,0xf0,
0xff,0xc5,0x01,0xf2,0x9d,0xcd,0x00,0xf2,0xe0,0x00,0xf4,0x01,0x84,0x15,0x00,0xf0,
0x6b,0x3c,0x40,0xe8,0x40,0xe8,0x1d,0xde,0x81,0xc7,0xeb,0x3f,0xef,0x3d,0x40,0xf0,
0xff,0xc5,0x01,0xf2,0xc0,0xcd,0x00,0xf2,0xd0,0x00,0xf4,0x01,0xc7,0x4f,0x00,0xe8,
0x8c,0xcf,0x00,0xe2,0x62,0x3c,0x84,0x01,0xc8,0x00,0x0b,0xde,0xc7,0x4f,0x00,0xe8,
0x8d,0xcf,0x00,0xe2,0x04,0x14,0x85,0x01,0x1f,0x14,0x03,0xde,0x00,0xe8,0xf6,0x00,
0x40,0xf0,0xc7,0x4f,0x01,0xf4,0x6f,0x3e,0x1b,0xe0,0x00,0xce,0x02,0xe8,0xaf,0x3b,
0x0f,0xf8,0x13,0x4f,0x01,0xe2,0x1b,0x3e,0xfe,0x3f,0xff,0xc7,0xaf,0x03,0xff,0xe7,
0x6c,0x3c,0x40,0xe8,0x40,0xe8,0xed,0xdd,0x81,0xc7,0xec,0x3f,0x6f,0x3e,0x40,0xf0,
0x7f,0xc6,0x01,0xf2,0x00,0xe8,0xed,0x00,0x1d,0x14,0x42,0x79,0x08,0x71,0x01,0xe8,
0x00,0x15,0xd4,0x00,0x81,0x17,0x81,0x00,0x2d,0xe1,0x00,0x17,0x84,0x26,0x19,0x3c,
0x8e,0x3f,0x2d,0xe1,0x00,0x17,0x88,0x2e,0x00,0xe2,0x8c,0x2f,0x68,0xe0,0x00,0xcd,
0x82,0x38,0x2e,0x39,0x80,0xcc,0x00,0xe2,0xa1,0x34,0x77,0x04,0xee,0x00,0xa1,0x37,
0x83,0x04,0x79,0x3c,0x4f,0x3f,0x29,0x3c,0xc1,0x34,0xc1,0x37,0x00,0x00,0xee,0x00,
0x00,0xe2,0xe8,0x3d,0xab,0x05,0x03,0xcd,0x49,0x3c,0x0c,0xe0,0x03,0xc6,0x00,0xe2,
0x7c,0xc5,0x26,0x2e,0x21,0x35,0x0c,0xe0,0x18,0xc6,0x00,0xe2,0x99,0xa7,0x80,0xe1,
0x22,0xe0,0x06,0x26,0xac,0x3e,0xf0,0x16,0x82,0x3e,0x6f,0x3f,0x93,0x06,0x70,0xc5,
0x19,0xa7,0x80,0xe1,0x9b,0xbf,0x80,0xe1,0x99,0xa7,0x80,0xe1,0x1b,0xbf,0x80,0xe1,
0x19,0xa7,0x80,0xe1,0x9b,0xbf,0x80,0xe1,0x99,0xa7,0x80,0xe1,0x80,0xe1,0x70,0xc5,
0x6f,0x06,0x1b,0xbf,0x9b,0xbf,0x80,0xe1,0x03,0xc5,0x00,0xe2,0x87,0x06,0x7f,0xc5,
0x19,0x86,0x80,0xe1,0x80,0xe1,0x7f,0xc5,0x7b,0x06,0x1b,0xae,0x00,0x00,0x82,0x38,
0x03,0xcd,0x00,0xe2,0x01,0xe2,0xaf,0x05,0x0c,0xe0,0xff,0xc4,0xcc,0x3c,0xa8,0x34,
0xa0,0x34,0x0c,0xe4,0x41,0xe0,0xcc,0x3c,0x00,0xe2,0x48,0x3e,0x0b,0xe0,0x03,0xc6,
0x0d,0xe0,0x18,0x3e,0x6d,0x3e,0x2c,0x3d,0x0c,0xc6,0x00,0xe2,0x23,0xe0,0x05,0x26,
0xac,0x3f,0xdc,0x17,0xff,0xe1,0x82,0x3f,0x8b,0x06,0xf0,0xc6,0x9b,0xbc,0x80,0xe1,
0x9b,0xbc,0x80,0xe1,0x9b,0xbc,0x80,0xe1,0x80,0xe1,0xf0,0xc6,0x77,0x06,0x9b,0xbc,
0xc0,0xe0,0x18,0x3d,0x9a,0xac,0xba,0xac,0x88,0xac,0xaa,0xac,0xa8,0xac,0x98,0xac,
0xe8,0x3d,0x82,0x38,0x85,0x06,0x7f,0xc5,0x9b,0xac,0x80,0xe1,0x7d,0x06,0x7f,0xc5,
0xb1,0x08,0x82,0x38,0x87,0x3c,0x60,0xe0,0x80,0x7f,0x04,0xea,0x60,0x15,0x00,0xe0,
0x87,0xdf,0x6f,0x3c,0x17,0x3c,0x60,0xe0,0x00,0x00,0xe1,0x08,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x04,0x02,0x00,0x90,0x05,0x02,0x00,
0x70,0x05,0x02,0x00,0xce,0x07,0x00,0x00,0xcc,0x04,0x02,0x00,0x4e,0x05,0x00,0x00,
0xec,0x04,0x02,0x00,0x20,0x05,0x02,0x00,0x60,0x02,0x02,0x00,0x6c,0x03,0x02,0x00,
0x30,0x05,0x02,0x00,0x78,0x04,0x02,0x00,0xdc,0x05,0x00,0x00,0x9c,0x04,0x02,0x00,
0x0b,0x80,0x06,0x80,0x00,0x00,0x00,0x01,0x18,0x01,0x02,0x00,0x00,0x00,0x00,0x01,
0xff,0x03,0xc6,0x80,0x00,0x00,0x70,0x72,0x00,0x0d,0x00,0x80,0x00,0x09,0x00,0x80,
0x00,0x07,0x00,0x80,0x00,0x06,0x00,0x80,0x00,0x04,0x00,0x80,0x00,0x02,0x00,0x80,
0x00,0x01,0x00,0x80,0x00,0x00,0x00,0x80,0x00,0x00,0x01,0x01,0x00,0x01,0x00,0x80,
0x00,0x04,0x00,0x80,0x00,0x02,0x00,0x80,