Merge commit 'AU_LINUX_ANDROID_ICS.04.00.04.00.126' into msm-3.4
AU_LINUX_ANDROID_ICS.04.00.04.00.126 from msm-3.0.
First parent is from google/android-3.4.
* commit 'AU_LINUX_ANDROID_ICS.04.00.04.00.126': (8712 commits)
PRNG: Device tree entry for qrng device.
vidc:1080p: Set video core timeout value for Thumbnail mode
msm: sps: improve the debugging support in SPS driver
board-8064 msm: Overlap secure and non secure video firmware heaps.
msm: clock: Add handoff ops for 7x30 and copper XO clocks
msm_fb: display: Wait for external vsync before DTV IOMMU unmap
msm: Fix ciruclar dependency in debug UART settings
msm: gdsc: Add GDSC regulator driver for msm-copper
defconfig: Enable Mobicore Driver.
mobicore: Add mobicore driver.
mobicore: rename variable to lower case.
mobicore: rename folder.
mobicore: add makefiles
mobicore: initial import of kernel driver
ASoC: msm: Add SLIMBUS_2_RX CPU DAI
board-8064-gpio: Update FUNC for EPM SPI CS
msm_fb: display: Remove chicken bit config during video playback
mmc: msm_sdcc: enable the sanitize capability
msm-fb: display: lm2 writeback support on mpq platfroms
msm_fb: display: Disable LVDS phy & pll during panel off
...
Signed-off-by: Steve Muckle <smuckle@codeaurora.org>
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 1e7c563..77a0aff 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -55,6 +55,18 @@
To compile this driver as a module, choose M here: the
module will be called ad7877.
+config TOUCHSCREEN_ATMEL_MAXTOUCH
+ tristate "Atmel maXTouch based touchscreens"
+ depends on I2C
+ default n
+ help
+ Say Y here if you have an Atmel Maxtouch based touchscreen.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called maXTouch.
+
config TOUCHSCREEN_AD7879
tristate "Analog Devices AD7879-1/AD7889-1 touchscreen interface"
help
@@ -431,6 +443,15 @@
To compile this driver as a module, choose M here: the
module will be called penmount.
+config TOUCHSCREEN_MSM
+ bool "Qualcomm MSM touchscreen controller"
+ depends on ARCH_MSM7X30 && MARIMBA_TSADC
+ default n
+ help
+ Say Y here if you have a 4-wire resistive touchscreen panel
+ connected to the TSSC touchscreen controller on a
+ Qualcomm MSM/QSD based SoC.
+
config TOUCHSCREEN_MIGOR
tristate "Renesas MIGO-R touchscreen"
depends on SH_MIGOR && I2C
@@ -457,6 +478,18 @@
help
This enables support for Synaptics RMI over I2C based touchscreens.
+config TOUCHSCREEN_SYNAPTICS_RMI4_I2C
+ tristate "Synaptics i2c touchscreen(ClearPad 3000)"
+ depends on I2C
+ select SYNA_MULTI_TOUCH
+ help
+ This enables support for Synaptics RMI over I2C based touchscreens(ClearPad 3000).
+
+config SYNA_MULTI_TOUCH
+ tristate "Synaptics i2c touchscreen(ClearPad 3000) MutilTouch support"
+ depends on TOUCHSCREEN_SYNAPTICS_RMI4_I2C
+ default y
+
config TOUCHSCREEN_TOUCHRIGHT
tristate "Touchright serial touchscreen"
select SERIO
@@ -798,6 +831,27 @@
To compile this driver as a module, choose M here: the
module will be called tsc2007.
+config TOUCHSCREEN_MSM_LEGACY
+ default n
+ tristate "MSM Touchscreen"
+ depends on ARCH_MSM && !ARCH_MSM7X30
+ help
+ Say Y here if you have a touchscreen interface using MSM
+ touchscreen controller.
+
+ To compile this driver as a module, choose M here: the
+ module will be called msm_touch.
+
+config ANDROID_TOUCHSCREEN_MSM_HACKS
+ default y
+ depends on TOUCHSCREEN_MSM_LEGACY
+ bool "Android MSM Touchscreen hacks"
+ help
+ Say Y here if you are running Android framework on Qualcomm
+ MSM/QSD based Surf or FFAs. These hacks are required inorder
+ to Android framework to receive adjusted x, y co-ordinates
+ until proper calibration framework is in place.
+
config TOUCHSCREEN_W90X900
tristate "W90P910 touchscreen driver"
depends on HAVE_CLK
@@ -851,4 +905,45 @@
To compile this driver as a module, choose M here: the
module will be called tps6507x_ts.
+config TOUCHSCREEN_CY8C_TS
+ tristate "Cypress TMA300-TMG200 based touchscreens"
+ depends on I2C
+ default n
+ help
+ Say Y here if you have a Cypress TMA300/TMG200 based touchscreen.
+ TMA300 is a multi-touch screen which can report upto 10
+ touches at a time. TMG200 supports 2 touches.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cy8c_ts.
+
+config TOUCHSCREEN_CYTTSP_I2C_QC
+ tristate "Cypress TTSP based touchscreens"
+ depends on I2C
+ default n
+ help
+ Say Y here if you have a Cypress TTSP based touchscreen.
+ TMA300 is a multi-touch screen which can report upto 10
+ touches at a time.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cyttsp-i2c.
+
+config TOUCHSCREEN_FT5X06
+ tristate "FocalTech touchscreens"
+ depends on I2C
+ help
+ Say Y here if you have a ft5X06 touchscreen.
+ Ft5x06 controllers are multi touch controllers which can
+ report 5 touches at a time.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ft5x06_ts.
+
endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 175d641..5a1eec7 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -12,10 +12,13 @@
obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o
obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o
obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
+obj-$(CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH) += atmel_maxtouch.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o
obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o
obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
+obj-$(CONFIG_TOUCHSCREEN_CYPRESS_TMG) += cy8c_tmg_ts.o
obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
obj-$(CONFIG_TOUCHSCREEN_CYTTSP_CORE) += cyttsp_core.o
@@ -26,6 +29,7 @@
obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
+obj-$(CONFIG_TOUCHSCREEN_ELAN_I2C_8232) += elan8232_i2c.o
obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
obj-$(CONFIG_TOUCHSCREEN_EGALAX) += egalax_ts.o
obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
@@ -39,6 +43,7 @@
obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
+obj-$(CONFIG_TOUCHSCREEN_MSM) += msm_ts.o
obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
@@ -52,6 +57,7 @@
obj-$(CONFIG_TOUCHSCREEN_TI_TSCADC) += ti_tscadc.o
obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI) += synaptics_i2c_rmi.o
+obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C) +=synaptics/
obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
@@ -70,3 +76,6 @@
obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
+obj-$(CONFIG_TOUCHSCREEN_MSM_LEGACY) += msm_touch.o
+obj-$(CONFIG_TOUCHSCREEN_CY8C_TS) += cy8c_ts.o
+obj-$(CONFIG_TOUCHSCREEN_CYTTSP_I2C_QC) += cyttsp-i2c-qc.o
diff --git a/drivers/input/touchscreen/atmel_maxtouch.c b/drivers/input/touchscreen/atmel_maxtouch.c
new file mode 100644
index 0000000..52f1f4a
--- /dev/null
+++ b/drivers/input/touchscreen/atmel_maxtouch.c
@@ -0,0 +1,2340 @@
+/*
+ * Atmel maXTouch Touchscreen Controller Driver
+ *
+ *
+ * Copyright (C) 2010 Atmel Corporation
+ * Copyright (C) 2010 Ulf Samuelsson (ulf@atmel.com)
+ * Copyright (C) 2009 Raphael Derosso Pereira <raphaelpereira@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *
+ * Driver for Atmel maXTouch family of touch controllers.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/debugfs.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/module.h>
+
+#include <asm/uaccess.h>
+
+#include <linux/atmel_maxtouch.h>
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+
+/* Early-suspend level */
+#define MXT_SUSPEND_LEVEL 1
+#endif
+
+
+#define DRIVER_VERSION "0.91a_mod"
+
+static int debug = DEBUG_INFO;
+static int comms = 0;
+module_param(debug, int, 0644);
+module_param(comms, int, 0644);
+
+MODULE_PARM_DESC(debug, "Activate debugging output");
+MODULE_PARM_DESC(comms, "Select communications mode");
+
+#define T7_DATA_SIZE 3
+
+/* Device Info descriptor */
+/* Parsed from maXTouch "Id information" inside device */
+struct mxt_device_info {
+ u8 family_id;
+ u8 variant_id;
+ u8 major;
+ u8 minor;
+ u8 build;
+ u8 num_objs;
+ u8 x_size;
+ u8 y_size;
+ char family_name[16]; /* Family name */
+ char variant_name[16]; /* Variant name */
+ u16 num_nodes; /* Number of sensor nodes */
+};
+
+/* object descriptor table, parsed from maXTouch "object table" */
+struct mxt_object {
+ u16 chip_addr;
+ u8 type;
+ u8 size;
+ u8 instances;
+ u8 num_report_ids;
+};
+
+
+/* Mapping from report id to object type and instance */
+struct report_id_map {
+ u8 object;
+ u8 instance;
+/*
+ * This is the first report ID belonging to object. It enables us to
+ * find out easily the touch number: each touch has different report
+ * ID (which are assigned to touches in increasing order). By
+ * subtracting the first report ID from current, we get the touch
+ * number.
+ */
+ u8 first_rid;
+};
+
+
+/* Driver datastructure */
+struct mxt_data {
+ struct i2c_client *client;
+ struct input_dev *input;
+ char phys_name[32];
+ int irq;
+
+ u16 last_read_addr;
+ bool new_msgs;
+ u8 *last_message;
+
+ int valid_irq_counter;
+ int invalid_irq_counter;
+ int irq_counter;
+ int message_counter;
+ int read_fail_counter;
+
+
+ int bytes_to_read;
+
+ struct delayed_work dwork;
+ u8 xpos_format;
+ u8 ypos_format;
+
+ u8 numtouch;
+
+ struct mxt_device_info device_info;
+
+ u32 info_block_crc;
+ u32 configuration_crc;
+ u16 report_id_count;
+ struct report_id_map *rid_map;
+ struct mxt_object *object_table;
+
+ u16 msg_proc_addr;
+ u8 message_size;
+
+ u16 min_x_val;
+ u16 min_y_val;
+ u16 max_x_val;
+ u16 max_y_val;
+
+ int (*init_hw)(struct i2c_client *client);
+ int (*exit_hw)(struct i2c_client *client);
+ int (*power_on)(bool on);
+ u8 (*valid_interrupt)(void);
+ u8 (*read_chg)(void);
+
+ /* debugfs variables */
+ struct dentry *debug_dir;
+ int current_debug_datap;
+
+ struct mutex debug_mutex;
+ u16 *debug_data;
+
+ /* Character device variables */
+ struct cdev cdev;
+ struct cdev cdev_messages; /* 2nd Char dev for messages */
+ dev_t dev_num;
+ struct class *mxt_class;
+
+
+ u16 address_pointer;
+ bool valid_ap;
+
+ /* Message buffer & pointers */
+ char *messages;
+ int msg_buffer_startp, msg_buffer_endp;
+ /* Put only non-touch messages to buffer if this is set */
+ char nontouch_msg_only;
+ struct mutex msg_mutex;
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+ u8 t7_data[T7_DATA_SIZE];
+ bool is_suspended;
+};
+/*default value, enough to read versioning*/
+#define CONFIG_DATA_SIZE 6
+static u16 t38_size = CONFIG_DATA_SIZE;
+static int mxt_read_block(struct i2c_client *client, u16 addr, u16 length,
+ u8 *value);
+static int mxt_write_byte(struct i2c_client *client, u16 addr, u8 value);
+static int mxt_write_block(struct i2c_client *client, u16 addr, u16 length,
+ u8 *value);
+static u8 mxt_valid_interrupt_dummy(void)
+{
+ return 1;
+}
+
+#define I2C_RETRY_COUNT 5
+#define I2C_PAYLOAD_SIZE 254
+
+/* Returns the start address of object in mXT memory. */
+#define MXT_BASE_ADDR(object_type, mxt) \
+ get_object_address(object_type, 0, mxt->object_table, \
+ mxt->device_info.num_objs)
+
+/* Maps a report ID to an object type (object type number). */
+#define REPORT_ID_TO_OBJECT(rid, mxt) \
+ (((rid) == 0xff) ? 0 : mxt->rid_map[rid].object)
+
+/* Maps a report ID to an object type (string). */
+#define REPORT_ID_TO_OBJECT_NAME(rid, mxt) \
+ object_type_name[REPORT_ID_TO_OBJECT(rid, mxt)]
+
+/* Returns non-zero if given object is a touch object */
+#define IS_TOUCH_OBJECT(object) \
+ ((object == MXT_TOUCH_MULTITOUCHSCREEN_T9) || \
+ (object == MXT_TOUCH_KEYARRAY_T15) || \
+ (object == MXT_TOUCH_PROXIMITY_T23) || \
+ (object == MXT_TOUCH_SINGLETOUCHSCREEN_T10) || \
+ (object == MXT_TOUCH_XSLIDER_T11) || \
+ (object == MXT_TOUCH_YSLIDER_T12) || \
+ (object == MXT_TOUCH_XWHEEL_T13) || \
+ (object == MXT_TOUCH_YWHEEL_T14) || \
+ (object == MXT_TOUCH_KEYSET_T31) || \
+ (object == MXT_TOUCH_XSLIDERSET_T32) ? 1 : 0)
+
+#define mxt_debug(level, ...) \
+ do { \
+ if (debug >= (level)) \
+ pr_debug(__VA_ARGS__); \
+ } while (0)
+
+
+/*
+ * Check whether we have multi-touch enabled kernel; if not, report just the
+ * first touch (on mXT224, the maximum is 10 simultaneous touches).
+ * Because just the 1st one is reported, it might seem that the screen is not
+ * responding to touch if the first touch is removed while the screen is being
+ * touched by another finger, so beware.
+ *
+ */
+
+#ifdef ABS_MT_TRACKING_ID
+static inline void report_mt(int touch_number, int size, int x, int y, struct
+ mxt_data *mxt) {
+ input_report_abs(mxt->input, ABS_MT_TRACKING_ID, touch_number);
+ input_report_abs(mxt->input, ABS_MT_TOUCH_MAJOR, size);
+ input_report_abs(mxt->input, ABS_MT_POSITION_X, x);
+ input_report_abs(mxt->input, ABS_MT_POSITION_Y, y);
+ input_mt_sync(mxt->input);
+}
+#else
+static inline void report_mt(int touch_number, int size, int x, int y, struct
+ mxt_data *mxt) {
+ if (touch_number == 0) {
+ input_report_abs(mxt->input, ABS_TOOL_WIDTH, size);
+ input_report_abs(mxt->input, ABS_X, x);
+ input_report_abs(mxt->input, ABS_Y, y);
+ }
+}
+#endif
+
+
+static inline void report_gesture(int data, struct mxt_data *mxt)
+{
+ input_event(mxt->input, EV_MSC, MSC_GESTURE, data);
+}
+
+
+static const u8 *object_type_name[] = {
+ [0] = "Reserved",
+ [5] = "GEN_MESSAGEPROCESSOR_T5",
+ [6] = "GEN_COMMANDPROCESSOR_T6",
+ [7] = "GEN_POWERCONFIG_T7",
+ [8] = "GEN_ACQUIRECONFIG_T8",
+ [9] = "TOUCH_MULTITOUCHSCREEN_T9",
+ [15] = "TOUCH_KEYARRAY_T15",
+ [17] = "SPT_COMMSCONFIG_T18",
+ [19] = "SPT_GPIOPWM_T19",
+ [20] = "PROCI_GRIPFACESUPPRESSION_T20",
+ [22] = "PROCG_NOISESUPPRESSION_T22",
+ [23] = "TOUCH_PROXIMITY_T23",
+ [24] = "PROCI_ONETOUCHGESTUREPROCESSOR_T24",
+ [25] = "SPT_SELFTEST_T25",
+ [27] = "PROCI_TWOTOUCHGESTUREPROCESSOR_T27",
+ [28] = "SPT_CTECONFIG_T28",
+ [37] = "DEBUG_DIAGNOSTICS_T37",
+ [38] = "SPT_USER_DATA_T38",
+ [40] = "PROCI_GRIPSUPPRESSION_T40",
+ [41] = "PROCI_PALMSUPPRESSION_T41",
+ [42] = "PROCI_FACESUPPRESSION_T42",
+ [43] = "SPT_DIGITIZER_T43",
+ [44] = "SPT_MESSAGECOUNT_T44",
+};
+
+
+static u16 get_object_address(uint8_t object_type,
+ uint8_t instance,
+ struct mxt_object *object_table,
+ int max_objs);
+
+int mxt_write_ap(struct mxt_data *mxt, u16 ap);
+
+static int mxt_read_block_wo_addr(struct i2c_client *client,
+ u16 length,
+ u8 *value);
+
+ssize_t debug_data_read(struct mxt_data *mxt, char *buf, size_t count,
+ loff_t *ppos, u8 debug_command){
+ int i;
+ u16 *data;
+ u16 diagnostics_reg;
+ int offset = 0;
+ int size;
+ int read_size;
+ int error;
+ char *buf_start;
+ u16 debug_data_addr;
+ u16 page_address;
+ u8 page;
+ u8 debug_command_reg;
+
+ data = mxt->debug_data;
+ if (data == NULL)
+ return -EIO;
+
+ /* If first read after open, read all data to buffer. */
+ if (mxt->current_debug_datap == 0){
+
+ diagnostics_reg = MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6,
+ mxt) +
+ MXT_ADR_T6_DIAGNOSTIC;
+ if (count > (mxt->device_info.num_nodes * 2))
+ count = mxt->device_info.num_nodes;
+
+ debug_data_addr = MXT_BASE_ADDR(MXT_DEBUG_DIAGNOSTIC_T37, mxt)+
+ MXT_ADR_T37_DATA;
+ page_address = MXT_BASE_ADDR(MXT_DEBUG_DIAGNOSTIC_T37, mxt) +
+ MXT_ADR_T37_PAGE;
+ error = mxt_read_block(mxt->client, page_address, 1, &page);
+ if (error < 0)
+ return error;
+ mxt_debug(DEBUG_TRACE, "debug data page = %d\n", page);
+ while (page != 0) {
+ error = mxt_write_byte(mxt->client,
+ diagnostics_reg,
+ MXT_CMD_T6_PAGE_DOWN);
+ if (error < 0)
+ return error;
+ /* Wait for command to be handled; when it has, the
+ register will be cleared. */
+ debug_command_reg = 1;
+ while (debug_command_reg != 0) {
+ error = mxt_read_block(mxt->client,
+ diagnostics_reg, 1,
+ &debug_command_reg);
+ if (error < 0)
+ return error;
+ mxt_debug(DEBUG_TRACE,
+ "Waiting for debug diag command "
+ "to propagate...\n");
+
+ }
+ error = mxt_read_block(mxt->client, page_address, 1,
+ &page);
+ if (error < 0)
+ return error;
+ mxt_debug(DEBUG_TRACE, "debug data page = %d\n", page);
+ }
+
+ /*
+ * Lock mutex to prevent writing some unwanted data to debug
+ * command register. User can still write through the char
+ * device interface though. TODO: fix?
+ */
+
+ mutex_lock(&mxt->debug_mutex);
+ /* Configure Debug Diagnostics object to show deltas/refs */
+ error = mxt_write_byte(mxt->client, diagnostics_reg,
+ debug_command);
+
+ /* Wait for command to be handled; when it has, the
+ * register will be cleared. */
+ debug_command_reg = 1;
+ while (debug_command_reg != 0) {
+ error = mxt_read_block(mxt->client,
+ diagnostics_reg, 1,
+ &debug_command_reg);
+ if (error < 0)
+ return error;
+ mxt_debug(DEBUG_TRACE, "Waiting for debug diag command "
+ "to propagate...\n");
+
+ }
+
+ if (error < 0) {
+ printk (KERN_WARNING
+ "Error writing to maXTouch device!\n");
+ return error;
+ }
+
+ size = mxt->device_info.num_nodes * sizeof(u16);
+
+ while (size > 0) {
+ read_size = size > 128 ? 128 : size;
+ mxt_debug(DEBUG_TRACE,
+ "Debug data read loop, reading %d bytes...\n",
+ read_size);
+ error = mxt_read_block(mxt->client,
+ debug_data_addr,
+ read_size,
+ (u8 *) &data[offset]);
+ if (error < 0) {
+ printk(KERN_WARNING
+ "Error reading debug data\n");
+ goto error;
+ }
+ offset += read_size/2;
+ size -= read_size;
+
+ /* Select next page */
+ error = mxt_write_byte(mxt->client, diagnostics_reg,
+ MXT_CMD_T6_PAGE_UP);
+ if (error < 0) {
+ printk(KERN_WARNING
+ "Error writing to maXTouch device!\n");
+ goto error;
+ }
+ }
+ mutex_unlock(&mxt->debug_mutex);
+ }
+
+ buf_start = buf;
+ i = mxt->current_debug_datap;
+
+ while (((buf- buf_start) < (count - 6)) &&
+ (i < mxt->device_info.num_nodes)){
+
+ mxt->current_debug_datap++;
+ if (debug_command == MXT_CMD_T6_REFERENCES_MODE)
+ buf += sprintf(buf, "%d: %5d\n", i,
+ (u16) le16_to_cpu(data[i]));
+ else if (debug_command == MXT_CMD_T6_DELTAS_MODE)
+ buf += sprintf(buf, "%d: %5d\n", i,
+ (s16) le16_to_cpu(data[i]));
+ i++;
+ }
+
+ return (buf - buf_start);
+error:
+ mutex_unlock(&mxt->debug_mutex);
+ return error;
+}
+
+ssize_t deltas_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+ return debug_data_read(file->private_data, buf, count, ppos,
+ MXT_CMD_T6_DELTAS_MODE);
+}
+
+ssize_t refs_read(struct file *file, char *buf, size_t count,
+ loff_t *ppos)
+{
+ return debug_data_read(file->private_data, buf, count, ppos,
+ MXT_CMD_T6_REFERENCES_MODE);
+}
+
+int debug_data_open(struct inode *inode, struct file *file)
+{
+ struct mxt_data *mxt;
+ int i;
+ mxt = inode->i_private;
+ if (mxt == NULL)
+ return -EIO;
+ mxt->current_debug_datap = 0;
+ mxt->debug_data = kmalloc(mxt->device_info.num_nodes * sizeof(u16),
+ GFP_KERNEL);
+ if (mxt->debug_data == NULL)
+ return -ENOMEM;
+
+
+ for (i = 0; i < mxt->device_info.num_nodes; i++)
+ mxt->debug_data[i] = 7777;
+
+
+ file->private_data = mxt;
+ return 0;
+}
+
+int debug_data_release(struct inode *inode, struct file *file)
+{
+ struct mxt_data *mxt;
+ mxt = file->private_data;
+ kfree(mxt->debug_data);
+ return 0;
+}
+
+static struct file_operations delta_fops = {
+ .owner = THIS_MODULE,
+ .open = debug_data_open,
+ .release = debug_data_release,
+ .read = deltas_read,
+};
+
+static struct file_operations refs_fops = {
+ .owner = THIS_MODULE,
+ .open = debug_data_open,
+ .release = debug_data_release,
+ .read = refs_read,
+};
+
+
+int mxt_memory_open(struct inode *inode, struct file *file)
+{
+ struct mxt_data *mxt;
+ mxt = container_of(inode->i_cdev, struct mxt_data, cdev);
+ if (mxt == NULL)
+ return -EIO;
+ file->private_data = mxt;
+ return 0;
+}
+
+int mxt_message_open(struct inode *inode, struct file *file)
+{
+ struct mxt_data *mxt;
+ mxt = container_of(inode->i_cdev, struct mxt_data, cdev_messages);
+ if (mxt == NULL)
+ return -EIO;
+ file->private_data = mxt;
+ return 0;
+}
+
+
+ssize_t mxt_memory_read(struct file *file, char *buf, size_t count,
+ loff_t *ppos)
+{
+ int i;
+ struct mxt_data *mxt;
+
+ mxt = file->private_data;
+ if (mxt->valid_ap){
+ mxt_debug(DEBUG_TRACE, "Reading %d bytes from current ap\n",
+ (int) count);
+ i = mxt_read_block_wo_addr(mxt->client, count, (u8 *) buf);
+ } else {
+ mxt_debug(DEBUG_TRACE, "Address pointer changed since set;"
+ "writing AP (%d) before reading %d bytes",
+ mxt->address_pointer, (int) count);
+ i = mxt_read_block(mxt->client, mxt->address_pointer, count,
+ buf);
+ }
+
+ return i;
+}
+
+ssize_t mxt_memory_write(struct file *file, const char *buf, size_t count,
+ loff_t *ppos)
+{
+ int i;
+ int whole_blocks;
+ int last_block_size;
+ struct mxt_data *mxt;
+ u16 address;
+
+ mxt = file->private_data;
+ address = mxt->address_pointer;
+
+ mxt_debug(DEBUG_TRACE, "mxt_memory_write entered\n");
+ whole_blocks = count / I2C_PAYLOAD_SIZE;
+ last_block_size = count % I2C_PAYLOAD_SIZE;
+
+ for (i = 0; i < whole_blocks; i++) {
+ mxt_debug(DEBUG_TRACE, "About to write to %d...",
+ address);
+ mxt_write_block(mxt->client, address, I2C_PAYLOAD_SIZE,
+ (u8 *) buf);
+ address += I2C_PAYLOAD_SIZE;
+ buf += I2C_PAYLOAD_SIZE;
+ }
+
+ mxt_write_block(mxt->client, address, last_block_size, (u8 *) buf);
+
+ return count;
+}
+
+static long mxt_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int retval;
+ struct mxt_data *mxt;
+
+ retval = 0;
+ mxt = file->private_data;
+
+ switch (cmd) {
+ case MXT_SET_ADDRESS_IOCTL:
+ retval = mxt_write_ap(mxt, (u16) arg);
+ if (retval >= 0) {
+ mxt->address_pointer = (u16) arg;
+ mxt->valid_ap = 1;
+ }
+ break;
+ case MXT_RESET_IOCTL:
+ retval = mxt_write_byte(mxt->client,
+ MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6, mxt) +
+ MXT_ADR_T6_RESET,
+ 1);
+ break;
+ case MXT_CALIBRATE_IOCTL:
+ retval = mxt_write_byte(mxt->client,
+ MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6, mxt) +
+ MXT_ADR_T6_CALIBRATE,
+ 1);
+
+ break;
+ case MXT_BACKUP_IOCTL:
+ retval = mxt_write_byte(mxt->client,
+ MXT_BASE_ADDR(MXT_GEN_COMMANDPROCESSOR_T6, mxt) +
+ MXT_ADR_T6_BACKUPNV,
+ MXT_CMD_T6_BACKUP);
+ break;
+ case MXT_NONTOUCH_MSG_IOCTL:
+ mxt->nontouch_msg_only = 1;
+ break;
+ case MXT_ALL_MSG_IOCTL:
+ mxt->nontouch_msg_only = 0;
+ break;
+ default:
+ return -EIO;
+ }
+
+ return retval;
+}
+
+/*
+ * Copies messages from buffer to user space.
+ *
+ * NOTE: if less than (mxt->message_size * 5 + 1) bytes requested,
+ * this will return 0!
+ *
+ */
+ssize_t mxt_message_read(struct file *file, char *buf, size_t count,
+ loff_t *ppos)
+{
+ int i;
+ struct mxt_data *mxt;
+ char *buf_start;
+
+ mxt = file->private_data;
+ if (mxt == NULL)
+ return -EIO;
+ buf_start = buf;
+
+ mutex_lock(&mxt->msg_mutex);
+ /* Copy messages until buffer empty, or 'count' bytes written */
+ while ((mxt->msg_buffer_startp != mxt->msg_buffer_endp) &&
+ ((buf - buf_start) < (count - (5 * mxt->message_size) - 1))){
+
+ for (i = 0; i < mxt->message_size; i++){
+ buf += sprintf(buf, "[%2X] ",
+ *(mxt->messages + mxt->msg_buffer_endp *
+ mxt->message_size + i));
+ }
+ buf += sprintf(buf, "\n");
+ if (mxt->msg_buffer_endp < MXT_MESSAGE_BUFFER_SIZE)
+ mxt->msg_buffer_endp++;
+ else
+ mxt->msg_buffer_endp = 0;
+ }
+ mutex_unlock(&mxt->msg_mutex);
+ return (buf - buf_start);
+}
+
+static struct file_operations mxt_message_fops = {
+ .owner = THIS_MODULE,
+ .open = mxt_message_open,
+ .read = mxt_message_read,
+};
+
+static struct file_operations mxt_memory_fops = {
+ .owner = THIS_MODULE,
+ .open = mxt_memory_open,
+ .read = mxt_memory_read,
+ .write = mxt_memory_write,
+ .unlocked_ioctl = mxt_ioctl,
+};
+
+
+/* Writes the address pointer (to set up following reads). */
+
+int mxt_write_ap(struct mxt_data *mxt, u16 ap)
+{
+ struct i2c_client *client;
+ __le16 le_ap = cpu_to_le16(ap);
+ client = mxt->client;
+ if (mxt != NULL)
+ mxt->last_read_addr = -1;
+ if (i2c_master_send(client, (u8 *) &le_ap, 2) == 2) {
+ mxt_debug(DEBUG_TRACE, "Address pointer set to %d\n", ap);
+ return 0;
+ } else {
+ mxt_debug(DEBUG_INFO, "Error writing address pointer!\n");
+ return -EIO;
+ }
+}
+
+
+
+/* Calculates the 24-bit CRC sum. */
+static u32 CRC_24(u32 crc, u8 byte1, u8 byte2)
+{
+ static const u32 crcpoly = 0x80001B;
+ u32 result;
+ u32 data_word;
+
+ data_word = ((((u16) byte2) << 8u) | byte1);
+ result = ((crc << 1u) ^ data_word);
+ if (result & 0x1000000)
+ result ^= crcpoly;
+ return result;
+}
+
+/* Returns object address in mXT chip, or zero if object is not found */
+static u16 get_object_address(uint8_t object_type,
+ uint8_t instance,
+ struct mxt_object *object_table,
+ int max_objs)
+{
+ uint8_t object_table_index = 0;
+ uint8_t address_found = 0;
+ uint16_t address = 0;
+ struct mxt_object *obj;
+
+ while ((object_table_index < max_objs) && !address_found) {
+ obj = &object_table[object_table_index];
+ if (obj->type == object_type) {
+ address_found = 1;
+ /* Are there enough instances defined in the FW? */
+ if (obj->instances >= instance) {
+ address = obj->chip_addr +
+ (obj->size + 1) * instance;
+ } else {
+ return 0;
+ }
+ }
+ object_table_index++;
+ }
+ return address;
+}
+
+
+/*
+ * Reads a block of bytes from given address from mXT chip. If we are
+ * reading from message window, and previous read was from message window,
+ * there's no need to write the address pointer: the mXT chip will
+ * automatically set the address pointer back to message window start.
+ */
+
+static int mxt_read_block(struct i2c_client *client,
+ u16 addr,
+ u16 length,
+ u8 *value)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ struct i2c_msg msg[2];
+ __le16 le_addr;
+ struct mxt_data *mxt;
+
+ mxt = i2c_get_clientdata(client);
+
+ if (mxt != NULL) {
+ if ((mxt->last_read_addr == addr) &&
+ (addr == mxt->msg_proc_addr)) {
+ if (i2c_master_recv(client, value, length) == length)
+ return length;
+ else
+ return -EIO;
+ } else {
+ mxt->last_read_addr = addr;
+ }
+ }
+
+ mxt_debug(DEBUG_TRACE, "Writing address pointer & reading %d bytes "
+ "in on i2c transaction...\n", length);
+
+ le_addr = cpu_to_le16(addr);
+ msg[0].addr = client->addr;
+ msg[0].flags = 0x00;
+ msg[0].len = 2;
+ msg[0].buf = (u8 *) &le_addr;
+
+ msg[1].addr = client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = length;
+ msg[1].buf = (u8 *) value;
+ if (i2c_transfer(adapter, msg, 2) == 2)
+ return length;
+ else
+ return -EIO;
+
+}
+
+/* Reads a block of bytes from current address from mXT chip. */
+
+static int mxt_read_block_wo_addr(struct i2c_client *client,
+ u16 length,
+ u8 *value)
+{
+
+
+ if (i2c_master_recv(client, value, length) == length) {
+ mxt_debug(DEBUG_TRACE, "I2C block read ok\n");
+ return length;
+ } else {
+ mxt_debug(DEBUG_INFO, "I2C block read failed\n");
+ return -EIO;
+ }
+
+}
+
+
+/* Writes one byte to given address in mXT chip. */
+
+static int mxt_write_byte(struct i2c_client *client, u16 addr, u8 value)
+{
+ struct {
+ __le16 le_addr;
+ u8 data;
+
+ } i2c_byte_transfer;
+
+ struct mxt_data *mxt;
+
+ mxt = i2c_get_clientdata(client);
+ if (mxt != NULL)
+ mxt->last_read_addr = -1;
+ i2c_byte_transfer.le_addr = cpu_to_le16(addr);
+ i2c_byte_transfer.data = value;
+ if (i2c_master_send(client, (u8 *) &i2c_byte_transfer, 3) == 3)
+ return 0;
+ else
+ return -EIO;
+}
+
+
+/* Writes a block of bytes (max 256) to given address in mXT chip. */
+static int mxt_write_block(struct i2c_client *client,
+ u16 addr,
+ u16 length,
+ u8 *value)
+{
+ int i;
+ struct {
+ __le16 le_addr;
+ u8 data[256];
+
+ } i2c_block_transfer;
+
+ struct mxt_data *mxt;
+
+ mxt_debug(DEBUG_TRACE, "Writing %d bytes to %d...", length, addr);
+ if (length > 256)
+ return -EINVAL;
+ mxt = i2c_get_clientdata(client);
+ if (mxt != NULL)
+ mxt->last_read_addr = -1;
+ for (i = 0; i < length; i++)
+ i2c_block_transfer.data[i] = *value++;
+ i2c_block_transfer.le_addr = cpu_to_le16(addr);
+ i = i2c_master_send(client, (u8 *) &i2c_block_transfer, length + 2);
+ if (i == (length + 2))
+ return length;
+ else
+ return -EIO;
+}
+
+/* Calculates the CRC value for mXT infoblock. */
+int calculate_infoblock_crc(u32 *crc_result, u8 *data, int crc_area_size)
+{
+ u32 crc = 0;
+ int i;
+
+ for (i = 0; i < (crc_area_size - 1); i = i + 2)
+ crc = CRC_24(crc, *(data + i), *(data + i + 1));
+ /* If uneven size, pad with zero */
+ if (crc_area_size & 0x0001)
+ crc = CRC_24(crc, *(data + i), 0);
+ /* Return only 24 bits of CRC. */
+ *crc_result = (crc & 0x00FFFFFF);
+
+ return 0;
+}
+
+/* Processes a touchscreen message. */
+void process_T9_message(u8 *message, struct mxt_data *mxt, int last_touch)
+{
+
+ struct input_dev *input;
+ u8 status;
+ u16 xpos = 0xFFFF;
+ u16 ypos = 0xFFFF;
+ u8 touch_size = 255;
+ u8 touch_number;
+ u8 amplitude;
+ u8 report_id;
+
+ static int stored_size[10];
+ static int stored_x[10];
+ static int stored_y[10];
+ int i;
+ int active_touches = 0;
+ /*
+ * If the 'last_touch' flag is set, we have received all the touch
+ * messages
+ * there are available in this cycle, so send the events for touches
+ * that are
+ * active.
+ */
+ if (last_touch){
+ /* TODO: For compatibility with single-touch systems, send ABS_X &
+ * ABS_Y */
+ /*
+ if (stored_size[0]){
+ input_report_abs(mxt->input, ABS_X, stored_x[0]);
+ input_report_abs(mxt->input, ABS_Y, stored_y[0]);
+ }*/
+
+
+ for (i = 0; i < 10; i++){
+ if (stored_size[i]){
+ active_touches++;
+ input_report_abs(mxt->input,
+ ABS_MT_TRACKING_ID,
+ i);
+ input_report_abs(mxt->input,
+ ABS_MT_TOUCH_MAJOR,
+ stored_size[i]);
+ input_report_abs(mxt->input,
+ ABS_MT_POSITION_X,
+ stored_x[i]);
+ input_report_abs(mxt->input,
+ ABS_MT_POSITION_Y,
+ stored_y[i]);
+ input_mt_sync(mxt->input);
+ }
+ }
+ input_report_key(mxt->input, BTN_TOUCH, !!active_touches);
+ if (active_touches == 0)
+ input_mt_sync(mxt->input);
+ input_sync(mxt->input);
+
+ }else{
+
+ input = mxt->input;
+ status = message[MXT_MSG_T9_STATUS];
+ report_id = message[0];
+
+ if (status & MXT_MSGB_T9_SUPPRESS) {
+ /* Touch has been suppressed by grip/face */
+ /* detection */
+ mxt_debug(DEBUG_TRACE, "SUPRESS");
+ } else {
+ /* Put together the 10-/12-bit coordinate values. */
+ xpos = message[MXT_MSG_T9_XPOSMSB] * 16 +
+ ((message[MXT_MSG_T9_XYPOSLSB] >> 4) & 0xF);
+ ypos = message[MXT_MSG_T9_YPOSMSB] * 16 +
+ ((message[MXT_MSG_T9_XYPOSLSB] >> 0) & 0xF);
+
+ if (mxt->max_x_val < 1024)
+ xpos >>= 2;
+ if (mxt->max_y_val < 1024)
+ ypos >>= 2;
+
+ touch_number = message[MXT_MSG_REPORTID] -
+ mxt->rid_map[report_id].first_rid;
+
+ stored_x[touch_number] = xpos;
+ stored_y[touch_number] = ypos;
+
+ if (status & MXT_MSGB_T9_DETECT) {
+ /*
+ * mXT224 reports the number of touched nodes,
+ * so the exact value for touch ellipse major
+ * axis length in nodes would be 2*sqrt(touch_size/pi)
+ * (assuming round touch shape), which would then need
+ * to be scaled using information about how many sensor
+ * lines we do have. So this is very much simplified,
+ * but sufficient for most if not all apps?
+ */
+ touch_size = message[MXT_MSG_T9_TCHAREA];
+ touch_size = touch_size >> 2;
+ if (!touch_size)
+ touch_size = 1;
+ /*
+ * report_mt(touch_number, touch_size, xpos, ypos, mxt);
+ */
+
+ stored_size[touch_number] = touch_size;
+
+ if (status & MXT_MSGB_T9_AMP)
+ /* Amplitude of touch has changed */
+ amplitude = message[MXT_MSG_T9_TCHAMPLITUDE];
+ }
+
+ if (status & MXT_MSGB_T9_RELEASE) {
+ /* The previously reported touch has been removed.*/
+ /* report_mt(touch_number, 0, xpos, ypos, mxt); */
+ stored_size[touch_number] = 0;
+ }
+
+ /* input_sync(input); */
+ }
+
+ if (status & MXT_MSGB_T9_SUPPRESS) {
+ mxt_debug(DEBUG_TRACE, "SUPRESS");
+ } else {
+ if (status & MXT_MSGB_T9_DETECT) {
+ mxt_debug(DEBUG_TRACE, "DETECT:%s%s%s%s",
+ ((status & MXT_MSGB_T9_PRESS) ? " PRESS" : ""),
+ ((status & MXT_MSGB_T9_MOVE) ? " MOVE" : ""),
+ ((status & MXT_MSGB_T9_AMP) ? " AMP" : ""),
+ ((status & MXT_MSGB_T9_VECTOR) ? " VECT" : ""));
+
+ } else if (status & MXT_MSGB_T9_RELEASE) {
+ mxt_debug(DEBUG_TRACE, "RELEASE");
+ }
+ }
+ mxt_debug(DEBUG_TRACE, "X=%d, Y=%d, TOUCHSIZE=%d",
+ xpos, ypos, touch_size);
+ }
+ return;
+}
+
+
+int process_message(u8 *message, u8 object, struct mxt_data *mxt)
+{
+ struct i2c_client *client;
+ u8 status;
+ u16 xpos = 0xFFFF;
+ u16 ypos = 0xFFFF;
+ u8 event;
+ u8 direction;
+ u16 distance;
+ u8 length;
+ u8 report_id;
+ static u8 error_cond = 0;
+
+ client = mxt->client;
+ length = mxt->message_size;
+ report_id = message[0];
+
+ if ((mxt->nontouch_msg_only == 0) ||
+ (!IS_TOUCH_OBJECT(object))){
+ mutex_lock(&mxt->msg_mutex);
+ /* Copy the message to buffer */
+ if (mxt->msg_buffer_startp < MXT_MESSAGE_BUFFER_SIZE) {
+ mxt->msg_buffer_startp++;
+ } else {
+ mxt->msg_buffer_startp = 0;
+ }
+
+ if (mxt->msg_buffer_startp == mxt->msg_buffer_endp) {
+ mxt_debug(DEBUG_TRACE,
+ "Message buf full, discarding last entry.\n");
+ if (mxt->msg_buffer_endp < MXT_MESSAGE_BUFFER_SIZE) {
+ mxt->msg_buffer_endp++;
+ } else {
+ mxt->msg_buffer_endp = 0;
+ }
+ }
+ memcpy((mxt->messages + mxt->msg_buffer_startp * length),
+ message,
+ length);
+ mutex_unlock(&mxt->msg_mutex);
+ }
+
+ switch (object) {
+ case MXT_GEN_COMMANDPROCESSOR_T6:
+ status = message[1];
+
+ if (status & MXT_MSGB_T6_COMSERR) {
+ if ((!error_cond) & MXT_MSGB_T6_COMSERR){
+ dev_err(&client->dev,
+ "maXTouch checksum error\n");
+ error_cond |= MXT_MSGB_T6_COMSERR;
+ }
+ }
+ if (status & MXT_MSGB_T6_CFGERR) {
+ /*
+ * Configuration error. A proper configuration
+ * needs to be written to chip and backed up.
+ */
+ if ((!error_cond) & MXT_MSGB_T6_CFGERR){
+ dev_err(&client->dev,
+ "maXTouch configuration error\n");
+ error_cond |= MXT_MSGB_T6_CFGERR;
+ }
+ }
+ if (status & MXT_MSGB_T6_CAL) {
+ /* Calibration in action, no need to react */
+ dev_dbg(&client->dev,
+ "maXTouch calibration in progress\n");
+ }
+ if (status & MXT_MSGB_T6_SIGERR) {
+ /*
+ * Signal acquisition error, something is seriously
+ * wrong, not much we can in the driver to correct
+ * this
+ */
+ if ((!error_cond) & MXT_MSGB_T6_SIGERR){
+ dev_err(&client->dev,
+ "maXTouch acquisition error\n");
+ error_cond |= MXT_MSGB_T6_SIGERR;
+ }
+ }
+ if (status & MXT_MSGB_T6_OFL) {
+ /*
+ * Cycle overflow, the acquisition interval is too
+ * short.
+ */
+ dev_err(&client->dev,
+ "maXTouch cycle overflow\n");
+ }
+ if (status & MXT_MSGB_T6_RESET) {
+ /* Chip has reseted, no need to react. */
+ dev_dbg(&client->dev,
+ "maXTouch chip reset\n");
+ }
+ if (status == 0) {
+ /* Chip status back to normal. */
+ dev_dbg(&client->dev,
+ "maXTouch status normal\n");
+ error_cond = 0;
+ }
+ break;
+
+ case MXT_TOUCH_MULTITOUCHSCREEN_T9:
+ process_T9_message(message, mxt, 0);
+ break;
+
+ case MXT_SPT_GPIOPWM_T19:
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev,
+ "Receiving GPIO message\n");
+ break;
+
+ case MXT_PROCI_GRIPFACESUPPRESSION_T20:
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev,
+ "Receiving face suppression msg\n");
+ break;
+
+ case MXT_PROCG_NOISESUPPRESSION_T22:
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev,
+ "Receiving noise suppression msg\n");
+ status = message[MXT_MSG_T22_STATUS];
+ if (status & MXT_MSGB_T22_FHCHG) {
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev,
+ "maXTouch: Freq changed\n");
+ }
+ if (status & MXT_MSGB_T22_GCAFERR) {
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev,
+ "maXTouch: High noise "
+ "level\n");
+ }
+ if (status & MXT_MSGB_T22_FHERR) {
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev,
+ "maXTouch: Freq changed - "
+ "Noise level too high\n");
+ }
+ break;
+
+ case MXT_PROCI_ONETOUCHGESTUREPROCESSOR_T24:
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev,
+ "Receiving one-touch gesture msg\n");
+
+ event = message[MXT_MSG_T24_STATUS] & 0x0F;
+ xpos = message[MXT_MSG_T24_XPOSMSB] * 16 +
+ ((message[MXT_MSG_T24_XYPOSLSB] >> 4) & 0x0F);
+ ypos = message[MXT_MSG_T24_YPOSMSB] * 16 +
+ ((message[MXT_MSG_T24_XYPOSLSB] >> 0) & 0x0F);
+ if (mxt->max_x_val < 1024)
+ xpos >>= 2;
+ if (mxt->max_y_val < 1024)
+ ypos >>= 2;
+ direction = message[MXT_MSG_T24_DIR];
+ distance = message[MXT_MSG_T24_DIST] +
+ (message[MXT_MSG_T24_DIST + 1] << 16);
+
+ report_gesture((event << 24) | (direction << 16) | distance,
+ mxt);
+ report_gesture((xpos << 16) | ypos, mxt);
+
+ break;
+
+ case MXT_SPT_SELFTEST_T25:
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev,
+ "Receiving Self-Test msg\n");
+
+ if (message[MXT_MSG_T25_STATUS] == MXT_MSGR_T25_OK) {
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev,
+ "maXTouch: Self-Test OK\n");
+
+ } else {
+ dev_err(&client->dev,
+ "maXTouch: Self-Test Failed [%02x]:"
+ "{%02x,%02x,%02x,%02x,%02x}\n",
+ message[MXT_MSG_T25_STATUS],
+ message[MXT_MSG_T25_STATUS + 0],
+ message[MXT_MSG_T25_STATUS + 1],
+ message[MXT_MSG_T25_STATUS + 2],
+ message[MXT_MSG_T25_STATUS + 3],
+ message[MXT_MSG_T25_STATUS + 4]
+ );
+ }
+ break;
+
+ case MXT_PROCI_TWOTOUCHGESTUREPROCESSOR_T27:
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev,
+ "Receiving 2-touch gesture message\n");
+
+ event = message[MXT_MSG_T27_STATUS] & 0xF0;
+ xpos = message[MXT_MSG_T27_XPOSMSB] * 16 +
+ ((message[MXT_MSG_T27_XYPOSLSB] >> 4) & 0x0F);
+ ypos = message[MXT_MSG_T27_YPOSMSB] * 16 +
+ ((message[MXT_MSG_T27_XYPOSLSB] >> 0) & 0x0F);
+ if (mxt->max_x_val < 1024)
+ xpos >>= 2;
+ if (mxt->max_y_val < 1024)
+ ypos >>= 2;
+
+ direction = message[MXT_MSG_T27_ANGLE];
+ distance = message[MXT_MSG_T27_SEPARATION] +
+ (message[MXT_MSG_T27_SEPARATION + 1] << 16);
+
+ report_gesture((event << 24) | (direction << 16) | distance,
+ mxt);
+ report_gesture((xpos << 16) | ypos, mxt);
+
+
+ break;
+
+ case MXT_SPT_CTECONFIG_T28:
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev,
+ "Receiving CTE message...\n");
+ status = message[MXT_MSG_T28_STATUS];
+ if (status & MXT_MSGB_T28_CHKERR)
+ dev_err(&client->dev,
+ "maXTouch: Power-Up CRC failure\n");
+
+ break;
+ default:
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev,
+ "maXTouch: Unknown message!\n");
+
+ break;
+ }
+
+ return 0;
+}
+
+
+/*
+ * Processes messages when the interrupt line (CHG) is asserted. Keeps
+ * reading messages until a message with report ID 0xFF is received,
+ * which indicates that there is no more new messages.
+ *
+ */
+
+static void mxt_worker(struct work_struct *work)
+{
+ struct mxt_data *mxt;
+ struct i2c_client *client;
+
+ u8 *message;
+ u16 message_length;
+ u16 message_addr;
+ u8 report_id;
+ u8 object;
+ int error;
+ int i;
+ char *message_string;
+ char *message_start;
+
+ message = NULL;
+ mxt = container_of(work, struct mxt_data, dwork.work);
+ client = mxt->client;
+ message_addr = mxt->msg_proc_addr;
+ message_length = mxt->message_size;
+
+ if (message_length < 256) {
+ message = kmalloc(message_length, GFP_KERNEL);
+ if (message == NULL) {
+ dev_err(&client->dev, "Error allocating memory\n");
+ goto fail_worker;
+ }
+ } else {
+ dev_err(&client->dev,
+ "Message length larger than 256 bytes not supported\n");
+ goto fail_worker;
+ }
+
+ mxt_debug(DEBUG_TRACE, "maXTouch worker active:\n");
+
+ do {
+ /* Read next message, reread on failure. */
+ /* TODO: message length, CRC included? */
+ mxt->message_counter++;
+ for (i = 1; i < I2C_RETRY_COUNT; i++) {
+ error = mxt_read_block(client,
+ message_addr,
+ message_length - 1,
+ message);
+ if (error >= 0)
+ break;
+ mxt->read_fail_counter++;
+ dev_err(&client->dev,
+ "Failure reading maxTouch device\n");
+ }
+ if (error < 0) {
+ kfree(message);
+ goto fail_worker;
+ }
+
+ if (mxt->address_pointer != message_addr)
+ mxt->valid_ap = 0;
+ report_id = message[0];
+
+ if (debug >= DEBUG_RAW) {
+ mxt_debug(DEBUG_RAW, "%s message [msg count: %08x]:",
+ REPORT_ID_TO_OBJECT_NAME(report_id, mxt),
+ mxt->message_counter
+ );
+ /* 5 characters per one byte */
+ message_string = kmalloc(message_length * 5,
+ GFP_KERNEL);
+ if (message_string == NULL) {
+ dev_err(&client->dev,
+ "Error allocating memory\n");
+ kfree(message);
+ goto fail_worker;
+ }
+ message_start = message_string;
+ for (i = 0; i < message_length; i++) {
+ message_string +=
+ sprintf(message_string,
+ "0x%02X ", message[i]);
+ }
+ mxt_debug(DEBUG_RAW, "%s", message_start);
+ kfree(message_start);
+ }
+
+ if ((report_id != MXT_END_OF_MESSAGES) && (report_id != 0)) {
+ memcpy(mxt->last_message, message, message_length);
+ mxt->new_msgs = 1;
+ smp_wmb();
+ /* Get type of object and process the message */
+ object = mxt->rid_map[report_id].object;
+ process_message(message, object, mxt);
+ }
+
+ mxt_debug(DEBUG_TRACE, "chgline: %d\n", mxt->read_chg());
+ } while (comms ? (mxt->read_chg() == 0) :
+ ((report_id != MXT_END_OF_MESSAGES) && (report_id != 0)));
+
+ /* All messages processed, send the events) */
+ process_T9_message(NULL, mxt, 1);
+
+ kfree(message);
+
+fail_worker:
+ /* Make sure we just didn't miss a interrupt. */
+ if (mxt->read_chg() == 0){
+ schedule_delayed_work(&mxt->dwork, 0);
+ } else
+ enable_irq(mxt->irq);
+}
+
+
+/*
+ * The maXTouch device will signal the host about a new message by asserting
+ * the CHG line. This ISR schedules a worker routine to read the message when
+ * that happens.
+ */
+
+static irqreturn_t mxt_irq_handler(int irq, void *_mxt)
+{
+ struct mxt_data *mxt = _mxt;
+
+ mxt->irq_counter++;
+ if (mxt->valid_interrupt()) {
+ /* Send the signal only if falling edge generated the irq. */
+ disable_irq_nosync(mxt->irq);
+ schedule_delayed_work(&mxt->dwork, 0);
+ mxt->valid_irq_counter++;
+ } else {
+ mxt->invalid_irq_counter++;
+ return IRQ_NONE;
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+
+/******************************************************************************/
+/* Initialization of driver */
+/******************************************************************************/
+
+static int __devinit mxt_identify(struct i2c_client *client,
+ struct mxt_data *mxt,
+ u8 *id_block_data)
+{
+ u8 buf[MXT_ID_BLOCK_SIZE];
+ int error;
+ int identified;
+
+ identified = 0;
+
+ /* Read Device info to check if chip is valid */
+ error = mxt_read_block(client, MXT_ADDR_INFO_BLOCK, MXT_ID_BLOCK_SIZE,
+ (u8 *) buf);
+
+ if (error < 0) {
+ mxt->read_fail_counter++;
+ dev_err(&client->dev, "Failure accessing maXTouch device\n");
+ return -EIO;
+ }
+
+ memcpy(id_block_data, buf, MXT_ID_BLOCK_SIZE);
+
+ mxt->device_info.family_id = buf[0];
+ mxt->device_info.variant_id = buf[1];
+ mxt->device_info.major = ((buf[2] >> 4) & 0x0F);
+ mxt->device_info.minor = (buf[2] & 0x0F);
+ mxt->device_info.build = buf[3];
+ mxt->device_info.x_size = buf[4];
+ mxt->device_info.y_size = buf[5];
+ mxt->device_info.num_objs = buf[6];
+ mxt->device_info.num_nodes = mxt->device_info.x_size *
+ mxt->device_info.y_size;
+
+ /*
+ * Check Family & Variant Info; warn if not recognized but
+ * still continue.
+ */
+
+ /* MXT224 */
+ if (mxt->device_info.family_id == MXT224_FAMILYID) {
+ strcpy(mxt->device_info.family_name, "mXT224");
+
+ if (mxt->device_info.variant_id == MXT224_CAL_VARIANTID) {
+ strcpy(mxt->device_info.variant_name, "Calibrated");
+ } else if (mxt->device_info.variant_id ==
+ MXT224_UNCAL_VARIANTID) {
+ strcpy(mxt->device_info.variant_name, "Uncalibrated");
+ } else {
+ dev_err(&client->dev,
+ "Warning: maXTouch Variant ID [%d] not "
+ "supported\n",
+ mxt->device_info.variant_id);
+ strcpy(mxt->device_info.variant_name, "UNKNOWN");
+ /* identified = -ENXIO; */
+ }
+
+ /* MXT1386 */
+ } else if (mxt->device_info.family_id == MXT1386_FAMILYID) {
+ strcpy(mxt->device_info.family_name, "mXT1386");
+
+ if (mxt->device_info.variant_id == MXT1386_CAL_VARIANTID) {
+ strcpy(mxt->device_info.variant_name, "Calibrated");
+ } else {
+ dev_err(&client->dev,
+ "Warning: maXTouch Variant ID [%d] not "
+ "supported\n",
+ mxt->device_info.variant_id);
+ strcpy(mxt->device_info.variant_name, "UNKNOWN");
+ /* identified = -ENXIO; */
+ }
+ /* Unknown family ID! */
+ } else {
+ dev_err(&client->dev,
+ "Warning: maXTouch Family ID [%d] not supported\n",
+ mxt->device_info.family_id);
+ strcpy(mxt->device_info.family_name, "UNKNOWN");
+ strcpy(mxt->device_info.variant_name, "UNKNOWN");
+ /* identified = -ENXIO; */
+ }
+
+ dev_info(
+ &client->dev,
+ "Atmel maXTouch (Family %s (%X), Variant %s (%X)) Firmware "
+ "version [%d.%d] Build %d\n",
+ mxt->device_info.family_name,
+ mxt->device_info.family_id,
+ mxt->device_info.variant_name,
+ mxt->device_info.variant_id,
+ mxt->device_info.major,
+ mxt->device_info.minor,
+ mxt->device_info.build
+ );
+ dev_dbg(
+ &client->dev,
+ "Atmel maXTouch Configuration "
+ "[X: %d] x [Y: %d]\n",
+ mxt->device_info.x_size,
+ mxt->device_info.y_size
+ );
+ return identified;
+}
+
+/*
+ * Reads the object table from maXTouch chip to get object data like
+ * address, size, report id. For Info Block CRC calculation, already read
+ * id data is passed to this function too (Info Block consists of the ID
+ * block and object table).
+ *
+ */
+static int __devinit mxt_read_object_table(struct i2c_client *client,
+ struct mxt_data *mxt,
+ u8 *raw_id_data)
+{
+ u16 report_id_count;
+ u8 buf[MXT_OBJECT_TABLE_ELEMENT_SIZE];
+ u8 *raw_ib_data;
+ u8 object_type;
+ u16 object_address;
+ u16 object_size;
+ u8 object_instances;
+ u8 object_report_ids;
+ u16 object_info_address;
+ u32 crc;
+ u32 calculated_crc;
+ int i;
+ int error;
+
+ u8 object_instance;
+ u8 object_report_id;
+ u8 report_id;
+ int first_report_id;
+ int ib_pointer;
+ struct mxt_object *object_table;
+
+ mxt_debug(DEBUG_TRACE, "maXTouch driver reading configuration\n");
+
+ object_table = kzalloc(sizeof(struct mxt_object) *
+ mxt->device_info.num_objs,
+ GFP_KERNEL);
+ if (object_table == NULL) {
+ printk(KERN_WARNING "maXTouch: Memory allocation failed!\n");
+ error = -ENOMEM;
+ goto err_object_table_alloc;
+ }
+
+ raw_ib_data = kmalloc(MXT_OBJECT_TABLE_ELEMENT_SIZE *
+ mxt->device_info.num_objs + MXT_ID_BLOCK_SIZE,
+ GFP_KERNEL);
+ if (raw_ib_data == NULL) {
+ printk(KERN_WARNING "maXTouch: Memory allocation failed!\n");
+ error = -ENOMEM;
+ goto err_ib_alloc;
+ }
+
+ /* Copy the ID data for CRC calculation. */
+ memcpy(raw_ib_data, raw_id_data, MXT_ID_BLOCK_SIZE);
+ ib_pointer = MXT_ID_BLOCK_SIZE;
+
+ mxt->object_table = object_table;
+
+ mxt_debug(DEBUG_TRACE, "maXTouch driver Memory allocated\n");
+
+ object_info_address = MXT_ADDR_OBJECT_TABLE;
+
+ report_id_count = 0;
+ for (i = 0; i < mxt->device_info.num_objs; i++) {
+ mxt_debug(DEBUG_TRACE, "Reading maXTouch at [0x%04x]: ",
+ object_info_address);
+
+ error = mxt_read_block(client, object_info_address,
+ MXT_OBJECT_TABLE_ELEMENT_SIZE, buf);
+
+ if (error < 0) {
+ mxt->read_fail_counter++;
+ dev_err(&client->dev,
+ "maXTouch Object %d could not be read\n", i);
+ error = -EIO;
+ goto err_object_read;
+ }
+
+ memcpy(raw_ib_data + ib_pointer, buf,
+ MXT_OBJECT_TABLE_ELEMENT_SIZE);
+ ib_pointer += MXT_OBJECT_TABLE_ELEMENT_SIZE;
+
+ object_type = buf[0];
+ object_address = (buf[2] << 8) + buf[1];
+ object_size = buf[3] + 1;
+ object_instances = buf[4] + 1;
+ object_report_ids = buf[5];
+ mxt_debug(DEBUG_TRACE, "Type=%03d, Address=0x%04x, "
+ "Size=0x%02x, %d instances, %d report id's\n",
+ object_type,
+ object_address,
+ object_size,
+ object_instances,
+ object_report_ids
+ );
+
+ if (object_type == 38)
+ t38_size = object_size;
+ /* TODO: check whether object is known and supported? */
+
+ /* Save frequently needed info. */
+ if (object_type == MXT_GEN_MESSAGEPROCESSOR_T5) {
+ mxt->msg_proc_addr = object_address;
+ mxt->message_size = object_size;
+ }
+
+ object_table[i].type = object_type;
+ object_table[i].chip_addr = object_address;
+ object_table[i].size = object_size;
+ object_table[i].instances = object_instances;
+ object_table[i].num_report_ids = object_report_ids;
+ report_id_count += object_instances * object_report_ids;
+
+ object_info_address += MXT_OBJECT_TABLE_ELEMENT_SIZE;
+ }
+
+ mxt->rid_map =
+ kzalloc(sizeof(struct report_id_map) * (report_id_count + 1),
+ /* allocate for report_id 0, even if not used */
+ GFP_KERNEL);
+ if (mxt->rid_map == NULL) {
+ printk(KERN_WARNING "maXTouch: Can't allocate memory!\n");
+ error = -ENOMEM;
+ goto err_rid_map_alloc;
+ }
+
+ mxt->messages = kzalloc(mxt->message_size * MXT_MESSAGE_BUFFER_SIZE,
+ GFP_KERNEL);
+ if (mxt->messages == NULL) {
+ printk(KERN_WARNING "maXTouch: Can't allocate memory!\n");
+ error = -ENOMEM;
+ goto err_msg_alloc;
+ }
+
+ mxt->last_message = kzalloc(mxt->message_size, GFP_KERNEL);
+ if (mxt->last_message == NULL) {
+ printk(KERN_WARNING "maXTouch: Can't allocate memory!\n");
+ error = -ENOMEM;
+ goto err_msg_alloc;
+ }
+
+ mxt->report_id_count = report_id_count;
+ if (report_id_count > 254) { /* 0 & 255 are reserved */
+ dev_err(&client->dev,
+ "Too many maXTouch report id's [%d]\n",
+ report_id_count);
+ error = -ENXIO;
+ goto err_max_rid;
+ }
+
+ /* Create a mapping from report id to object type */
+ report_id = 1; /* Start from 1, 0 is reserved. */
+
+ /* Create table associating report id's with objects & instances */
+ for (i = 0; i < mxt->device_info.num_objs; i++) {
+ for (object_instance = 0;
+ object_instance < object_table[i].instances;
+ object_instance++){
+ first_report_id = report_id;
+ for (object_report_id = 0;
+ object_report_id < object_table[i].num_report_ids;
+ object_report_id++) {
+ mxt->rid_map[report_id].object =
+ object_table[i].type;
+ mxt->rid_map[report_id].instance =
+ object_instance;
+ mxt->rid_map[report_id].first_rid =
+ first_report_id;
+ report_id++;
+ }
+ }
+ }
+
+ /* Read 3 byte CRC */
+ error = mxt_read_block(client, object_info_address, 3, buf);
+ if (error < 0) {
+ mxt->read_fail_counter++;
+ dev_err(&client->dev, "Error reading CRC\n");
+ }
+
+ crc = (buf[2] << 16) | (buf[1] << 8) | buf[0];
+
+ if (calculate_infoblock_crc(&calculated_crc, raw_ib_data,
+ ib_pointer)) {
+ printk(KERN_WARNING "Error while calculating CRC!\n");
+ calculated_crc = 0;
+ }
+ kfree(raw_ib_data);
+
+ mxt_debug(DEBUG_TRACE, "\nReported info block CRC = 0x%6X\n", crc);
+ mxt_debug(DEBUG_TRACE, "Calculated info block CRC = 0x%6X\n\n",
+ calculated_crc);
+
+ if (crc == calculated_crc) {
+ mxt->info_block_crc = crc;
+ } else {
+ mxt->info_block_crc = 0;
+ printk(KERN_ALERT "maXTouch: Info block CRC invalid!\n");
+ }
+
+ if (debug >= DEBUG_VERBOSE) {
+
+ dev_info(&client->dev, "maXTouch: %d Objects\n",
+ mxt->device_info.num_objs);
+
+ for (i = 0; i < mxt->device_info.num_objs; i++) {
+ dev_info(&client->dev, "Type:\t\t\t[%d]: %s\n",
+ object_table[i].type,
+ object_type_name[object_table[i].type]);
+ dev_info(&client->dev, "\tAddress:\t0x%04X\n",
+ object_table[i].chip_addr);
+ dev_info(&client->dev, "\tSize:\t\t%d Bytes\n",
+ object_table[i].size);
+ dev_info(&client->dev, "\tInstances:\t%d\n",
+ object_table[i].instances);
+ dev_info(&client->dev, "\tReport Id's:\t%d\n",
+ object_table[i].num_report_ids);
+ }
+ }
+
+ return 0;
+
+
+err_max_rid:
+ kfree(mxt->last_message);
+err_msg_alloc:
+ kfree(mxt->rid_map);
+err_rid_map_alloc:
+err_object_read:
+ kfree(raw_ib_data);
+err_ib_alloc:
+ kfree(object_table);
+err_object_table_alloc:
+ return error;
+}
+
+#if defined(CONFIG_PM)
+static int mxt_suspend(struct device *dev)
+{
+ struct mxt_data *mxt = dev_get_drvdata(dev);
+ int error, i;
+ u8 t7_deepsl_data[T7_DATA_SIZE];
+ u16 t7_addr;
+
+ if (device_may_wakeup(dev)) {
+ enable_irq_wake(mxt->irq);
+ return 0;
+ }
+
+ disable_irq(mxt->irq);
+
+ flush_delayed_work_sync(&mxt->dwork);
+
+ for (i = 0; i < T7_DATA_SIZE; i++)
+ t7_deepsl_data[i] = 0;
+
+ t7_addr = MXT_BASE_ADDR(MXT_GEN_POWERCONFIG_T7, mxt);
+ /* save current power state values */
+ error = mxt_read_block(mxt->client, t7_addr,
+ ARRAY_SIZE(mxt->t7_data), mxt->t7_data);
+ if (error < 0)
+ goto err_enable_irq;
+
+ /* configure deep sleep mode */
+ error = mxt_write_block(mxt->client, t7_addr,
+ ARRAY_SIZE(t7_deepsl_data), t7_deepsl_data);
+ if (error < 0)
+ goto err_enable_irq;
+
+ /* power off the device */
+ if (mxt->power_on) {
+ error = mxt->power_on(false);
+ if (error) {
+ dev_err(dev, "power off failed");
+ goto err_write_block;
+ }
+ }
+ mxt->is_suspended = true;
+ return 0;
+
+err_write_block:
+ mxt_write_block(mxt->client, t7_addr,
+ ARRAY_SIZE(mxt->t7_data), mxt->t7_data);
+err_enable_irq:
+ enable_irq(mxt->irq);
+ return error;
+}
+
+static int mxt_resume(struct device *dev)
+{
+ struct mxt_data *mxt = dev_get_drvdata(dev);
+ int error;
+ u16 t7_addr;
+
+ if (device_may_wakeup(dev)) {
+ disable_irq_wake(mxt->irq);
+ return 0;
+ }
+
+ if (!mxt->is_suspended)
+ return 0;
+
+ /* power on the device */
+ if (mxt->power_on) {
+ error = mxt->power_on(true);
+ if (error) {
+ dev_err(dev, "power on failed");
+ return error;
+ }
+ }
+
+ t7_addr = MXT_BASE_ADDR(MXT_GEN_POWERCONFIG_T7, mxt);
+ /* restore the old power state values */
+ error = mxt_write_block(mxt->client, t7_addr,
+ ARRAY_SIZE(mxt->t7_data), mxt->t7_data);
+ if (error < 0)
+ goto err_write_block;
+
+ /* Make sure we just didn't miss a interrupt. */
+ if (mxt->read_chg() == 0)
+ schedule_delayed_work(&mxt->dwork, 0);
+ else
+ enable_irq(mxt->irq);
+
+ mxt->is_suspended = false;
+
+ return 0;
+
+err_write_block:
+ if (mxt->power_on)
+ mxt->power_on(false);
+ return error;
+}
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+static void mxt_early_suspend(struct early_suspend *h)
+{
+ struct mxt_data *mxt = container_of(h, struct mxt_data, early_suspend);
+
+ mxt_suspend(&mxt->client->dev);
+}
+
+static void mxt_late_resume(struct early_suspend *h)
+{
+ struct mxt_data *mxt = container_of(h, struct mxt_data, early_suspend);
+
+ mxt_resume(&mxt->client->dev);
+}
+#endif
+
+static const struct dev_pm_ops mxt_pm_ops = {
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = mxt_suspend,
+ .resume = mxt_resume,
+#endif
+};
+#endif
+
+static int __devinit mxt_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct mxt_data *mxt;
+ struct maxtouch_platform_data *pdata;
+ struct input_dev *input;
+ u8 *id_data;
+ u8 *t38_data;
+ u16 t38_addr;
+ int error;
+
+ mxt_debug(DEBUG_INFO, "mXT224: mxt_probe\n");
+
+ if (client == NULL) {
+ pr_debug("maXTouch: client == NULL\n");
+ return -EINVAL;
+ } else if (client->adapter == NULL) {
+ pr_debug("maXTouch: client->adapter == NULL\n");
+ return -EINVAL;
+ } else if (&client->dev == NULL) {
+ pr_debug("maXTouch: client->dev == NULL\n");
+ return -EINVAL;
+ } else if (&client->adapter->dev == NULL) {
+ pr_debug("maXTouch: client->adapter->dev == NULL\n");
+ return -EINVAL;
+ } else if (id == NULL) {
+ pr_debug("maXTouch: id == NULL\n");
+ return -EINVAL;
+ }
+
+ /* Enable runtime PM ops, start in ACTIVE mode */
+ error = pm_runtime_set_active(&client->dev);
+ if (error < 0)
+ dev_dbg(&client->dev, "unable to set runtime pm state\n");
+ pm_runtime_enable(&client->dev);
+
+ mxt_debug(DEBUG_INFO, "maXTouch driver v. %s\n", DRIVER_VERSION);
+ mxt_debug(DEBUG_INFO, "\t \"%s\"\n", client->name);
+ mxt_debug(DEBUG_INFO, "\taddr:\t0x%04x\n", client->addr);
+ mxt_debug(DEBUG_INFO, "\tirq:\t%d\n", client->irq);
+ mxt_debug(DEBUG_INFO, "\tflags:\t0x%04x\n", client->flags);
+ mxt_debug(DEBUG_INFO, "\tadapter:\"%s\"\n", client->adapter->name);
+ mxt_debug(DEBUG_INFO, "\tdevice:\t\"%s\"\n", client->dev.init_name);
+
+ mxt_debug(DEBUG_TRACE, "maXTouch driver functionality OK\n");
+
+ /* Allocate structure - we need it to identify device */
+ mxt = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
+ if (mxt == NULL) {
+ dev_err(&client->dev, "insufficient memory\n");
+ error = -ENOMEM;
+ goto err_mxt_alloc;
+ }
+
+ id_data = kmalloc(MXT_ID_BLOCK_SIZE, GFP_KERNEL);
+ if (id_data == NULL) {
+ dev_err(&client->dev, "insufficient memory\n");
+ error = -ENOMEM;
+ goto err_id_alloc;
+ }
+
+ input = input_allocate_device();
+ if (!input) {
+ dev_err(&client->dev, "error allocating input device\n");
+ error = -ENOMEM;
+ goto err_input_dev_alloc;
+ }
+
+ /* Initialize Platform data */
+
+ pdata = client->dev.platform_data;
+ if (pdata == NULL) {
+ dev_err(&client->dev, "platform data is required!\n");
+ error = -EINVAL;
+ goto err_pdata;
+ }
+ if (debug >= DEBUG_TRACE)
+ printk(KERN_INFO "Platform OK: pdata = 0x%08x\n",
+ (unsigned int) pdata);
+
+ mxt->is_suspended = false;
+ mxt->read_fail_counter = 0;
+ mxt->message_counter = 0;
+
+ if (pdata->min_x)
+ mxt->min_x_val = pdata->min_x;
+ else
+ mxt->min_x_val = 0;
+
+ if (pdata->min_y)
+ mxt->min_y_val = pdata->min_y;
+ else
+ mxt->min_y_val = 0;
+
+ mxt->max_x_val = pdata->max_x;
+ mxt->max_y_val = pdata->max_y;
+
+ /* Get data that is defined in board specific code. */
+ mxt->init_hw = pdata->init_platform_hw;
+ mxt->exit_hw = pdata->exit_platform_hw;
+ mxt->power_on = pdata->power_on;
+ mxt->read_chg = pdata->read_chg;
+
+ if (pdata->valid_interrupt != NULL)
+ mxt->valid_interrupt = pdata->valid_interrupt;
+ else
+ mxt->valid_interrupt = mxt_valid_interrupt_dummy;
+
+ if (mxt->init_hw) {
+ error = mxt->init_hw(client);
+ if (error) {
+ dev_err(&client->dev, "hw init failed");
+ goto err_init_hw;
+ }
+ }
+
+ /* power on the device */
+ if (mxt->power_on) {
+ error = mxt->power_on(true);
+ if (error) {
+ dev_err(&client->dev, "power on failed");
+ goto err_pwr_on;
+ }
+ }
+
+ if (debug >= DEBUG_TRACE)
+ printk(KERN_INFO "maXTouch driver identifying chip\n");
+
+ if (mxt_identify(client, mxt, id_data) < 0) {
+ dev_err(&client->dev, "Chip could not be identified\n");
+ error = -ENODEV;
+ goto err_identify;
+ }
+ /* Chip is valid and active. */
+ if (debug >= DEBUG_TRACE)
+ printk(KERN_INFO "maXTouch driver allocating input device\n");
+
+ mxt->client = client;
+ mxt->input = input;
+
+ INIT_DELAYED_WORK(&mxt->dwork, mxt_worker);
+ mutex_init(&mxt->debug_mutex);
+ mutex_init(&mxt->msg_mutex);
+ mxt_debug(DEBUG_TRACE, "maXTouch driver creating device name\n");
+
+ snprintf(
+ mxt->phys_name,
+ sizeof(mxt->phys_name),
+ "%s/input0",
+ dev_name(&client->dev)
+ );
+ input->name = "Atmel maXTouch Touchscreen controller";
+ input->phys = mxt->phys_name;
+ input->id.bustype = BUS_I2C;
+ input->dev.parent = &client->dev;
+
+ mxt_debug(DEBUG_INFO, "maXTouch name: \"%s\"\n", input->name);
+ mxt_debug(DEBUG_INFO, "maXTouch phys: \"%s\"\n", input->phys);
+ mxt_debug(DEBUG_INFO, "maXTouch driver setting abs parameters\n");
+
+ set_bit(BTN_TOUCH, input->keybit);
+
+ /* Single touch */
+ input_set_abs_params(input, ABS_X, mxt->min_x_val,
+ mxt->max_x_val, 0, 0);
+ input_set_abs_params(input, ABS_Y, mxt->min_y_val,
+ mxt->max_y_val, 0, 0);
+ input_set_abs_params(input, ABS_PRESSURE, 0, MXT_MAX_REPORTED_PRESSURE,
+ 0, 0);
+ input_set_abs_params(input, ABS_TOOL_WIDTH, 0, MXT_MAX_REPORTED_WIDTH,
+ 0, 0);
+
+ /* Multitouch */
+ input_set_abs_params(input, ABS_MT_POSITION_X, mxt->min_x_val,
+ mxt->max_x_val, 0, 0);
+ input_set_abs_params(input, ABS_MT_POSITION_Y, mxt->min_y_val,
+ mxt->max_y_val, 0, 0);
+ input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, MXT_MAX_TOUCH_SIZE,
+ 0, 0);
+ input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, MXT_MAX_NUM_TOUCHES,
+ 0, 0);
+
+ __set_bit(EV_ABS, input->evbit);
+ __set_bit(EV_SYN, input->evbit);
+ __set_bit(EV_KEY, input->evbit);
+ __set_bit(EV_MSC, input->evbit);
+ input->mscbit[0] = BIT_MASK(MSC_GESTURE);
+
+ mxt_debug(DEBUG_TRACE, "maXTouch driver setting client data\n");
+ i2c_set_clientdata(client, mxt);
+ mxt_debug(DEBUG_TRACE, "maXTouch driver setting drv data\n");
+ input_set_drvdata(input, mxt);
+ mxt_debug(DEBUG_TRACE, "maXTouch driver input register device\n");
+ error = input_register_device(mxt->input);
+ if (error < 0) {
+ dev_err(&client->dev,
+ "Failed to register input device\n");
+ goto err_register_device;
+ }
+
+ error = mxt_read_object_table(client, mxt, id_data);
+ if (error < 0)
+ goto err_read_ot;
+
+
+ /* Create debugfs entries. */
+ mxt->debug_dir = debugfs_create_dir("maXTouch", NULL);
+ if (mxt->debug_dir == ERR_PTR(-ENODEV)) {
+ /* debugfs is not enabled. */
+ printk(KERN_WARNING "debugfs not enabled in kernel\n");
+ } else if (mxt->debug_dir == NULL) {
+ printk(KERN_WARNING "error creating debugfs dir\n");
+ } else {
+ mxt_debug(DEBUG_TRACE, "created \"maXTouch\" debugfs dir\n");
+
+ debugfs_create_file("deltas", S_IRUSR, mxt->debug_dir, mxt,
+ &delta_fops);
+ debugfs_create_file("refs", S_IRUSR, mxt->debug_dir, mxt,
+ &refs_fops);
+ }
+
+ /* Create character device nodes for reading & writing registers */
+ mxt->mxt_class = class_create(THIS_MODULE, "maXTouch_memory");
+ if (IS_ERR(mxt->mxt_class)){
+ printk(KERN_WARNING "class create failed! exiting...");
+ goto err_class_create;
+
+ }
+ /* 2 numbers; one for memory and one for messages */
+ error = alloc_chrdev_region(&mxt->dev_num, 0, 2,
+ "maXTouch_memory");
+ mxt_debug(DEBUG_VERBOSE,
+ "device number %d allocated!\n", MAJOR(mxt->dev_num));
+ if (error){
+ printk(KERN_WARNING "Error registering device\n");
+ }
+ cdev_init(&mxt->cdev, &mxt_memory_fops);
+ cdev_init(&mxt->cdev_messages, &mxt_message_fops);
+
+ mxt_debug(DEBUG_VERBOSE, "cdev initialized\n");
+ mxt->cdev.owner = THIS_MODULE;
+ mxt->cdev_messages.owner = THIS_MODULE;
+
+ error = cdev_add(&mxt->cdev, mxt->dev_num, 1);
+ if (error){
+ printk(KERN_WARNING "Bad cdev\n");
+ }
+
+ error = cdev_add(&mxt->cdev_messages, mxt->dev_num + 1, 1);
+ if (error){
+ printk(KERN_WARNING "Bad cdev\n");
+ }
+
+ mxt_debug(DEBUG_VERBOSE, "cdev added\n");
+
+ device_create(mxt->mxt_class, NULL, MKDEV(MAJOR(mxt->dev_num), 0), NULL,
+ "maXTouch");
+
+ device_create(mxt->mxt_class, NULL, MKDEV(MAJOR(mxt->dev_num), 1), NULL,
+ "maXTouch_messages");
+
+ mxt->msg_buffer_startp = 0;
+ mxt->msg_buffer_endp = 0;
+
+ /* Allocate the interrupt */
+ mxt_debug(DEBUG_TRACE, "maXTouch driver allocating interrupt...\n");
+ mxt->irq = client->irq;
+ mxt->valid_irq_counter = 0;
+ mxt->invalid_irq_counter = 0;
+ mxt->irq_counter = 0;
+ if (mxt->irq) {
+ /* Try to request IRQ with falling edge first. This is
+ * not always supported. If it fails, try with any edge. */
+ error = request_irq(mxt->irq,
+ mxt_irq_handler,
+ IRQF_TRIGGER_FALLING,
+ client->dev.driver->name,
+ mxt);
+ if (error < 0) {
+ /* TODO: why only 0 works on STK1000? */
+ error = request_irq(mxt->irq,
+ mxt_irq_handler,
+ 0,
+ client->dev.driver->name,
+ mxt);
+ }
+
+ if (error < 0) {
+ dev_err(&client->dev,
+ "failed to allocate irq %d\n", mxt->irq);
+ goto err_irq;
+ }
+ }
+
+ if (debug > DEBUG_INFO)
+ dev_info(&client->dev, "touchscreen, irq %d\n", mxt->irq);
+
+ t38_data = kmalloc(t38_size*sizeof(u8), GFP_KERNEL);
+
+ if (t38_data == NULL) {
+ dev_err(&client->dev, "insufficient memory\n");
+ error = -ENOMEM;
+ goto err_t38;
+ }
+
+ t38_addr = MXT_BASE_ADDR(MXT_USER_INFO_T38, mxt);
+ mxt_read_block(client, t38_addr, t38_size, t38_data);
+ dev_info(&client->dev, "VERSION:%02x.%02x.%02x, DATE: %d/%d/%d\n",
+ t38_data[0], t38_data[1], t38_data[2],
+ t38_data[3], t38_data[4], t38_data[5]);
+
+ /* Schedule a worker routine to read any messages that might have
+ * been sent before interrupts were enabled. */
+ cancel_delayed_work(&mxt->dwork);
+ disable_irq(mxt->irq);
+ schedule_delayed_work(&mxt->dwork, 0);
+ kfree(t38_data);
+ kfree(id_data);
+
+ device_init_wakeup(&client->dev, pdata->wakeup);
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ mxt->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+ MXT_SUSPEND_LEVEL;
+ mxt->early_suspend.suspend = mxt_early_suspend;
+ mxt->early_suspend.resume = mxt_late_resume;
+ register_early_suspend(&mxt->early_suspend);
+#endif
+
+ return 0;
+
+err_t38:
+ free_irq(mxt->irq, mxt);
+err_irq:
+ kfree(mxt->rid_map);
+ kfree(mxt->object_table);
+ kfree(mxt->last_message);
+err_class_create:
+ if (mxt->debug_dir)
+ debugfs_remove(mxt->debug_dir);
+ kfree(mxt->last_message);
+ kfree(mxt->rid_map);
+ kfree(mxt->object_table);
+err_read_ot:
+ input_unregister_device(mxt->input);
+ mxt->input = NULL;
+err_register_device:
+ mutex_destroy(&mxt->debug_mutex);
+ mutex_destroy(&mxt->msg_mutex);
+err_identify:
+ if (mxt->power_on)
+ mxt->power_on(false);
+err_pwr_on:
+ if (mxt->exit_hw != NULL)
+ mxt->exit_hw(client);
+err_init_hw:
+err_pdata:
+ input_free_device(input);
+err_input_dev_alloc:
+ kfree(id_data);
+err_id_alloc:
+ kfree(mxt);
+err_mxt_alloc:
+ pm_runtime_set_suspended(&client->dev);
+ pm_runtime_disable(&client->dev);
+ return error;
+}
+
+static int __devexit mxt_remove(struct i2c_client *client)
+{
+ struct mxt_data *mxt;
+
+ pm_runtime_set_suspended(&client->dev);
+ pm_runtime_disable(&client->dev);
+
+ mxt = i2c_get_clientdata(client);
+
+ /* Remove debug dir entries */
+ debugfs_remove_recursive(mxt->debug_dir);
+
+ device_init_wakeup(&client->dev, 0);
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ unregister_early_suspend(&mxt->early_suspend);
+#endif
+
+ if (mxt != NULL) {
+ if (mxt->power_on)
+ mxt->power_on(false);
+
+ if (mxt->exit_hw != NULL)
+ mxt->exit_hw(client);
+
+ if (mxt->irq) {
+ free_irq(mxt->irq, mxt);
+ }
+
+ unregister_chrdev_region(mxt->dev_num, 2);
+ device_destroy(mxt->mxt_class, MKDEV(MAJOR(mxt->dev_num), 0));
+ device_destroy(mxt->mxt_class, MKDEV(MAJOR(mxt->dev_num), 1));
+ cdev_del(&mxt->cdev);
+ cdev_del(&mxt->cdev_messages);
+ cancel_delayed_work_sync(&mxt->dwork);
+ input_unregister_device(mxt->input);
+ class_destroy(mxt->mxt_class);
+ debugfs_remove(mxt->debug_dir);
+
+ kfree(mxt->rid_map);
+ kfree(mxt->object_table);
+ kfree(mxt->last_message);
+ }
+ kfree(mxt);
+
+ i2c_set_clientdata(client, NULL);
+ if (debug >= DEBUG_TRACE)
+ dev_info(&client->dev, "Touchscreen unregistered\n");
+
+ return 0;
+}
+
+static const struct i2c_device_id mxt_idtable[] = {
+ {"maXTouch", 0,},
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, mxt_idtable);
+
+static struct i2c_driver mxt_driver = {
+ .driver = {
+ .name = "maXTouch",
+ .owner = THIS_MODULE,
+#if defined(CONFIG_PM)
+ .pm = &mxt_pm_ops,
+#endif
+ },
+
+ .id_table = mxt_idtable,
+ .probe = mxt_probe,
+ .remove = __devexit_p(mxt_remove),
+};
+
+static int __init mxt_init(void)
+{
+ int err;
+ err = i2c_add_driver(&mxt_driver);
+ if (err) {
+ printk(KERN_WARNING "Adding maXTouch driver failed "
+ "(errno = %d)\n", err);
+ } else {
+ mxt_debug(DEBUG_TRACE, "Successfully added driver %s\n",
+ mxt_driver.driver.name);
+ }
+ return err;
+}
+
+static void __exit mxt_cleanup(void)
+{
+ i2c_del_driver(&mxt_driver);
+}
+
+
+module_init(mxt_init);
+module_exit(mxt_cleanup);
+
+MODULE_AUTHOR("Iiro Valkonen");
+MODULE_DESCRIPTION("Driver for Atmel maXTouch Touchscreen Controller");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 19d4ea6..7fe5498 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -3,6 +3,7 @@
*
* Copyright (C) 2010 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com>
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -20,21 +21,54 @@
#include <linux/input/mt.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/regulator/consumer.h>
+#include <linux/string.h>
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+/* Early-suspend level */
+#define MXT_SUSPEND_LEVEL 1
+#endif
+
+/* Family ID */
+#define MXT224_ID 0x80
+#define MXT224E_ID 0x81
+#define MXT1386_ID 0xA0
/* Version */
#define MXT_VER_20 20
#define MXT_VER_21 21
#define MXT_VER_22 22
-/* Slave addresses */
-#define MXT_APP_LOW 0x4a
-#define MXT_APP_HIGH 0x4b
-#define MXT_BOOT_LOW 0x24
-#define MXT_BOOT_HIGH 0x25
+/* I2C slave address pairs */
+struct mxt_address_pair {
+ int bootloader;
+ int application;
+};
+
+static const struct mxt_address_pair mxt_slave_addresses[] = {
+ { 0x24, 0x4a },
+ { 0x25, 0x4b },
+ { 0x25, 0x4b },
+ { 0x26, 0x4c },
+ { 0x27, 0x4d },
+ { 0x34, 0x5a },
+ { 0x35, 0x5b },
+ { 0 },
+};
+
+enum mxt_device_state { INIT, APPMODE, BOOTLOADER };
/* Firmware */
#define MXT_FW_NAME "maxtouch.fw"
+/* Firmware frame size including frame data and CRC */
+#define MXT_SINGLE_FW_MAX_FRAME_SIZE 278
+#define MXT_CHIPSET_FW_MAX_FRAME_SIZE 534
+
/* Registers */
#define MXT_FAMILY_ID 0x00
#define MXT_VARIANT_ID 0x01
@@ -66,6 +100,7 @@
#define MXT_PROCI_PALM_T41 41
#define MXT_PROCI_TOUCHSUPPRESSION_T42 42
#define MXT_PROCI_STYLUS_T47 47
+#define MXT_PROCI_SHIELDLESS_T56 56
#define MXT_PROCG_NOISESUPPRESSION_T48 48
#define MXT_SPT_COMMSCONFIG_T18 18
#define MXT_SPT_GPIOPWM_T19 19
@@ -97,7 +132,7 @@
#define MXT_ACQUIRE_ATCHCALST 6
#define MXT_ACQUIRE_ATCHCALSTHR 7
-/* MXT_TOUCH_MULTI_T9 field */
+/* MXT_TOUCH_MULT_T9 field */
#define MXT_TOUCH_CTRL 0
#define MXT_TOUCH_XORIGIN 1
#define MXT_TOUCH_YORIGIN 2
@@ -172,13 +207,35 @@
#define MXT_VOLTAGE_DEFAULT 2700000
#define MXT_VOLTAGE_STEP 10000
+/* Analog voltage @2.7 V */
+#define MXT_VTG_MIN_UV 2700000
+#define MXT_VTG_MAX_UV 3300000
+#define MXT_ACTIVE_LOAD_UA 15000
+#define MXT_LPM_LOAD_UA 10
+/* Digital voltage @1.8 V */
+#define MXT_VTG_DIG_MIN_UV 1800000
+#define MXT_VTG_DIG_MAX_UV 1800000
+#define MXT_ACTIVE_LOAD_DIG_UA 10000
+#define MXT_LPM_LOAD_DIG_UA 10
+
+#define MXT_I2C_VTG_MIN_UV 1800000
+#define MXT_I2C_VTG_MAX_UV 1800000
+#define MXT_I2C_LOAD_UA 10000
+#define MXT_I2C_LPM_LOAD_UA 10
+
/* Define for MXT_GEN_COMMAND_T6 */
#define MXT_BOOT_VALUE 0xa5
#define MXT_BACKUP_VALUE 0x55
#define MXT_BACKUP_TIME 25 /* msec */
-#define MXT_RESET_TIME 65 /* msec */
+#define MXT224_RESET_TIME 65 /* msec */
+#define MXT224E_RESET_TIME 22 /* msec */
+#define MXT1386_RESET_TIME 250 /* msec */
+#define MXT_RESET_TIME 250 /* msec */
+#define MXT_RESET_NOCHGREAD 400 /* msec */
-#define MXT_FWRESET_TIME 175 /* msec */
+#define MXT_FWRESET_TIME 1000 /* msec */
+
+#define MXT_WAKE_TIME 25
/* Command to unlock bootloader */
#define MXT_UNLOCK_CMD_MSB 0xaa
@@ -192,6 +249,8 @@
#define MXT_FRAME_CRC_PASS 0x04
#define MXT_APP_CRC_FAIL 0x40 /* valid 7 8 bit only */
#define MXT_BOOT_STATUS_MASK 0x3f
+#define MXT_BOOT_EXTENDED_ID (1 << 5)
+#define MXT_BOOT_ID_MASK 0x1f
/* Touch status */
#define MXT_SUPPRESS (1 << 1)
@@ -212,6 +271,17 @@
#define MXT_MAX_FINGER 10
+#define T7_DATA_SIZE 3
+#define MXT_MAX_RW_TRIES 3
+#define MXT_BLOCK_SIZE 256
+#define MXT_CFG_VERSION_LEN 3
+#define MXT_CFG_VERSION_EQUAL 0
+#define MXT_CFG_VERSION_LESS 1
+#define MXT_CFG_VERSION_GREATER 2
+
+#define MXT_DEBUGFS_DIR "atmel_mxt_ts"
+#define MXT_DEBUGFS_FILE "object"
+
struct mxt_info {
u8 family_id;
u8 variant_id;
@@ -252,14 +322,36 @@
struct i2c_client *client;
struct input_dev *input_dev;
const struct mxt_platform_data *pdata;
+ const struct mxt_config_info *config_info;
+ enum mxt_device_state state;
struct mxt_object *object_table;
struct mxt_info info;
struct mxt_finger finger[MXT_MAX_FINGER];
unsigned int irq;
- unsigned int max_x;
- unsigned int max_y;
+ struct regulator *vcc_ana;
+ struct regulator *vcc_dig;
+ struct regulator *vcc_i2c;
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+
+ u8 t7_data[T7_DATA_SIZE];
+ u16 t7_start_addr;
+ u32 keyarray_old;
+ u32 keyarray_new;
+ u8 t9_max_reportid;
+ u8 t9_min_reportid;
+ u8 t15_max_reportid;
+ u8 t15_min_reportid;
+ u8 cfg_version[MXT_CFG_VERSION_LEN];
+ int cfg_version_idx;
+ int t38_start_addr;
+ bool update_cfg;
+ const char *fw_name;
};
+static struct dentry *debug_base;
+
static bool mxt_object_readable(unsigned int type)
{
switch (type) {
@@ -280,6 +372,7 @@
case MXT_PROCI_PALM_T41:
case MXT_PROCI_TOUCHSUPPRESSION_T42:
case MXT_PROCI_STYLUS_T47:
+ case MXT_PROCI_SHIELDLESS_T56:
case MXT_PROCG_NOISESUPPRESSION_T48:
case MXT_SPT_COMMSCONFIG_T18:
case MXT_SPT_GPIOPWM_T19:
@@ -312,11 +405,13 @@
case MXT_PROCI_PALM_T41:
case MXT_PROCI_TOUCHSUPPRESSION_T42:
case MXT_PROCI_STYLUS_T47:
+ case MXT_PROCI_SHIELDLESS_T56:
case MXT_PROCG_NOISESUPPRESSION_T48:
case MXT_SPT_COMMSCONFIG_T18:
case MXT_SPT_GPIOPWM_T19:
case MXT_SPT_SELFTEST_T25:
case MXT_SPT_CTECONFIG_T28:
+ case MXT_SPT_USERDATA_T38:
case MXT_SPT_DIGITIZER_T43:
case MXT_SPT_CTECONFIG_T46:
return true;
@@ -339,8 +434,116 @@
dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
}
+static int mxt_switch_to_bootloader_address(struct mxt_data *data)
+{
+ int i;
+ struct i2c_client *client = data->client;
+
+ if (data->state == BOOTLOADER) {
+ dev_err(&client->dev, "Already in BOOTLOADER state\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
+ if (mxt_slave_addresses[i].application == client->addr) {
+ dev_info(&client->dev, "Changing to bootloader address: "
+ "%02x -> %02x",
+ client->addr,
+ mxt_slave_addresses[i].bootloader);
+
+ client->addr = mxt_slave_addresses[i].bootloader;
+ data->state = BOOTLOADER;
+ return 0;
+ }
+ }
+
+ dev_err(&client->dev, "Address 0x%02x not found in address table",
+ client->addr);
+ return -EINVAL;
+}
+
+static int mxt_switch_to_appmode_address(struct mxt_data *data)
+{
+ int i;
+ struct i2c_client *client = data->client;
+
+ if (data->state == APPMODE) {
+ dev_err(&client->dev, "Already in APPMODE state\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; mxt_slave_addresses[i].application != 0; i++) {
+ if (mxt_slave_addresses[i].bootloader == client->addr) {
+ dev_info(&client->dev,
+ "Changing to application mode address: "
+ "0x%02x -> 0x%02x",
+ client->addr,
+ mxt_slave_addresses[i].application);
+
+ client->addr = mxt_slave_addresses[i].application;
+ data->state = APPMODE;
+ return 0;
+ }
+ }
+
+ dev_err(&client->dev, "Address 0x%02x not found in address table",
+ client->addr);
+ return -EINVAL;
+}
+
+static int mxt_get_bootloader_version(struct i2c_client *client, u8 val)
+{
+ u8 buf[3];
+
+ if (val | MXT_BOOT_EXTENDED_ID) {
+ dev_dbg(&client->dev,
+ "Retrieving extended mode ID information");
+
+ if (i2c_master_recv(client, &buf[0], 3) != 3) {
+ dev_err(&client->dev, "%s: i2c recv failed\n",
+ __func__);
+ return -EIO;
+ }
+
+ dev_info(&client->dev, "Bootloader ID:%d Version:%d",
+ buf[1], buf[2]);
+
+ return buf[0];
+ } else {
+ dev_info(&client->dev, "Bootloader ID:%d",
+ val & MXT_BOOT_ID_MASK);
+
+ return val;
+ }
+}
+
+static int mxt_get_bootloader_id(struct i2c_client *client)
+{
+ u8 val;
+ u8 buf[3];
+
+ if (i2c_master_recv(client, &val, 1) != 1) {
+ dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
+ return -EIO;
+ }
+
+ if (val | MXT_BOOT_EXTENDED_ID) {
+ if (i2c_master_recv(client, &buf[0], 3) != 3) {
+ dev_err(&client->dev, "%s: i2c recv failed\n",
+ __func__);
+ return -EIO;
+ }
+ return buf[1];
+ } else {
+ dev_info(&client->dev, "Bootloader ID:%d",
+ val & MXT_BOOT_ID_MASK);
+
+ return val & MXT_BOOT_ID_MASK;
+ }
+}
+
static int mxt_check_bootloader(struct i2c_client *client,
- unsigned int state)
+ unsigned int state)
{
u8 val;
@@ -352,19 +555,28 @@
switch (state) {
case MXT_WAITING_BOOTLOAD_CMD:
+ val = mxt_get_bootloader_version(client, val);
+ val &= ~MXT_BOOT_STATUS_MASK;
+ break;
case MXT_WAITING_FRAME_DATA:
+ case MXT_APP_CRC_FAIL:
val &= ~MXT_BOOT_STATUS_MASK;
break;
case MXT_FRAME_CRC_PASS:
if (val == MXT_FRAME_CRC_CHECK)
goto recheck;
+ if (val == MXT_FRAME_CRC_FAIL) {
+ dev_err(&client->dev, "Bootloader CRC fail\n");
+ return -EINVAL;
+ }
break;
default:
return -EINVAL;
}
if (val != state) {
- dev_err(&client->dev, "Unvalid bootloader mode state\n");
+ dev_err(&client->dev, "Invalid bootloader mode state %X\n",
+ val);
return -EINVAL;
}
@@ -387,7 +599,7 @@
}
static int mxt_fw_write(struct i2c_client *client,
- const u8 *data, unsigned int frame_size)
+ const u8 *data, unsigned int frame_size)
{
if (i2c_master_send(client, data, frame_size) != frame_size) {
dev_err(&client->dev, "%s: i2c send failed\n", __func__);
@@ -402,6 +614,7 @@
{
struct i2c_msg xfer[2];
u8 buf[2];
+ int i = 0;
buf[0] = reg & 0xff;
buf[1] = (reg >> 8) & 0xff;
@@ -418,12 +631,14 @@
xfer[1].len = len;
xfer[1].buf = val;
- if (i2c_transfer(client->adapter, xfer, 2) != 2) {
- dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
- return -EIO;
- }
+ do {
+ if (i2c_transfer(client->adapter, xfer, 2) == 2)
+ return 0;
+ msleep(MXT_WAKE_TIME);
+ } while (++i < MXT_MAX_RW_TRIES);
- return 0;
+ dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
+ return -EIO;
}
static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
@@ -431,20 +646,33 @@
return __mxt_read_reg(client, reg, 1, val);
}
+static int __mxt_write_reg(struct i2c_client *client,
+ u16 addr, u16 length, u8 *value)
+{
+ u8 buf[MXT_BLOCK_SIZE + 2];
+ int i, tries = 0;
+
+ if (length > MXT_BLOCK_SIZE)
+ return -EINVAL;
+
+ buf[0] = addr & 0xff;
+ buf[1] = (addr >> 8) & 0xff;
+ for (i = 0; i < length; i++)
+ buf[i + 2] = *value++;
+
+ do {
+ if (i2c_master_send(client, buf, length + 2) == (length + 2))
+ return 0;
+ msleep(MXT_WAKE_TIME);
+ } while (++tries < MXT_MAX_RW_TRIES);
+
+ dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+ return -EIO;
+}
+
static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
{
- u8 buf[3];
-
- buf[0] = reg & 0xff;
- buf[1] = (reg >> 8) & 0xff;
- buf[2] = val;
-
- if (i2c_master_send(client, buf, 3) != 3) {
- dev_err(&client->dev, "%s: i2c send failed\n", __func__);
- return -EIO;
- }
-
- return 0;
+ return __mxt_write_reg(client, reg, 1, &val);
}
static int mxt_read_object_table(struct i2c_client *client,
@@ -526,6 +754,17 @@
continue;
input_mt_slot(input_dev, id);
+ /* Firmware reports min/max values when the touch is
+ * outside screen area. Send a release event in
+ * such cases to avoid unwanted touches.
+ */
+ if (finger[id].x <= data->pdata->panel_minx ||
+ finger[id].x >= data->pdata->panel_maxx ||
+ finger[id].y <= data->pdata->panel_miny ||
+ finger[id].y >= data->pdata->panel_maxy) {
+ finger[id].status = MXT_RELEASE;
+ }
+
input_mt_report_slot_state(input_dev, MT_TOOL_FINGER,
finger[id].status != MXT_RELEASE);
@@ -538,7 +777,7 @@
input_report_abs(input_dev, ABS_MT_POSITION_Y,
finger[id].y);
input_report_abs(input_dev, ABS_MT_PRESSURE,
- finger[id].pressure);
+ finger[id].pressure);
} else {
finger[id].status = 0;
}
@@ -546,11 +785,18 @@
input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
+ if (finger[single_id].x <= data->pdata->panel_minx ||
+ finger[single_id].x >= data->pdata->panel_maxx ||
+ finger[single_id].y <= data->pdata->panel_miny ||
+ finger[single_id].y >= data->pdata->panel_maxy) {
+ status = MXT_RELEASE;
+ }
+
if (status != MXT_RELEASE) {
input_report_abs(input_dev, ABS_X, finger[single_id].x);
input_report_abs(input_dev, ABS_Y, finger[single_id].y);
input_report_abs(input_dev,
- ABS_PRESSURE, finger[single_id].pressure);
+ ABS_PRESSURE, finger[single_id].pressure);
}
input_sync(input_dev);
@@ -584,9 +830,9 @@
x = (message->message[1] << 4) | ((message->message[3] >> 4) & 0xf);
y = (message->message[2] << 4) | ((message->message[3] & 0xf));
- if (data->max_x < 1024)
+ if (data->pdata->panel_maxx < 1024)
x = x >> 2;
- if (data->max_y < 1024)
+ if (data->pdata->panel_maxy < 1024)
y = y >> 2;
area = message->message[4];
@@ -606,36 +852,75 @@
mxt_input_report(data, id);
}
+static void mxt_handle_key_array(struct mxt_data *data,
+ struct mxt_message *message)
+{
+ u32 keys_changed;
+ int i;
+
+ if (!data->pdata->key_codes) {
+ dev_err(&data->client->dev, "keyarray is not supported\n");
+ return;
+ }
+
+ data->keyarray_new = message->message[1] |
+ (message->message[2] << 8) |
+ (message->message[3] << 16) |
+ (message->message[4] << 24);
+
+ keys_changed = data->keyarray_old ^ data->keyarray_new;
+
+ if (!keys_changed) {
+ dev_dbg(&data->client->dev, "no keys changed\n");
+ return;
+ }
+
+ for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
+ if (!(keys_changed & (1 << i)))
+ continue;
+
+ input_report_key(data->input_dev, data->pdata->key_codes[i],
+ (data->keyarray_new & (1 << i)));
+ input_sync(data->input_dev);
+ }
+
+ data->keyarray_old = data->keyarray_new;
+}
+
static irqreturn_t mxt_interrupt(int irq, void *dev_id)
{
struct mxt_data *data = dev_id;
struct mxt_message message;
- struct mxt_object *object;
struct device *dev = &data->client->dev;
int id;
u8 reportid;
- u8 max_reportid;
- u8 min_reportid;
+
+ if (data->state != APPMODE) {
+ dev_err(dev, "Ignoring IRQ - not in APPMODE state\n");
+ return IRQ_HANDLED;
+ }
do {
if (mxt_read_message(data, &message)) {
dev_err(dev, "Failed to read message\n");
goto end;
}
-
reportid = message.reportid;
- /* whether reportid is thing of MXT_TOUCH_MULTI_T9 */
- object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
- if (!object)
- goto end;
+ if (!reportid) {
+ dev_dbg(dev, "Report id 0 is reserved\n");
+ continue;
+ }
- max_reportid = object->max_reportid;
- min_reportid = max_reportid - object->num_report_ids + 1;
- id = reportid - min_reportid;
+ /* check whether report id is part of T9 or T15 */
+ id = reportid - data->t9_min_reportid;
- if (reportid >= min_reportid && reportid <= max_reportid)
+ if (reportid >= data->t9_min_reportid &&
+ reportid <= data->t9_max_reportid)
mxt_input_touchevent(data, &message, id);
+ else if (reportid >= data->t15_min_reportid &&
+ reportid <= data->t15_max_reportid)
+ mxt_handle_key_array(data, &message);
else
mxt_dump_message(dev, &message);
} while (reportid != 0xff);
@@ -646,13 +931,13 @@
static int mxt_check_reg_init(struct mxt_data *data)
{
- const struct mxt_platform_data *pdata = data->pdata;
+ const struct mxt_config_info *config_info = data->config_info;
struct mxt_object *object;
struct device *dev = &data->client->dev;
int index = 0;
int i, j, config_offset;
- if (!pdata->config) {
+ if (!config_info) {
dev_dbg(dev, "No cfg data defined, skipping reg init\n");
return 0;
}
@@ -663,18 +948,16 @@
if (!mxt_object_writable(object->type))
continue;
- for (j = 0;
- j < (object->size + 1) * (object->instances + 1);
- j++) {
+ for (j = 0; j < object->size + 1; j++) {
config_offset = index + j;
- if (config_offset > pdata->config_length) {
+ if (config_offset > config_info->config_length) {
dev_err(dev, "Not enough config data!\n");
return -EINVAL;
}
mxt_write_object(data, object->type, j,
- pdata->config[config_offset]);
+ config_info->config[config_offset]);
}
- index += (object->size + 1) * (object->instances + 1);
+ index += object->size + 1;
}
return 0;
@@ -702,54 +985,6 @@
return 0;
}
-static void mxt_handle_pdata(struct mxt_data *data)
-{
- const struct mxt_platform_data *pdata = data->pdata;
- u8 voltage;
-
- /* Set touchscreen lines */
- mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_XSIZE,
- pdata->x_line);
- mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_YSIZE,
- pdata->y_line);
-
- /* Set touchscreen orient */
- mxt_write_object(data, MXT_TOUCH_MULTI_T9, MXT_TOUCH_ORIENT,
- pdata->orient);
-
- /* Set touchscreen burst length */
- mxt_write_object(data, MXT_TOUCH_MULTI_T9,
- MXT_TOUCH_BLEN, pdata->blen);
-
- /* Set touchscreen threshold */
- mxt_write_object(data, MXT_TOUCH_MULTI_T9,
- MXT_TOUCH_TCHTHR, pdata->threshold);
-
- /* Set touchscreen resolution */
- mxt_write_object(data, MXT_TOUCH_MULTI_T9,
- MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff);
- mxt_write_object(data, MXT_TOUCH_MULTI_T9,
- MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8);
- mxt_write_object(data, MXT_TOUCH_MULTI_T9,
- MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff);
- mxt_write_object(data, MXT_TOUCH_MULTI_T9,
- MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8);
-
- /* Set touchscreen voltage */
- if (pdata->voltage) {
- if (pdata->voltage < MXT_VOLTAGE_DEFAULT) {
- voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) /
- MXT_VOLTAGE_STEP;
- voltage = 0xff - voltage + 1;
- } else
- voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) /
- MXT_VOLTAGE_STEP;
-
- mxt_write_object(data, MXT_SPT_CTECONFIG_T28,
- MXT_CTE_VOLTAGE, voltage);
- }
-}
-
static int mxt_get_info(struct mxt_data *data)
{
struct i2c_client *client = data->client;
@@ -792,6 +1027,7 @@
u16 reg;
u8 reportid = 0;
u8 buf[MXT_OBJECT_SIZE];
+ bool found_t38 = false;
for (i = 0; i < data->info.object_num; i++) {
struct mxt_object *object = data->object_table + i;
@@ -812,6 +1048,278 @@
(object->instances + 1);
object->max_reportid = reportid;
}
+
+ /* Calculate index for config major version in config array.
+ * Major version is the first byte in object T38.
+ */
+ if (object->type == MXT_SPT_USERDATA_T38) {
+ data->t38_start_addr = object->start_address;
+ found_t38 = true;
+ }
+ if (!found_t38 && mxt_object_writable(object->type))
+ data->cfg_version_idx += object->size + 1;
+ }
+
+ return 0;
+}
+
+static int compare_versions(const u8 *v1, const u8 *v2)
+{
+ int i;
+
+ if (!v1 || !v2)
+ return -EINVAL;
+
+ /* The major version number stays the same across different versions for
+ * a particular controller on a target. The minor and sub-minor version
+ * numbers indicate which version is newer.
+ */
+ if (v1[0] != v2[0])
+ return -EINVAL;
+
+ for (i = 1; i < MXT_CFG_VERSION_LEN; i++) {
+ if (v1[i] > v2[i])
+ return MXT_CFG_VERSION_LESS; /* v2 is older */
+
+ if (v1[i] < v2[i])
+ return MXT_CFG_VERSION_GREATER; /* v2 is newer */
+ }
+
+ return MXT_CFG_VERSION_EQUAL; /* v1 and v2 are equal */
+}
+
+static void mxt_check_config_version(struct mxt_data *data,
+ const struct mxt_config_info *cfg_info,
+ bool match_major,
+ const u8 **cfg_version_found,
+ bool *found_cfg_major_match)
+{
+ const u8 *cfg_version;
+ int result = -EINVAL;
+
+ cfg_version = cfg_info->config + data->cfg_version_idx;
+
+ if (*cfg_version_found)
+ result = compare_versions(*cfg_version_found, cfg_version);
+
+ if (match_major) {
+ if (result >= MXT_CFG_VERSION_EQUAL)
+ *found_cfg_major_match = true;
+
+ if (result == MXT_CFG_VERSION_EQUAL ||
+ result == MXT_CFG_VERSION_GREATER) {
+ data->config_info = cfg_info;
+ data->fw_name = cfg_info->fw_name;
+ *cfg_version_found = cfg_version;
+ }
+
+ if (result == MXT_CFG_VERSION_GREATER)
+ data->update_cfg = true;
+ } else if (!*cfg_version_found || result == MXT_CFG_VERSION_GREATER) {
+ data->config_info = cfg_info;
+ data->fw_name = cfg_info->fw_name;
+ data->update_cfg = true;
+ *cfg_version_found = cfg_version;
+ }
+}
+
+/* If the controller's config version has a non-zero major number, call this
+ * function with match_major = true to look for the latest config present in
+ * the pdata based on matching family id, variant id, f/w version, build, and
+ * config major number. If the controller is programmed with wrong config data
+ * previously, call this function with match_major = false to look for latest
+ * config based on based on matching family id, variant id, f/w version and
+ * build only.
+ */
+static int mxt_search_config_array(struct mxt_data *data, bool match_major)
+{
+
+ const struct mxt_platform_data *pdata = data->pdata;
+ const struct mxt_config_info *cfg_info;
+ const struct mxt_info *info = &data->info;
+ const u8 *cfg_version_found;
+ bool found_cfg_major_match = false;
+ int i;
+
+ cfg_version_found = match_major ? data->cfg_version : NULL;
+
+ for (i = 0; i < pdata->config_array_size; i++) {
+
+ cfg_info = &pdata->config_array[i];
+
+ if (!cfg_info->config || !cfg_info->config_length)
+ continue;
+
+ if (info->family_id == cfg_info->family_id &&
+ info->variant_id == cfg_info->variant_id &&
+ info->version == cfg_info->version &&
+ info->build == cfg_info->build) {
+
+ mxt_check_config_version(data, cfg_info, match_major,
+ &cfg_version_found, &found_cfg_major_match);
+ }
+ }
+
+ if (data->config_info || found_cfg_major_match)
+ return 0;
+
+ data->config_info = NULL;
+ data->fw_name = NULL;
+
+ return -EINVAL;
+}
+
+static int mxt_get_config(struct mxt_data *data)
+{
+ const struct mxt_platform_data *pdata = data->pdata;
+ struct device *dev = &data->client->dev;
+ struct mxt_object *object;
+ int error;
+
+ if (!pdata->config_array || !pdata->config_array_size) {
+ dev_dbg(dev, "No cfg data provided by platform data\n");
+ return 0;
+ }
+
+ /* Get current config version */
+ object = mxt_get_object(data, MXT_SPT_USERDATA_T38);
+ if (!object) {
+ dev_err(dev, "Unable to obtain USERDATA object\n");
+ return -EINVAL;
+ }
+
+ error = __mxt_read_reg(data->client, object->start_address,
+ sizeof(data->cfg_version), data->cfg_version);
+ if (error) {
+ dev_err(dev, "Unable to read config version\n");
+ return error;
+ }
+ dev_info(dev, "Current config version on the controller is %d.%d.%d\n",
+ data->cfg_version[0], data->cfg_version[1],
+ data->cfg_version[2]);
+
+ /* It is possible that the config data on the controller is not
+ * versioned and the version number returns 0. In this case,
+ * find a match without the config version checking.
+ */
+ error = mxt_search_config_array(data,
+ data->cfg_version[0] != 0 ? true : false);
+ if (error) {
+ /* If a match wasn't found for a non-zero config version,
+ * it means the controller has the wrong config data. Search
+ * for a best match based on controller and firmware version,
+ * but not config version.
+ */
+ if (data->cfg_version[0])
+ error = mxt_search_config_array(data, false);
+ if (error) {
+ dev_err(dev,
+ "Unable to find matching config in pdata\n");
+ return error;
+ }
+ }
+
+ return 0;
+}
+
+static void mxt_reset_delay(struct mxt_data *data)
+{
+ struct mxt_info *info = &data->info;
+
+ switch (info->family_id) {
+ case MXT224_ID:
+ msleep(MXT224_RESET_TIME);
+ break;
+ case MXT224E_ID:
+ msleep(MXT224E_RESET_TIME);
+ break;
+ case MXT1386_ID:
+ msleep(MXT1386_RESET_TIME);
+ break;
+ default:
+ msleep(MXT_RESET_TIME);
+ }
+}
+
+static int mxt_backup_nv(struct mxt_data *data)
+{
+ int error;
+ u8 command_register;
+ int timeout_counter = 0;
+
+ /* Backup to memory */
+ mxt_write_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_BACKUPNV,
+ MXT_BACKUP_VALUE);
+ msleep(MXT_BACKUP_TIME);
+
+ do {
+ error = mxt_read_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_BACKUPNV,
+ &command_register);
+ if (error)
+ return error;
+
+ usleep_range(1000, 2000);
+
+ } while ((command_register != 0) && (++timeout_counter <= 100));
+
+ if (timeout_counter > 100) {
+ dev_err(&data->client->dev, "No response after backup!\n");
+ return -EIO;
+ }
+
+ /* Soft reset */
+ mxt_write_object(data, MXT_GEN_COMMAND_T6, MXT_COMMAND_RESET, 1);
+
+ mxt_reset_delay(data);
+
+ return 0;
+}
+
+static int mxt_save_objects(struct mxt_data *data)
+{
+ struct i2c_client *client = data->client;
+ struct mxt_object *t7_object;
+ struct mxt_object *t9_object;
+ struct mxt_object *t15_object;
+ int error;
+
+ /* Store T7 and T9 locally, used in suspend/resume operations */
+ t7_object = mxt_get_object(data, MXT_GEN_POWER_T7);
+ if (!t7_object) {
+ dev_err(&client->dev, "Failed to get T7 object\n");
+ return -EINVAL;
+ }
+
+ data->t7_start_addr = t7_object->start_address;
+ error = __mxt_read_reg(client, data->t7_start_addr,
+ T7_DATA_SIZE, data->t7_data);
+ if (error < 0) {
+ dev_err(&client->dev,
+ "Failed to save current power state\n");
+ return error;
+ }
+
+ /* Store T9, T15's min and max report ids */
+ t9_object = mxt_get_object(data, MXT_TOUCH_MULTI_T9);
+ if (!t9_object) {
+ dev_err(&client->dev, "Failed to get T9 object\n");
+ return -EINVAL;
+ }
+ data->t9_max_reportid = t9_object->max_reportid;
+ data->t9_min_reportid = t9_object->max_reportid -
+ t9_object->num_report_ids + 1;
+
+ if (data->pdata->key_codes) {
+ t15_object = mxt_get_object(data, MXT_TOUCH_KEYARRAY_T15);
+ if (!t15_object)
+ dev_dbg(&client->dev, "T15 object is not available\n");
+ else {
+ data->t15_max_reportid = t15_object->max_reportid;
+ data->t15_min_reportid = t15_object->max_reportid -
+ t15_object->num_report_ids + 1;
+ }
}
return 0;
@@ -823,10 +1331,33 @@
struct mxt_info *info = &data->info;
int error;
u8 val;
+ const u8 *cfg_ver;
error = mxt_get_info(data);
- if (error)
- return error;
+ if (error) {
+ /* Try bootloader mode */
+ error = mxt_switch_to_bootloader_address(data);
+ if (error)
+ return error;
+
+ error = mxt_check_bootloader(client, MXT_APP_CRC_FAIL);
+ if (error)
+ return error;
+
+ dev_err(&client->dev, "Application CRC failure\n");
+ data->state = BOOTLOADER;
+
+ return 0;
+ }
+
+ dev_info(&client->dev,
+ "Family ID: %d Variant ID: %d Version: %d.%d "
+ "Build: 0x%02X Object Num: %d\n",
+ info->family_id, info->variant_id,
+ info->version >> 4, info->version & 0xf,
+ info->build, info->object_num);
+
+ data->state = APPMODE;
data->object_table = kcalloc(info->object_num,
sizeof(struct mxt_object),
@@ -839,62 +1370,68 @@
/* Get object table information */
error = mxt_get_object_table(data);
if (error)
- return error;
+ goto free_object_table;
+
+ /* Get config data from platform data */
+ error = mxt_get_config(data);
+ if (error)
+ dev_dbg(&client->dev, "Config info not found.\n");
/* Check register init values */
- error = mxt_check_reg_init(data);
+ if (data->config_info && data->config_info->config) {
+ if (data->update_cfg) {
+ error = mxt_check_reg_init(data);
+ if (error) {
+ dev_err(&client->dev,
+ "Failed to check reg init value\n");
+ goto free_object_table;
+ }
+
+ error = mxt_backup_nv(data);
+ if (error) {
+ dev_err(&client->dev, "Failed to back up NV\n");
+ goto free_object_table;
+ }
+
+ cfg_ver = data->config_info->config +
+ data->cfg_version_idx;
+ dev_info(&client->dev,
+ "Config updated from %d.%d.%d to %d.%d.%d\n",
+ data->cfg_version[0], data->cfg_version[1],
+ data->cfg_version[2],
+ cfg_ver[0], cfg_ver[1], cfg_ver[2]);
+
+ memcpy(data->cfg_version, cfg_ver, MXT_CFG_VERSION_LEN);
+ }
+ } else {
+ dev_info(&client->dev,
+ "No cfg data defined, skipping check reg init\n");
+ }
+
+ error = mxt_save_objects(data);
if (error)
- return error;
-
- mxt_handle_pdata(data);
-
- /* Backup to memory */
- mxt_write_object(data, MXT_GEN_COMMAND_T6,
- MXT_COMMAND_BACKUPNV,
- MXT_BACKUP_VALUE);
- msleep(MXT_BACKUP_TIME);
-
- /* Soft reset */
- mxt_write_object(data, MXT_GEN_COMMAND_T6,
- MXT_COMMAND_RESET, 1);
- msleep(MXT_RESET_TIME);
+ goto free_object_table;
/* Update matrix size at info struct */
error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
if (error)
- return error;
+ goto free_object_table;
info->matrix_xsize = val;
error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
if (error)
- return error;
+ goto free_object_table;
info->matrix_ysize = val;
dev_info(&client->dev,
- "Family ID: %d Variant ID: %d Version: %d Build: %d\n",
- info->family_id, info->variant_id, info->version,
- info->build);
-
- dev_info(&client->dev,
- "Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
- info->matrix_xsize, info->matrix_ysize,
- info->object_num);
+ "Matrix X Size: %d Matrix Y Size: %d\n",
+ info->matrix_xsize, info->matrix_ysize);
return 0;
-}
-static void mxt_calc_resolution(struct mxt_data *data)
-{
- unsigned int max_x = data->pdata->x_size - 1;
- unsigned int max_y = data->pdata->y_size - 1;
-
- if (data->pdata->orient & MXT_XY_SWITCH) {
- data->max_x = max_y;
- data->max_y = max_x;
- } else {
- data->max_x = max_x;
- data->max_y = max_y;
- }
+free_object_table:
+ kfree(data->object_table);
+ return error;
}
static ssize_t mxt_object_show(struct device *dev,
@@ -944,107 +1481,238 @@
return count;
}
+static int strtobyte(const char *data, u8 *value)
+{
+ char str[3];
+
+ str[0] = data[0];
+ str[1] = data[1];
+ str[2] = '\0';
+
+ return kstrtou8(str, 16, value);
+}
+
static int mxt_load_fw(struct device *dev, const char *fn)
{
struct mxt_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
const struct firmware *fw = NULL;
unsigned int frame_size;
+ unsigned int retry = 0;
unsigned int pos = 0;
- int ret;
+ int ret, i, max_frame_size;
+ u8 *frame;
- ret = request_firmware(&fw, fn, dev);
- if (ret) {
- dev_err(dev, "Unable to open firmware %s\n", fn);
- return ret;
+ switch (data->info.family_id) {
+ case MXT224_ID:
+ max_frame_size = MXT_SINGLE_FW_MAX_FRAME_SIZE;
+ break;
+ case MXT1386_ID:
+ max_frame_size = MXT_CHIPSET_FW_MAX_FRAME_SIZE;
+ break;
+ default:
+ return -EINVAL;
}
- /* Change to the bootloader mode */
- mxt_write_object(data, MXT_GEN_COMMAND_T6,
- MXT_COMMAND_RESET, MXT_BOOT_VALUE);
- msleep(MXT_RESET_TIME);
+ frame = kmalloc(max_frame_size, GFP_KERNEL);
+ if (!frame) {
+ dev_err(dev, "Unable to allocate memory for frame data\n");
+ return -ENOMEM;
+ }
- /* Change to slave address of bootloader */
- if (client->addr == MXT_APP_LOW)
- client->addr = MXT_BOOT_LOW;
- else
- client->addr = MXT_BOOT_HIGH;
+ ret = request_firmware(&fw, fn, dev);
+ if (ret < 0) {
+ dev_err(dev, "Unable to open firmware %s\n", fn);
+ goto free_frame;
+ }
+
+ if (data->state != BOOTLOADER) {
+ /* Change to the bootloader mode */
+ mxt_write_object(data, MXT_GEN_COMMAND_T6,
+ MXT_COMMAND_RESET, MXT_BOOT_VALUE);
+ mxt_reset_delay(data);
+
+ ret = mxt_switch_to_bootloader_address(data);
+ if (ret)
+ goto release_firmware;
+ }
ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
- if (ret)
- goto out;
+ if (ret) {
+ /* Bootloader may still be unlocked from previous update
+ * attempt */
+ ret = mxt_check_bootloader(client,
+ MXT_WAITING_FRAME_DATA);
- /* Unlock bootloader */
- mxt_unlock_bootloader(client);
+ if (ret)
+ goto return_to_app_mode;
+ } else {
+ dev_info(dev, "Unlocking bootloader\n");
+ /* Unlock bootloader */
+ mxt_unlock_bootloader(client);
+ }
while (pos < fw->size) {
ret = mxt_check_bootloader(client,
MXT_WAITING_FRAME_DATA);
if (ret)
- goto out;
+ goto release_firmware;
- frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
+ /* Get frame length MSB */
+ ret = strtobyte(fw->data + pos, frame);
+ if (ret)
+ goto release_firmware;
+
+ /* Get frame length LSB */
+ ret = strtobyte(fw->data + pos + 2, frame + 1);
+ if (ret)
+ goto release_firmware;
+
+ frame_size = ((*frame << 8) | *(frame + 1));
/* We should add 2 at frame size as the the firmware data is not
* included the CRC bytes.
*/
frame_size += 2;
+ if (frame_size > max_frame_size) {
+ dev_err(dev, "Invalid frame size - %d\n", frame_size);
+ ret = -EINVAL;
+ goto release_firmware;
+ }
+
+ /* Convert frame data and CRC from hex to binary */
+ for (i = 2; i < frame_size; i++) {
+ ret = strtobyte(fw->data + pos + i * 2, frame + i);
+ if (ret)
+ goto release_firmware;
+ }
+
/* Write one frame to device */
- mxt_fw_write(client, fw->data + pos, frame_size);
+ mxt_fw_write(client, frame, frame_size);
ret = mxt_check_bootloader(client,
MXT_FRAME_CRC_PASS);
- if (ret)
- goto out;
+ if (ret) {
+ retry++;
- pos += frame_size;
+ /* Back off by 20ms per retry */
+ msleep(retry * 20);
- dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
+ if (retry > 20)
+ goto release_firmware;
+ } else {
+ retry = 0;
+ pos += frame_size * 2;
+ dev_dbg(dev, "Updated %d/%zd bytes\n", pos, fw->size);
+ }
}
-out:
+return_to_app_mode:
+ mxt_switch_to_appmode_address(data);
+release_firmware:
release_firmware(fw);
-
- /* Change to slave address of application */
- if (client->addr == MXT_BOOT_LOW)
- client->addr = MXT_APP_LOW;
- else
- client->addr = MXT_APP_HIGH;
+free_frame:
+ kfree(frame);
return ret;
}
+static const char *
+mxt_search_fw_name(struct mxt_data *data, u8 bootldr_id)
+{
+ const struct mxt_platform_data *pdata = data->pdata;
+ const struct mxt_config_info *cfg_info;
+ const char *fw_name = NULL;
+ int i;
+
+ for (i = 0; i < pdata->config_array_size; i++) {
+ cfg_info = &pdata->config_array[i];
+ if (bootldr_id == cfg_info->bootldr_id && cfg_info->fw_name) {
+ data->config_info = cfg_info;
+ data->info.family_id = cfg_info->family_id;
+ fw_name = cfg_info->fw_name;
+ }
+ }
+
+ return fw_name;
+}
+
static ssize_t mxt_update_fw_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct mxt_data *data = dev_get_drvdata(dev);
int error;
+ const char *fw_name;
+ u8 bootldr_id;
+ u8 cfg_version[MXT_CFG_VERSION_LEN] = {0};
+
+ /* If fw_name is set, then the existing firmware has an upgrade */
+ if (!data->fw_name) {
+ /*
+ * If the device boots up in the bootloader mode, check if
+ * there is a firmware to upgrade.
+ */
+ if (data->state == BOOTLOADER) {
+ bootldr_id = mxt_get_bootloader_id(data->client);
+ if (bootldr_id <= 0) {
+ dev_err(dev,
+ "Unable to retrieve bootloader id\n");
+ return -EINVAL;
+ }
+ fw_name = mxt_search_fw_name(data, bootldr_id);
+ if (fw_name == NULL) {
+ dev_err(dev,
+ "Unable to find fw from bootloader id\n");
+ return -EINVAL;
+ }
+ } else {
+ /* In APPMODE, if the f/w name does not exist, quit */
+ dev_err(dev,
+ "Firmware name not specified in platform data\n");
+ return -EINVAL;
+ }
+ } else {
+ fw_name = data->fw_name;
+ }
+
+ dev_info(dev, "Upgrading the firmware file to %s\n", fw_name);
disable_irq(data->irq);
- error = mxt_load_fw(dev, MXT_FW_NAME);
+ error = mxt_load_fw(dev, fw_name);
if (error) {
dev_err(dev, "The firmware update failed(%d)\n", error);
count = error;
} else {
- dev_dbg(dev, "The firmware update succeeded\n");
+ dev_info(dev, "The firmware update succeeded\n");
/* Wait for reset */
msleep(MXT_FWRESET_TIME);
+ data->state = INIT;
kfree(data->object_table);
data->object_table = NULL;
+ data->cfg_version_idx = 0;
+ data->update_cfg = false;
+
+ error = __mxt_write_reg(data->client, data->t38_start_addr,
+ sizeof(cfg_version), cfg_version);
+ if (error)
+ dev_err(dev,
+ "Unable to zero out config version after fw upgrade\n");
mxt_initialize(data);
}
- enable_irq(data->irq);
+ if (data->state == APPMODE) {
+ enable_irq(data->irq);
- error = mxt_make_highchg(data);
- if (error)
- return error;
+ error = mxt_make_highchg(data);
+ if (error)
+ return error;
+ }
return count;
}
@@ -1062,25 +1730,50 @@
.attrs = mxt_attrs,
};
-static void mxt_start(struct mxt_data *data)
+static int mxt_start(struct mxt_data *data)
{
- /* Touch enable */
- mxt_write_object(data,
- MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0x83);
+ int error;
+
+ /* restore the old power state values and reenable touch */
+ error = __mxt_write_reg(data->client, data->t7_start_addr,
+ T7_DATA_SIZE, data->t7_data);
+ if (error < 0) {
+ dev_err(&data->client->dev,
+ "failed to restore old power state\n");
+ return error;
+ }
+
+ return 0;
}
-static void mxt_stop(struct mxt_data *data)
+static int mxt_stop(struct mxt_data *data)
{
- /* Touch disable */
- mxt_write_object(data,
- MXT_TOUCH_MULTI_T9, MXT_TOUCH_CTRL, 0);
+ int error;
+ u8 t7_data[T7_DATA_SIZE] = {0};
+
+ error = __mxt_write_reg(data->client, data->t7_start_addr,
+ T7_DATA_SIZE, t7_data);
+ if (error < 0) {
+ dev_err(&data->client->dev,
+ "failed to configure deep sleep mode\n");
+ return error;
+ }
+
+ return 0;
}
static int mxt_input_open(struct input_dev *dev)
{
struct mxt_data *data = input_get_drvdata(dev);
+ int error;
- mxt_start(data);
+ if (data->state == APPMODE) {
+ error = mxt_start(data);
+ if (error < 0) {
+ dev_err(&data->client->dev, "mxt_start failed in input_open\n");
+ return error;
+ }
+ }
return 0;
}
@@ -1088,8 +1781,447 @@
static void mxt_input_close(struct input_dev *dev)
{
struct mxt_data *data = input_get_drvdata(dev);
+ int error;
- mxt_stop(data);
+ if (data->state == APPMODE) {
+ error = mxt_stop(data);
+ if (error < 0)
+ dev_err(&data->client->dev, "mxt_stop failed in input_close\n");
+ }
+}
+
+static int reg_set_optimum_mode_check(struct regulator *reg, int load_uA)
+{
+ return (regulator_count_voltages(reg) > 0) ?
+ regulator_set_optimum_mode(reg, load_uA) : 0;
+}
+
+static int mxt_power_on(struct mxt_data *data, bool on)
+{
+ int rc;
+
+ if (on == false)
+ goto power_off;
+
+ rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
+ if (rc < 0) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_ana set_opt failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_enable(data->vcc_ana);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_ana enable failed rc=%d\n", rc);
+ goto error_reg_en_vcc_ana;
+ }
+
+ if (data->pdata->digital_pwr_regulator) {
+ rc = reg_set_optimum_mode_check(data->vcc_dig,
+ MXT_ACTIVE_LOAD_DIG_UA);
+ if (rc < 0) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_dig set_opt failed rc=%d\n",
+ rc);
+ goto error_reg_opt_vcc_dig;
+ }
+
+ rc = regulator_enable(data->vcc_dig);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_dig enable failed rc=%d\n", rc);
+ goto error_reg_en_vcc_dig;
+ }
+ }
+
+ if (data->pdata->i2c_pull_up) {
+ rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
+ if (rc < 0) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
+ goto error_reg_opt_i2c;
+ }
+
+ rc = regulator_enable(data->vcc_i2c);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_i2c enable failed rc=%d\n", rc);
+ goto error_reg_en_vcc_i2c;
+ }
+ }
+
+ msleep(130);
+
+ return 0;
+
+error_reg_en_vcc_i2c:
+ if (data->pdata->i2c_pull_up)
+ reg_set_optimum_mode_check(data->vcc_i2c, 0);
+error_reg_opt_i2c:
+ if (data->pdata->digital_pwr_regulator)
+ regulator_disable(data->vcc_dig);
+error_reg_en_vcc_dig:
+ if (data->pdata->digital_pwr_regulator)
+ reg_set_optimum_mode_check(data->vcc_dig, 0);
+error_reg_opt_vcc_dig:
+ regulator_disable(data->vcc_ana);
+error_reg_en_vcc_ana:
+ reg_set_optimum_mode_check(data->vcc_ana, 0);
+ return rc;
+
+power_off:
+ reg_set_optimum_mode_check(data->vcc_ana, 0);
+ regulator_disable(data->vcc_ana);
+ if (data->pdata->digital_pwr_regulator) {
+ reg_set_optimum_mode_check(data->vcc_dig, 0);
+ regulator_disable(data->vcc_dig);
+ }
+ if (data->pdata->i2c_pull_up) {
+ reg_set_optimum_mode_check(data->vcc_i2c, 0);
+ regulator_disable(data->vcc_i2c);
+ }
+ msleep(50);
+ return 0;
+}
+
+static int mxt_regulator_configure(struct mxt_data *data, bool on)
+{
+ int rc;
+
+ if (on == false)
+ goto hw_shutdown;
+
+ data->vcc_ana = regulator_get(&data->client->dev, "vdd_ana");
+ if (IS_ERR(data->vcc_ana)) {
+ rc = PTR_ERR(data->vcc_ana);
+ dev_err(&data->client->dev,
+ "Regulator get failed vcc_ana rc=%d\n", rc);
+ return rc;
+ }
+
+ if (regulator_count_voltages(data->vcc_ana) > 0) {
+ rc = regulator_set_voltage(data->vcc_ana, MXT_VTG_MIN_UV,
+ MXT_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "regulator set_vtg failed rc=%d\n", rc);
+ goto error_set_vtg_vcc_ana;
+ }
+ }
+ if (data->pdata->digital_pwr_regulator) {
+ data->vcc_dig = regulator_get(&data->client->dev, "vdd_dig");
+ if (IS_ERR(data->vcc_dig)) {
+ rc = PTR_ERR(data->vcc_dig);
+ dev_err(&data->client->dev,
+ "Regulator get dig failed rc=%d\n", rc);
+ goto error_get_vtg_vcc_dig;
+ }
+
+ if (regulator_count_voltages(data->vcc_dig) > 0) {
+ rc = regulator_set_voltage(data->vcc_dig,
+ MXT_VTG_DIG_MIN_UV, MXT_VTG_DIG_MAX_UV);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "regulator set_vtg failed rc=%d\n", rc);
+ goto error_set_vtg_vcc_dig;
+ }
+ }
+ }
+ if (data->pdata->i2c_pull_up) {
+ data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
+ if (IS_ERR(data->vcc_i2c)) {
+ rc = PTR_ERR(data->vcc_i2c);
+ dev_err(&data->client->dev,
+ "Regulator get failed rc=%d\n", rc);
+ goto error_get_vtg_i2c;
+ }
+ if (regulator_count_voltages(data->vcc_i2c) > 0) {
+ rc = regulator_set_voltage(data->vcc_i2c,
+ MXT_I2C_VTG_MIN_UV, MXT_I2C_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "regulator set_vtg failed rc=%d\n", rc);
+ goto error_set_vtg_i2c;
+ }
+ }
+ }
+
+ return 0;
+
+error_set_vtg_i2c:
+ regulator_put(data->vcc_i2c);
+error_get_vtg_i2c:
+ if (data->pdata->digital_pwr_regulator)
+ if (regulator_count_voltages(data->vcc_dig) > 0)
+ regulator_set_voltage(data->vcc_dig, 0,
+ MXT_VTG_DIG_MAX_UV);
+error_set_vtg_vcc_dig:
+ if (data->pdata->digital_pwr_regulator)
+ regulator_put(data->vcc_dig);
+error_get_vtg_vcc_dig:
+ if (regulator_count_voltages(data->vcc_ana) > 0)
+ regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
+error_set_vtg_vcc_ana:
+ regulator_put(data->vcc_ana);
+ return rc;
+
+hw_shutdown:
+ if (regulator_count_voltages(data->vcc_ana) > 0)
+ regulator_set_voltage(data->vcc_ana, 0, MXT_VTG_MAX_UV);
+ regulator_put(data->vcc_ana);
+ if (data->pdata->digital_pwr_regulator) {
+ if (regulator_count_voltages(data->vcc_dig) > 0)
+ regulator_set_voltage(data->vcc_dig, 0,
+ MXT_VTG_DIG_MAX_UV);
+ regulator_put(data->vcc_dig);
+ }
+ if (data->pdata->i2c_pull_up) {
+ if (regulator_count_voltages(data->vcc_i2c) > 0)
+ regulator_set_voltage(data->vcc_i2c, 0,
+ MXT_I2C_VTG_MAX_UV);
+ regulator_put(data->vcc_i2c);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxt_regulator_lpm(struct mxt_data *data, bool on)
+{
+
+ int rc;
+
+ if (on == false)
+ goto regulator_hpm;
+
+ rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
+ if (rc < 0) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_ana set_opt failed rc=%d\n", rc);
+ goto fail_regulator_lpm;
+ }
+
+ if (data->pdata->digital_pwr_regulator) {
+ rc = reg_set_optimum_mode_check(data->vcc_dig,
+ MXT_LPM_LOAD_DIG_UA);
+ if (rc < 0) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_dig set_opt failed rc=%d\n", rc);
+ goto fail_regulator_lpm;
+ }
+ }
+
+ if (data->pdata->i2c_pull_up) {
+ rc = reg_set_optimum_mode_check(data->vcc_i2c,
+ MXT_I2C_LPM_LOAD_UA);
+ if (rc < 0) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
+ goto fail_regulator_lpm;
+ }
+ }
+
+ return 0;
+
+regulator_hpm:
+
+ rc = reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
+ if (rc < 0) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_ana set_opt failed rc=%d\n", rc);
+ goto fail_regulator_hpm;
+ }
+
+ if (data->pdata->digital_pwr_regulator) {
+ rc = reg_set_optimum_mode_check(data->vcc_dig,
+ MXT_ACTIVE_LOAD_DIG_UA);
+ if (rc < 0) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_dig set_opt failed rc=%d\n", rc);
+ goto fail_regulator_hpm;
+ }
+ }
+
+ if (data->pdata->i2c_pull_up) {
+ rc = reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
+ if (rc < 0) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_i2c set_opt failed rc=%d\n", rc);
+ goto fail_regulator_hpm;
+ }
+ }
+
+ return 0;
+
+fail_regulator_lpm:
+ reg_set_optimum_mode_check(data->vcc_ana, MXT_ACTIVE_LOAD_UA);
+ if (data->pdata->digital_pwr_regulator)
+ reg_set_optimum_mode_check(data->vcc_dig,
+ MXT_ACTIVE_LOAD_DIG_UA);
+ if (data->pdata->i2c_pull_up)
+ reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LOAD_UA);
+
+ return rc;
+
+fail_regulator_hpm:
+ reg_set_optimum_mode_check(data->vcc_ana, MXT_LPM_LOAD_UA);
+ if (data->pdata->digital_pwr_regulator)
+ reg_set_optimum_mode_check(data->vcc_dig, MXT_LPM_LOAD_DIG_UA);
+ if (data->pdata->i2c_pull_up)
+ reg_set_optimum_mode_check(data->vcc_i2c, MXT_I2C_LPM_LOAD_UA);
+
+ return rc;
+}
+
+static int mxt_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mxt_data *data = i2c_get_clientdata(client);
+ struct input_dev *input_dev = data->input_dev;
+ int error;
+
+ mutex_lock(&input_dev->mutex);
+
+ if (input_dev->users) {
+ error = mxt_stop(data);
+ if (error < 0) {
+ dev_err(dev, "mxt_stop failed in suspend\n");
+ mutex_unlock(&input_dev->mutex);
+ return error;
+ }
+
+ }
+
+ mutex_unlock(&input_dev->mutex);
+
+ /* put regulators in low power mode */
+ error = mxt_regulator_lpm(data, true);
+ if (error < 0) {
+ dev_err(dev, "failed to enter low power mode\n");
+ return error;
+ }
+
+ return 0;
+}
+
+static int mxt_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mxt_data *data = i2c_get_clientdata(client);
+ struct input_dev *input_dev = data->input_dev;
+ int error;
+
+ /* put regulators in high power mode */
+ error = mxt_regulator_lpm(data, false);
+ if (error < 0) {
+ dev_err(dev, "failed to enter high power mode\n");
+ return error;
+ }
+
+ mutex_lock(&input_dev->mutex);
+
+ if (input_dev->users) {
+ error = mxt_start(data);
+ if (error < 0) {
+ dev_err(dev, "mxt_start failed in resume\n");
+ mutex_unlock(&input_dev->mutex);
+ return error;
+ }
+ }
+
+ mutex_unlock(&input_dev->mutex);
+
+ return 0;
+}
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+static void mxt_early_suspend(struct early_suspend *h)
+{
+ struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
+
+ mxt_suspend(&data->client->dev);
+}
+
+static void mxt_late_resume(struct early_suspend *h)
+{
+ struct mxt_data *data = container_of(h, struct mxt_data, early_suspend);
+
+ mxt_resume(&data->client->dev);
+}
+#endif
+
+static const struct dev_pm_ops mxt_pm_ops = {
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = mxt_suspend,
+ .resume = mxt_resume,
+#endif
+};
+#endif
+
+static int mxt_debugfs_object_show(struct seq_file *m, void *v)
+{
+ struct mxt_data *data = m->private;
+ struct mxt_object *object;
+ struct device *dev = &data->client->dev;
+ int i, j, k;
+ int error;
+ int obj_size;
+ u8 val;
+
+ for (i = 0; i < data->info.object_num; i++) {
+ object = data->object_table + i;
+ obj_size = object->size + 1;
+
+ seq_printf(m, "Object[%d] (Type %d)\n", i + 1, object->type);
+
+ for (j = 0; j < object->instances + 1; j++) {
+ seq_printf(m, "[Instance %d]\n", j);
+
+ for (k = 0; k < obj_size; k++) {
+ error = mxt_read_object(data, object->type,
+ j * obj_size + k, &val);
+ if (error) {
+ dev_err(dev,
+ "Failed to read object %d "
+ "instance %d at offset %d\n",
+ object->type, j, k);
+ return error;
+ }
+
+ seq_printf(m, "Byte %d: 0x%02x (%d)\n",
+ k, val, val);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int mxt_debugfs_object_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, mxt_debugfs_object_show, inode->i_private);
+}
+
+static const struct file_operations mxt_object_fops = {
+ .owner = THIS_MODULE,
+ .open = mxt_debugfs_object_open,
+ .read = seq_read,
+ .release = single_release,
+};
+
+static void __devinit mxt_debugfs_init(struct mxt_data *data)
+{
+ debug_base = debugfs_create_dir(MXT_DEBUGFS_DIR, NULL);
+ if (IS_ERR_OR_NULL(debug_base))
+ pr_err("atmel_mxt_ts: Failed to create debugfs dir\n");
+ if (IS_ERR_OR_NULL(debugfs_create_file(MXT_DEBUGFS_FILE,
+ 0444,
+ debug_base,
+ data,
+ &mxt_object_fops))) {
+ pr_err("atmel_mxt_ts: Failed to create object file\n");
+ debugfs_remove_recursive(debug_base);
+ }
}
static int __devinit mxt_probe(struct i2c_client *client,
@@ -1098,7 +2230,7 @@
const struct mxt_platform_data *pdata = client->dev.platform_data;
struct mxt_data *data;
struct input_dev *input_dev;
- int error;
+ int error, i;
if (!pdata)
return -EINVAL;
@@ -1111,7 +2243,8 @@
goto err_free_mem;
}
- input_dev->name = "Atmel maXTouch Touchscreen";
+ data->state = INIT;
+ input_dev->name = "atmel_mxt_ts";
input_dev->id.bustype = BUS_I2C;
input_dev->dev.parent = &client->dev;
input_dev->open = mxt_input_open;
@@ -1122,17 +2255,15 @@
data->pdata = pdata;
data->irq = client->irq;
- mxt_calc_resolution(data);
-
__set_bit(EV_ABS, input_dev->evbit);
__set_bit(EV_KEY, input_dev->evbit);
__set_bit(BTN_TOUCH, input_dev->keybit);
/* For single touch */
input_set_abs_params(input_dev, ABS_X,
- 0, data->max_x, 0, 0);
+ pdata->disp_minx, pdata->disp_maxx, 0, 0);
input_set_abs_params(input_dev, ABS_Y,
- 0, data->max_y, 0, 0);
+ pdata->disp_miny, pdata->disp_maxy, 0, 0);
input_set_abs_params(input_dev, ABS_PRESSURE,
0, 255, 0, 0);
@@ -1141,18 +2272,83 @@
input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
0, MXT_MAX_AREA, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_X,
- 0, data->max_x, 0, 0);
+ pdata->disp_minx, pdata->disp_maxx, 0, 0);
input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
- 0, data->max_y, 0, 0);
+ pdata->disp_miny, pdata->disp_maxy, 0, 0);
input_set_abs_params(input_dev, ABS_MT_PRESSURE,
0, 255, 0, 0);
+ /* set key array supported keys */
+ if (pdata->key_codes) {
+ for (i = 0; i < MXT_KEYARRAY_MAX_KEYS; i++) {
+ if (pdata->key_codes[i])
+ input_set_capability(input_dev, EV_KEY,
+ pdata->key_codes[i]);
+ }
+ }
+
input_set_drvdata(input_dev, data);
i2c_set_clientdata(client, data);
+ if (pdata->init_hw)
+ error = pdata->init_hw(true);
+ else
+ error = mxt_regulator_configure(data, true);
+ if (error) {
+ dev_err(&client->dev, "Failed to intialize hardware\n");
+ goto err_free_mem;
+ }
+
+ if (pdata->power_on)
+ error = pdata->power_on(true);
+ else
+ error = mxt_power_on(data, true);
+ if (error) {
+ dev_err(&client->dev, "Failed to power on hardware\n");
+ goto err_regulator_on;
+ }
+
+ if (gpio_is_valid(pdata->irq_gpio)) {
+ /* configure touchscreen irq gpio */
+ error = gpio_request(pdata->irq_gpio,
+ "mxt_irq_gpio");
+ if (error) {
+ pr_err("%s: unable to request gpio [%d]\n", __func__,
+ pdata->irq_gpio);
+ goto err_power_on;
+ }
+ error = gpio_direction_input(pdata->irq_gpio);
+ if (error) {
+ pr_err("%s: unable to set_direction for gpio [%d]\n",
+ __func__, pdata->irq_gpio);
+ goto err_irq_gpio_req;
+ }
+ }
+
+ if (gpio_is_valid(pdata->reset_gpio)) {
+ /* configure touchscreen reset out gpio */
+ error = gpio_request(pdata->reset_gpio,
+ "mxt_reset_gpio");
+ if (error) {
+ pr_err("%s: unable to request reset gpio %d\n",
+ __func__, pdata->reset_gpio);
+ goto err_irq_gpio_req;
+ }
+
+ error = gpio_direction_output(
+ pdata->reset_gpio, 1);
+ if (error) {
+ pr_err("%s: unable to set direction for gpio %d\n",
+ __func__, pdata->reset_gpio);
+ goto err_reset_gpio_req;
+ }
+ }
+
+ mxt_reset_delay(data);
+
error = mxt_initialize(data);
if (error)
- goto err_free_object;
+ goto err_reset_gpio_req;
error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
pdata->irqflags, client->dev.driver->name, data);
@@ -1161,9 +2357,13 @@
goto err_free_object;
}
- error = mxt_make_highchg(data);
- if (error)
- goto err_free_irq;
+ if (data->state == APPMODE) {
+ error = mxt_make_highchg(data);
+ if (error) {
+ dev_err(&client->dev, "Failed to make high CHG\n");
+ goto err_free_irq;
+ }
+ }
error = input_register_device(input_dev);
if (error)
@@ -1173,6 +2373,16 @@
if (error)
goto err_unregister_device;
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+ MXT_SUSPEND_LEVEL;
+ data->early_suspend.suspend = mxt_early_suspend;
+ data->early_suspend.resume = mxt_late_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+
+ mxt_debugfs_init(data);
+
return 0;
err_unregister_device:
@@ -1182,6 +2392,22 @@
free_irq(client->irq, data);
err_free_object:
kfree(data->object_table);
+err_reset_gpio_req:
+ if (gpio_is_valid(pdata->reset_gpio))
+ gpio_free(pdata->reset_gpio);
+err_irq_gpio_req:
+ if (gpio_is_valid(pdata->irq_gpio))
+ gpio_free(pdata->irq_gpio);
+err_power_on:
+ if (pdata->power_on)
+ pdata->power_on(false);
+ else
+ mxt_power_on(data, false);
+err_regulator_on:
+ if (pdata->init_hw)
+ pdata->init_hw(false);
+ else
+ mxt_regulator_configure(data, false);
err_free_mem:
input_free_device(input_dev);
kfree(data);
@@ -1195,57 +2421,34 @@
sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
free_irq(data->irq, data);
input_unregister_device(data->input_dev);
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ unregister_early_suspend(&data->early_suspend);
+#endif
+
+ if (data->pdata->power_on)
+ data->pdata->power_on(false);
+ else
+ mxt_power_on(data, false);
+
+ if (data->pdata->init_hw)
+ data->pdata->init_hw(false);
+ else
+ mxt_regulator_configure(data, false);
+
+ if (gpio_is_valid(data->pdata->reset_gpio))
+ gpio_free(data->pdata->reset_gpio);
+
+ if (gpio_is_valid(data->pdata->irq_gpio))
+ gpio_free(data->pdata->irq_gpio);
+
kfree(data->object_table);
kfree(data);
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int mxt_suspend(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct mxt_data *data = i2c_get_clientdata(client);
- struct input_dev *input_dev = data->input_dev;
-
- mutex_lock(&input_dev->mutex);
-
- if (input_dev->users)
- mxt_stop(data);
-
- mutex_unlock(&input_dev->mutex);
+ debugfs_remove_recursive(debug_base);
return 0;
}
-static int mxt_resume(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct mxt_data *data = i2c_get_clientdata(client);
- struct input_dev *input_dev = data->input_dev;
-
- /* Soft reset */
- mxt_write_object(data, MXT_GEN_COMMAND_T6,
- MXT_COMMAND_RESET, 1);
-
- msleep(MXT_RESET_TIME);
-
- mutex_lock(&input_dev->mutex);
-
- if (input_dev->users)
- mxt_start(data);
-
- mutex_unlock(&input_dev->mutex);
-
- return 0;
-}
-
-static const struct dev_pm_ops mxt_pm_ops = {
- .suspend = mxt_suspend,
- .resume = mxt_resume,
-};
-#endif
-
static const struct i2c_device_id mxt_id[] = {
{ "qt602240_ts", 0 },
{ "atmel_mxt_ts", 0 },
diff --git a/drivers/input/touchscreen/cy8c_tmg_ts.c b/drivers/input/touchscreen/cy8c_tmg_ts.c
new file mode 100644
index 0000000..f48374e
--- /dev/null
+++ b/drivers/input/touchscreen/cy8c_tmg_ts.c
@@ -0,0 +1,467 @@
+/* drivers/input/touchscreen/cy8c_tmg_ts.c
+ *
+ * Copyright (C) 2007-2008 HTC Corporation.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/cy8c_tmg_ts.h>
+#include <linux/delay.h>
+#include <linux/earlysuspend.h>
+#include <linux/hrtimer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define CY8C_REG_START_NEW_SCAN 0x0F
+#define CY8C_REG_INTR_STATUS 0x3C
+#define CY8C_REG_VERSION 0x3E
+
+struct cy8c_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ int use_irq;
+ struct hrtimer timer;
+ struct work_struct work;
+ uint16_t version;
+ int (*power) (int on);
+ struct early_suspend early_suspend;
+};
+
+struct workqueue_struct *cypress_touch_wq;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void cy8c_ts_early_suspend(struct early_suspend *h);
+static void cy8c_ts_late_resume(struct early_suspend *h);
+#endif
+
+uint16_t sample_count, X_mean, Y_mean, first_touch;
+
+static s32 cy8c_read_word_data(struct i2c_client *client,
+ u8 command, uint16_t * data)
+{
+ s32 ret = i2c_smbus_read_word_data(client, command);
+ if (ret != -1) {
+ *data = (u16) ((ret << 8) | (ret >> 8));
+ }
+ return ret;
+}
+
+static int cy8c_init_panel(struct cy8c_ts_data *ts)
+{
+ int ret;
+ sample_count = X_mean = Y_mean = first_touch = 0;
+
+ /* clean intr busy */
+ ret = i2c_smbus_write_byte_data(ts->client, CY8C_REG_INTR_STATUS,
+ 0x00);
+ if (ret < 0) {
+ dev_err(&ts->client->dev,
+ "cy8c_init_panel failed for clean intr busy\n");
+ goto exit;
+ }
+
+ /* start new scan */
+ ret = i2c_smbus_write_byte_data(ts->client, CY8C_REG_START_NEW_SCAN,
+ 0x01);
+ if (ret < 0) {
+ dev_err(&ts->client->dev,
+ "cy8c_init_panel failed for start new scan\n");
+ goto exit;
+ }
+
+exit:
+ return ret;
+}
+
+static void cy8c_ts_reset(struct i2c_client *client)
+{
+ struct cy8c_ts_data *ts = i2c_get_clientdata(client);
+
+ if (ts->power) {
+ ts->power(0);
+ msleep(10);
+ ts->power(1);
+ msleep(10);
+ }
+
+ cy8c_init_panel(ts);
+}
+
+static void cy8c_ts_work_func(struct work_struct *work)
+{
+ struct cy8c_ts_data *ts = container_of(work, struct cy8c_ts_data, work);
+ uint16_t x1, y1, x2, y2;
+ uint8_t is_touch, start_reg, force, area, finger2_pressed;
+ uint8_t buf[11];
+ struct i2c_msg msg[2];
+ int ret = 0;
+
+ x2 = y2 = 0;
+
+ /*printk("%s: enter\n",__func__);*/
+ is_touch = i2c_smbus_read_byte_data(ts->client, 0x20);
+ dev_dbg(&ts->client->dev, "fIsTouch %d,\n", is_touch);
+ if (is_touch < 0 || is_touch > 3) {
+ pr_err("%s: invalid is_touch = %d\n", __func__, is_touch);
+ cy8c_ts_reset(ts->client);
+ msleep(10);
+ goto done;
+ }
+
+ msg[0].addr = ts->client->addr;
+ msg[0].flags = 0;
+ msg[0].len = 1;
+ start_reg = 0x16;
+ msg[0].buf = &start_reg;
+
+ msg[1].addr = ts->client->addr;
+ msg[1].flags = I2C_M_RD;
+ msg[1].len = sizeof(buf);
+ msg[1].buf = buf;
+
+ ret = i2c_transfer(ts->client->adapter, msg, 2);
+ if (ret < 0)
+ goto done;
+
+ /* parse data */
+ force = buf[0];
+ area = buf[1];
+ x1 = (buf[2] << 8) | buf[3];
+ y1 = (buf[6] << 8) | buf[7];
+ is_touch = buf[10];
+
+ if (is_touch == 2) {
+ x2 = (buf[4] << 8) | buf[5];
+ y2 = (buf[8] << 8) | buf[9];
+ finger2_pressed = 1;
+ }
+
+ dev_dbg(&ts->client->dev,
+ "bFingerForce %d, bFingerArea %d \n", force, area);
+ dev_dbg(&ts->client->dev, "x1: %d, y1: %d \n", x1, y1);
+ if (finger2_pressed)
+ dev_dbg(&ts->client->dev, "x2: %d, y2: %d \n", x2, y2);
+
+ /* drop the first one? */
+ if ((is_touch == 1) && (first_touch == 0)) {
+ first_touch = 1;
+ goto done;
+ }
+
+ if (!first_touch)
+ goto done;
+
+ if (is_touch == 2)
+ finger2_pressed = 1;
+
+ input_report_abs(ts->input_dev, ABS_X, x1);
+ input_report_abs(ts->input_dev, ABS_Y, y1);
+ input_report_abs(ts->input_dev, ABS_PRESSURE, force);
+ input_report_abs(ts->input_dev, ABS_TOOL_WIDTH, area);
+ input_report_key(ts->input_dev, BTN_TOUCH, is_touch);
+ input_report_key(ts->input_dev, BTN_2, finger2_pressed);
+
+ if (finger2_pressed) {
+ input_report_abs(ts->input_dev, ABS_HAT0X, x2);
+ input_report_abs(ts->input_dev, ABS_HAT0Y, y2);
+ }
+ input_sync(ts->input_dev);
+
+done:
+ if (is_touch == 0)
+ first_touch = sample_count = 0;
+
+ /* prepare for next intr */
+ i2c_smbus_write_byte_data(ts->client, CY8C_REG_INTR_STATUS, 0x00);
+ if (!ts->use_irq)
+ hrtimer_start(&ts->timer, ktime_set(0, 12500000), HRTIMER_MODE_REL);
+ else
+ enable_irq(ts->client->irq);
+}
+
+static enum hrtimer_restart cy8c_ts_timer_func(struct hrtimer *timer)
+{
+ struct cy8c_ts_data *ts;
+
+ ts = container_of(timer, struct cy8c_ts_data, timer);
+ queue_work(cypress_touch_wq, &ts->work);
+ return HRTIMER_NORESTART;
+}
+
+static irqreturn_t cy8c_ts_irq_handler(int irq, void *dev_id)
+{
+ struct cy8c_ts_data *ts = dev_id;
+
+ disable_irq_nosync(ts->client->irq);
+ queue_work(cypress_touch_wq, &ts->work);
+ return IRQ_HANDLED;
+}
+
+static int cy8c_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct cy8c_ts_data *ts;
+ struct cy8c_i2c_platform_data *pdata;
+ uint16_t panel_version;
+ int ret = 0;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "need I2C_FUNC_I2C\n");
+ ret = -ENODEV;
+ goto err_check_functionality_failed;
+ }
+
+ ts = kzalloc(sizeof(struct cy8c_ts_data), GFP_KERNEL);
+ if (ts == NULL) {
+ dev_err(&client->dev, "allocate cy8c_ts_data failed\n");
+ ret = -ENOMEM;
+ goto err_alloc_data_failed;
+ }
+
+ INIT_WORK(&ts->work, cy8c_ts_work_func);
+ ts->client = client;
+ i2c_set_clientdata(client, ts);
+
+ pdata = client->dev.platform_data;
+ if (pdata) {
+ ts->version = pdata->version;
+ ts->power = pdata->power;
+ }
+
+ if (ts->power) {
+ ret = ts->power(1);
+ msleep(10);
+ if (ret < 0) {
+ dev_err(&client->dev, "power on failed\n");
+ goto err_power_failed;
+ }
+ }
+
+ ret = cy8c_read_word_data(ts->client, CY8C_REG_VERSION, &panel_version);
+ if (ret < 0) {
+ dev_err(&client->dev, "init panel failed\n");
+ goto err_detect_failed;
+ }
+ dev_info(&client->dev, "Panel Version %04X\n", panel_version);
+ if (pdata) {
+ while (pdata->version > panel_version) {
+ dev_info(&client->dev, "old tp detected, "
+ "panel version = %x\n", panel_version);
+ pdata++;
+ }
+ }
+
+ ret = cy8c_init_panel(ts);
+ if (ret < 0) {
+ dev_err(&client->dev, "init panel failed\n");
+ goto err_detect_failed;
+ }
+
+ ts->input_dev = input_allocate_device();
+ if (ts->input_dev == NULL) {
+ ret = -ENOMEM;
+ dev_err(&client->dev, "Failed to allocate input device\n");
+ goto err_input_dev_alloc_failed;
+ }
+ ts->input_dev->name = "cy8c-touchscreen";
+
+ set_bit(EV_SYN, ts->input_dev->evbit);
+ set_bit(EV_ABS, ts->input_dev->evbit);
+ set_bit(EV_KEY, ts->input_dev->evbit);
+ input_set_capability(ts->input_dev, EV_KEY, BTN_TOUCH);
+ input_set_capability(ts->input_dev, EV_KEY, BTN_2);
+
+ input_set_abs_params(ts->input_dev, ABS_X,
+ pdata->abs_x_min, pdata->abs_x_max, 5, 0);
+ input_set_abs_params(ts->input_dev, ABS_Y,
+ pdata->abs_y_min, pdata->abs_y_max, 5, 0);
+ input_set_abs_params(ts->input_dev, ABS_HAT0X,
+ pdata->abs_x_min, pdata->abs_x_max, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_HAT0Y,
+ pdata->abs_y_min, pdata->abs_y_max, 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_PRESSURE,
+ pdata->abs_pressure_min, pdata->abs_pressure_max,
+ 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_TOOL_WIDTH,
+ pdata->abs_width_min, pdata->abs_width_max, 0, 0);
+
+ ret = input_register_device(ts->input_dev);
+ if (ret) {
+ dev_err(&client->dev,
+ "cy8c_ts_probe: Unable to register %s input device\n",
+ ts->input_dev->name);
+ goto err_input_register_device_failed;
+ }
+
+ if (client->irq) {
+ ret = request_irq(client->irq, cy8c_ts_irq_handler,
+ IRQF_TRIGGER_LOW, CYPRESS_TMG_NAME, ts);
+ if (ret == 0)
+ ts->use_irq = 1;
+ else
+ dev_err(&client->dev, "request_irq failed\n");
+ }
+
+ if (!ts->use_irq) {
+ hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ ts->timer.function = cy8c_ts_timer_func;
+ hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ ts->early_suspend.suspend = cy8c_ts_early_suspend;
+ ts->early_suspend.resume = cy8c_ts_late_resume;
+ register_early_suspend(&ts->early_suspend);
+#endif
+
+ dev_info(&client->dev, "Start touchscreen %s in %s mode\n",
+ ts->input_dev->name, (ts->use_irq ? "interrupt" : "polling"));
+
+ return 0;
+
+err_input_register_device_failed:
+ input_free_device(ts->input_dev);
+
+err_input_dev_alloc_failed:
+ if (ts->power)
+ ts->power(0);
+
+err_detect_failed:
+err_power_failed:
+ kfree(ts);
+
+err_alloc_data_failed:
+err_check_functionality_failed:
+ return ret;
+}
+
+static int cy8c_ts_remove(struct i2c_client *client)
+{
+ struct cy8c_ts_data *ts = i2c_get_clientdata(client);
+
+ unregister_early_suspend(&ts->early_suspend);
+
+ if (ts->use_irq)
+ free_irq(client->irq, ts);
+ else
+ hrtimer_cancel(&ts->timer);
+
+ input_unregister_device(ts->input_dev);
+ kfree(ts);
+
+ return 0;
+}
+
+static int cy8c_ts_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ struct cy8c_ts_data *ts = i2c_get_clientdata(client);
+ int ret;
+
+ if (ts->use_irq)
+ disable_irq_nosync(client->irq);
+ else
+ hrtimer_cancel(&ts->timer);
+
+ ret = cancel_work_sync(&ts->work);
+ if (ret && ts->use_irq)
+ enable_irq(client->irq);
+
+ if (ts->power)
+ ts->power(0);
+
+ return 0;
+}
+
+static int cy8c_ts_resume(struct i2c_client *client)
+{
+ int ret;
+ struct cy8c_ts_data *ts = i2c_get_clientdata(client);
+
+ if (ts->power) {
+ ret = ts->power(1);
+ if (ret < 0)
+ dev_err(&client->dev,
+ "cy8c_ts_resume power on failed\n");
+ msleep(10);
+
+ cy8c_init_panel(ts);
+ }
+
+ if (ts->use_irq)
+ enable_irq(client->irq);
+ else
+ hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+
+ return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void cy8c_ts_early_suspend(struct early_suspend *h)
+{
+ struct cy8c_ts_data *ts;
+ ts = container_of(h, struct cy8c_ts_data, early_suspend);
+ cy8c_ts_suspend(ts->client, PMSG_SUSPEND);
+}
+
+static void cy8c_ts_late_resume(struct early_suspend *h)
+{
+ struct cy8c_ts_data *ts;
+ ts = container_of(h, struct cy8c_ts_data, early_suspend);
+ cy8c_ts_resume(ts->client);
+}
+#endif
+
+static const struct i2c_device_id cy8c_ts_i2c_id[] = {
+ {CYPRESS_TMG_NAME, 0},
+ {}
+};
+
+static struct i2c_driver cy8c_ts_driver = {
+ .id_table = cy8c_ts_i2c_id,
+ .probe = cy8c_ts_probe,
+ .remove = cy8c_ts_remove,
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = cy8c_ts_suspend,
+ .resume = cy8c_ts_resume,
+#endif
+ .driver = {
+ .name = CYPRESS_TMG_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __devinit cy8c_ts_init(void)
+{
+ cypress_touch_wq = create_singlethread_workqueue("cypress_touch_wq");
+ if (!cypress_touch_wq)
+ return -ENOMEM;
+
+ return i2c_add_driver(&cy8c_ts_driver);
+}
+
+static void __exit cy8c_ts_exit(void)
+{
+ if (cypress_touch_wq)
+ destroy_workqueue(cypress_touch_wq);
+
+ i2c_del_driver(&cy8c_ts_driver);
+}
+
+module_init(cy8c_ts_init);
+module_exit(cy8c_ts_exit);
+
+MODULE_DESCRIPTION("Cypress TMG Touchscreen Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/input/touchscreen/cy8c_ts.c b/drivers/input/touchscreen/cy8c_ts.c
new file mode 100644
index 0000000..f708582
--- /dev/null
+++ b/drivers/input/touchscreen/cy8c_ts.c
@@ -0,0 +1,824 @@
+/* Source for:
+ * Cypress CY8CTMA300 Prototype touchscreen driver.
+ * drivers/input/touchscreen/cy8c_ts.c
+ *
+ * Copyright (C) 2009, 2010 Cypress Semiconductor, Inc.
+ * Copyright (c) 2010, 2011 Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, and only version 2, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Cypress reserves the right to make changes without further notice
+ * to the materials described herein. Cypress does not assume any
+ * liability arising out of the application described herein.
+ *
+ * Contact Cypress Semiconductor at www.cypress.com
+ *
+ * History:
+ * (C) 2010 Cypress - Update for GPL distribution
+ * (C) 2009 Cypress - Assume maintenance ownership
+ * (C) 2009 Enea - Original prototype
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/input/cy8c_ts.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+
+/* Early-suspend level */
+#define CY8C_TS_SUSPEND_LEVEL 1
+#endif
+
+#define CY8CTMA300 0x0
+#define CY8CTMG200 0x1
+#define CY8CTMA340 0x2
+
+#define INVALID_DATA 0xff
+
+#define TOUCHSCREEN_TIMEOUT (msecs_to_jiffies(10))
+#define INITIAL_DELAY (msecs_to_jiffies(25000))
+
+struct cy8c_ts_data {
+ u8 x_index;
+ u8 y_index;
+ u8 z_index;
+ u8 id_index;
+ u8 touch_index;
+ u8 data_reg;
+ u8 status_reg;
+ u8 data_size;
+ u8 touch_bytes;
+ u8 update_data;
+ u8 touch_meta_data;
+ u8 finger_size;
+};
+
+static struct cy8c_ts_data devices[] = {
+ [0] = {
+ .x_index = 6,
+ .y_index = 4,
+ .z_index = 3,
+ .id_index = 0,
+ .data_reg = 0x3,
+ .status_reg = 0x1,
+ .update_data = 0x4,
+ .touch_bytes = 8,
+ .touch_meta_data = 3,
+ .finger_size = 70,
+ },
+ [1] = {
+ .x_index = 2,
+ .y_index = 4,
+ .id_index = 6,
+ .data_reg = 0x6,
+ .status_reg = 0x5,
+ .update_data = 0x1,
+ .touch_bytes = 12,
+ .finger_size = 70,
+ },
+ [2] = {
+ .x_index = 1,
+ .y_index = 3,
+ .z_index = 5,
+ .id_index = 6,
+ .data_reg = 0x2,
+ .status_reg = 0,
+ .update_data = 0x4,
+ .touch_bytes = 6,
+ .touch_meta_data = 3,
+ .finger_size = 70,
+ },
+};
+
+struct cy8c_ts {
+ struct i2c_client *client;
+ struct input_dev *input;
+ struct delayed_work work;
+ struct workqueue_struct *wq;
+ struct cy8c_ts_platform_data *pdata;
+ struct cy8c_ts_data *dd;
+ u8 *touch_data;
+ u8 device_id;
+ u8 prev_touches;
+ bool is_suspended;
+ bool int_pending;
+ struct mutex sus_lock;
+ u32 pen_irq;
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+};
+
+static inline u16 join_bytes(u8 a, u8 b)
+{
+ u16 ab = 0;
+ ab = ab | a;
+ ab = ab << 8 | b;
+ return ab;
+}
+
+static s32 cy8c_ts_write_reg_u8(struct i2c_client *client, u8 reg, u8 val)
+{
+ s32 data;
+
+ data = i2c_smbus_write_byte_data(client, reg, val);
+ if (data < 0)
+ dev_err(&client->dev, "error %d in writing reg 0x%x\n",
+ data, reg);
+
+ return data;
+}
+
+static s32 cy8c_ts_read_reg_u8(struct i2c_client *client, u8 reg)
+{
+ s32 data;
+
+ data = i2c_smbus_read_byte_data(client, reg);
+ if (data < 0)
+ dev_err(&client->dev, "error %d in reading reg 0x%x\n",
+ data, reg);
+
+ return data;
+}
+
+static int cy8c_ts_read(struct i2c_client *client, u8 reg, u8 *buf, int num)
+{
+ struct i2c_msg xfer_msg[2];
+
+ xfer_msg[0].addr = client->addr;
+ xfer_msg[0].len = 1;
+ xfer_msg[0].flags = 0;
+ xfer_msg[0].buf = ®
+
+ xfer_msg[1].addr = client->addr;
+ xfer_msg[1].len = num;
+ xfer_msg[1].flags = I2C_M_RD;
+ xfer_msg[1].buf = buf;
+
+ return i2c_transfer(client->adapter, xfer_msg, 2);
+}
+
+static void report_data(struct cy8c_ts *ts, u16 x, u16 y, u8 pressure, u8 id)
+{
+ if (ts->pdata->swap_xy)
+ swap(x, y);
+
+ /* handle inverting coordinates */
+ if (ts->pdata->invert_x)
+ x = ts->pdata->res_x - x;
+ if (ts->pdata->invert_y)
+ y = ts->pdata->res_y - y;
+
+ input_report_abs(ts->input, ABS_MT_TRACKING_ID, id);
+ input_report_abs(ts->input, ABS_MT_POSITION_X, x);
+ input_report_abs(ts->input, ABS_MT_POSITION_Y, y);
+ input_report_abs(ts->input, ABS_MT_PRESSURE, pressure);
+ input_mt_sync(ts->input);
+}
+
+static void process_tma300_data(struct cy8c_ts *ts)
+{
+ u8 id, pressure, touches, i;
+ u16 x, y;
+
+ touches = ts->touch_data[ts->dd->touch_index];
+
+ for (i = 0; i < touches; i++) {
+ id = ts->touch_data[i * ts->dd->touch_bytes +
+ ts->dd->id_index];
+ pressure = ts->touch_data[i * ts->dd->touch_bytes +
+ ts->dd->z_index];
+ x = join_bytes(ts->touch_data[i * ts->dd->touch_bytes +
+ ts->dd->x_index],
+ ts->touch_data[i * ts->dd->touch_bytes +
+ ts->dd->x_index + 1]);
+ y = join_bytes(ts->touch_data[i * ts->dd->touch_bytes +
+ ts->dd->y_index],
+ ts->touch_data[i * ts->dd->touch_bytes +
+ ts->dd->y_index + 1]);
+
+ report_data(ts, x, y, pressure, id);
+ }
+
+ for (i = 0; i < ts->prev_touches - touches; i++) {
+ input_report_abs(ts->input, ABS_MT_PRESSURE, 0);
+ input_mt_sync(ts->input);
+ }
+
+ ts->prev_touches = touches;
+ input_sync(ts->input);
+}
+
+static void process_tmg200_data(struct cy8c_ts *ts)
+{
+ u8 id, touches, i;
+ u16 x, y;
+
+ touches = ts->touch_data[ts->dd->touch_index];
+
+ if (touches > 0) {
+ x = join_bytes(ts->touch_data[ts->dd->x_index],
+ ts->touch_data[ts->dd->x_index+1]);
+ y = join_bytes(ts->touch_data[ts->dd->y_index],
+ ts->touch_data[ts->dd->y_index+1]);
+ id = ts->touch_data[ts->dd->id_index];
+
+ report_data(ts, x, y, 255, id - 1);
+
+ if (touches == 2) {
+ x = join_bytes(ts->touch_data[ts->dd->x_index+5],
+ ts->touch_data[ts->dd->x_index+6]);
+ y = join_bytes(ts->touch_data[ts->dd->y_index+5],
+ ts->touch_data[ts->dd->y_index+6]);
+ id = ts->touch_data[ts->dd->id_index+5];
+
+ report_data(ts, x, y, 255, id - 1);
+ }
+ } else {
+ for (i = 0; i < ts->prev_touches; i++) {
+ input_report_abs(ts->input, ABS_MT_PRESSURE, 0);
+ input_mt_sync(ts->input);
+ }
+ }
+
+ input_sync(ts->input);
+ ts->prev_touches = touches;
+}
+
+static void cy8c_ts_xy_worker(struct work_struct *work)
+{
+ int rc;
+ struct cy8c_ts *ts = container_of(work, struct cy8c_ts,
+ work.work);
+
+ mutex_lock(&ts->sus_lock);
+ if (ts->is_suspended == true) {
+ dev_dbg(&ts->client->dev, "TS is supended\n");
+ ts->int_pending = true;
+ mutex_unlock(&ts->sus_lock);
+ return;
+ }
+ mutex_unlock(&ts->sus_lock);
+
+ /* read data from DATA_REG */
+ rc = cy8c_ts_read(ts->client, ts->dd->data_reg, ts->touch_data,
+ ts->dd->data_size);
+ if (rc < 0) {
+ dev_err(&ts->client->dev, "read failed\n");
+ goto schedule;
+ }
+
+ if (ts->touch_data[ts->dd->touch_index] == INVALID_DATA)
+ goto schedule;
+
+ if ((ts->device_id == CY8CTMA300) || (ts->device_id == CY8CTMA340))
+ process_tma300_data(ts);
+ else
+ process_tmg200_data(ts);
+
+schedule:
+ enable_irq(ts->pen_irq);
+
+ /* write to STATUS_REG to update coordinates*/
+ rc = cy8c_ts_write_reg_u8(ts->client, ts->dd->status_reg,
+ ts->dd->update_data);
+ if (rc < 0) {
+ dev_err(&ts->client->dev, "write failed, try once more\n");
+
+ rc = cy8c_ts_write_reg_u8(ts->client, ts->dd->status_reg,
+ ts->dd->update_data);
+ if (rc < 0)
+ dev_err(&ts->client->dev, "write failed, exiting\n");
+ }
+}
+
+static irqreturn_t cy8c_ts_irq(int irq, void *dev_id)
+{
+ struct cy8c_ts *ts = dev_id;
+
+ disable_irq_nosync(irq);
+
+ queue_delayed_work(ts->wq, &ts->work, 0);
+
+ return IRQ_HANDLED;
+}
+
+static int cy8c_ts_init_ts(struct i2c_client *client, struct cy8c_ts *ts)
+{
+ struct input_dev *input_device;
+ int rc = 0;
+
+ ts->dd = &devices[ts->device_id];
+
+ if (!ts->pdata->nfingers) {
+ dev_err(&client->dev, "Touches information not specified\n");
+ return -EINVAL;
+ }
+
+ if (ts->device_id == CY8CTMA300) {
+ if (ts->pdata->nfingers > 10) {
+ dev_err(&client->dev, "Touches >=1 & <= 10\n");
+ return -EINVAL;
+ }
+ ts->dd->data_size = ts->pdata->nfingers * ts->dd->touch_bytes +
+ ts->dd->touch_meta_data;
+ ts->dd->touch_index = ts->pdata->nfingers *
+ ts->dd->touch_bytes;
+ } else if (ts->device_id == CY8CTMG200) {
+ if (ts->pdata->nfingers > 2) {
+ dev_err(&client->dev, "Touches >=1 & <= 2\n");
+ return -EINVAL;
+ }
+ ts->dd->data_size = ts->dd->touch_bytes;
+ ts->dd->touch_index = 0x0;
+ } else if (ts->device_id == CY8CTMA340) {
+ if (ts->pdata->nfingers > 10) {
+ dev_err(&client->dev, "Touches >=1 & <= 10\n");
+ return -EINVAL;
+ }
+ ts->dd->data_size = ts->pdata->nfingers * ts->dd->touch_bytes +
+ ts->dd->touch_meta_data;
+ ts->dd->touch_index = 0x0;
+ }
+
+ ts->touch_data = kzalloc(ts->dd->data_size, GFP_KERNEL);
+ if (!ts->touch_data) {
+ pr_err("%s: Unable to allocate memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ ts->prev_touches = 0;
+
+ input_device = input_allocate_device();
+ if (!input_device) {
+ rc = -ENOMEM;
+ goto error_alloc_dev;
+ }
+
+ ts->input = input_device;
+ input_device->name = ts->pdata->ts_name;
+ input_device->id.bustype = BUS_I2C;
+ input_device->dev.parent = &client->dev;
+ input_set_drvdata(input_device, ts);
+
+ __set_bit(EV_ABS, input_device->evbit);
+
+ if (ts->device_id == CY8CTMA340) {
+ /* set up virtual key */
+ __set_bit(EV_KEY, input_device->evbit);
+ /* set dummy key to make driver work with virtual keys */
+ input_set_capability(input_device, EV_KEY, KEY_PROG1);
+ }
+
+ input_set_abs_params(input_device, ABS_MT_POSITION_X,
+ ts->pdata->dis_min_x, ts->pdata->dis_max_x, 0, 0);
+ input_set_abs_params(input_device, ABS_MT_POSITION_Y,
+ ts->pdata->dis_min_y, ts->pdata->dis_max_y, 0, 0);
+ input_set_abs_params(input_device, ABS_MT_PRESSURE,
+ ts->pdata->min_touch, ts->pdata->max_touch, 0, 0);
+ input_set_abs_params(input_device, ABS_MT_TRACKING_ID,
+ ts->pdata->min_tid, ts->pdata->max_tid, 0, 0);
+
+ ts->wq = create_singlethread_workqueue("kworkqueue_ts");
+ if (!ts->wq) {
+ dev_err(&client->dev, "Could not create workqueue\n");
+ goto error_wq_create;
+ }
+
+ INIT_DELAYED_WORK(&ts->work, cy8c_ts_xy_worker);
+
+ rc = input_register_device(input_device);
+ if (rc)
+ goto error_unreg_device;
+
+ return 0;
+
+error_unreg_device:
+ destroy_workqueue(ts->wq);
+error_wq_create:
+ input_free_device(input_device);
+error_alloc_dev:
+ kfree(ts->touch_data);
+ return rc;
+}
+
+#ifdef CONFIG_PM
+static int cy8c_ts_suspend(struct device *dev)
+{
+ struct cy8c_ts *ts = dev_get_drvdata(dev);
+ int rc = 0;
+
+ if (device_may_wakeup(dev)) {
+ /* mark suspend flag */
+ mutex_lock(&ts->sus_lock);
+ ts->is_suspended = true;
+ mutex_unlock(&ts->sus_lock);
+
+ enable_irq_wake(ts->pen_irq);
+ } else {
+ disable_irq_nosync(ts->pen_irq);
+
+ rc = cancel_delayed_work_sync(&ts->work);
+
+ if (rc) {
+ /* missed the worker, write to STATUS_REG to
+ acknowledge interrupt */
+ rc = cy8c_ts_write_reg_u8(ts->client,
+ ts->dd->status_reg, ts->dd->update_data);
+ if (rc < 0) {
+ dev_err(&ts->client->dev,
+ "write failed, try once more\n");
+
+ rc = cy8c_ts_write_reg_u8(ts->client,
+ ts->dd->status_reg,
+ ts->dd->update_data);
+ if (rc < 0)
+ dev_err(&ts->client->dev,
+ "write failed, exiting\n");
+ }
+
+ enable_irq(ts->pen_irq);
+ }
+
+ gpio_free(ts->pdata->irq_gpio);
+
+ if (ts->pdata->power_on) {
+ rc = ts->pdata->power_on(0);
+ if (rc) {
+ dev_err(dev, "unable to goto suspend\n");
+ return rc;
+ }
+ }
+ }
+ return 0;
+}
+
+static int cy8c_ts_resume(struct device *dev)
+{
+ struct cy8c_ts *ts = dev_get_drvdata(dev);
+ int rc = 0;
+
+ if (device_may_wakeup(dev)) {
+ disable_irq_wake(ts->pen_irq);
+
+ mutex_lock(&ts->sus_lock);
+ ts->is_suspended = false;
+
+ if (ts->int_pending == true) {
+ ts->int_pending = false;
+
+ /* start a delayed work */
+ queue_delayed_work(ts->wq, &ts->work, 0);
+ }
+ mutex_unlock(&ts->sus_lock);
+
+ } else {
+ if (ts->pdata->power_on) {
+ rc = ts->pdata->power_on(1);
+ if (rc) {
+ dev_err(dev, "unable to resume\n");
+ return rc;
+ }
+ }
+
+ /* configure touchscreen interrupt gpio */
+ rc = gpio_request(ts->pdata->irq_gpio, "cy8c_irq_gpio");
+ if (rc) {
+ pr_err("%s: unable to request gpio %d\n",
+ __func__, ts->pdata->irq_gpio);
+ goto err_power_off;
+ }
+
+ rc = gpio_direction_input(ts->pdata->irq_gpio);
+ if (rc) {
+ pr_err("%s: unable to set direction for gpio %d\n",
+ __func__, ts->pdata->irq_gpio);
+ goto err_gpio_free;
+ }
+
+ enable_irq(ts->pen_irq);
+
+ /* Clear the status register of the TS controller */
+ rc = cy8c_ts_write_reg_u8(ts->client,
+ ts->dd->status_reg, ts->dd->update_data);
+ if (rc < 0) {
+ dev_err(&ts->client->dev,
+ "write failed, try once more\n");
+
+ rc = cy8c_ts_write_reg_u8(ts->client,
+ ts->dd->status_reg,
+ ts->dd->update_data);
+ if (rc < 0)
+ dev_err(&ts->client->dev,
+ "write failed, exiting\n");
+ }
+ }
+ return 0;
+err_gpio_free:
+ gpio_free(ts->pdata->irq_gpio);
+err_power_off:
+ if (ts->pdata->power_on)
+ rc = ts->pdata->power_on(0);
+ return rc;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void cy8c_ts_early_suspend(struct early_suspend *h)
+{
+ struct cy8c_ts *ts = container_of(h, struct cy8c_ts, early_suspend);
+
+ cy8c_ts_suspend(&ts->client->dev);
+}
+
+static void cy8c_ts_late_resume(struct early_suspend *h)
+{
+ struct cy8c_ts *ts = container_of(h, struct cy8c_ts, early_suspend);
+
+ cy8c_ts_resume(&ts->client->dev);
+}
+#endif
+
+static struct dev_pm_ops cy8c_ts_pm_ops = {
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = cy8c_ts_suspend,
+ .resume = cy8c_ts_resume,
+#endif
+};
+#endif
+
+static int __devinit cy8c_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct cy8c_ts *ts;
+ struct cy8c_ts_platform_data *pdata = client->dev.platform_data;
+ int rc, temp_reg;
+
+ if (!pdata) {
+ dev_err(&client->dev, "platform data is required!\n");
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_WORD_DATA)) {
+ dev_err(&client->dev, "I2C functionality not supported\n");
+ return -EIO;
+ }
+
+ ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ /* Enable runtime PM ops, start in ACTIVE mode */
+ rc = pm_runtime_set_active(&client->dev);
+ if (rc < 0)
+ dev_dbg(&client->dev, "unable to set runtime pm state\n");
+ pm_runtime_enable(&client->dev);
+
+ ts->client = client;
+ ts->pdata = pdata;
+ i2c_set_clientdata(client, ts);
+ ts->device_id = id->driver_data;
+
+ if (ts->pdata->dev_setup) {
+ rc = ts->pdata->dev_setup(1);
+ if (rc < 0) {
+ dev_err(&client->dev, "dev setup failed\n");
+ goto error_touch_data_alloc;
+ }
+ }
+
+ /* power on the device */
+ if (ts->pdata->power_on) {
+ rc = ts->pdata->power_on(1);
+ if (rc) {
+ pr_err("%s: Unable to power on the device\n", __func__);
+ goto error_dev_setup;
+ }
+ }
+
+ /* read one byte to make sure i2c device exists */
+ if (id->driver_data == CY8CTMA300)
+ temp_reg = 0x01;
+ else if (id->driver_data == CY8CTMA340)
+ temp_reg = 0x00;
+ else
+ temp_reg = 0x05;
+
+ rc = cy8c_ts_read_reg_u8(client, temp_reg);
+ if (rc < 0) {
+ dev_err(&client->dev, "i2c sanity check failed\n");
+ goto error_power_on;
+ }
+
+ ts->is_suspended = false;
+ ts->int_pending = false;
+ mutex_init(&ts->sus_lock);
+
+ rc = cy8c_ts_init_ts(client, ts);
+ if (rc < 0) {
+ dev_err(&client->dev, "CY8CTMG200-TMA300 init failed\n");
+ goto error_mutex_destroy;
+ }
+
+ if (ts->pdata->resout_gpio < 0)
+ goto config_irq_gpio;
+
+ /* configure touchscreen reset out gpio */
+ rc = gpio_request(ts->pdata->resout_gpio, "cy8c_resout_gpio");
+ if (rc) {
+ pr_err("%s: unable to request gpio %d\n",
+ __func__, ts->pdata->resout_gpio);
+ goto error_uninit_ts;
+ }
+
+ rc = gpio_direction_output(ts->pdata->resout_gpio, 0);
+ if (rc) {
+ pr_err("%s: unable to set direction for gpio %d\n",
+ __func__, ts->pdata->resout_gpio);
+ goto error_resout_gpio_dir;
+ }
+ /* reset gpio stabilization time */
+ msleep(20);
+
+config_irq_gpio:
+ /* configure touchscreen interrupt gpio */
+ rc = gpio_request(ts->pdata->irq_gpio, "cy8c_irq_gpio");
+ if (rc) {
+ pr_err("%s: unable to request gpio %d\n",
+ __func__, ts->pdata->irq_gpio);
+ goto error_irq_gpio_req;
+ }
+
+ rc = gpio_direction_input(ts->pdata->irq_gpio);
+ if (rc) {
+ pr_err("%s: unable to set direction for gpio %d\n",
+ __func__, ts->pdata->irq_gpio);
+ goto error_irq_gpio_dir;
+ }
+
+ ts->pen_irq = gpio_to_irq(ts->pdata->irq_gpio);
+ rc = request_irq(ts->pen_irq, cy8c_ts_irq,
+ IRQF_TRIGGER_FALLING,
+ ts->client->dev.driver->name, ts);
+ if (rc) {
+ dev_err(&ts->client->dev, "could not request irq\n");
+ goto error_req_irq_fail;
+ }
+
+ /* Clear the status register of the TS controller */
+ rc = cy8c_ts_write_reg_u8(ts->client, ts->dd->status_reg,
+ ts->dd->update_data);
+ if (rc < 0) {
+ /* Do multiple writes in case of failure */
+ dev_err(&ts->client->dev, "%s: write failed %d"
+ "trying again\n", __func__, rc);
+ rc = cy8c_ts_write_reg_u8(ts->client,
+ ts->dd->status_reg, ts->dd->update_data);
+ if (rc < 0) {
+ dev_err(&ts->client->dev, "%s: write failed"
+ "second time(%d)\n", __func__, rc);
+ }
+ }
+
+ device_init_wakeup(&client->dev, ts->pdata->wakeup);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+ CY8C_TS_SUSPEND_LEVEL;
+ ts->early_suspend.suspend = cy8c_ts_early_suspend;
+ ts->early_suspend.resume = cy8c_ts_late_resume;
+ register_early_suspend(&ts->early_suspend);
+#endif
+
+ return 0;
+error_req_irq_fail:
+error_irq_gpio_dir:
+ gpio_free(ts->pdata->irq_gpio);
+error_irq_gpio_req:
+error_resout_gpio_dir:
+ if (ts->pdata->resout_gpio >= 0)
+ gpio_free(ts->pdata->resout_gpio);
+error_uninit_ts:
+ destroy_workqueue(ts->wq);
+ input_unregister_device(ts->input);
+ kfree(ts->touch_data);
+error_mutex_destroy:
+ mutex_destroy(&ts->sus_lock);
+error_power_on:
+ if (ts->pdata->power_on)
+ ts->pdata->power_on(0);
+error_dev_setup:
+ if (ts->pdata->dev_setup)
+ ts->pdata->dev_setup(0);
+error_touch_data_alloc:
+ pm_runtime_set_suspended(&client->dev);
+ pm_runtime_disable(&client->dev);
+ kfree(ts);
+ return rc;
+}
+
+static int __devexit cy8c_ts_remove(struct i2c_client *client)
+{
+ struct cy8c_ts *ts = i2c_get_clientdata(client);
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ unregister_early_suspend(&ts->early_suspend);
+#endif
+ pm_runtime_set_suspended(&client->dev);
+ pm_runtime_disable(&client->dev);
+
+ device_init_wakeup(&client->dev, 0);
+
+ cancel_delayed_work_sync(&ts->work);
+
+ free_irq(ts->pen_irq, ts);
+
+ gpio_free(ts->pdata->irq_gpio);
+
+ if (ts->pdata->resout_gpio >= 0)
+ gpio_free(ts->pdata->resout_gpio);
+
+ destroy_workqueue(ts->wq);
+
+ input_unregister_device(ts->input);
+
+ mutex_destroy(&ts->sus_lock);
+
+ if (ts->pdata->power_on)
+ ts->pdata->power_on(0);
+
+ if (ts->pdata->dev_setup)
+ ts->pdata->dev_setup(0);
+
+ kfree(ts->touch_data);
+ kfree(ts);
+
+ return 0;
+}
+
+static const struct i2c_device_id cy8c_ts_id[] = {
+ {"cy8ctma300", CY8CTMA300},
+ {"cy8ctmg200", CY8CTMG200},
+ {"cy8ctma340", CY8CTMA340},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, cy8c_ts_id);
+
+
+static struct i2c_driver cy8c_ts_driver = {
+ .driver = {
+ .name = "cy8c_ts",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &cy8c_ts_pm_ops,
+#endif
+ },
+ .probe = cy8c_ts_probe,
+ .remove = __devexit_p(cy8c_ts_remove),
+ .id_table = cy8c_ts_id,
+};
+
+static int __init cy8c_ts_init(void)
+{
+ return i2c_add_driver(&cy8c_ts_driver);
+}
+/* Making this as late init to avoid power fluctuations
+ * during LCD initialization.
+ */
+late_initcall(cy8c_ts_init);
+
+static void __exit cy8c_ts_exit(void)
+{
+ return i2c_del_driver(&cy8c_ts_driver);
+}
+module_exit(cy8c_ts_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("CY8CTMA340-CY8CTMG200 touchscreen controller driver");
+MODULE_AUTHOR("Cypress");
+MODULE_ALIAS("platform:cy8c_ts");
diff --git a/drivers/input/touchscreen/cyttsp-i2c-qc.c b/drivers/input/touchscreen/cyttsp-i2c-qc.c
new file mode 100644
index 0000000..e82dd13
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp-i2c-qc.c
@@ -0,0 +1,3132 @@
+/* Source for:
+ * Cypress TrueTouch(TM) Standard Product I2C touchscreen driver.
+ * drivers/input/touchscreen/cyttsp-i2c.c
+ *
+ * Copyright (C) 2009, 2010 Cypress Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, and only version 2, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Cypress reserves the right to make changes without further notice
+ * to the materials described herein. Cypress does not assume any
+ * liability arising out of the application described herein.
+ *
+ * Contact Cypress Semiconductor at www.cypress.com
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/byteorder/generic.h>
+#include <linux/bitops.h>
+#include <linux/pm_runtime.h>
+#include <linux/firmware.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+#define CY_DECLARE_GLOBALS
+
+#include <linux/cyttsp-qc.h>
+
+uint32_t cyttsp_tsdebug1 = 0xff;
+module_param_named(tsdebug1, cyttsp_tsdebug1, uint, 0664);
+
+#define FW_FNAME_LEN 40
+#define TTSP_BUFF_SIZE 50
+
+/* CY TTSP I2C Driver private data */
+struct cyttsp {
+ struct i2c_client *client;
+ struct input_dev *input;
+ struct timer_list timer;
+ struct mutex mutex;
+ char phys[32];
+ struct cyttsp_platform_data *platform_data;
+ u8 num_prv_st_tch;
+ u16 fw_start_addr;
+ u16 act_trk[CY_NUM_TRK_ID];
+ u16 prv_st_tch[CY_NUM_ST_TCH_ID];
+ u16 prv_mt_tch[CY_NUM_MT_TCH_ID];
+ u16 prv_mt_pos[CY_NUM_TRK_ID][2];
+ atomic_t irq_enabled;
+ bool cyttsp_update_fw;
+ bool cyttsp_fwloader_mode;
+ bool is_suspended;
+ struct regulator **vdd;
+ char fw_fname[FW_FNAME_LEN];
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+};
+static u8 irq_cnt; /* comparison counter with register valuw */
+static u32 irq_cnt_total; /* total interrupts */
+static u32 irq_err_cnt; /* count number of touch interrupts with err */
+#define CY_IRQ_CNT_MASK 0x000000FF /* mapped for sizeof count in reg */
+#define CY_IRQ_CNT_REG 0x00 /* tt_undef[0]=reg 0x1B - Gen3 only */
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void cyttsp_early_suspend(struct early_suspend *handler);
+static void cyttsp_late_resume(struct early_suspend *handler);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+
+/* ****************************************************************************
+ * Prototypes for static functions
+ * ************************************************************************** */
+static irqreturn_t cyttsp_irq(int irq, void *handle);
+static int cyttsp_inlist(u16 prev_track[],
+ u8 cur_trk_id, u8 *prev_loc, u8 num_touches);
+static int cyttsp_next_avail_inlist(u16 cur_trk[],
+ u8 *new_loc, u8 num_touches);
+static int cyttsp_putbl(struct cyttsp *ts, int show,
+ int show_status, int show_version, int show_cid);
+static int __devinit cyttsp_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int __devexit cyttsp_remove(struct i2c_client *client);
+static int cyttsp_resume(struct device *dev);
+static int cyttsp_suspend(struct device *dev);
+
+/* Static variables */
+static struct cyttsp_gen3_xydata_t g_xy_data;
+static struct cyttsp_bootloader_data_t g_bl_data;
+static struct cyttsp_sysinfo_data_t g_sysinfo_data;
+static const struct i2c_device_id cyttsp_id[] = {
+ { CY_I2C_NAME, 0 }, { }
+};
+static u8 bl_cmd[] = {
+ CY_BL_FILE0, CY_BL_CMD, CY_BL_EXIT,
+ CY_BL_KEY0, CY_BL_KEY1, CY_BL_KEY2,
+ CY_BL_KEY3, CY_BL_KEY4, CY_BL_KEY5,
+ CY_BL_KEY6, CY_BL_KEY7};
+
+MODULE_DEVICE_TABLE(i2c, cyttsp_id);
+
+#ifdef CONFIG_PM
+static const struct dev_pm_ops cyttsp_pm_ops = {
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = cyttsp_suspend,
+ .resume = cyttsp_resume,
+#endif
+};
+#endif
+
+static struct i2c_driver cyttsp_driver = {
+ .driver = {
+ .name = CY_I2C_NAME,
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &cyttsp_pm_ops,
+#endif
+ },
+ .probe = cyttsp_probe,
+ .remove = __devexit_p(cyttsp_remove),
+ .id_table = cyttsp_id,
+};
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cypress TrueTouch(R) Standard touchscreen driver");
+MODULE_AUTHOR("Cypress");
+
+static ssize_t cyttsp_irq_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct cyttsp *ts = i2c_get_clientdata(client);
+ return snprintf(buf, TTSP_BUFF_SIZE, "%u\n",
+ atomic_read(&ts->irq_enabled));
+}
+
+static ssize_t cyttsp_irq_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct cyttsp *ts = i2c_get_clientdata(client);
+ int err = 0;
+ unsigned long value;
+
+ if (size > 2)
+ return -EINVAL;
+
+ err = strict_strtoul(buf, 10, &value);
+ if (err != 0)
+ return err;
+
+ switch (value) {
+ case 0:
+ if (atomic_cmpxchg(&ts->irq_enabled, 1, 0)) {
+ pr_info("touch irq disabled!\n");
+ disable_irq_nosync(ts->client->irq);
+ }
+ err = size;
+ break;
+ case 1:
+ if (!atomic_cmpxchg(&ts->irq_enabled, 0, 1)) {
+ pr_info("touch irq enabled!\n");
+ enable_irq(ts->client->irq);
+ }
+ err = size;
+ break;
+ default:
+ pr_info("cyttsp_irq_enable failed -> irq_enabled = %d\n",
+ atomic_read(&ts->irq_enabled));
+ err = -EINVAL;
+ break;
+ }
+
+ return err;
+}
+
+static DEVICE_ATTR(irq_enable, 0664, cyttsp_irq_status, cyttsp_irq_enable);
+
+static ssize_t cyttsp_fw_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, TTSP_BUFF_SIZE, "%d.%d.%d\n", g_bl_data.appid_lo,
+ g_bl_data.appver_hi, g_bl_data.appver_lo);
+}
+
+static DEVICE_ATTR(cyttsp_fw_ver, 0664, cyttsp_fw_show, NULL);
+
+/* firmware flashing block */
+#define BLK_SIZE 16
+#define DATA_REC_LEN 64
+#define BLK_SEED 0xff
+#define RECAL_REG 0x1b
+
+enum bl_commands {
+ BL_CMD_WRBLK = 0x39,
+ BL_CMD_INIT = 0x38,
+ BL_CMD_TERMINATE = 0x3b,
+};
+/* TODO: Add key as part of platform data */
+#define KEY_CS (0 + 1 + 2 + 3 + 4 + 5 + 6 + 7)
+#define KEY {0, 1, 2, 3, 4, 5, 6, 7}
+
+static const char _key[] = KEY;
+#define KEY_LEN sizeof(_key)
+
+static int rec_cnt;
+struct fw_record {
+ u8 seed;
+ u8 cmd;
+ u8 key[KEY_LEN];
+ u8 blk_hi;
+ u8 blk_lo;
+ u8 data[DATA_REC_LEN];
+ u8 data_cs;
+ u8 rec_cs;
+};
+#define fw_rec_size (sizeof(struct fw_record))
+
+struct cmd_record {
+ u8 reg;
+ u8 seed;
+ u8 cmd;
+ u8 key[KEY_LEN];
+};
+#define cmd_rec_size (sizeof(struct cmd_record))
+
+static struct fw_record data_record = {
+ .seed = BLK_SEED,
+ .cmd = BL_CMD_WRBLK,
+ .key = KEY,
+};
+
+static const struct cmd_record terminate_rec = {
+ .reg = 0,
+ .seed = BLK_SEED,
+ .cmd = BL_CMD_TERMINATE,
+ .key = KEY,
+};
+static const struct cmd_record initiate_rec = {
+ .reg = 0,
+ .seed = BLK_SEED,
+ .cmd = BL_CMD_INIT,
+ .key = KEY,
+};
+
+#define BL_REC1_ADDR 0x0780
+#define BL_REC2_ADDR 0x07c0
+#define BL_CHECKSUM_MASK 0x01
+
+#define ID_INFO_REC ":40078000"
+#define ID_INFO_OFFSET_IN_REC 77
+
+#define REC_START_CHR ':'
+#define REC_LEN_OFFSET 1
+#define REC_ADDR_HI_OFFSET 3
+#define REC_ADDR_LO_OFFSET 5
+#define REC_TYPE_OFFSET 7
+#define REC_DATA_OFFSET 9
+#define REC_LINE_SIZE 141
+
+#define NUM_CHAR_IN_HEX 2
+#define ID_INFO_REC_LEN 9
+
+static int cyttsp_soft_reset(struct cyttsp *ts)
+{
+ int retval = 0, tries = 0;
+ u8 host_reg = CY_SOFT_RESET_MODE;
+
+ do {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(host_reg), &host_reg);
+ if (retval < 0)
+ msleep(20);
+ } while (tries++ < 10 && (retval < 0));
+
+ if (retval < 0) {
+ pr_err("%s: failed\n", __func__);
+ return retval;
+ }
+
+ tries = 0;
+ do {
+ msleep(20);
+ cyttsp_putbl(ts, 1, true, true, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+
+ if (g_bl_data.bl_status != 0x11 && g_bl_data.bl_status != 0x10)
+ return -EINVAL;
+
+ return 0;
+}
+
+static void cyttsp_exit_bl_mode(struct cyttsp *ts)
+{
+ int retval, tries = 0;
+
+ do {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(bl_cmd), bl_cmd);
+ if (retval < 0)
+ msleep(20);
+ } while (tries++ < 10 && (retval < 0));
+}
+
+static void cyttsp_set_sysinfo_mode(struct cyttsp *ts)
+{
+ int retval, tries = 0;
+ u8 host_reg = CY_SYSINFO_MODE;
+
+ do {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(host_reg), &host_reg);
+ if (retval < 0)
+ msleep(20);
+ } while (tries++ < 10 && (retval < 0));
+
+ /* wait for TTSP Device to complete switch to SysInfo mode */
+ if (!(retval < 0)) {
+ retval = i2c_smbus_read_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ sizeof(struct cyttsp_sysinfo_data_t),
+ (u8 *)&g_sysinfo_data);
+ } else
+ pr_err("%s: failed\n", __func__);
+}
+
+static void cyttsp_set_opmode(struct cyttsp *ts)
+{
+ int retval, tries = 0;
+ u8 host_reg = CY_OP_MODE;
+
+ do {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(host_reg), &host_reg);
+ if (retval < 0)
+ msleep(20);
+ } while (tries++ < 10 && (retval < 0));
+}
+
+static int str2uc(char *str, u8 *val)
+{
+ char substr[3];
+ unsigned long ulval;
+ int rc;
+
+ if (!str)
+ return -EINVAL;
+
+ if (strnlen(str, NUM_CHAR_IN_HEX) < 2)
+ return -EINVAL;
+
+ substr[0] = str[0];
+ substr[1] = str[1];
+ substr[2] = '\0';
+
+ rc = strict_strtoul(substr, 16, &ulval);
+ if (rc != 0)
+ return rc;
+
+ *val = (u8) ulval;
+
+ return 0;
+}
+
+static int flash_block(struct cyttsp *ts, u8 *blk, int len)
+{
+ int retval, i, tries = 0;
+ char buf[(2 * (BLK_SIZE + 1)) + 1];
+ char *p = buf;
+
+ for (i = 0; i < len; i++, p += 2)
+ snprintf(p, TTSP_BUFF_SIZE, "%02x", blk[i]);
+ pr_debug("%s: size %d, pos %ld payload %s\n",
+ __func__, len, (long)0, buf);
+
+ do {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, len, blk);
+ if (retval < 0)
+ msleep(20);
+ } while (tries++ < 20 && (retval < 0));
+
+ if (retval < 0) {
+ pr_err("%s: failed\n", __func__);
+ return retval;
+ }
+
+ return 0;
+}
+
+static int flash_command(struct cyttsp *ts, const struct cmd_record *record)
+{
+ return flash_block(ts, (u8 *)record, cmd_rec_size);
+}
+
+static void init_data_record(struct fw_record *rec, unsigned short addr)
+{
+ addr >>= 6;
+ rec->blk_hi = (addr >> 8) & 0xff;
+ rec->blk_lo = addr & 0xff;
+ rec->rec_cs = rec->blk_hi + rec->blk_lo +
+ (unsigned char)(BLK_SEED + BL_CMD_WRBLK + KEY_CS);
+ rec->data_cs = 0;
+}
+
+static int check_record(struct cyttsp *ts, u8 *rec)
+{
+ int rc;
+ u16 addr;
+ u8 r_len, type, hi_off, lo_off;
+
+ rc = str2uc(rec + REC_LEN_OFFSET, &r_len);
+ if (rc < 0)
+ return rc;
+
+ rc = str2uc(rec + REC_TYPE_OFFSET, &type);
+ if (rc < 0)
+ return rc;
+
+ if (*rec != REC_START_CHR || r_len != DATA_REC_LEN || type != 0)
+ return -EINVAL;
+
+ rc = str2uc(rec + REC_ADDR_HI_OFFSET, &hi_off);
+ if (rc < 0)
+ return rc;
+
+ rc = str2uc(rec + REC_ADDR_LO_OFFSET, &lo_off);
+ if (rc < 0)
+ return rc;
+
+ addr = (hi_off << 8) | lo_off;
+
+ if (addr >= ts->fw_start_addr || addr == BL_REC1_ADDR
+ || addr == BL_REC2_ADDR)
+ return 0;
+
+ return -EINVAL;
+}
+
+static struct fw_record *prepare_record(u8 *rec)
+{
+ int i, rc;
+ u16 addr;
+ u8 hi_off, lo_off;
+ u8 *p;
+
+ rc = str2uc(rec + REC_ADDR_HI_OFFSET, &hi_off);
+ if (rc < 0)
+ return ERR_PTR((long) rc);
+
+ rc = str2uc(rec + REC_ADDR_LO_OFFSET, &lo_off);
+ if (rc < 0)
+ return ERR_PTR((long) rc);
+
+ addr = (hi_off << 8) | lo_off;
+
+ init_data_record(&data_record, addr);
+ p = rec + REC_DATA_OFFSET;
+ for (i = 0; i < DATA_REC_LEN; i++) {
+ rc = str2uc(p, &data_record.data[i]);
+ if (rc < 0)
+ return ERR_PTR((long) rc);
+ data_record.data_cs += data_record.data[i];
+ data_record.rec_cs += data_record.data[i];
+ p += 2;
+ }
+ data_record.rec_cs += data_record.data_cs;
+
+ return &data_record;
+}
+
+static int flash_record(struct cyttsp *ts, const struct fw_record *record)
+{
+ int len = fw_rec_size;
+ int blk_len, rc;
+ u8 *rec = (u8 *)record;
+ u8 data[BLK_SIZE + 1];
+ u8 blk_offset;
+
+ for (blk_offset = 0; len; len -= blk_len) {
+ data[0] = blk_offset;
+ blk_len = len > BLK_SIZE ? BLK_SIZE : len;
+ memcpy(data + 1, rec, blk_len);
+ rec += blk_len;
+ rc = flash_block(ts, data, blk_len + 1);
+ if (rc < 0)
+ return rc;
+ blk_offset += blk_len;
+ }
+ return 0;
+}
+
+static int flash_data_rec(struct cyttsp *ts, u8 *buf)
+{
+ struct fw_record *rec;
+ int rc, tries;
+
+ if (!buf)
+ return -EINVAL;
+
+ rc = check_record(ts, buf);
+
+ if (rc < 0) {
+ pr_debug("%s: record ignored %s", __func__, buf);
+ return 0;
+ }
+
+ rec = prepare_record(buf);
+ if (IS_ERR_OR_NULL(rec))
+ return PTR_ERR(rec);
+
+ rc = flash_record(ts, rec);
+ if (rc < 0)
+ return rc;
+
+ tries = 0;
+ do {
+ if (rec_cnt%2)
+ msleep(20);
+ cyttsp_putbl(ts, 4, true, false, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+ rec_cnt++;
+ return rc;
+}
+
+static int cyttspfw_flash_firmware(struct cyttsp *ts, const u8 *data,
+ int data_len)
+{
+ u8 *buf;
+ int i, j;
+ int rc, tries = 0;
+
+ /* initiate bootload: this will erase all the existing data */
+ rc = flash_command(ts, &initiate_rec);
+ if (rc < 0)
+ return rc;
+
+ do {
+ msleep(100);
+ cyttsp_putbl(ts, 4, true, false, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+
+ buf = kzalloc(REC_LINE_SIZE + 1, GFP_KERNEL);
+ if (!buf) {
+ pr_err("%s: no memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ rec_cnt = 0;
+ /* flash data records */
+ for (i = 0, j = 0; i < data_len; i++, j++) {
+ if ((data[i] == REC_START_CHR) && j) {
+ buf[j] = 0;
+ rc = flash_data_rec(ts, buf);
+ if (rc < 0)
+ return rc;
+ j = 0;
+ }
+ buf[j] = data[i];
+ }
+
+ /* flash last data record */
+ if (j) {
+ buf[j] = 0;
+ rc = flash_data_rec(ts, buf);
+ if (rc < 0)
+ return rc;
+ }
+
+ kfree(buf);
+
+ /* termiate bootload */
+ tries = 0;
+ rc = flash_command(ts, &terminate_rec);
+ do {
+ msleep(100);
+ cyttsp_putbl(ts, 4, true, false, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+
+ return rc;
+}
+
+static int get_hex_fw_ver(u8 *p, u8 *ttspver_hi, u8 *ttspver_lo,
+ u8 *appid_hi, u8 *appid_lo, u8 *appver_hi,
+ u8 *appver_lo, u8 *cid_0, u8 *cid_1, u8 *cid_2)
+{
+ int rc;
+
+ p = p + ID_INFO_OFFSET_IN_REC;
+ rc = str2uc(p, ttspver_hi);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, ttspver_lo);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, appid_hi);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, appid_lo);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, appver_hi);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, appver_lo);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, cid_0);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, cid_1);
+ if (rc < 0)
+ return rc;
+ p += 2;
+ rc = str2uc(p, cid_2);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static void cyttspfw_flash_start(struct cyttsp *ts, const u8 *data,
+ int data_len, u8 *buf, bool force)
+{
+ int rc;
+ u8 ttspver_hi = 0, ttspver_lo = 0, fw_upgrade = 0;
+ u8 appid_hi = 0, appid_lo = 0;
+ u8 appver_hi = 0, appver_lo = 0;
+ u8 cid_0 = 0, cid_1 = 0, cid_2 = 0;
+ char *p = buf;
+
+ /* get hex firmware version */
+ rc = get_hex_fw_ver(p, &ttspver_hi, &ttspver_lo,
+ &appid_hi, &appid_lo, &appver_hi,
+ &appver_lo, &cid_0, &cid_1, &cid_2);
+
+ if (rc < 0) {
+ pr_err("%s: unable to get hex firmware version\n", __func__);
+ return;
+ }
+
+ /* disable interrupts before flashing */
+ if (ts->client->irq == 0)
+ del_timer(&ts->timer);
+ else
+ disable_irq(ts->client->irq);
+
+ /* enter bootloader idle mode */
+ rc = cyttsp_soft_reset(ts);
+
+ if (rc < 0) {
+ pr_err("%s: try entering into idle mode"
+ " second time\n", __func__);
+ msleep(1000);
+ rc = cyttsp_soft_reset(ts);
+ }
+
+ if (rc < 0) {
+ pr_err("%s: try again later\n", __func__);
+ return;
+ }
+
+
+ pr_info("Current firmware: %d.%d.%d", g_bl_data.appid_lo,
+ g_bl_data.appver_hi, g_bl_data.appver_lo);
+ pr_info("New firmware: %d.%d.%d", appid_lo, appver_hi, appver_lo);
+
+ if (force)
+ fw_upgrade = 1;
+ else if (!(g_bl_data.bl_status & BL_CHECKSUM_MASK) &&
+ (appid_lo == ts->platform_data->correct_fw_ver))
+ fw_upgrade = 1;
+ else if ((appid_hi == g_bl_data.appid_hi) &&
+ (appid_lo == g_bl_data.appid_lo))
+ if (appver_hi > g_bl_data.appver_hi)
+ fw_upgrade = 1;
+ else if ((appver_hi == g_bl_data.appver_hi) &&
+ (appver_lo > g_bl_data.appver_lo))
+ fw_upgrade = 1;
+ else {
+ fw_upgrade = 0;
+ pr_info("%s: Firmware version "
+ "lesser/equal to existing firmware, "
+ "upgrade not needed\n", __func__);
+ }
+ else if (appid_lo == ts->platform_data->correct_fw_ver)
+ fw_upgrade = 1;
+ else {
+ fw_upgrade = 0;
+ pr_info("%s: Firmware versions do not match, "
+ "cannot upgrade\n", __func__);
+ }
+
+ if (fw_upgrade) {
+ pr_info("%s: Starting firmware upgrade\n", __func__);
+ rc = cyttspfw_flash_firmware(ts, data, data_len);
+ if (rc < 0)
+ pr_err("%s: firmware upgrade failed\n", __func__);
+ else
+ pr_info("%s: firmware upgrade success\n", __func__);
+ }
+
+ /* enter bootloader idle mode */
+ cyttsp_soft_reset(ts);
+ /* exit bootloader mode */
+ cyttsp_exit_bl_mode(ts);
+ msleep(100);
+ /* set sysinfo details */
+ cyttsp_set_sysinfo_mode(ts);
+ /* enter application mode */
+ cyttsp_set_opmode(ts);
+
+ /* enable interrupts */
+ if (ts->client->irq == 0)
+ mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
+ else
+ enable_irq(ts->client->irq);
+}
+
+static void cyttspfw_upgrade_start(struct cyttsp *ts, const u8 *data,
+ int data_len, bool force)
+{
+ int i, j;
+ u8 *buf;
+
+ buf = kzalloc(REC_LINE_SIZE + 1, GFP_KERNEL);
+ if (!buf) {
+ pr_err("%s: no memory\n", __func__);
+ return;
+ }
+
+ for (i = 0, j = 0; i < data_len; i++, j++) {
+ if ((data[i] == REC_START_CHR) && j) {
+ buf[j] = 0;
+ j = 0;
+ if (!strncmp(buf, ID_INFO_REC,
+ strnlen(ID_INFO_REC, ID_INFO_REC_LEN))) {
+ cyttspfw_flash_start(ts, data, data_len,
+ buf, force);
+ break;
+ }
+ }
+ buf[j] = data[i];
+ }
+
+ /* check in the last record of firmware */
+ if (j) {
+ buf[j] = 0;
+ if (!strncmp(buf, ID_INFO_REC,
+ strnlen(ID_INFO_REC, ID_INFO_REC_LEN))) {
+ cyttspfw_flash_start(ts, data, data_len,
+ buf, force);
+ }
+ }
+
+ kfree(buf);
+}
+
+static void cyttspfw_upgrade(struct device *dev, bool force)
+{
+ struct cyttsp *ts = dev_get_drvdata(dev);
+ const struct firmware *cyttsp_fw;
+ int retval = 0;
+
+ if (ts->is_suspended == true) {
+ pr_err("%s: in suspend state, resume it\n", __func__);
+ retval = cyttsp_resume(dev);
+ if (retval < 0) {
+ pr_err("%s: unable to resume\n", __func__);
+ return;
+ }
+ }
+
+ retval = request_firmware(&cyttsp_fw, ts->fw_fname, dev);
+ if (retval < 0) {
+ pr_err("%s: %s request failed(%d)\n", __func__,
+ ts->fw_fname, retval);
+ } else {
+ /* check and start upgrade */
+ cyttspfw_upgrade_start(ts, cyttsp_fw->data,
+ cyttsp_fw->size, force);
+ release_firmware(cyttsp_fw);
+ }
+}
+
+static ssize_t cyttsp_update_fw_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cyttsp *ts = dev_get_drvdata(dev);
+ return snprintf(buf, 2, "%d\n", ts->cyttsp_fwloader_mode);
+}
+
+static ssize_t cyttsp_force_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct cyttsp *ts = dev_get_drvdata(dev);
+ unsigned long val;
+ int rc;
+
+ if (size > 2)
+ return -EINVAL;
+
+ rc = strict_strtoul(buf, 10, &val);
+ if (rc != 0)
+ return rc;
+
+ mutex_lock(&ts->mutex);
+ if (!ts->cyttsp_fwloader_mode && val) {
+ ts->cyttsp_fwloader_mode = 1;
+ cyttspfw_upgrade(dev, true);
+ ts->cyttsp_fwloader_mode = 0;
+ }
+ mutex_unlock(&ts->mutex);
+ return size;
+}
+
+static DEVICE_ATTR(cyttsp_force_update_fw, 0664, cyttsp_update_fw_show,
+ cyttsp_force_update_fw_store);
+
+static ssize_t cyttsp_update_fw_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct cyttsp *ts = dev_get_drvdata(dev);
+ unsigned long val;
+ int rc;
+
+ if (size > 2)
+ return -EINVAL;
+
+ rc = strict_strtoul(buf, 10, &val);
+ if (rc != 0)
+ return rc;
+
+ mutex_lock(&ts->mutex);
+ if (!ts->cyttsp_fwloader_mode && val) {
+ ts->cyttsp_fwloader_mode = 1;
+ cyttspfw_upgrade(dev, false);
+ ts->cyttsp_fwloader_mode = 0;
+ }
+ mutex_unlock(&ts->mutex);
+
+ return size;
+}
+
+static DEVICE_ATTR(cyttsp_update_fw, 0664, cyttsp_update_fw_show,
+ cyttsp_update_fw_store);
+
+static ssize_t cyttsp_fw_name_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct cyttsp *ts = dev_get_drvdata(dev);
+ return snprintf(buf, FW_FNAME_LEN - 1, "%s\n", ts->fw_fname);
+}
+
+static ssize_t cyttsp_fw_name_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct cyttsp *ts = dev_get_drvdata(dev);
+
+ if (size > FW_FNAME_LEN - 1)
+ return -EINVAL;
+
+ strlcpy(ts->fw_fname, buf, size);
+ if (ts->fw_fname[size-1] == '\n')
+ ts->fw_fname[size-1] = 0;
+
+ return size;
+}
+
+static DEVICE_ATTR(cyttsp_fw_name, 0664, cyttsp_fw_name_show,
+ cyttsp_fw_name_store);
+
+static void cyttsp_xy_handler(struct cyttsp *ts)
+{
+ u8 id, tilt, rev_x, rev_y;
+ u8 i, loc;
+ u8 prv_tch; /* number of previous touches */
+ u8 cur_tch; /* number of current touches */
+ u16 tmp_trk[CY_NUM_MT_TCH_ID];
+ u16 snd_trk[CY_NUM_MT_TCH_ID];
+ u16 cur_trk[CY_NUM_TRK_ID];
+ u16 cur_st_tch[CY_NUM_ST_TCH_ID];
+ u16 cur_mt_tch[CY_NUM_MT_TCH_ID];
+ /* if NOT CY_USE_TRACKING_ID then
+ * only uses CY_NUM_MT_TCH_ID positions */
+ u16 cur_mt_pos[CY_NUM_TRK_ID][2];
+ /* if NOT CY_USE_TRACKING_ID then
+ * only uses CY_NUM_MT_TCH_ID positions */
+ u8 cur_mt_z[CY_NUM_TRK_ID];
+ u8 curr_tool_width;
+ u16 st_x1, st_y1;
+ u8 st_z1;
+ u16 st_x2, st_y2;
+ u8 st_z2;
+ s32 retval;
+ int val;
+
+ cyttsp_xdebug("TTSP handler start 1:\n");
+
+ /* get event data from CYTTSP device */
+ i = CY_NUM_RETRY;
+ do {
+ retval = i2c_smbus_read_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ sizeof(struct cyttsp_gen3_xydata_t), (u8 *)&g_xy_data);
+ } while ((retval < CY_OK) && --i);
+
+ if (retval < CY_OK) {
+ /* return immediately on
+ * failure to read device on the i2c bus */
+ goto exit_xy_handler;
+ }
+
+ cyttsp_xdebug("TTSP handler start 2:\n");
+
+ /* compare own irq counter with the device irq counter */
+ if (ts->client->irq) {
+ u8 host_reg;
+ u8 cur_cnt;
+ if (ts->platform_data->use_hndshk) {
+
+ host_reg = g_xy_data.hst_mode & CY_HNDSHK_BIT ?
+ g_xy_data.hst_mode & ~CY_HNDSHK_BIT :
+ g_xy_data.hst_mode | CY_HNDSHK_BIT;
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(host_reg), &host_reg);
+ }
+ cur_cnt = g_xy_data.tt_undef[CY_IRQ_CNT_REG];
+ irq_cnt_total++;
+ irq_cnt++;
+ if (irq_cnt != cur_cnt) {
+ irq_err_cnt++;
+ cyttsp_debug("i_c_ER: dv=%d fw=%d hm=%02X t=%lu te=%lu\n", \
+ irq_cnt, \
+ cur_cnt, g_xy_data.hst_mode, \
+ (unsigned long)irq_cnt_total, \
+ (unsigned long)irq_err_cnt);
+ } else {
+ cyttsp_debug("i_c_ok: dv=%d fw=%d hm=%02X t=%lu te=%lu\n", \
+ irq_cnt, \
+ cur_cnt, g_xy_data.hst_mode, \
+ (unsigned long)irq_cnt_total, \
+ (unsigned long)irq_err_cnt);
+ }
+ irq_cnt = cur_cnt;
+ }
+
+ /* Get the current num touches and return if there are no touches */
+ if ((GET_BOOTLOADERMODE(g_xy_data.tt_mode) == 1) ||
+ (GET_HSTMODE(g_xy_data.hst_mode) != CY_OK)) {
+ u8 host_reg, tries;
+ /* the TTSP device has suffered spurious reset or mode switch */
+ cyttsp_debug( \
+ "Spurious err opmode (tt_mode=%02X hst_mode=%02X)\n", \
+ g_xy_data.tt_mode, g_xy_data.hst_mode);
+ cyttsp_debug("Reset TTSP Device; Terminating active tracks\n");
+ /* terminate all active tracks */
+ cur_tch = CY_NTCH;
+ /* reset TTSP part and take it back out of Bootloader mode */
+ /* reset TTSP Device back to bootloader mode */
+ host_reg = CY_SOFT_RESET_MODE;
+ retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
+ sizeof(host_reg), &host_reg);
+ /* wait for TTSP Device to complete reset back to bootloader */
+ tries = 0;
+ do {
+ usleep_range(1000, 1000);
+ cyttsp_putbl(ts, 1, false, false, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+ retval = cyttsp_putbl(ts, 1, true, true, true);
+ /* switch back to operational mode */
+ /* take TTSP device out of bootloader mode;
+ * switch back to TrueTouch operational mode */
+ if (!(retval < CY_OK)) {
+ int tries;
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ sizeof(bl_cmd), bl_cmd);
+ /* wait for TTSP Device to complete
+ * switch to Operational mode */
+ tries = 0;
+ do {
+ msleep(100);
+ cyttsp_putbl(ts, 2, false, false, false);
+ } while (GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
+ tries++ < 100);
+ cyttsp_putbl(ts, 2, true, false, false);
+ }
+ goto exit_xy_handler;
+ } else {
+ cur_tch = GET_NUM_TOUCHES(g_xy_data.tt_stat);
+ if (IS_LARGE_AREA(g_xy_data.tt_stat)) {
+ /* terminate all active tracks */
+ cur_tch = CY_NTCH;
+ cyttsp_debug("Large obj detect (tt_stat=0x%02X). Terminate act trks\n", \
+ g_xy_data.tt_stat);
+ } else if (cur_tch > CY_NUM_MT_TCH_ID) {
+ /* if the number of fingers on the touch surface
+ * is more than the maximum then
+ * there will be no new track information
+ * even for the original touches.
+ * Therefore, terminate all active tracks.
+ */
+ cur_tch = CY_NTCH;
+ cyttsp_debug("Num touch err (tt_stat=0x%02X). Terminate act trks\n", \
+ g_xy_data.tt_stat);
+ }
+ }
+
+ /* set tool size */
+ curr_tool_width = CY_SMALL_TOOL_WIDTH;
+
+ /* translate Gen2 interface data into comparable Gen3 data */
+ if (ts->platform_data->gen == CY_GEN2) {
+ struct cyttsp_gen2_xydata_t *pxy_gen2_data;
+ pxy_gen2_data = (struct cyttsp_gen2_xydata_t *)(&g_xy_data);
+
+ /* use test data? */
+ cyttsp_testdat(&g_xy_data, &tt_gen2_testray, \
+ sizeof(struct cyttsp_gen3_xydata_t));
+
+ if (ts->platform_data->disable_ghost_det &&
+ (cur_tch == CY_GEN2_GHOST))
+ cur_tch = CY_GEN2_2TOUCH;
+
+ if (pxy_gen2_data->evnt_idx == CY_GEN2_NOTOUCH) {
+ cur_tch = 0;
+ } else if (cur_tch == CY_GEN2_GHOST) {
+ cur_tch = 0;
+ } else if (cur_tch == CY_GEN2_2TOUCH) {
+ /* stuff artificial track ID1 and ID2 */
+ g_xy_data.touch12_id = 0x12;
+ g_xy_data.z1 = CY_MAXZ;
+ g_xy_data.z2 = CY_MAXZ;
+ cur_tch--; /* 2 touches */
+ } else if (cur_tch == CY_GEN2_1TOUCH) {
+ /* stuff artificial track ID1 and ID2 */
+ g_xy_data.touch12_id = 0x12;
+ g_xy_data.z1 = CY_MAXZ;
+ g_xy_data.z2 = CY_NTCH;
+ if (pxy_gen2_data->evnt_idx == CY_GEN2_TOUCH2) {
+ /* push touch 2 data into touch1
+ * (first finger up; second finger down) */
+ /* stuff artificial track ID1 for touch2 info */
+ g_xy_data.touch12_id = 0x20;
+ /* stuff touch 1 with touch 2 coordinate data */
+ g_xy_data.x1 = g_xy_data.x2;
+ g_xy_data.y1 = g_xy_data.y2;
+ }
+ } else {
+ cur_tch = 0;
+ }
+ } else {
+ /* use test data? */
+ cyttsp_testdat(&g_xy_data, &tt_gen3_testray, \
+ sizeof(struct cyttsp_gen3_xydata_t));
+ }
+
+
+
+ /* clear current active track ID array and count previous touches */
+ for (id = 0, prv_tch = CY_NTCH;
+ id < CY_NUM_TRK_ID; id++) {
+ cur_trk[id] = CY_NTCH;
+ prv_tch += ts->act_trk[id];
+ }
+
+ /* send no events if no previous touches and no new touches */
+ if ((prv_tch == CY_NTCH) &&
+ ((cur_tch == CY_NTCH) ||
+ (cur_tch > CY_NUM_MT_TCH_ID))) {
+ goto exit_xy_handler;
+ }
+
+ cyttsp_debug("prev=%d curr=%d\n", prv_tch, cur_tch);
+
+ for (id = 0; id < CY_NUM_ST_TCH_ID; id++) {
+ /* clear current single touches array */
+ cur_st_tch[id] = CY_IGNR_TCH;
+ }
+
+ /* clear single touch positions */
+ st_x1 = CY_NTCH;
+ st_y1 = CY_NTCH;
+ st_z1 = CY_NTCH;
+ st_x2 = CY_NTCH;
+ st_y2 = CY_NTCH;
+ st_z2 = CY_NTCH;
+
+ for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
+ /* clear current multi-touches array and
+ * multi-touch positions/z */
+ cur_mt_tch[id] = CY_IGNR_TCH;
+ }
+
+ if (ts->platform_data->use_trk_id) {
+ for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
+ cur_mt_pos[id][CY_XPOS] = 0;
+ cur_mt_pos[id][CY_YPOS] = 0;
+ cur_mt_z[id] = 0;
+ }
+ } else {
+ for (id = 0; id < CY_NUM_TRK_ID; id++) {
+ cur_mt_pos[id][CY_XPOS] = 0;
+ cur_mt_pos[id][CY_YPOS] = 0;
+ cur_mt_z[id] = 0;
+ }
+ }
+
+ /* Determine if display is tilted */
+ if (FLIP_DATA(ts->platform_data->flags))
+ tilt = true;
+ else
+ tilt = false;
+
+ /* Check for switch in origin */
+ if (REVERSE_X(ts->platform_data->flags))
+ rev_x = true;
+ else
+ rev_x = false;
+
+ if (REVERSE_Y(ts->platform_data->flags))
+ rev_y = true;
+ else
+ rev_y = false;
+
+ if (cur_tch) {
+ struct cyttsp_gen2_xydata_t *pxy_gen2_data;
+ struct cyttsp_gen3_xydata_t *pxy_gen3_data;
+ switch (ts->platform_data->gen) {
+ case CY_GEN2: {
+ pxy_gen2_data =
+ (struct cyttsp_gen2_xydata_t *)(&g_xy_data);
+ cyttsp_xdebug("TTSP Gen2 report:\n");
+ cyttsp_xdebug("%02X %02X %02X\n", \
+ pxy_gen2_data->hst_mode, \
+ pxy_gen2_data->tt_mode, \
+ pxy_gen2_data->tt_stat);
+ cyttsp_xdebug("%04X %04X %02X %02X\n", \
+ pxy_gen2_data->x1, \
+ pxy_gen2_data->y1, \
+ pxy_gen2_data->z1, \
+ pxy_gen2_data->evnt_idx);
+ cyttsp_xdebug("%04X %04X %02X\n", \
+ pxy_gen2_data->x2, \
+ pxy_gen2_data->y2, \
+ pxy_gen2_data->tt_undef1);
+ cyttsp_xdebug("%02X %02X %02X\n", \
+ pxy_gen2_data->gest_cnt, \
+ pxy_gen2_data->gest_id, \
+ pxy_gen2_data->gest_set);
+ break;
+ }
+ case CY_GEN3:
+ default: {
+ pxy_gen3_data =
+ (struct cyttsp_gen3_xydata_t *)(&g_xy_data);
+ cyttsp_xdebug("TTSP Gen3 report:\n");
+ cyttsp_xdebug("%02X %02X %02X\n", \
+ pxy_gen3_data->hst_mode,
+ pxy_gen3_data->tt_mode,
+ pxy_gen3_data->tt_stat);
+ cyttsp_xdebug("%04X %04X %02X %02X", \
+ pxy_gen3_data->x1,
+ pxy_gen3_data->y1,
+ pxy_gen3_data->z1, \
+ pxy_gen3_data->touch12_id);
+ cyttsp_xdebug("%04X %04X %02X\n", \
+ pxy_gen3_data->x2, \
+ pxy_gen3_data->y2, \
+ pxy_gen3_data->z2);
+ cyttsp_xdebug("%02X %02X %02X\n", \
+ pxy_gen3_data->gest_cnt, \
+ pxy_gen3_data->gest_id, \
+ pxy_gen3_data->gest_set);
+ cyttsp_xdebug("%04X %04X %02X %02X\n", \
+ pxy_gen3_data->x3, \
+ pxy_gen3_data->y3, \
+ pxy_gen3_data->z3, \
+ pxy_gen3_data->touch34_id);
+ cyttsp_xdebug("%04X %04X %02X\n", \
+ pxy_gen3_data->x4, \
+ pxy_gen3_data->y4, \
+ pxy_gen3_data->z4);
+ break;
+ }
+ }
+ }
+
+ /* process the touches */
+ switch (cur_tch) {
+ case 4: {
+ g_xy_data.x4 = be16_to_cpu(g_xy_data.x4);
+ g_xy_data.y4 = be16_to_cpu(g_xy_data.y4);
+ if (tilt)
+ FLIP_XY(g_xy_data.x4, g_xy_data.y4);
+
+ if (rev_x) {
+ val = INVERT_X(g_xy_data.x4,
+ ts->platform_data->panel_maxx);
+ if (val >= 0)
+ g_xy_data.x4 = val;
+ else
+ pr_debug("X value is negative. Please configure"
+ " maxx in platform data structure\n");
+ }
+ if (rev_y) {
+ val = INVERT_X(g_xy_data.y4,
+ ts->platform_data->panel_maxy);
+ if (val >= 0)
+ g_xy_data.y4 = val;
+ else
+ pr_debug("Y value is negative. Please configure"
+ " maxy in platform data structure\n");
+
+ }
+ id = GET_TOUCH4_ID(g_xy_data.touch34_id);
+ if (ts->platform_data->use_trk_id) {
+ cur_mt_pos[CY_MT_TCH4_IDX][CY_XPOS] =
+ g_xy_data.x4;
+ cur_mt_pos[CY_MT_TCH4_IDX][CY_YPOS] =
+ g_xy_data.y4;
+ cur_mt_z[CY_MT_TCH4_IDX] = g_xy_data.z4;
+ } else {
+ cur_mt_pos[id][CY_XPOS] = g_xy_data.x4;
+ cur_mt_pos[id][CY_YPOS] = g_xy_data.y4;
+ cur_mt_z[id] = g_xy_data.z4;
+ }
+ cur_mt_tch[CY_MT_TCH4_IDX] = id;
+ cur_trk[id] = CY_TCH;
+ if (ts->prv_st_tch[CY_ST_FNGR1_IDX] <
+ CY_NUM_TRK_ID) {
+ if (ts->prv_st_tch[CY_ST_FNGR1_IDX] == id) {
+ st_x1 = g_xy_data.x4;
+ st_y1 = g_xy_data.y4;
+ st_z1 = g_xy_data.z4;
+ cur_st_tch[CY_ST_FNGR1_IDX] = id;
+ } else if (ts->prv_st_tch[CY_ST_FNGR2_IDX] == id) {
+ st_x2 = g_xy_data.x4;
+ st_y2 = g_xy_data.y4;
+ st_z2 = g_xy_data.z4;
+ cur_st_tch[CY_ST_FNGR2_IDX] = id;
+ }
+ }
+ cyttsp_xdebug("4th XYZ:% 3d,% 3d,% 3d ID:% 2d\n\n", \
+ g_xy_data.x4, g_xy_data.y4, g_xy_data.z4, \
+ (g_xy_data.touch34_id & 0x0F));
+ /* do not break */
+ }
+ case 3: {
+ g_xy_data.x3 = be16_to_cpu(g_xy_data.x3);
+ g_xy_data.y3 = be16_to_cpu(g_xy_data.y3);
+ if (tilt)
+ FLIP_XY(g_xy_data.x3, g_xy_data.y3);
+
+ if (rev_x) {
+ val = INVERT_X(g_xy_data.x3,
+ ts->platform_data->panel_maxx);
+ if (val >= 0)
+ g_xy_data.x3 = val;
+ else
+ pr_debug("X value is negative. Please configure"
+ " maxx in platform data structure\n");
+
+ }
+ if (rev_y) {
+ val = INVERT_X(g_xy_data.y3,
+ ts->platform_data->panel_maxy);
+ if (val >= 0)
+ g_xy_data.y3 = val;
+ else
+ pr_debug("Y value is negative. Please configure"
+ " maxy in platform data structure\n");
+
+ }
+ id = GET_TOUCH3_ID(g_xy_data.touch34_id);
+ if (ts->platform_data->use_trk_id) {
+ cur_mt_pos[CY_MT_TCH3_IDX][CY_XPOS] =
+ g_xy_data.x3;
+ cur_mt_pos[CY_MT_TCH3_IDX][CY_YPOS] =
+ g_xy_data.y3;
+ cur_mt_z[CY_MT_TCH3_IDX] = g_xy_data.z3;
+ } else {
+ cur_mt_pos[id][CY_XPOS] = g_xy_data.x3;
+ cur_mt_pos[id][CY_YPOS] = g_xy_data.y3;
+ cur_mt_z[id] = g_xy_data.z3;
+ }
+ cur_mt_tch[CY_MT_TCH3_IDX] = id;
+ cur_trk[id] = CY_TCH;
+ if (ts->prv_st_tch[CY_ST_FNGR1_IDX] <
+ CY_NUM_TRK_ID) {
+ if (ts->prv_st_tch[CY_ST_FNGR1_IDX] == id) {
+ st_x1 = g_xy_data.x3;
+ st_y1 = g_xy_data.y3;
+ st_z1 = g_xy_data.z3;
+ cur_st_tch[CY_ST_FNGR1_IDX] = id;
+ } else if (ts->prv_st_tch[CY_ST_FNGR2_IDX] == id) {
+ st_x2 = g_xy_data.x3;
+ st_y2 = g_xy_data.y3;
+ st_z2 = g_xy_data.z3;
+ cur_st_tch[CY_ST_FNGR2_IDX] = id;
+ }
+ }
+ cyttsp_xdebug("3rd XYZ:% 3d,% 3d,% 3d ID:% 2d\n", \
+ g_xy_data.x3, g_xy_data.y3, g_xy_data.z3, \
+ ((g_xy_data.touch34_id >> 4) & 0x0F));
+ /* do not break */
+ }
+ case 2: {
+ g_xy_data.x2 = be16_to_cpu(g_xy_data.x2);
+ g_xy_data.y2 = be16_to_cpu(g_xy_data.y2);
+ if (tilt)
+ FLIP_XY(g_xy_data.x2, g_xy_data.y2);
+
+ if (rev_x) {
+ val = INVERT_X(g_xy_data.x2,
+ ts->platform_data->panel_maxx);
+ if (val >= 0)
+ g_xy_data.x2 = val;
+ else
+ pr_debug("X value is negative. Please configure"
+ " maxx in platform data structure\n");
+ }
+ if (rev_y) {
+ val = INVERT_X(g_xy_data.y2,
+ ts->platform_data->panel_maxy);
+ if (val >= 0)
+ g_xy_data.y2 = val;
+ else
+ pr_debug("Y value is negative. Please configure"
+ " maxy in platform data structure\n");
+ }
+ id = GET_TOUCH2_ID(g_xy_data.touch12_id);
+ if (ts->platform_data->use_trk_id) {
+ cur_mt_pos[CY_MT_TCH2_IDX][CY_XPOS] =
+ g_xy_data.x2;
+ cur_mt_pos[CY_MT_TCH2_IDX][CY_YPOS] =
+ g_xy_data.y2;
+ cur_mt_z[CY_MT_TCH2_IDX] = g_xy_data.z2;
+ } else {
+ cur_mt_pos[id][CY_XPOS] = g_xy_data.x2;
+ cur_mt_pos[id][CY_YPOS] = g_xy_data.y2;
+ cur_mt_z[id] = g_xy_data.z2;
+ }
+ cur_mt_tch[CY_MT_TCH2_IDX] = id;
+ cur_trk[id] = CY_TCH;
+ if (ts->prv_st_tch[CY_ST_FNGR1_IDX] <
+ CY_NUM_TRK_ID) {
+ if (ts->prv_st_tch[CY_ST_FNGR1_IDX] == id) {
+ st_x1 = g_xy_data.x2;
+ st_y1 = g_xy_data.y2;
+ st_z1 = g_xy_data.z2;
+ cur_st_tch[CY_ST_FNGR1_IDX] = id;
+ } else if (ts->prv_st_tch[CY_ST_FNGR2_IDX] == id) {
+ st_x2 = g_xy_data.x2;
+ st_y2 = g_xy_data.y2;
+ st_z2 = g_xy_data.z2;
+ cur_st_tch[CY_ST_FNGR2_IDX] = id;
+ }
+ }
+ cyttsp_xdebug("2nd XYZ:% 3d,% 3d,% 3d ID:% 2d\n", \
+ g_xy_data.x2, g_xy_data.y2, g_xy_data.z2, \
+ (g_xy_data.touch12_id & 0x0F));
+ /* do not break */
+ }
+ case 1: {
+ g_xy_data.x1 = be16_to_cpu(g_xy_data.x1);
+ g_xy_data.y1 = be16_to_cpu(g_xy_data.y1);
+ if (tilt)
+ FLIP_XY(g_xy_data.x1, g_xy_data.y1);
+
+ if (rev_x) {
+ val = INVERT_X(g_xy_data.x1,
+ ts->platform_data->panel_maxx);
+ if (val >= 0)
+ g_xy_data.x1 = val;
+ else
+ pr_debug("X value is negative. Please configure"
+ " maxx in platform data structure\n");
+ }
+ if (rev_y) {
+ val = INVERT_X(g_xy_data.y1,
+ ts->platform_data->panel_maxy);
+ if (val >= 0)
+ g_xy_data.y1 = val;
+ else
+ pr_debug("Y value is negative. Please configure"
+ " maxy in platform data structure");
+ }
+ id = GET_TOUCH1_ID(g_xy_data.touch12_id);
+ if (ts->platform_data->use_trk_id) {
+ cur_mt_pos[CY_MT_TCH1_IDX][CY_XPOS] =
+ g_xy_data.x1;
+ cur_mt_pos[CY_MT_TCH1_IDX][CY_YPOS] =
+ g_xy_data.y1;
+ cur_mt_z[CY_MT_TCH1_IDX] = g_xy_data.z1;
+ } else {
+ cur_mt_pos[id][CY_XPOS] = g_xy_data.x1;
+ cur_mt_pos[id][CY_YPOS] = g_xy_data.y1;
+ cur_mt_z[id] = g_xy_data.z1;
+ }
+ cur_mt_tch[CY_MT_TCH1_IDX] = id;
+ cur_trk[id] = CY_TCH;
+ if (ts->prv_st_tch[CY_ST_FNGR1_IDX] <
+ CY_NUM_TRK_ID) {
+ if (ts->prv_st_tch[CY_ST_FNGR1_IDX] == id) {
+ st_x1 = g_xy_data.x1;
+ st_y1 = g_xy_data.y1;
+ st_z1 = g_xy_data.z1;
+ cur_st_tch[CY_ST_FNGR1_IDX] = id;
+ } else if (ts->prv_st_tch[CY_ST_FNGR2_IDX] == id) {
+ st_x2 = g_xy_data.x1;
+ st_y2 = g_xy_data.y1;
+ st_z2 = g_xy_data.z1;
+ cur_st_tch[CY_ST_FNGR2_IDX] = id;
+ }
+ }
+ cyttsp_xdebug("1st XYZ:% 3d,% 3d,% 3d ID:% 2d\n", \
+ g_xy_data.x1, g_xy_data.y1, g_xy_data.z1, \
+ ((g_xy_data.touch12_id >> 4) & 0x0F));
+ break;
+ }
+ case 0:
+ default:{
+ break;
+ }
+ }
+
+ /* handle Single Touch signals */
+ if (ts->platform_data->use_st) {
+ cyttsp_xdebug("ST STEP 0 - ST1 ID=%d ST2 ID=%d\n", \
+ cur_st_tch[CY_ST_FNGR1_IDX], \
+ cur_st_tch[CY_ST_FNGR2_IDX]);
+ if (cur_st_tch[CY_ST_FNGR1_IDX] > CY_NUM_TRK_ID) {
+ /* reassign finger 1 and 2 positions to new tracks */
+ if (cur_tch > 0) {
+ /* reassign st finger1 */
+ if (ts->platform_data->use_trk_id) {
+ id = CY_MT_TCH1_IDX;
+ cur_st_tch[CY_ST_FNGR1_IDX] = cur_mt_tch[id];
+ } else {
+ id = GET_TOUCH1_ID(g_xy_data.touch12_id);
+ cur_st_tch[CY_ST_FNGR1_IDX] = id;
+ }
+ st_x1 = cur_mt_pos[id][CY_XPOS];
+ st_y1 = cur_mt_pos[id][CY_YPOS];
+ st_z1 = cur_mt_z[id];
+ cyttsp_xdebug("ST STEP 1 - ST1 ID=%3d\n", \
+ cur_st_tch[CY_ST_FNGR1_IDX]);
+ if ((cur_tch > 1) &&
+ (cur_st_tch[CY_ST_FNGR2_IDX] >
+ CY_NUM_TRK_ID)) {
+ /* reassign st finger2 */
+ if (cur_tch > 1) {
+ if (ts->platform_data->use_trk_id) {
+ id = CY_MT_TCH2_IDX;
+ cur_st_tch[CY_ST_FNGR2_IDX] = cur_mt_tch[id];
+ } else {
+ id = GET_TOUCH2_ID(g_xy_data.touch12_id);
+ cur_st_tch[CY_ST_FNGR2_IDX] = id;
+ }
+ st_x2 = cur_mt_pos[id][CY_XPOS];
+ st_y2 = cur_mt_pos[id][CY_YPOS];
+ st_z2 = cur_mt_z[id];
+ cyttsp_xdebug("ST STEP 2 - ST2 ID=%3d\n", \
+ cur_st_tch[CY_ST_FNGR2_IDX]);
+ }
+ }
+ }
+ } else if (cur_st_tch[CY_ST_FNGR2_IDX] > CY_NUM_TRK_ID) {
+ if (cur_tch > 1) {
+ /* reassign st finger2 */
+ if (ts->platform_data->use_trk_id) {
+ /* reassign st finger2 */
+ id = CY_MT_TCH2_IDX;
+ cur_st_tch[CY_ST_FNGR2_IDX] =
+ cur_mt_tch[id];
+ } else {
+ /* reassign st finger2 */
+ id = GET_TOUCH2_ID(g_xy_data.touch12_id);
+ cur_st_tch[CY_ST_FNGR2_IDX] = id;
+ }
+ st_x2 = cur_mt_pos[id][CY_XPOS];
+ st_y2 = cur_mt_pos[id][CY_YPOS];
+ st_z2 = cur_mt_z[id];
+ cyttsp_xdebug("ST STEP 3 - ST2 ID=%3d\n", \
+ cur_st_tch[CY_ST_FNGR2_IDX]);
+ }
+ }
+ /* if the 1st touch is missing and there is a 2nd touch,
+ * then set the 1st touch to 2nd touch and terminate 2nd touch
+ */
+ if ((cur_st_tch[CY_ST_FNGR1_IDX] > CY_NUM_TRK_ID) &&
+ (cur_st_tch[CY_ST_FNGR2_IDX] < CY_NUM_TRK_ID)) {
+ st_x1 = st_x2;
+ st_y1 = st_y2;
+ st_z1 = st_z2;
+ cur_st_tch[CY_ST_FNGR1_IDX] =
+ cur_st_tch[CY_ST_FNGR2_IDX];
+ cur_st_tch[CY_ST_FNGR2_IDX] =
+ CY_IGNR_TCH;
+ }
+ /* if the 2nd touch ends up equal to the 1st touch,
+ * then just report a single touch */
+ if (cur_st_tch[CY_ST_FNGR1_IDX] ==
+ cur_st_tch[CY_ST_FNGR2_IDX]) {
+ cur_st_tch[CY_ST_FNGR2_IDX] =
+ CY_IGNR_TCH;
+ }
+ /* set Single Touch current event signals */
+ if (cur_st_tch[CY_ST_FNGR1_IDX] < CY_NUM_TRK_ID) {
+ input_report_abs(ts->input,
+ ABS_X, st_x1);
+ input_report_abs(ts->input,
+ ABS_Y, st_y1);
+ input_report_abs(ts->input,
+ ABS_PRESSURE, st_z1);
+ input_report_key(ts->input,
+ BTN_TOUCH,
+ CY_TCH);
+ input_report_abs(ts->input,
+ ABS_TOOL_WIDTH,
+ curr_tool_width);
+ cyttsp_debug("ST->F1:%3d X:%3d Y:%3d Z:%3d\n", \
+ cur_st_tch[CY_ST_FNGR1_IDX], \
+ st_x1, st_y1, st_z1);
+ if (cur_st_tch[CY_ST_FNGR2_IDX] < CY_NUM_TRK_ID) {
+ input_report_key(ts->input, BTN_2, CY_TCH);
+ input_report_abs(ts->input, ABS_HAT0X, st_x2);
+ input_report_abs(ts->input, ABS_HAT0Y, st_y2);
+ cyttsp_debug("ST->F2:%3d X:%3d Y:%3d Z:%3d\n", \
+ cur_st_tch[CY_ST_FNGR2_IDX],
+ st_x2, st_y2, st_z2);
+ } else {
+ input_report_key(ts->input,
+ BTN_2,
+ CY_NTCH);
+ }
+ } else {
+ input_report_abs(ts->input, ABS_PRESSURE, CY_NTCH);
+ input_report_key(ts->input, BTN_TOUCH, CY_NTCH);
+ input_report_key(ts->input, BTN_2, CY_NTCH);
+ }
+ /* update platform data for the current single touch info */
+ ts->prv_st_tch[CY_ST_FNGR1_IDX] = cur_st_tch[CY_ST_FNGR1_IDX];
+ ts->prv_st_tch[CY_ST_FNGR2_IDX] = cur_st_tch[CY_ST_FNGR2_IDX];
+
+ }
+
+ /* handle Multi-touch signals */
+ if (ts->platform_data->use_mt) {
+ if (ts->platform_data->use_trk_id) {
+ /* terminate any previous touch where the track
+ * is missing from the current event */
+ for (id = 0; id < CY_NUM_TRK_ID; id++) {
+ if ((ts->act_trk[id] != CY_NTCH) &&
+ (cur_trk[id] == CY_NTCH)) {
+ input_report_abs(ts->input,
+ ABS_MT_TRACKING_ID,
+ id);
+ input_report_abs(ts->input,
+ ABS_MT_TOUCH_MAJOR,
+ CY_NTCH);
+ input_report_abs(ts->input,
+ ABS_MT_WIDTH_MAJOR,
+ curr_tool_width);
+ input_report_abs(ts->input,
+ ABS_MT_POSITION_X,
+ ts->prv_mt_pos[id][CY_XPOS]);
+ input_report_abs(ts->input,
+ ABS_MT_POSITION_Y,
+ ts->prv_mt_pos[id][CY_YPOS]);
+ CY_MT_SYNC(ts->input);
+ ts->act_trk[id] = CY_NTCH;
+ ts->prv_mt_pos[id][CY_XPOS] = 0;
+ ts->prv_mt_pos[id][CY_YPOS] = 0;
+ }
+ }
+ /* set Multi-Touch current event signals */
+ for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
+ if (cur_mt_tch[id] < CY_NUM_TRK_ID) {
+ input_report_abs(ts->input,
+ ABS_MT_TRACKING_ID,
+ cur_mt_tch[id]);
+ input_report_abs(ts->input,
+ ABS_MT_TOUCH_MAJOR,
+ cur_mt_z[id]);
+ input_report_abs(ts->input,
+ ABS_MT_WIDTH_MAJOR,
+ curr_tool_width);
+ input_report_abs(ts->input,
+ ABS_MT_POSITION_X,
+ cur_mt_pos[id][CY_XPOS]);
+ input_report_abs(ts->input,
+ ABS_MT_POSITION_Y,
+ cur_mt_pos[id][CY_YPOS]);
+ CY_MT_SYNC(ts->input);
+ ts->act_trk[id] = CY_TCH;
+ ts->prv_mt_pos[id][CY_XPOS] =
+ cur_mt_pos[id][CY_XPOS];
+ ts->prv_mt_pos[id][CY_YPOS] =
+ cur_mt_pos[id][CY_YPOS];
+ }
+ }
+ } else {
+ /* set temporary track array elements to voids */
+ for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
+ tmp_trk[id] = CY_IGNR_TCH;
+ snd_trk[id] = CY_IGNR_TCH;
+ }
+
+ /* get what is currently active */
+ for (i = 0, id = 0;
+ id < CY_NUM_TRK_ID && i < CY_NUM_MT_TCH_ID;
+ id++) {
+ if (cur_trk[id] == CY_TCH) {
+ /* only incr counter if track found */
+ tmp_trk[i] = id;
+ i++;
+ }
+ }
+ cyttsp_xdebug("T1: t0=%d, t1=%d, t2=%d, t3=%d\n", \
+ tmp_trk[0], tmp_trk[1], tmp_trk[2], \
+ tmp_trk[3]);
+ cyttsp_xdebug("T1: p0=%d, p1=%d, p2=%d, p3=%d\n", \
+ ts->prv_mt_tch[0], ts->prv_mt_tch[1], \
+ ts->prv_mt_tch[2], ts->prv_mt_tch[3]);
+
+ /* pack in still active previous touches */
+ for (id = 0, prv_tch = 0;
+ id < CY_NUM_MT_TCH_ID; id++) {
+ if (tmp_trk[id] < CY_NUM_TRK_ID) {
+ if (cyttsp_inlist(ts->prv_mt_tch,
+ tmp_trk[id], &loc,
+ CY_NUM_MT_TCH_ID)) {
+ loc &= CY_NUM_MT_TCH_ID - 1;
+ snd_trk[loc] = tmp_trk[id];
+ prv_tch++;
+ cyttsp_xdebug("inlist s[%d]=%d t[%d]=%d l=%d p=%d\n", \
+ loc, snd_trk[loc], \
+ id, tmp_trk[id], \
+ loc, prv_tch);
+ } else {
+ cyttsp_xdebug("not inlist s[%d]=%d t[%d]=%d l=%d \n", \
+ id, snd_trk[id], \
+ id, tmp_trk[id], \
+ loc);
+ }
+ }
+ }
+ cyttsp_xdebug("S1: s0=%d, s1=%d, s2=%d, s3=%d p=%d\n", \
+ snd_trk[0], snd_trk[1], snd_trk[2], \
+ snd_trk[3], prv_tch);
+
+ /* pack in new touches */
+ for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
+ if (tmp_trk[id] < CY_NUM_TRK_ID) {
+ if (!cyttsp_inlist(snd_trk, tmp_trk[id], &loc, CY_NUM_MT_TCH_ID)) {
+ cyttsp_xdebug("not inlist t[%d]=%d l=%d\n", \
+ id, tmp_trk[id], loc);
+ if (cyttsp_next_avail_inlist(snd_trk, &loc, CY_NUM_MT_TCH_ID)) {
+ loc &= CY_NUM_MT_TCH_ID - 1;
+ snd_trk[loc] = tmp_trk[id];
+ cyttsp_xdebug("put inlist s[%d]=%d t[%d]=%d\n",
+ loc, snd_trk[loc], id, tmp_trk[id]);
+ }
+ } else {
+ cyttsp_xdebug("is in list s[%d]=%d t[%d]=%d loc=%d\n", \
+ id, snd_trk[id], id, tmp_trk[id], loc);
+ }
+ }
+ }
+ cyttsp_xdebug("S2: s0=%d, s1=%d, s2=%d, s3=%d\n", \
+ snd_trk[0], snd_trk[1],
+ snd_trk[2], snd_trk[3]);
+
+ /* sync motion event signals for each current touch */
+ for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
+ /* z will either be 0 (NOTOUCH) or
+ * some pressure (TOUCH) */
+ cyttsp_xdebug("MT0 prev[%d]=%d temp[%d]=%d send[%d]=%d\n", \
+ id, ts->prv_mt_tch[id], \
+ id, tmp_trk[id], \
+ id, snd_trk[id]);
+ if (snd_trk[id] < CY_NUM_TRK_ID) {
+ input_report_abs(ts->input,
+ ABS_MT_TOUCH_MAJOR,
+ cur_mt_z[snd_trk[id]]);
+ input_report_abs(ts->input,
+ ABS_MT_WIDTH_MAJOR,
+ curr_tool_width);
+ input_report_abs(ts->input,
+ ABS_MT_POSITION_X,
+ cur_mt_pos[snd_trk[id]][CY_XPOS]);
+ input_report_abs(ts->input,
+ ABS_MT_POSITION_Y,
+ cur_mt_pos[snd_trk[id]][CY_YPOS]);
+ CY_MT_SYNC(ts->input);
+ cyttsp_debug("MT1->TID:%2d X:%3d Y:%3d Z:%3d touch-sent\n", \
+ snd_trk[id], \
+ cur_mt_pos[snd_trk[id]][CY_XPOS], \
+ cur_mt_pos[snd_trk[id]][CY_YPOS], \
+ cur_mt_z[snd_trk[id]]);
+ } else if (ts->prv_mt_tch[id] < CY_NUM_TRK_ID) {
+ /* void out this touch */
+ input_report_abs(ts->input,
+ ABS_MT_TOUCH_MAJOR,
+ CY_NTCH);
+ input_report_abs(ts->input,
+ ABS_MT_WIDTH_MAJOR,
+ curr_tool_width);
+ input_report_abs(ts->input,
+ ABS_MT_POSITION_X,
+ ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_XPOS]);
+ input_report_abs(ts->input,
+ ABS_MT_POSITION_Y,
+ ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_YPOS]);
+ CY_MT_SYNC(ts->input);
+ cyttsp_debug("MT2->TID:%2d X:%3d Y:%3d Z:%3d lift off-sent\n", \
+ ts->prv_mt_tch[id], \
+ ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_XPOS], \
+ ts->prv_mt_pos[ts->prv_mt_tch[id]][CY_YPOS], \
+ CY_NTCH);
+ } else {
+ /* do not stuff any signals for this
+ * previously and currently
+ * void touches */
+ cyttsp_xdebug("MT3->send[%d]=%d - No touch - NOT sent\n", \
+ id, snd_trk[id]);
+ }
+ }
+
+ /* save current posted tracks to
+ * previous track memory */
+ for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
+ ts->prv_mt_tch[id] = snd_trk[id];
+ if (snd_trk[id] < CY_NUM_TRK_ID) {
+ ts->prv_mt_pos[snd_trk[id]][CY_XPOS] =
+ cur_mt_pos[snd_trk[id]][CY_XPOS];
+ ts->prv_mt_pos[snd_trk[id]][CY_YPOS] =
+ cur_mt_pos[snd_trk[id]][CY_YPOS];
+ cyttsp_xdebug("MT4->TID:%2d X:%3d Y:%3d Z:%3d save for previous\n", \
+ snd_trk[id], \
+ ts->prv_mt_pos[snd_trk[id]][CY_XPOS], \
+ ts->prv_mt_pos[snd_trk[id]][CY_YPOS], \
+ CY_NTCH);
+ }
+ }
+ for (id = 0; id < CY_NUM_TRK_ID; id++)
+ ts->act_trk[id] = CY_NTCH;
+ for (id = 0; id < CY_NUM_MT_TCH_ID; id++) {
+ if (snd_trk[id] < CY_NUM_TRK_ID)
+ ts->act_trk[snd_trk[id]] = CY_TCH;
+ }
+ }
+ }
+
+ /* handle gestures */
+ if (ts->platform_data->use_gestures) {
+ if (g_xy_data.gest_id) {
+ input_report_key(ts->input,
+ BTN_3, CY_TCH);
+ input_report_abs(ts->input,
+ ABS_HAT1X, g_xy_data.gest_id);
+ input_report_abs(ts->input,
+ ABS_HAT2Y, g_xy_data.gest_cnt);
+ }
+ }
+
+ /* signal the view motion event */
+ input_sync(ts->input);
+
+ for (id = 0; id < CY_NUM_TRK_ID; id++) {
+ /* update platform data for the current MT information */
+ ts->act_trk[id] = cur_trk[id];
+ }
+
+exit_xy_handler:
+ /* restart event timer */
+ if (ts->client->irq == 0)
+ mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
+ return;
+}
+
+static int cyttsp_inlist(u16 prev_track[], u8 cur_trk_id,
+ u8 *prev_loc, u8 num_touches)
+{
+ u8 id = 0;
+
+ *prev_loc = CY_IGNR_TCH;
+
+ cyttsp_xdebug("IN p[%d]=%d c=%d n=%d loc=%d\n", \
+ id, prev_track[id], cur_trk_id, \
+ num_touches, *prev_loc);
+ for (id = 0, *prev_loc = CY_IGNR_TCH;
+ (id < num_touches); id++) {
+ cyttsp_xdebug("p[%d]=%d c=%d n=%d loc=%d\n", \
+ id, prev_track[id], cur_trk_id, \
+ num_touches, *prev_loc);
+ if (prev_track[id] == cur_trk_id) {
+ *prev_loc = id;
+ break;
+ }
+ }
+ cyttsp_xdebug("OUT p[%d]=%d c=%d n=%d loc=%d\n", \
+ id, prev_track[id], cur_trk_id, num_touches, *prev_loc);
+
+ return ((*prev_loc < CY_NUM_TRK_ID) ? true : false);
+}
+
+static int cyttsp_next_avail_inlist(u16 cur_trk[],
+ u8 *new_loc, u8 num_touches)
+{
+ u8 id;
+
+ for (id = 0, *new_loc = CY_IGNR_TCH;
+ (id < num_touches); id++) {
+ if (cur_trk[id] > CY_NUM_TRK_ID) {
+ *new_loc = id;
+ break;
+ }
+ }
+
+ return ((*new_loc < CY_NUM_TRK_ID) ? true : false);
+}
+
+/* Timer function used as dummy interrupt driver */
+static void cyttsp_timer(unsigned long handle)
+{
+ struct cyttsp *ts = (struct cyttsp *) handle;
+
+ cyttsp_xdebug("TTSP Device timer event\n");
+
+ /* schedule motion signal handling */
+ cyttsp_xy_handler(ts);
+
+ return;
+}
+
+
+
+/* ************************************************************************
+ * ISR function. This function is general, initialized in drivers init
+ * function
+ * ************************************************************************ */
+static irqreturn_t cyttsp_irq(int irq, void *handle)
+{
+ struct cyttsp *ts = (struct cyttsp *) handle;
+
+ cyttsp_xdebug("%s: Got IRQ\n", CY_I2C_NAME);
+
+ cyttsp_xy_handler(ts);
+
+ return IRQ_HANDLED;
+}
+
+/* ************************************************************************
+ * Probe initialization functions
+ * ************************************************************************ */
+static int cyttsp_putbl(struct cyttsp *ts, int show,
+ int show_status, int show_version, int show_cid)
+{
+ int retval = CY_OK;
+
+ int num_bytes = (show_status * 3) + (show_version * 6) + (show_cid * 3);
+
+ if (show_cid)
+ num_bytes = sizeof(struct cyttsp_bootloader_data_t);
+ else if (show_version)
+ num_bytes = sizeof(struct cyttsp_bootloader_data_t) - 3;
+ else
+ num_bytes = sizeof(struct cyttsp_bootloader_data_t) - 9;
+
+ if (show) {
+ retval = i2c_smbus_read_i2c_block_data(ts->client,
+ CY_REG_BASE, num_bytes, (u8 *)&g_bl_data);
+ if (show_status) {
+ cyttsp_debug("BL%d: f=%02X s=%02X err=%02X bl=%02X%02X bld=%02X%02X\n", \
+ show, \
+ g_bl_data.bl_file, \
+ g_bl_data.bl_status, \
+ g_bl_data.bl_error, \
+ g_bl_data.blver_hi, g_bl_data.blver_lo, \
+ g_bl_data.bld_blver_hi, g_bl_data.bld_blver_lo);
+ }
+ if (show_version) {
+ cyttsp_debug("BL%d: ttspver=0x%02X%02X appid=0x%02X%02X appver=0x%02X%02X\n", \
+ show, \
+ g_bl_data.ttspver_hi, g_bl_data.ttspver_lo, \
+ g_bl_data.appid_hi, g_bl_data.appid_lo, \
+ g_bl_data.appver_hi, g_bl_data.appver_lo);
+ }
+ if (show_cid) {
+ cyttsp_debug("BL%d: cid=0x%02X%02X%02X\n", \
+ show, \
+ g_bl_data.cid_0, \
+ g_bl_data.cid_1, \
+ g_bl_data.cid_2);
+ }
+ }
+
+ return retval;
+}
+
+#ifdef CY_INCLUDE_LOAD_FILE
+#define CY_MAX_I2C_LEN 256
+#define CY_MAX_TRY 10
+#define CY_BL_PAGE_SIZE 16
+#define CY_BL_NUM_PAGES 5
+static int cyttsp_i2c_wr_blk_chunks(struct cyttsp *ts, u8 command,
+ u8 length, const u8 *values)
+{
+ int retval = CY_OK;
+ int block = 1;
+
+ u8 dataray[CY_MAX_I2C_LEN];
+
+ /* first page already includes the bl page offset */
+ retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
+ CY_BL_PAGE_SIZE+1, values);
+ values += CY_BL_PAGE_SIZE+1;
+ length -= CY_BL_PAGE_SIZE+1;
+
+ /* rem blocks require bl page offset stuffing */
+ while (length &&
+ (block < CY_BL_NUM_PAGES) &&
+ !(retval < CY_OK)) {
+ udelay(43*2); /* TRM * 2 */
+ dataray[0] = CY_BL_PAGE_SIZE*block;
+ memcpy(&dataray[1], values,
+ length >= CY_BL_PAGE_SIZE ?
+ CY_BL_PAGE_SIZE : length);
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ length >= CY_BL_PAGE_SIZE ?
+ CY_BL_PAGE_SIZE + 1 : length+1, dataray);
+ values += CY_BL_PAGE_SIZE;
+ length = length >= CY_BL_PAGE_SIZE ?
+ length - CY_BL_PAGE_SIZE : 0;
+ block++;
+ }
+
+ return retval;
+}
+
+static int cyttsp_bootload_app(struct cyttsp *ts)
+{
+ int retval = CY_OK;
+ int i, tries;
+ u8 host_reg;
+
+ cyttsp_debug("load new firmware \n");
+ /* reset TTSP Device back to bootloader mode */
+ host_reg = CY_SOFT_RESET_MODE;
+ retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
+ sizeof(host_reg), &host_reg);
+ /* wait for TTSP Device to complete reset back to bootloader */
+ tries = 0;
+ do {
+ usleep_range(1000, 1000);
+ cyttsp_putbl(ts, 3, false, false, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+ cyttsp_debug("load file - tver=0x%02X%02X a_id=0x%02X%02X aver=0x%02X%02X\n", \
+ cyttsp_fw_tts_verh, cyttsp_fw_tts_verl, \
+ cyttsp_fw_app_idh, cyttsp_fw_app_idl, \
+ cyttsp_fw_app_verh, cyttsp_fw_app_verl);
+
+ /* download new TTSP Application to the Bootloader */
+ if (!(retval < CY_OK)) {
+ i = 0;
+ /* send bootload initiation command */
+ if (cyttsp_fw[i].Command == CY_BL_INIT_LOAD) {
+ g_bl_data.bl_file = 0;
+ g_bl_data.bl_status = 0;
+ g_bl_data.bl_error = 0;
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ cyttsp_fw[i].Length, cyttsp_fw[i].Block);
+ /* delay to allow bl to get ready for block writes */
+ i++;
+ tries = 0;
+ do {
+ msleep(100);
+ cyttsp_putbl(ts, 4, false, false, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+ cyttsp_debug("wait init f=%02X, s=%02X, e=%02X t=%d\n", \
+ g_bl_data.bl_file, g_bl_data.bl_status, \
+ g_bl_data.bl_error, tries);
+ /* send bootload firmware load blocks */
+ if (!(retval < CY_OK)) {
+ while (cyttsp_fw[i].Command == CY_BL_WRITE_BLK) {
+ retval = cyttsp_i2c_wr_blk_chunks(ts,
+ CY_REG_BASE,
+ cyttsp_fw[i].Length,
+ cyttsp_fw[i].Block);
+ cyttsp_xdebug("BL DNLD Rec=% 3d Len=% 3d Addr=%04X\n", \
+ cyttsp_fw[i].Record, \
+ cyttsp_fw[i].Length, \
+ cyttsp_fw[i].Address);
+ i++;
+ if (retval < CY_OK) {
+ cyttsp_debug("BL fail Rec=%3d retval=%d\n", \
+ cyttsp_fw[i-1].Record, \
+ retval);
+ break;
+ } else {
+ tries = 0;
+ cyttsp_putbl(ts, 5, false, false, false);
+ while (!((g_bl_data.bl_status == 0x10) &&
+ (g_bl_data.bl_error == 0x20)) &&
+ !((g_bl_data.bl_status == 0x11) &&
+ (g_bl_data.bl_error == 0x20)) &&
+ (tries++ < 100)) {
+ usleep_range(1000, 1000);
+ cyttsp_putbl(ts, 5, false, false, false);
+ }
+ }
+ }
+
+ if (!(retval < CY_OK)) {
+ while (i < cyttsp_fw_records) {
+ retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
+ cyttsp_fw[i].Length,
+ cyttsp_fw[i].Block);
+ i++;
+ tries = 0;
+ do {
+ msleep(100);
+ cyttsp_putbl(ts, 6, true, false, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+ cyttsp_debug("wait term f=%02X, s=%02X, e=%02X t=%d\n", \
+ g_bl_data.bl_file, \
+ g_bl_data.bl_status, \
+ g_bl_data.bl_error, \
+ tries);
+ if (retval < CY_OK)
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* reset TTSP Device back to bootloader mode */
+ host_reg = CY_SOFT_RESET_MODE;
+ retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
+ sizeof(host_reg), &host_reg);
+ /* wait for TTSP Device to complete reset back to bootloader */
+ tries = 0;
+ do {
+ usleep_range(1000, 1000);
+ cyttsp_putbl(ts, 3, false, false, false);
+ } while (g_bl_data.bl_status != 0x10 &&
+ g_bl_data.bl_status != 0x11 &&
+ tries++ < 100);
+
+ /* set arg2 to non-0 to activate */
+ retval = cyttsp_putbl(ts, 8, true, true, true);
+
+ return retval;
+}
+#else
+static int cyttsp_bootload_app(struct cyttsp *ts)
+{
+ cyttsp_debug("no-load new firmware \n");
+ return CY_OK;
+}
+#endif /* CY_INCLUDE_LOAD_FILE */
+
+
+static int cyttsp_power_on(struct cyttsp *ts)
+{
+ int retval = CY_OK;
+ u8 host_reg;
+ int tries;
+
+ cyttsp_debug("Power up \n");
+
+ /* check if the TTSP device has a bootloader installed */
+ host_reg = CY_SOFT_RESET_MODE;
+ retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
+ sizeof(host_reg), &host_reg);
+ tries = 0;
+ do {
+ usleep_range(1000, 1000);
+
+ /* set arg2 to non-0 to activate */
+ retval = cyttsp_putbl(ts, 1, true, true, true);
+ cyttsp_info("BL%d: f=%02X s=%02X err=%02X bl=%02X%02X bld=%02X%02X R=%d\n", \
+ 101, \
+ g_bl_data.bl_file, g_bl_data.bl_status, \
+ g_bl_data.bl_error, \
+ g_bl_data.blver_hi, g_bl_data.blver_lo, \
+ g_bl_data.bld_blver_hi, g_bl_data.bld_blver_lo,
+ retval);
+ cyttsp_info("BL%d: tver=%02X%02X a_id=%02X%02X aver=%02X%02X\n", \
+ 102, \
+ g_bl_data.ttspver_hi, g_bl_data.ttspver_lo, \
+ g_bl_data.appid_hi, g_bl_data.appid_lo, \
+ g_bl_data.appver_hi, g_bl_data.appver_lo);
+ cyttsp_info("BL%d: c_id=%02X%02X%02X\n", \
+ 103, \
+ g_bl_data.cid_0, g_bl_data.cid_1, g_bl_data.cid_2);
+ } while (!(retval < CY_OK) &&
+ !GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
+ !(g_bl_data.bl_file == CY_OP_MODE + CY_LOW_PWR_MODE) &&
+ tries++ < 100);
+
+ /* is bootloader missing? */
+ if (!(retval < CY_OK)) {
+ cyttsp_xdebug("Ret=%d Check if bootloader is missing...\n", \
+ retval);
+ if (!GET_BOOTLOADERMODE(g_bl_data.bl_status)) {
+ /* skip all bl and sys info and go to op mode */
+ if (!(retval < CY_OK)) {
+ cyttsp_xdebug("Bl is missing (ret=%d)\n", \
+ retval);
+ host_reg = CY_OP_MODE/* + CY_LOW_PWR_MODE*/;
+ retval = i2c_smbus_write_i2c_block_data(ts->client, CY_REG_BASE,
+ sizeof(host_reg), &host_reg);
+ /* wait for TTSP Device to complete switch to
+ * Operational mode */
+ msleep(1000);
+ goto bypass;
+ }
+ }
+ }
+
+
+ /* take TTSP out of bootloader mode; go to TrueTouch operational mode */
+ if (!(retval < CY_OK)) {
+ cyttsp_xdebug1("exit bootloader; go operational\n");
+ tries = 0;
+ do {
+ msleep(100);
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(bl_cmd), bl_cmd);
+ if (retval == CY_OK)
+ break;
+ } while (tries++ < 5);
+
+ if (retval == CY_OK) {
+ tries = 0;
+ do {
+ msleep(100);
+ cyttsp_putbl(ts, 4, true, false, false);
+ cyttsp_info("BL%d: f=%02X s=%02X err=%02X" \
+ "bl=%02X%02X bld=%02X%02X\n", 104, \
+ g_bl_data.bl_file, \
+ g_bl_data.bl_status, \
+ g_bl_data.bl_error, \
+ g_bl_data.blver_hi, \
+ g_bl_data.blver_lo, \
+ g_bl_data.bld_blver_hi, \
+ g_bl_data.bld_blver_lo);
+ } while (GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
+ tries++ < 5);
+ }
+ }
+
+ if (!(retval < CY_OK) &&
+ cyttsp_app_load()) {
+ if (CY_DIFF(g_bl_data.ttspver_hi, cyttsp_tts_verh()) ||
+ CY_DIFF(g_bl_data.ttspver_lo, cyttsp_tts_verl()) ||
+ CY_DIFF(g_bl_data.appid_hi, cyttsp_app_idh()) ||
+ CY_DIFF(g_bl_data.appid_lo, cyttsp_app_idl()) ||
+ CY_DIFF(g_bl_data.appver_hi, cyttsp_app_verh()) ||
+ CY_DIFF(g_bl_data.appver_lo, cyttsp_app_verl()) ||
+ CY_DIFF(g_bl_data.cid_0, cyttsp_cid_0()) ||
+ CY_DIFF(g_bl_data.cid_1, cyttsp_cid_1()) ||
+ CY_DIFF(g_bl_data.cid_2, cyttsp_cid_2()) ||
+ cyttsp_force_fw_load()) {
+ cyttsp_debug("blttsp=0x%02X%02X flttsp=0x%02X%02X force=%d\n", \
+ g_bl_data.ttspver_hi, g_bl_data.ttspver_lo, \
+ cyttsp_tts_verh(), cyttsp_tts_verl(), \
+ cyttsp_force_fw_load());
+ cyttsp_debug("blappid=0x%02X%02X flappid=0x%02X%02X\n", \
+ g_bl_data.appid_hi, g_bl_data.appid_lo, \
+ cyttsp_app_idh(), cyttsp_app_idl());
+ cyttsp_debug("blappver=0x%02X%02X flappver=0x%02X%02X\n", \
+ g_bl_data.appver_hi, g_bl_data.appver_lo, \
+ cyttsp_app_verh(), cyttsp_app_verl());
+ cyttsp_debug("blcid=0x%02X%02X%02X flcid=0x%02X%02X%02X\n", \
+ g_bl_data.cid_0, \
+ g_bl_data.cid_1, \
+ g_bl_data.cid_2, \
+ cyttsp_cid_0(), \
+ cyttsp_cid_1(), \
+ cyttsp_cid_2());
+ /* enter bootloader to load new app into TTSP Device */
+ retval = cyttsp_bootload_app(ts);
+ /* take TTSP device out of bootloader mode;
+ * switch back to TrueTouch operational mode */
+ if (!(retval < CY_OK)) {
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ sizeof(bl_cmd), bl_cmd);
+ /* wait for TTSP Device to complete
+ * switch to Operational mode */
+ tries = 0;
+ do {
+ msleep(100);
+ cyttsp_putbl(ts, 9, false, false, false);
+ } while (GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
+ tries++ < 100);
+ cyttsp_putbl(ts, 9, true, false, false);
+ }
+ }
+ }
+
+bypass:
+ /* switch to System Information mode to read versions
+ * and set interval registers */
+ if (!(retval < CY_OK)) {
+ cyttsp_debug("switch to sysinfo mode \n");
+ host_reg = CY_SYSINFO_MODE;
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE, sizeof(host_reg), &host_reg);
+ /* wait for TTSP Device to complete switch to SysInfo mode */
+ msleep(100);
+ if (!(retval < CY_OK)) {
+ retval = i2c_smbus_read_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ sizeof(struct cyttsp_sysinfo_data_t),
+ (u8 *)&g_sysinfo_data);
+ cyttsp_debug("SI2: hst_mode=0x%02X mfg_cmd=0x%02X mfg_stat=0x%02X\n", \
+ g_sysinfo_data.hst_mode, \
+ g_sysinfo_data.mfg_cmd, \
+ g_sysinfo_data.mfg_stat);
+ cyttsp_debug("SI2: bl_ver=0x%02X%02X\n", \
+ g_sysinfo_data.bl_verh, \
+ g_sysinfo_data.bl_verl);
+ cyttsp_debug("SI2: sysinfo act_int=0x%02X tch_tmout=0x%02X lp_int=0x%02X\n", \
+ g_sysinfo_data.act_intrvl, \
+ g_sysinfo_data.tch_tmout, \
+ g_sysinfo_data.lp_intrvl);
+ cyttsp_info("SI%d: tver=%02X%02X a_id=%02X%02X aver=%02X%02X\n", \
+ 102, \
+ g_sysinfo_data.tts_verh, \
+ g_sysinfo_data.tts_verl, \
+ g_sysinfo_data.app_idh, \
+ g_sysinfo_data.app_idl, \
+ g_sysinfo_data.app_verh, \
+ g_sysinfo_data.app_verl);
+ cyttsp_info("SI%d: c_id=%02X%02X%02X\n", \
+ 103, \
+ g_sysinfo_data.cid[0], \
+ g_sysinfo_data.cid[1], \
+ g_sysinfo_data.cid[2]);
+ if (!(retval < CY_OK) &&
+ (CY_DIFF(ts->platform_data->act_intrvl,
+ CY_ACT_INTRVL_DFLT) ||
+ CY_DIFF(ts->platform_data->tch_tmout,
+ CY_TCH_TMOUT_DFLT) ||
+ CY_DIFF(ts->platform_data->lp_intrvl,
+ CY_LP_INTRVL_DFLT))) {
+ if (!(retval < CY_OK)) {
+ u8 intrvl_ray[sizeof(ts->platform_data->act_intrvl) +
+ sizeof(ts->platform_data->tch_tmout) +
+ sizeof(ts->platform_data->lp_intrvl)];
+ u8 i = 0;
+
+ intrvl_ray[i++] =
+ ts->platform_data->act_intrvl;
+ intrvl_ray[i++] =
+ ts->platform_data->tch_tmout;
+ intrvl_ray[i++] =
+ ts->platform_data->lp_intrvl;
+
+ cyttsp_debug("SI2: platinfo act_intrvl=0x%02X tch_tmout=0x%02X lp_intrvl=0x%02X\n", \
+ ts->platform_data->act_intrvl, \
+ ts->platform_data->tch_tmout, \
+ ts->platform_data->lp_intrvl);
+ /* set intrvl registers */
+ retval = i2c_smbus_write_i2c_block_data(
+ ts->client,
+ CY_REG_ACT_INTRVL,
+ sizeof(intrvl_ray), intrvl_ray);
+ msleep(CY_DLY_SYSINFO);
+ }
+ }
+ }
+ /* switch back to Operational mode */
+ cyttsp_debug("switch back to operational mode \n");
+ if (!(retval < CY_OK)) {
+ host_reg = CY_OP_MODE/* + CY_LOW_PWR_MODE*/;
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ sizeof(host_reg), &host_reg);
+ /* wait for TTSP Device to complete
+ * switch to Operational mode */
+ msleep(100);
+ }
+ }
+ /* init gesture setup;
+ * this is required even if not using gestures
+ * in order to set the active distance */
+ if (!(retval < CY_OK)) {
+ u8 gesture_setup;
+ cyttsp_debug("init gesture setup \n");
+ gesture_setup = ts->platform_data->gest_set;
+ retval = i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_GEST_SET,
+ sizeof(gesture_setup), &gesture_setup);
+ msleep(CY_DLY_DFLT);
+ }
+
+ if (!(retval < CY_OK))
+ ts->platform_data->power_state = CY_ACTIVE_STATE;
+ else
+ ts->platform_data->power_state = CY_IDLE_STATE;
+
+ cyttsp_debug("Retval=%d Power state is %s\n", \
+ retval, \
+ ts->platform_data->power_state == CY_ACTIVE_STATE ? \
+ "ACTIVE" : "IDLE");
+
+ return retval;
+}
+
+static int cyttsp_power_device(struct cyttsp *ts, bool on)
+{
+ int rc = 0, i;
+ const struct cyttsp_regulator *reg_info =
+ ts->platform_data->regulator_info;
+ u8 num_reg = ts->platform_data->num_regulators;
+
+ if (!reg_info) {
+ pr_err("regulator pdata not specified\n");
+ return -EINVAL;
+ }
+
+ if (on == false) /* Turn off the regulators */
+ goto ts_reg_disable;
+
+ ts->vdd = kzalloc(num_reg * sizeof(struct regulator *), GFP_KERNEL);
+ if (!ts->vdd) {
+ pr_err("unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < num_reg; i++) {
+ ts->vdd[i] = regulator_get(&ts->client->dev, reg_info[i].name);
+ if (IS_ERR(ts->vdd[i])) {
+ rc = PTR_ERR(ts->vdd[i]);
+ pr_err("%s:regulator get failed rc=%d\n",
+ __func__, rc);
+ goto error_vdd;
+ }
+
+ if (regulator_count_voltages(ts->vdd[i]) > 0) {
+ rc = regulator_set_voltage(ts->vdd[i],
+ reg_info[i].min_uV, reg_info[i].max_uV);
+ if (rc) {
+ pr_err("%s: regulator_set_voltage"
+ "failed rc =%d\n", __func__, rc);
+ regulator_put(ts->vdd[i]);
+ goto error_vdd;
+ }
+
+ rc = regulator_set_optimum_mode(ts->vdd[i],
+ reg_info[i].hpm_load_uA);
+ if (rc < 0) {
+ pr_err("%s: regulator_set_optimum_mode failed "
+ "rc=%d\n", __func__, rc);
+
+ regulator_set_voltage(ts->vdd[i], 0,
+ reg_info[i].max_uV);
+ regulator_put(ts->vdd[i]);
+ goto error_vdd;
+ }
+ }
+
+ rc = regulator_enable(ts->vdd[i]);
+ if (rc) {
+ pr_err("%s: regulator_enable failed rc =%d\n",
+ __func__, rc);
+ if (regulator_count_voltages(ts->vdd[i]) > 0) {
+ regulator_set_optimum_mode(ts->vdd[i], 0);
+ regulator_set_voltage(ts->vdd[i], 0,
+ reg_info[i].max_uV);
+ }
+ regulator_put(ts->vdd[i]);
+ goto error_vdd;
+ }
+ }
+
+ return rc;
+
+ts_reg_disable:
+ i = ts->platform_data->num_regulators;
+error_vdd:
+ while (--i >= 0) {
+ if (regulator_count_voltages(ts->vdd[i]) > 0) {
+ regulator_set_voltage(ts->vdd[i], 0,
+ reg_info[i].max_uV);
+ regulator_set_optimum_mode(ts->vdd[i], 0);
+ }
+ regulator_disable(ts->vdd[i]);
+ regulator_put(ts->vdd[i]);
+ }
+ kfree(ts->vdd);
+ return rc;
+}
+
+/* cyttsp_initialize: Driver Initialization. This function takes
+ * care of the following tasks:
+ * 1. Create and register an input device with input layer
+ * 2. Take CYTTSP device out of bootloader mode; go operational
+ * 3. Start any timers/Work queues. */
+static int cyttsp_initialize(struct i2c_client *client, struct cyttsp *ts)
+{
+ struct input_dev *input_device;
+ int error = 0;
+ int retval = CY_OK;
+ u8 id;
+
+ /* Create the input device and register it. */
+ input_device = input_allocate_device();
+ if (!input_device) {
+ error = -ENOMEM;
+ cyttsp_xdebug1("err input allocate device\n");
+ goto error_free_device;
+ }
+
+ if (!client) {
+ error = ~ENODEV;
+ cyttsp_xdebug1("err client is Null\n");
+ goto error_free_device;
+ }
+
+ if (!ts) {
+ error = ~ENODEV;
+ cyttsp_xdebug1("err context is Null\n");
+ goto error_free_device;
+ }
+
+ ts->input = input_device;
+ input_device->name = CY_I2C_NAME;
+ input_device->phys = ts->phys;
+ input_device->dev.parent = &client->dev;
+
+ /* init the touch structures */
+ ts->num_prv_st_tch = CY_NTCH;
+ for (id = 0; id < CY_NUM_TRK_ID; id++) {
+ ts->act_trk[id] = CY_NTCH;
+ ts->prv_mt_pos[id][CY_XPOS] = 0;
+ ts->prv_mt_pos[id][CY_YPOS] = 0;
+ }
+
+ for (id = 0; id < CY_NUM_MT_TCH_ID; id++)
+ ts->prv_mt_tch[id] = CY_IGNR_TCH;
+
+ for (id = 0; id < CY_NUM_ST_TCH_ID; id++)
+ ts->prv_st_tch[id] = CY_IGNR_TCH;
+
+ set_bit(EV_SYN, input_device->evbit);
+ set_bit(EV_KEY, input_device->evbit);
+ set_bit(EV_ABS, input_device->evbit);
+ set_bit(BTN_TOUCH, input_device->keybit);
+ set_bit(BTN_2, input_device->keybit);
+ if (ts->platform_data->use_gestures)
+ set_bit(BTN_3, input_device->keybit);
+
+ input_set_abs_params(input_device, ABS_X, ts->platform_data->disp_minx,
+ ts->platform_data->disp_maxx, 0, 0);
+ input_set_abs_params(input_device, ABS_Y, ts->platform_data->disp_miny,
+ ts->platform_data->disp_maxy, 0, 0);
+ input_set_abs_params(input_device,
+ ABS_TOOL_WIDTH, 0, CY_LARGE_TOOL_WIDTH, 0 , 0);
+ input_set_abs_params(input_device,
+ ABS_PRESSURE, 0, CY_MAXZ, 0, 0);
+ input_set_abs_params(input_device,
+ ABS_HAT0X, 0, ts->platform_data->panel_maxx, 0, 0);
+ input_set_abs_params(input_device,
+ ABS_HAT0Y, 0, ts->platform_data->panel_maxy, 0, 0);
+ if (ts->platform_data->use_gestures) {
+ input_set_abs_params(input_device,
+ ABS_HAT1X, 0, CY_MAXZ, 0, 0);
+ input_set_abs_params(input_device,
+ ABS_HAT1Y, 0, CY_MAXZ, 0, 0);
+ }
+ if (ts->platform_data->use_mt) {
+ input_set_abs_params(input_device, ABS_MT_POSITION_X,
+ ts->platform_data->disp_minx,
+ ts->platform_data->disp_maxx, 0, 0);
+ input_set_abs_params(input_device, ABS_MT_POSITION_Y,
+ ts->platform_data->disp_miny,
+ ts->platform_data->disp_maxy, 0, 0);
+ input_set_abs_params(input_device,
+ ABS_MT_TOUCH_MAJOR, 0, CY_MAXZ, 0, 0);
+ input_set_abs_params(input_device,
+ ABS_MT_WIDTH_MAJOR, 0, CY_LARGE_TOOL_WIDTH, 0, 0);
+ if (ts->platform_data->use_trk_id) {
+ input_set_abs_params(input_device,
+ ABS_MT_TRACKING_ID, 0, CY_NUM_TRK_ID, 0, 0);
+ }
+ }
+
+ /* set dummy key to make driver work with virtual keys */
+ input_set_capability(input_device, EV_KEY, KEY_PROG1);
+
+ cyttsp_info("%s: Register input device\n", CY_I2C_NAME);
+ error = input_register_device(input_device);
+ if (error) {
+ cyttsp_alert("%s: Failed to register input device\n", \
+ CY_I2C_NAME);
+ retval = error;
+ goto error_free_device;
+ }
+
+ if (gpio_is_valid(ts->platform_data->resout_gpio)) {
+ /* configure touchscreen reset out gpio */
+ retval = gpio_request(ts->platform_data->resout_gpio,
+ "cyttsp_resout_gpio");
+ if (retval) {
+ pr_err("%s: unable to request reset gpio %d\n",
+ __func__, ts->platform_data->resout_gpio);
+ goto error_free_device;
+ }
+
+ retval = gpio_direction_output(
+ ts->platform_data->resout_gpio, 1);
+ if (retval) {
+ pr_err("%s: unable to set direction for gpio %d\n",
+ __func__, ts->platform_data->resout_gpio);
+ goto error_resout_gpio_dir;
+ }
+ }
+
+ if (gpio_is_valid(ts->platform_data->sleep_gpio)) {
+ /* configure touchscreen reset out gpio */
+ retval = gpio_request(ts->platform_data->sleep_gpio,
+ "cy8c_sleep_gpio");
+ if (retval) {
+ pr_err("%s: unable to request sleep gpio %d\n",
+ __func__, ts->platform_data->sleep_gpio);
+ goto error_sleep_gpio_req;
+ }
+
+ retval = gpio_direction_output(
+ ts->platform_data->sleep_gpio, 0);
+ if (retval) {
+ pr_err("%s: unable to set direction for gpio %d\n",
+ __func__, ts->platform_data->resout_gpio);
+ goto error_sleep_gpio_dir;
+ }
+ }
+
+ if (gpio_is_valid(ts->platform_data->irq_gpio)) {
+ /* configure touchscreen irq gpio */
+ retval = gpio_request(ts->platform_data->irq_gpio,
+ "ts_irq_gpio");
+ if (retval) {
+ pr_err("%s: unable to request gpio [%d]\n", __func__,
+ ts->platform_data->irq_gpio);
+ goto error_irq_gpio_req;
+ }
+ retval = gpio_direction_input(ts->platform_data->irq_gpio);
+ if (retval) {
+ pr_err("%s: unable to set_direction for gpio [%d]\n",
+ __func__, ts->platform_data->irq_gpio);
+ goto error_irq_gpio_dir;
+ }
+ }
+
+ if (ts->platform_data->regulator_info) {
+ retval = cyttsp_power_device(ts, true);
+ if (retval) {
+ pr_err("%s: Unable to power device %d\n",
+ __func__, retval);
+ goto error_irq_gpio_dir;
+ }
+ }
+
+ /* Power on the chip and make sure that I/Os are set as specified
+ * in the platform */
+ if (ts->platform_data->init) {
+ retval = ts->platform_data->init(client);
+ if (retval) {
+ pr_err("%s: ts init failed\n", __func__);
+ goto error_power_device;
+ }
+ }
+
+ msleep(100);
+
+ /* check this device active by reading first byte/register */
+ retval = i2c_smbus_read_byte_data(ts->client, 0x01);
+ if (retval < 0) {
+ pr_err("%s: i2c sanity check failed\n", __func__);
+ goto error_power_device;
+ }
+
+ retval = cyttsp_power_on(ts);
+ if (retval < 0) {
+ pr_err("%s: cyttsp_power_on failed\n", __func__);
+ goto error_power_device;
+ }
+
+ /* Timer or Interrupt setup */
+ if (ts->client->irq == 0) {
+ cyttsp_info("Setting up timer\n");
+ setup_timer(&ts->timer, cyttsp_timer, (unsigned long) ts);
+ mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
+ } else {
+ cyttsp_info("Setting up interrupt\n");
+ error = request_threaded_irq(client->irq, NULL, cyttsp_irq,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ client->dev.driver->name, ts);
+ if (error) {
+ cyttsp_alert("error: could not request irq\n");
+ retval = error;
+ goto error_power_device;
+ }
+ }
+
+ irq_cnt = 0;
+ irq_cnt_total = 0;
+ irq_err_cnt = 0;
+
+ atomic_set(&ts->irq_enabled, 1);
+ retval = device_create_file(&ts->client->dev, &dev_attr_irq_enable);
+ if (retval < CY_OK) {
+ cyttsp_alert("File device creation failed: %d\n", retval);
+ retval = -ENODEV;
+ goto error_free_irq;
+ }
+
+ retval = device_create_file(&client->dev, &dev_attr_cyttsp_fw_ver);
+ if (retval) {
+ cyttsp_alert("sysfs entry for firmware version failed\n");
+ goto error_rm_dev_file_irq_en;
+ }
+
+ ts->cyttsp_fwloader_mode = 0;
+ retval = device_create_file(&client->dev, &dev_attr_cyttsp_update_fw);
+ if (retval) {
+ cyttsp_alert("sysfs entry for firmware update failed\n");
+ goto error_rm_dev_file_fw_ver;
+ }
+
+ retval = device_create_file(&client->dev,
+ &dev_attr_cyttsp_force_update_fw);
+ if (retval) {
+ cyttsp_alert("sysfs entry for force firmware update failed\n");
+ goto error_rm_dev_file_update_fw;
+ }
+ if (ts->platform_data->correct_fw_ver) {
+ if (g_bl_data.appid_lo != ts->platform_data->correct_fw_ver)
+ pr_warn("%s: Invalid firmware version detected;"
+ " Please update.\n", __func__);
+ }
+
+ retval = device_create_file(&client->dev,
+ &dev_attr_cyttsp_fw_name);
+ if (retval) {
+ cyttsp_alert("sysfs entry for file name selection failed\n");
+ goto error_rm_dev_file_fupdate_fw;
+ }
+
+ cyttsp_info("%s: Successful registration\n", CY_I2C_NAME);
+
+ goto success;
+
+error_rm_dev_file_fupdate_fw:
+ device_remove_file(&client->dev, &dev_attr_cyttsp_force_update_fw);
+error_rm_dev_file_update_fw:
+ device_remove_file(&client->dev, &dev_attr_cyttsp_update_fw);
+error_rm_dev_file_fw_ver:
+ device_remove_file(&client->dev, &dev_attr_cyttsp_fw_ver);
+error_rm_dev_file_irq_en:
+ device_remove_file(&client->dev, &dev_attr_irq_enable);
+error_free_irq:
+ if (ts->client->irq)
+ free_irq(client->irq, ts);
+error_power_device:
+ if (ts->platform_data->regulator_info)
+ cyttsp_power_device(ts, false);
+error_irq_gpio_dir:
+ if (gpio_is_valid(ts->platform_data->irq_gpio))
+ gpio_free(ts->platform_data->irq_gpio);
+error_irq_gpio_req:
+ if (gpio_is_valid(ts->platform_data->sleep_gpio))
+ gpio_direction_output(ts->platform_data->sleep_gpio, 1);
+error_sleep_gpio_dir:
+ if (gpio_is_valid(ts->platform_data->sleep_gpio))
+ gpio_free(ts->platform_data->sleep_gpio);
+error_sleep_gpio_req:
+ if (gpio_is_valid(ts->platform_data->resout_gpio))
+ gpio_direction_output(ts->platform_data->resout_gpio, 0);
+error_resout_gpio_dir:
+ if (gpio_is_valid(ts->platform_data->resout_gpio))
+ gpio_free(ts->platform_data->resout_gpio);
+error_free_device:
+ if (input_device)
+ input_free_device(input_device);
+
+success:
+ return retval;
+}
+
+/* I2C driver probe function */
+static int __devinit cyttsp_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct cyttsp *ts;
+ int error;
+ int retval = CY_OK;
+
+ cyttsp_info("Start Probe 1.2\n");
+
+ /* allocate and clear memory */
+ ts = kzalloc(sizeof(struct cyttsp), GFP_KERNEL);
+ if (ts == NULL) {
+ cyttsp_xdebug1("err kzalloc for cyttsp\n");
+ return -ENOMEM;
+ }
+
+ /* Enable runtime PM ops, start in ACTIVE mode */
+ error = pm_runtime_set_active(&client->dev);
+ if (error < 0)
+ dev_dbg(&client->dev, "unable to set runtime pm state\n");
+ pm_runtime_enable(&client->dev);
+
+ if (!(retval < CY_OK)) {
+ /* register driver_data */
+ ts->client = client;
+ ts->platform_data = client->dev.platform_data;
+
+ if (ts->platform_data->fw_fname)
+ strlcpy(ts->fw_fname, ts->platform_data->fw_fname,
+ FW_FNAME_LEN - 1);
+ else
+ strlcpy(ts->fw_fname, "cyttsp.hex", FW_FNAME_LEN - 1);
+
+ if (ts->platform_data->gen == CY_GEN3) {
+ ts->fw_start_addr = 0x0b00;
+ } else if (ts->platform_data->gen == CY_GEN2) {
+ ts->fw_start_addr = 0x0880;
+ } else {
+ pr_err("%s: unsupported cypress chip\n", __func__);
+ kfree(ts);
+ return -EINVAL;
+ }
+
+ i2c_set_clientdata(client, ts);
+
+ error = cyttsp_initialize(client, ts);
+ if (error) {
+ cyttsp_xdebug1("err cyttsp_initialize\n");
+ /* deallocate memory */
+ kfree(ts);
+/*
+ i2c_del_driver(&cyttsp_driver);
+*/
+ return -ENODEV;
+ }
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ if (!(retval < CY_OK)) {
+ ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ ts->early_suspend.suspend = cyttsp_early_suspend;
+ ts->early_suspend.resume = cyttsp_late_resume;
+ register_early_suspend(&ts->early_suspend);
+ }
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+ device_init_wakeup(&client->dev, ts->platform_data->wakeup);
+ mutex_init(&ts->mutex);
+
+ cyttsp_info("Start Probe %s\n", \
+ (retval < CY_OK) ? "FAIL" : "PASS");
+
+ return retval;
+}
+
+#ifdef CONFIG_PM
+static int cyttsp_regulator_lpm(struct cyttsp *ts, bool on)
+{
+ int rc = 0, i;
+ const struct cyttsp_regulator *reg_info =
+ ts->platform_data->regulator_info;
+ u8 num_reg = ts->platform_data->num_regulators;
+
+ if (on == false)
+ goto regulator_hpm;
+
+ for (i = 0; i < num_reg; i++) {
+ if (regulator_count_voltages(ts->vdd[i]) < 0)
+ continue;
+ rc = regulator_set_optimum_mode(ts->vdd[i],
+ reg_info[i].lpm_load_uA);
+ if (rc < 0) {
+ pr_err("%s: regulator_set_optimum failed rc = %d\n",
+ __func__, rc);
+ goto fail_regulator_lpm;
+ }
+
+ }
+
+ return 0;
+
+regulator_hpm:
+ for (i = 0; i < num_reg; i++) {
+ if (regulator_count_voltages(ts->vdd[i]) < 0)
+ continue;
+ rc = regulator_set_optimum_mode(ts->vdd[i],
+ reg_info[i].hpm_load_uA);
+ if (rc < 0) {
+ pr_err("%s: regulator_set_optimum failed"
+ "rc = %d\n", __func__, rc);
+ goto fail_regulator_hpm;
+ }
+ }
+
+ return 0;
+
+fail_regulator_lpm:
+ while (i--) {
+ if (regulator_count_voltages(ts->vdd[i]) < 0)
+ continue;
+ regulator_set_optimum_mode(ts->vdd[i],
+ reg_info[i].hpm_load_uA);
+ }
+
+ return rc;
+
+fail_regulator_hpm:
+ while (i--) {
+ if (regulator_count_voltages(ts->vdd[i]) < 0)
+ continue;
+ regulator_set_optimum_mode(ts->vdd[i],
+ reg_info[i].lpm_load_uA);
+ }
+
+ return rc;
+}
+
+/* Function to manage power-on resume */
+static int cyttsp_resume(struct device *dev)
+{
+ struct cyttsp *ts = dev_get_drvdata(dev);
+ int retval = CY_OK;
+
+ cyttsp_debug("Wake Up\n");
+
+ if (ts->is_suspended == false) {
+ pr_err("%s: in wakeup state\n", __func__);
+ return 0;
+ }
+
+ if (device_may_wakeup(dev)) {
+ if (ts->client->irq)
+ disable_irq_wake(ts->client->irq);
+ return 0;
+ }
+
+ /* re-enable the interrupt prior to wake device */
+ if (ts->client->irq)
+ enable_irq(ts->client->irq);
+
+ if (ts->platform_data->use_sleep &&
+ (ts->platform_data->power_state != CY_ACTIVE_STATE)) {
+ if (ts->platform_data->resume)
+ retval = ts->platform_data->resume(ts->client);
+ else
+ retval = cyttsp_regulator_lpm(ts, false);
+ /* take TTSP device out of bootloader mode;
+ * switch back to TrueTouch operational mode */
+ if (!(retval < CY_OK)) {
+ int tries = 0;
+ do {
+ msleep(100);
+ retval = i2c_smbus_write_i2c_block_data(
+ ts->client, CY_REG_BASE,
+ sizeof(bl_cmd), bl_cmd);
+ if (retval == CY_OK)
+ break;
+ } while (tries++ < 2);
+ /* wait for TTSP Device to complete
+ * switch to Operational mode */
+ tries = 0;
+ do {
+ msleep(100);
+ cyttsp_putbl(ts, 16, false, false, false);
+ } while (GET_BOOTLOADERMODE(g_bl_data.bl_status) &&
+ tries++ < 2);
+ cyttsp_putbl(ts, 16, true, false, false);
+ }
+ }
+
+ if (!(retval < CY_OK) &&
+ (GET_HSTMODE(g_bl_data.bl_file) == CY_OK)) {
+ ts->platform_data->power_state = CY_ACTIVE_STATE;
+
+ /* re-enable the timer after resuming */
+ if (ts->client->irq == 0)
+ mod_timer(&ts->timer, jiffies + TOUCHSCREEN_TIMEOUT);
+ } else
+ retval = -ENODEV;
+
+ ts->is_suspended = false;
+ cyttsp_debug("Wake Up %s\n", \
+ (retval < CY_OK) ? "FAIL" : "PASS");
+
+ return retval;
+}
+
+/* Function to manage low power suspend */
+static int cyttsp_suspend(struct device *dev)
+{
+ struct cyttsp *ts = dev_get_drvdata(dev);
+ u8 sleep_mode = CY_OK;
+ int retval = CY_OK;
+
+ cyttsp_debug("Enter Sleep\n");
+
+ if (ts->is_suspended == true) {
+ pr_err("%s: in sleep state\n", __func__);
+ return 0;
+ }
+
+ mutex_lock(&ts->mutex);
+ if (ts->cyttsp_fwloader_mode) {
+ pr_err("%s:firmware upgrade mode:"
+ "suspend not allowed\n", __func__);
+ mutex_unlock(&ts->mutex);
+ return -EBUSY;
+ }
+ mutex_unlock(&ts->mutex);
+
+ if (device_may_wakeup(dev)) {
+ if (ts->client->irq)
+ enable_irq_wake(ts->client->irq);
+ return 0;
+ }
+
+ if (ts->client->irq == 0)
+ del_timer(&ts->timer);
+ else
+ disable_irq(ts->client->irq);
+
+ if (!(retval < CY_OK)) {
+ if (ts->platform_data->use_sleep &&
+ (ts->platform_data->power_state == CY_ACTIVE_STATE)) {
+ if (ts->platform_data->suspend) {
+ retval =
+ ts->platform_data->suspend(ts->client);
+ } else {
+ retval = cyttsp_regulator_lpm(ts, true);
+ }
+ if (ts->platform_data->use_sleep & CY_USE_DEEP_SLEEP_SEL)
+ sleep_mode = CY_DEEP_SLEEP_MODE;
+ else
+ sleep_mode = CY_LOW_PWR_MODE;
+
+ if (!(retval < CY_OK)) {
+ retval =
+ i2c_smbus_write_i2c_block_data(ts->client,
+ CY_REG_BASE,
+ sizeof(sleep_mode), &sleep_mode);
+ }
+ }
+ }
+
+ if (!(retval < CY_OK)) {
+ if (sleep_mode == CY_DEEP_SLEEP_MODE)
+ ts->platform_data->power_state = CY_SLEEP_STATE;
+ else if (sleep_mode == CY_LOW_PWR_MODE)
+ ts->platform_data->power_state = CY_LOW_PWR_STATE;
+ }
+
+ ts->is_suspended = true;
+ cyttsp_debug("Sleep Power state is %s\n", \
+ (ts->platform_data->power_state == CY_ACTIVE_STATE) ? \
+ "ACTIVE" : \
+ ((ts->platform_data->power_state == CY_SLEEP_STATE) ? \
+ "SLEEP" : "LOW POWER"));
+
+ return retval;
+}
+#endif
+
+/* registered in driver struct */
+static int __devexit cyttsp_remove(struct i2c_client *client)
+{
+ /* clientdata registered on probe */
+ struct cyttsp *ts = i2c_get_clientdata(client);
+ int err;
+
+ cyttsp_alert("Unregister\n");
+
+ pm_runtime_set_suspended(&client->dev);
+ pm_runtime_disable(&client->dev);
+
+ device_init_wakeup(&client->dev, 0);
+ device_remove_file(&ts->client->dev, &dev_attr_irq_enable);
+ device_remove_file(&client->dev, &dev_attr_cyttsp_fw_ver);
+ device_remove_file(&client->dev, &dev_attr_cyttsp_update_fw);
+ device_remove_file(&client->dev, &dev_attr_cyttsp_force_update_fw);
+ device_remove_file(&client->dev, &dev_attr_cyttsp_fw_name);
+
+ /* free up timer or irq */
+ if (ts->client->irq == 0) {
+ err = del_timer(&ts->timer);
+ if (err < CY_OK)
+ cyttsp_alert("error: failed to delete timer\n");
+ } else
+ free_irq(client->irq, ts);
+
+ if (ts->platform_data->regulator_info)
+ cyttsp_power_device(ts, false);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ts->early_suspend);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+ mutex_destroy(&ts->mutex);
+
+ if (gpio_is_valid(ts->platform_data->sleep_gpio)) {
+ gpio_direction_output(ts->platform_data->sleep_gpio, 1);
+ gpio_free(ts->platform_data->sleep_gpio);
+ }
+
+ if (gpio_is_valid(ts->platform_data->resout_gpio)) {
+ gpio_direction_output(ts->platform_data->resout_gpio, 0);
+ gpio_free(ts->platform_data->resout_gpio);
+ }
+
+ if (gpio_is_valid(ts->platform_data->irq_gpio))
+ gpio_free(ts->platform_data->irq_gpio);
+
+ /* housekeeping */
+ kfree(ts);
+
+ cyttsp_alert("Leaving\n");
+
+ return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void cyttsp_early_suspend(struct early_suspend *handler)
+{
+ struct cyttsp *ts;
+
+ ts = container_of(handler, struct cyttsp, early_suspend);
+ cyttsp_suspend(&ts->client->dev);
+}
+
+static void cyttsp_late_resume(struct early_suspend *handler)
+{
+ struct cyttsp *ts;
+
+ ts = container_of(handler, struct cyttsp, early_suspend);
+ cyttsp_resume(&ts->client->dev);
+}
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+static int cyttsp_init(void)
+{
+ int ret;
+
+ cyttsp_info("Cypress TrueTouch(R) Standard Product\n");
+ cyttsp_info("I2C Touchscreen Driver (Built %s @ %s)\n", \
+ __DATE__, __TIME__);
+
+ ret = i2c_add_driver(&cyttsp_driver);
+
+ return ret;
+}
+
+static void cyttsp_exit(void)
+{
+ return i2c_del_driver(&cyttsp_driver);
+}
+
+module_init(cyttsp_init);
+module_exit(cyttsp_exit);
+MODULE_FIRMWARE("cyttsp.fw");
+
diff --git a/drivers/input/touchscreen/cyttsp_fw.h b/drivers/input/touchscreen/cyttsp_fw.h
new file mode 100644
index 0000000..f14153e
--- /dev/null
+++ b/drivers/input/touchscreen/cyttsp_fw.h
@@ -0,0 +1,4307 @@
+/* Header file for:
+ * Cypress TrueTouch(TM) Standard Product touchscreen drivers.
+ * drivers/input/touchscreen/cyttsp_fw.h
+ *
+ * Copyright (C) 2009, 2010 Cypress Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2, and only version 2, as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Cypress reserves the right to make changes without further notice
+ * to the materials described herein. Cypress does not assume any
+ * liability arising out of the application described herein.
+ *
+ * Contact Cypress Semiconductor at www.cypress.com
+ *
+ */
+
+#define CYTTSP_BL_OST_LEN 1
+#define CYTTSP_BL_CMD_LEN 2
+#define CYTTSP_BL_KEY_LEN 8
+#define CYTTSP_LD_ADR_LEN 2
+#define CYTTSP_LD_DAT_LEN 64
+#define CYTTSP_LD_CHK_LEN 2
+#define CYTTSP_LD_BLK_LEN (CYTTSP_BL_OST_LEN + CYTTSP_BL_CMD_LEN + CYTTSP_BL_KEY_LEN + \
+ CYTTSP_LD_ADR_LEN + CYTTSP_LD_DAT_LEN + CYTTSP_LD_CHK_LEN)
+
+typedef struct cyttsp_ld_blk_ray_t {
+ unsigned short Record;
+ unsigned short Length;
+ unsigned char Command;
+ unsigned short Address;
+ unsigned char Block[CYTTSP_LD_BLK_LEN];
+} cyttsp_ld_blk_ray, *pcyttsp_ld_blk_ray;
+
+cyttsp_ld_blk_ray cyttsp_fw[] = {
+ {
+ 0,
+ 11,
+ 0x38,
+ -1,
+ {
+ 0x00, 0xFF, 0x38, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ }
+ },
+ {
+ 1,
+ 79,
+ 0x39,
+ 0x002C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x2C, 0x40, 0x7D, 0x0B, 0x68, 0x30, 0x30, 0x30, 0x30, 0x7E, 0x30, 0x30, 0x30, 0x7D, 0x10, 0x12, 0x7E, 0x7D, 0x10, 0x36, 0x7E, 0x7E, 0x30, 0x30, 0x30, 0x7E, 0x30, 0x30, 0x30, 0x7D, 0x1F, 0x2A, 0x7E, 0x7E, 0x30, 0x30, 0x30, 0x7E, 0x30, 0x30, 0x30, 0x7E, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x7E, 0x30, 0x30, 0x30, 0x7E, 0x30, 0x30, 0x30, 0x7D, 0x20, 0x70, 0x7E, 0x7E, 0x30, 0x30, 0x30, 0x5B, 0x36
+ }
+ },
+ {
+ 2,
+ 79,
+ 0x39,
+ 0x002D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x2D, 0x7E, 0x30, 0x30, 0x30, 0x7E, 0x30, 0x30, 0x30, 0x7E, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x40, 0x43, 0xE6, 0x02, 0x40, 0x70, 0xCF, 0x71, 0x10, 0x62, 0xE3, 0x02, 0x70, 0xCF, 0x41, 0xFF, 0xEF, 0x50, 0x80, 0x4E, 0x5D, 0xD5, 0x08, 0x62, 0x44, 0x09
+ }
+ },
+ {
+ 3,
+ 79,
+ 0x39,
+ 0x002E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x2E, 0xD5, 0x00, 0x55, 0xFA, 0x01, 0x40, 0x50, 0x06, 0x55, 0xF8, 0x3A, 0x7C, 0x00, 0x60, 0x40, 0x40, 0x70, 0xCF, 0x71, 0x10, 0x51, 0xFA, 0x60, 0xE8, 0x70, 0xCF, 0x18, 0x60, 0xD5, 0x55, 0xF8, 0x00, 0x55, 0xF9, 0x00, 0x70, 0xCF, 0x71, 0x10, 0x41, 0x9F, 0xFE, 0x70, 0xCF, 0x62, 0xE3, 0x38, 0x62, 0xD1, 0x0F, 0x50, 0x00, 0x4E, 0x62, 0xD3, 0x0F, 0x62, 0xD0, 0x00, 0x62, 0xD5, 0x00, 0x62, 0xD4, 0x35, 0xEC
+ }
+ },
+ {
+ 4,
+ 79,
+ 0x39,
+ 0x002F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x2F, 0x00, 0x71, 0xC0, 0x7C, 0x0F, 0x76, 0x62, 0xD0, 0x00, 0x50, 0x0F, 0x57, 0x74, 0x08, 0x28, 0x53, 0xE9, 0x18, 0x75, 0x09, 0x00, 0x28, 0x4B, 0x51, 0xE9, 0x80, 0x04, 0x75, 0x09, 0x00, 0x62, 0xE3, 0x00, 0x08, 0x28, 0x60, 0xD5, 0x74, 0xA0, 0x4B, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0x53, 0xE9, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0xA0, 0x1C, 0x53, 0xE8, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0xCD, 0x1D
+ }
+ },
+ {
+ 5,
+ 79,
+ 0x39,
+ 0x0030,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x30, 0x3F, 0xE9, 0x47, 0xE9, 0xFF, 0xB0, 0x06, 0x5D, 0xD5, 0x74, 0x60, 0xD5, 0x18, 0x7A, 0xE8, 0xBF, 0xEB, 0x8F, 0xC9, 0x18, 0x75, 0x09, 0x00, 0x08, 0x28, 0x53, 0xE8, 0x50, 0x00, 0x3F, 0xE9, 0x47, 0xE9, 0xFF, 0xB0, 0x08, 0x5D, 0xD5, 0x74, 0x60, 0xD5, 0x50, 0x00, 0x7A, 0xE8, 0xBF, 0xEF, 0x18, 0x8F, 0xAA, 0x18, 0x70, 0xCF, 0x71, 0x10, 0x62, 0xEC, 0x10, 0x43, 0xE3, 0x00, 0x70, 0xCF, 0x62, 0x4D, 0x1E
+ }
+ },
+ {
+ 6,
+ 79,
+ 0x39,
+ 0x0031,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x31, 0xE0, 0x00, 0x41, 0xFE, 0xE7, 0x43, 0xFE, 0x10, 0x70, 0xCF, 0x71, 0x10, 0x62, 0xE0, 0x53, 0x70, 0xCF, 0x62, 0xE2, 0x00, 0x7C, 0x3E, 0xD3, 0x8F, 0xFF, 0x7F, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xE9, 0x57
+ }
+ },
+ {
+ 7,
+ 79,
+ 0x39,
+ 0x0032,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x32, 0x5D, 0x04, 0x73, 0x21, 0xA0, 0xBF, 0xFA, 0x5D, 0x04, 0x73, 0x21, 0xA0, 0xBF, 0xF3, 0x5D, 0x04, 0x73, 0x21, 0xA0, 0xBF, 0xEC, 0x50, 0x18, 0x49, 0x04, 0x20, 0xAF, 0xE5, 0x60, 0xFF, 0x49, 0xC9, 0x01, 0xB0, 0x1A, 0x41, 0xD6, 0xFE, 0x70, 0xCF, 0x71, 0x10, 0x41, 0x04, 0x5F, 0x70, 0xCF, 0x43, 0xD6, 0x01, 0x40, 0x70, 0xCF, 0x71, 0x10, 0x43, 0x04, 0xA0, 0x70, 0xCF, 0x7F, 0x30, 0x30, 0x30, 0x81, 0x88
+ }
+ },
+ {
+ 8,
+ 79,
+ 0x39,
+ 0x0033,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x87
+ }
+ },
+ {
+ 9,
+ 79,
+ 0x39,
+ 0x0034,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x34, 0x0A, 0x20, 0x20, 0x51, 0x55, 0x41, 0x4C, 0x43, 0x4F, 0x4D, 0x4D, 0x20, 0x56, 0x50, 0x30, 0x34, 0x33, 0x2D, 0x48, 0x32, 0x20, 0x54, 0x4D, 0x41, 0x33, 0x30, 0x30, 0x45, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x20, 0x49, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x42, 0x6C, 0x6F, 0x63, 0x6B, 0x0A, 0x20, 0x20, 0x20, 0x20, 0x56, 0x99, 0xBA
+ }
+ },
+ {
+ 10,
+ 79,
+ 0x39,
+ 0x0035,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x35, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x20, 0x30, 0x32, 0x2E, 0x30, 0x34, 0x2E, 0x30, 0x30, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x69, 0x6C, 0x65, 0x64, 0x20, 0x4A, 0x75, 0x6C, 0x20, 0x31, 0x34, 0x20, 0x32, 0x30, 0x31, 0x30, 0x20, 0x31, 0x32, 0x3A, 0x35, 0x33, 0x3A, 0x31, 0x33, 0x0A, 0x20, 0x20, 0x45, 0x6E, 0x64, 0x20, 0x6F, 0x66, 0x20, 0x49, 0x44, 0x20, 0x42, 0x6C, 0x6F, 0x63, 0x6B, 0x0A, 0x0D, 0xA3
+ }
+ },
+ {
+ 11,
+ 79,
+ 0x39,
+ 0x0036,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x36, 0x00, 0x03, 0x09, 0x10, 0x16, 0x06, 0x02, 0x02, 0x02, 0x01, 0xF4, 0x00, 0x0A, 0x01, 0xF4, 0x00, 0x0A, 0x01, 0xF4, 0x00, 0x0A, 0x14, 0x19, 0x19, 0x00, 0x32, 0x02, 0x14, 0x01, 0x01, 0xE0, 0x03, 0x98, 0x0C, 0x0C, 0x00, 0x10, 0x10, 0x08, 0x00, 0x04, 0x08, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x04, 0x08, 0x00, 0x00, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x01, 0x80, 0x10, 0x01, 0x80, 0x50, 0x2A
+ }
+ },
+ {
+ 12,
+ 79,
+ 0x39,
+ 0x0037,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x37, 0x01, 0x40, 0x04, 0x02, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x40, 0x08, 0x80, 0x20, 0x80, 0x08, 0x04, 0x02, 0x40, 0x20, 0x23, 0x04, 0x21, 0x20, 0x22, 0x00, 0x61, 0x00, 0xFD, 0x00, 0xA0, 0x00, 0xA1, 0x00, 0xA2, 0x00, 0xA3, 0x00, 0xA8, 0x00, 0xA7, 0x00, 0x7C, 0x00, 0x7A, 0x00, 0x7B, 0x00, 0x79, 0x00, 0xCA, 0x24, 0xD6, 0x04, 0xCF, 0x00, 0xC8, 0x00, 0xA9, 0x00, 0xB7, 0x00, 0xB0, 0xB3, 0xF1
+ }
+ },
+ {
+ 13,
+ 79,
+ 0x39,
+ 0x0038,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x38, 0xCA, 0xB1, 0x0B, 0xB2, 0x00, 0xB3, 0x33, 0xB4, 0x33, 0xB5, 0x80, 0xB6, 0x00, 0x6C, 0x00, 0x6D, 0x00, 0x6E, 0x00, 0x6F, 0x00, 0xE6, 0x00, 0xE9, 0x00, 0xEC, 0x00, 0xE8, 0x20, 0xEB, 0x00, 0xEE, 0x00, 0xE7, 0x00, 0xEA, 0x00, 0xED, 0x00, 0xFF, 0x23, 0x00, 0x20, 0x20, 0x21, 0x07, 0x22, 0x40, 0x76, 0x00, 0xAF, 0x00, 0xD1, 0x00, 0xA1, 0x00, 0xD3, 0x00, 0xA3, 0x00, 0xD0, 0x00, 0xA0, 0x00, 0x69, 0x5E
+ }
+ },
+ {
+ 14,
+ 79,
+ 0x39,
+ 0x0039,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x39, 0xD2, 0x00, 0xA2, 0x00, 0xDC, 0x08, 0xE1, 0xFF, 0xE2, 0x01, 0xDF, 0xFF, 0xDE, 0x02, 0xDD, 0x00, 0x99, 0x00, 0x9C, 0x00, 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, 0x9E, 0x00, 0xAC, 0x00, 0xFF, 0x70, 0xCF, 0x62, 0x00, 0x04, 0x70, 0xCF, 0x71, 0x10, 0x62, 0x00, 0xFF, 0x62, 0x01, 0xF6, 0x70, 0xCF, 0x62, 0x02, 0x00, 0x62, 0x01, 0x00, 0x62, 0x04, 0xAB, 0x70, 0xCF, 0x71, 0x10, 0x62, 0xF2, 0x71
+ }
+ },
+ {
+ 15,
+ 79,
+ 0x39,
+ 0x003A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x3A, 0x04, 0xEF, 0x62, 0x05, 0xFC, 0x70, 0xCF, 0x62, 0x06, 0x00, 0x62, 0x05, 0x00, 0x62, 0x08, 0x04, 0x70, 0xCF, 0x71, 0x10, 0x62, 0x08, 0xFF, 0x62, 0x09, 0x8F, 0x70, 0xCF, 0x62, 0x0A, 0x00, 0x62, 0x09, 0x00, 0x62, 0x0C, 0x00, 0x70, 0xCF, 0x71, 0x10, 0x62, 0x0C, 0xFF, 0x62, 0x0D, 0xFF, 0x70, 0xCF, 0x62, 0x0E, 0x00, 0x62, 0x0D, 0x00, 0x62, 0x10, 0x00, 0x70, 0xCF, 0x71, 0x10, 0x62, 0x10, 0xD6, 0x3A
+ }
+ },
+ {
+ 16,
+ 79,
+ 0x39,
+ 0x003B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x3B, 0xFF, 0x62, 0x11, 0xEF, 0x70, 0xCF, 0x62, 0x12, 0x00, 0x62, 0x11, 0x00, 0x70, 0xCF, 0x7F, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0xA8, 0x00, 0xA9, 0x00, 0xAA, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, 0xAB, 0x00, 0xAC, 0x00, 0xAD, 0x00, 0x88, 0x00, 0x89, 0x00, 0x8A, 0x00, 0x8B, 0x00, 0xAE, 0x00, 0xAF, 0x00, 0xB0, 0x00, 0x8C, 0x65, 0x59
+ }
+ },
+ {
+ 17,
+ 79,
+ 0x39,
+ 0x003C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x3C, 0x00, 0x8D, 0x00, 0x8E, 0x00, 0x8F, 0x00, 0xB1, 0x00, 0xB2, 0x00, 0xB3, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0xB4, 0x00, 0xB5, 0x00, 0xB6, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0xB7, 0x00, 0xB8, 0x00, 0xB9, 0x00, 0x98, 0x00, 0x99, 0x00, 0x9A, 0x00, 0x9B, 0x00, 0xBA, 0x00, 0xBB, 0x00, 0xBC, 0x00, 0x9C, 0x00, 0x9D, 0x00, 0x9E, 0x00, 0x9F, 0x00, 0xBD, 0x6D, 0x6A
+ }
+ },
+ {
+ 18,
+ 79,
+ 0x39,
+ 0x003D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x3D, 0x00, 0xBE, 0x00, 0xBF, 0x00, 0xA4, 0x00, 0xC0, 0x00, 0xFF, 0x11, 0x06, 0x12, 0x02, 0x13, 0x87, 0x14, 0x03, 0x1B, 0x30, 0x1C, 0x00, 0x19, 0x24, 0x1A, 0x30, 0x0A, 0x3C, 0x0B, 0x3C, 0xFF, 0x01, 0x02, 0x06, 0x00, 0x01, 0x02, 0x01, 0x00, 0x02, 0x00, 0x02, 0x01, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x02, 0x01, 0x00, 0x73, 0x97, 0x55, 0xAE, 0x04, 0x55, 0xAF, 0xAB, 0x55, 0xB0, 0x04, 0x55, 0x6F, 0x6F
+ }
+ },
+ {
+ 19,
+ 79,
+ 0x39,
+ 0x003E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x3E, 0xB1, 0x00, 0x55, 0xB2, 0x00, 0x7C, 0x0F, 0x8C, 0x7C, 0x0E, 0x61, 0x7F, 0x10, 0x70, 0xCF, 0x50, 0x00, 0x08, 0x50, 0x0D, 0x57, 0xD5, 0x7C, 0x0F, 0xBF, 0x18, 0x50, 0x01, 0x08, 0x50, 0x0E, 0x57, 0x28, 0x7C, 0x0F, 0xBF, 0x18, 0x50, 0x02, 0x08, 0x50, 0x0E, 0x57, 0xCF, 0x7C, 0x0F, 0xBF, 0x18, 0x50, 0x03, 0x08, 0x50, 0x0F, 0x57, 0x4A, 0x7C, 0x0F, 0xBF, 0x18, 0x70, 0xCF, 0x20, 0x7F, 0x38, 0x76, 0x7E
+ }
+ },
+ {
+ 20,
+ 79,
+ 0x39,
+ 0x003F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x3F, 0x02, 0x10, 0x08, 0x4F, 0x52, 0xF9, 0x64, 0x08, 0x64, 0x03, 0x00, 0x54, 0xFC, 0x18, 0x18, 0x20, 0x70, 0xCF, 0x62, 0xE3, 0x00, 0x10, 0x08, 0x28, 0x39, 0xFF, 0xA0, 0x30, 0x4F, 0x54, 0xFD, 0x52, 0xFC, 0x39, 0x00, 0xA0, 0x13, 0x11, 0x06, 0xE0, 0x01, 0x70, 0xCF, 0x71, 0x10, 0x80, 0x09, 0x70, 0xCF, 0x71, 0x20, 0x80, 0x03, 0x71, 0x30, 0x18, 0x20, 0x75, 0x09, 0x00, 0x10, 0x08, 0x28, 0x4F, 0x47, 0x21
+ }
+ },
+ {
+ 21,
+ 79,
+ 0x39,
+ 0x0040,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x40, 0x59, 0xFD, 0x61, 0x00, 0x18, 0x20, 0x75, 0x09, 0x00, 0x8F, 0xC6, 0x38, 0xFC, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x08, 0x10, 0x5D, 0xD0, 0x08, 0x5D, 0xD3, 0x08, 0x5D, 0xD4, 0x08, 0x5D, 0xD5, 0x08, 0x70, 0x3F, 0x71, 0x80, 0x62, 0xD0, 0x00, 0x18, 0x60, 0xD5, 0x18, 0x60, 0xD4, 0x18, 0x60, 0xD3, 0x18, 0x60, 0xD0, 0x20, 0x18, 0x7E, 0x08, 0x51, 0x54, 0x04, 0x01, 0x51, 0x53, 0x0C, 0x00, 0x51, 0xB4, 0xFC
+ }
+ },
+ {
+ 22,
+ 79,
+ 0x39,
+ 0x0041,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x41, 0x54, 0x04, 0x03, 0x51, 0x53, 0x0C, 0x02, 0x51, 0x54, 0x04, 0x05, 0x51, 0x53, 0x0C, 0x04, 0x51, 0x54, 0x04, 0x07, 0x51, 0x53, 0x0C, 0x06, 0x18, 0x08, 0x51, 0x0B, 0x04, 0x0D, 0x51, 0x0A, 0x0C, 0x0C, 0x41, 0x23, 0xFE, 0x55, 0xBB, 0x00, 0x51, 0x55, 0x60, 0x21, 0x62, 0xDB, 0xFE, 0x43, 0x23, 0x01, 0x18, 0x7E, 0x05, 0x62, 0xD0, 0x00, 0x51, 0x42, 0x08, 0x26, 0x42, 0xEF, 0x7C, 0x19, 0x73, 0xD7, 0x43
+ }
+ },
+ {
+ 23,
+ 79,
+ 0x39,
+ 0x0042,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x42, 0x7C, 0x19, 0x73, 0x62, 0xD0, 0x00, 0x18, 0x53, 0x42, 0x70, 0xBF, 0x57, 0x98, 0x62, 0xD3, 0x05, 0x52, 0x00, 0x73, 0x54, 0x00, 0x62, 0xD3, 0x05, 0x54, 0x00, 0x79, 0xDF, 0xF1, 0x7C, 0x19, 0x64, 0x7C, 0x19, 0x64, 0x70, 0xBF, 0x57, 0x98, 0x62, 0xD3, 0x05, 0x52, 0x00, 0x62, 0xD3, 0x08, 0x54, 0x00, 0x62, 0xD3, 0x07, 0x56, 0x00, 0x00, 0x79, 0xDF, 0xEE, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x7F, 0x12, 0xBA
+ }
+ },
+ {
+ 24,
+ 79,
+ 0x39,
+ 0x0043,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x43, 0x5C, 0x51, 0x41, 0xE0, 0x01, 0x80, 0x13, 0x80, 0x08, 0x80, 0x01, 0x5B, 0x9F, 0xF1, 0x80, 0x77, 0x62, 0xD3, 0x05, 0x51, 0x57, 0x54, 0x00, 0x80, 0x6E, 0x62, 0xD3, 0x05, 0x51, 0x57, 0x73, 0x53, 0x46, 0x47, 0x42, 0x07, 0xB0, 0x05, 0x54, 0x00, 0x80, 0x15, 0x47, 0x42, 0x04, 0xA0, 0x10, 0x62, 0xD3, 0x05, 0x3B, 0x00, 0xA0, 0x09, 0xC0, 0x04, 0x78, 0x80, 0x02, 0x74, 0x54, 0x00, 0x62, 0xD3, 0xA3, 0xDD
+ }
+ },
+ {
+ 25,
+ 79,
+ 0x39,
+ 0x0044,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x44, 0x08, 0x13, 0x00, 0xD0, 0x0E, 0x62, 0xD3, 0x02, 0x56, 0x00, 0x00, 0x3C, 0x0E, 0x00, 0xB0, 0x37, 0x80, 0x16, 0x62, 0xD3, 0x02, 0x08, 0x11, 0x05, 0xD0, 0x03, 0x50, 0x00, 0x54, 0x00, 0x18, 0x3A, 0x15, 0xD0, 0x24, 0x51, 0x0E, 0xB0, 0x20, 0x62, 0xD3, 0x08, 0x52, 0x00, 0x53, 0x45, 0x51, 0x47, 0x12, 0x45, 0x1E, 0x45, 0x00, 0x62, 0xD3, 0x07, 0x03, 0x00, 0x0E, 0x45, 0x00, 0x54, 0x00, 0x51, 0x53, 0x3E
+ }
+ },
+ {
+ 26,
+ 79,
+ 0x39,
+ 0x0045,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x45, 0x45, 0x62, 0xD3, 0x08, 0x54, 0x00, 0x7F, 0x7C, 0x21, 0xD2, 0x08, 0x18, 0x7F, 0x50, 0xFF, 0x3C, 0x10, 0x80, 0xC0, 0x11, 0x34, 0x12, 0x76, 0x12, 0x34, 0x11, 0x0E, 0x11, 0x00, 0x34, 0x10, 0x0E, 0x10, 0x00, 0x53, 0x0F, 0x50, 0x00, 0x53, 0x48, 0x53, 0x49, 0x53, 0x4A, 0x53, 0x4B, 0x55, 0x46, 0x18, 0x65, 0x12, 0x6B, 0x11, 0x6B, 0x10, 0x6B, 0x4B, 0x6B, 0x4A, 0x6B, 0x49, 0x51, 0x4B, 0x1A, 0xFD, 0x93
+ }
+ },
+ {
+ 27,
+ 79,
+ 0x39,
+ 0x0046,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x46, 0x14, 0x51, 0x4A, 0x1A, 0x13, 0x51, 0x49, 0x19, 0x00, 0xC0, 0x0D, 0x53, 0x49, 0x51, 0x14, 0x14, 0x4B, 0x51, 0x13, 0x1C, 0x4A, 0x76, 0x12, 0x7A, 0x46, 0xBF, 0xD7, 0x50, 0xFF, 0x3C, 0x0F, 0x80, 0xC0, 0x11, 0x34, 0x12, 0x76, 0x12, 0x34, 0x11, 0x0E, 0x11, 0x00, 0x34, 0x10, 0x0E, 0x10, 0x00, 0x34, 0x0F, 0x7F, 0x50, 0x00, 0x53, 0x48, 0x53, 0x49, 0x53, 0x4A, 0x53, 0x4B, 0x51, 0x12, 0x04, 0xCE, 0x36
+ }
+ },
+ {
+ 28,
+ 79,
+ 0x39,
+ 0x0047,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x47, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x90, 0x54, 0x90, 0x52, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x90, 0x48, 0x90, 0x46, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x90, 0x3C, 0x90, 0x3A, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x90, 0x30, 0x90, 0x2E, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x90, 0x24, 0x90, 0x22, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0xA3, 0xE1
+ }
+ },
+ {
+ 29,
+ 79,
+ 0x39,
+ 0x0048,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x48, 0x48, 0x90, 0x18, 0x90, 0x16, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x90, 0x0C, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x90, 0x02, 0x90, 0x00, 0x70, 0xFB, 0x6E, 0x48, 0x6E, 0x49, 0x6E, 0x4A, 0x6E, 0x4B, 0x7F, 0x50, 0x00, 0x53, 0x48, 0x53, 0x49, 0x53, 0x4A, 0x53, 0x4B, 0x9F, 0xE9, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x9F, 0xDF, 0x51, 0x12, 0x04, 0x49, 0xC6, 0x28
+ }
+ },
+ {
+ 30,
+ 79,
+ 0x39,
+ 0x0049,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x9F, 0xD5, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x9F, 0xCB, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x9F, 0xC1, 0x9F, 0xBF, 0x9F, 0xBD, 0x9F, 0xBB, 0x9F, 0xB9, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x9F, 0xAF, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x9F, 0xA5, 0x9F, 0xA3, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x32, 0x01
+ }
+ },
+ {
+ 31,
+ 79,
+ 0x39,
+ 0x004A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x4A, 0x9F, 0x99, 0x51, 0x12, 0x04, 0x49, 0x51, 0x11, 0x0C, 0x48, 0x9F, 0x8F, 0x9F, 0x8D, 0x8F, 0x8C, 0x70, 0xBF, 0x62, 0xD0, 0x00, 0x53, 0x44, 0x55, 0x0F, 0x80, 0x55, 0x10, 0x60, 0x55, 0x11, 0x00, 0x62, 0xD3, 0x02, 0x50, 0x10, 0x57, 0x98, 0x54, 0x00, 0x79, 0xDF, 0xFC, 0x62, 0xD3, 0x01, 0x51, 0x0F, 0x57, 0x1A, 0x54, 0xA0, 0x79, 0xDF, 0xFC, 0x55, 0x3D, 0x00, 0x7C, 0x17, 0x18, 0x55, 0x45, 0x6E, 0x7A
+ }
+ },
+ {
+ 32,
+ 79,
+ 0x39,
+ 0x004B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x4B, 0x00, 0x62, 0xD3, 0x01, 0x58, 0xA1, 0x51, 0x10, 0x54, 0xC5, 0x62, 0xD3, 0x01, 0x58, 0xA1, 0x51, 0x0F, 0x54, 0xA0, 0x55, 0x4A, 0x80, 0x52, 0xC5, 0x70, 0xCF, 0x71, 0x20, 0x60, 0xA5, 0x70, 0xCF, 0x62, 0xD3, 0x01, 0x58, 0xA1, 0x52, 0xA0, 0x60, 0xFD, 0x55, 0x4B, 0x10, 0x7C, 0x1B, 0x87, 0x51, 0xA0, 0x01, 0x00, 0x5C, 0x62, 0xD3, 0x02, 0x51, 0x45, 0x7C, 0x19, 0x8F, 0x43, 0xA4, 0x08, 0x47, 0x37, 0x0D
+ }
+ },
+ {
+ 33,
+ 79,
+ 0x39,
+ 0x004C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x4C, 0x9F, 0x01, 0xA0, 0x03, 0x71, 0x01, 0x70, 0xCF, 0x7C, 0x1C, 0x8E, 0x7C, 0x1C, 0xE3, 0x55, 0x56, 0x00, 0x55, 0x57, 0xFF, 0x55, 0x48, 0x07, 0x62, 0xD3, 0x00, 0x58, 0x48, 0x3D, 0x70, 0x00, 0xA0, 0x2A, 0x52, 0x68, 0x08, 0x51, 0x48, 0x64, 0x5C, 0x52, 0x59, 0x20, 0x62, 0xD3, 0x02, 0x3A, 0x44, 0xD0, 0x06, 0x51, 0x4B, 0x73, 0x25, 0x00, 0x51, 0x4B, 0x67, 0x2D, 0x00, 0x52, 0x00, 0x3A, 0x56, 0x92, 0xC4
+ }
+ },
+ {
+ 34,
+ 79,
+ 0x39,
+ 0x004D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x4D, 0xC0, 0x03, 0x53, 0x56, 0x3A, 0x57, 0xD0, 0x03, 0x53, 0x57, 0x7A, 0x48, 0xDF, 0xCA, 0x68, 0x4B, 0xDF, 0x9B, 0x51, 0x4A, 0xA0, 0x42, 0x47, 0x11, 0x01, 0xB0, 0x3D, 0x58, 0xA1, 0x62, 0xD3, 0x01, 0x51, 0x57, 0x02, 0x56, 0x39, 0x1F, 0xA0, 0x30, 0xD0, 0x06, 0x51, 0x4A, 0x73, 0x25, 0xA0, 0x51, 0x4A, 0x67, 0x21, 0x7F, 0x2D, 0xA0, 0x68, 0x4A, 0x26, 0x4A, 0x7F, 0x55, 0x48, 0x07, 0x62, 0xD3, 0xBE, 0x1D
+ }
+ },
+ {
+ 35,
+ 79,
+ 0x39,
+ 0x004E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x4E, 0x00, 0x58, 0x48, 0x3D, 0x70, 0x00, 0xA0, 0x0A, 0x52, 0x68, 0x5C, 0x62, 0xD3, 0x02, 0x56, 0x00, 0x10, 0x7A, 0x48, 0xDF, 0xEA, 0x8F, 0x4A, 0x47, 0x11, 0x02, 0xB0, 0x32, 0x3C, 0x56, 0x1F, 0xC0, 0x2D, 0x62, 0xD3, 0x01, 0x58, 0xA1, 0x3D, 0xC5, 0x40, 0xA0, 0x23, 0x17, 0xC5, 0x20, 0x55, 0x48, 0x07, 0x62, 0xD3, 0x00, 0x62, 0xD3, 0x00, 0x58, 0x48, 0x3D, 0x70, 0x00, 0xA0, 0x0A, 0x52, 0x68, 0xD7, 0x50
+ }
+ },
+ {
+ 36,
+ 79,
+ 0x39,
+ 0x004F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x4F, 0x5C, 0x62, 0xD3, 0x02, 0x56, 0x00, 0x10, 0x7A, 0x48, 0xDF, 0xEA, 0x8E, 0xFE, 0x76, 0xA1, 0x51, 0x45, 0x7C, 0x1A, 0xE9, 0x76, 0x45, 0x3C, 0x45, 0x03, 0xCE, 0xE7, 0x7C, 0x17, 0x55, 0x76, 0x3D, 0x3C, 0x3D, 0x09, 0xCE, 0xD7, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x70, 0xBF, 0x62, 0xD0, 0x00, 0x55, 0x44, 0x99, 0x53, 0x0F, 0x5A, 0x10, 0x55, 0x11, 0x03, 0x8E, 0xA6, 0x70, 0xBF, 0x62, 0xD0, 0x00, 0xAE, 0xFF
+ }
+ },
+ {
+ 37,
+ 79,
+ 0x39,
+ 0x0050,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x50, 0x55, 0x44, 0x99, 0x53, 0x0F, 0x55, 0x10, 0x60, 0x55, 0x11, 0x01, 0x8E, 0x94, 0x70, 0xBF, 0x62, 0xD0, 0x00, 0x55, 0x44, 0x99, 0x55, 0x0F, 0x80, 0x53, 0x10, 0x55, 0x11, 0x02, 0x8E, 0x82, 0x90, 0x11, 0x55, 0x38, 0x03, 0x51, 0x38, 0x90, 0x1A, 0x76, 0x38, 0x3C, 0x38, 0x0A, 0xCF, 0xF6, 0x90, 0x66, 0x7F, 0x62, 0xD5, 0x02, 0x62, 0xD0, 0x00, 0x55, 0x34, 0x99, 0x55, 0x0E, 0x00, 0x55, 0x33, 0x76, 0x90
+ }
+ },
+ {
+ 38,
+ 79,
+ 0x39,
+ 0x0051,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x51, 0x01, 0x7F, 0x70, 0xBF, 0x62, 0xD3, 0x02, 0x62, 0xD5, 0x02, 0x62, 0xD0, 0x00, 0x11, 0x02, 0x53, 0x45, 0x51, 0x33, 0x02, 0x4C, 0x53, 0x33, 0x53, 0x32, 0x55, 0x44, 0x01, 0x58, 0x32, 0x52, 0x00, 0x3A, 0x16, 0xC0, 0x24, 0x3B, 0x12, 0xC0, 0x20, 0x3B, 0x11, 0xC0, 0x1C, 0x3B, 0x10, 0xC0, 0x18, 0x3B, 0x01, 0xC0, 0x14, 0x78, 0x3B, 0xFF, 0xC0, 0x0F, 0x3B, 0xF0, 0xC0, 0x0B, 0x3B, 0xEF, 0xC0, 0x6C, 0x7D
+ }
+ },
+ {
+ 39,
+ 79,
+ 0x39,
+ 0x0052,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x52, 0x07, 0x3B, 0xEE, 0xC0, 0x03, 0x91, 0x84, 0x76, 0x32, 0x76, 0x44, 0x51, 0x4C, 0x78, 0x3A, 0x44, 0xBF, 0xCB, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x70, 0xBF, 0x62, 0xD3, 0x02, 0x62, 0xD5, 0x02, 0x62, 0xD0, 0x00, 0x55, 0x32, 0x01, 0x55, 0x44, 0x01, 0x55, 0x45, 0x00, 0x58, 0x32, 0x52, 0x00, 0x3A, 0x16, 0xC0, 0x18, 0x3B, 0x12, 0xC0, 0x14, 0x3B, 0x11, 0xC0, 0x10, 0x3B, 0x10, 0xC0, 0x0C, 0x3B, 0x06, 0xB2
+ }
+ },
+ {
+ 40,
+ 79,
+ 0x39,
+ 0x0053,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x53, 0x01, 0xC0, 0x08, 0x78, 0x3B, 0xFF, 0xC0, 0x03, 0x91, 0x41, 0x76, 0x32, 0x76, 0x44, 0x51, 0x4C, 0x78, 0x3A, 0x44, 0xBF, 0xD7, 0x55, 0x44, 0x01, 0x51, 0x4D, 0x78, 0x53, 0x45, 0x51, 0x4E, 0x12, 0x4C, 0x74, 0x74, 0x53, 0x32, 0x58, 0x32, 0x52, 0x00, 0x3A, 0x16, 0xC0, 0x18, 0x3B, 0x01, 0xC0, 0x14, 0x78, 0x3B, 0xFF, 0xC0, 0x0F, 0x3B, 0xF0, 0xC0, 0x0B, 0x3B, 0xEF, 0xC0, 0x07, 0x3B, 0xEE, 0xF2, 0x8B
+ }
+ },
+ {
+ 41,
+ 79,
+ 0x39,
+ 0x0054,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x54, 0xC0, 0x03, 0x91, 0x07, 0x76, 0x32, 0x76, 0x44, 0x51, 0x4C, 0x78, 0x3A, 0x44, 0xBF, 0xD7, 0x51, 0x4C, 0x78, 0x53, 0x44, 0x55, 0x45, 0x01, 0x02, 0x4C, 0x53, 0x32, 0x58, 0x32, 0x52, 0x00, 0x3A, 0x16, 0xC0, 0x18, 0x3B, 0x11, 0xC0, 0x14, 0x3B, 0x10, 0xC0, 0x10, 0x78, 0x3B, 0xFF, 0xC0, 0x0B, 0x3B, 0xEF, 0xC0, 0x07, 0x3B, 0xEE, 0xC0, 0x03, 0x90, 0xD1, 0x51, 0x4C, 0x04, 0x32, 0x76, 0x45, 0x88, 0xB8
+ }
+ },
+ {
+ 42,
+ 79,
+ 0x39,
+ 0x0055,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x55, 0x51, 0x4D, 0x78, 0x3A, 0x45, 0xBF, 0xD5, 0x55, 0x44, 0x00, 0x55, 0x45, 0x01, 0x51, 0x4C, 0x53, 0x32, 0x58, 0x32, 0x52, 0x00, 0x3A, 0x16, 0xC0, 0x18, 0x3B, 0x12, 0xC0, 0x14, 0x3B, 0x11, 0xC0, 0x10, 0x3B, 0x01, 0xC0, 0x0C, 0x78, 0x3B, 0xF0, 0xC0, 0x07, 0x3B, 0xEF, 0xC0, 0x03, 0x90, 0x9B, 0x51, 0x4C, 0x04, 0x32, 0x76, 0x45, 0x51, 0x4D, 0x78, 0x3A, 0x45, 0xBF, 0xD5, 0x50, 0x00, 0x53, 0xA4, 0xF1
+ }
+ },
+ {
+ 43,
+ 79,
+ 0x39,
+ 0x0056,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x56, 0x44, 0x53, 0x45, 0x55, 0x32, 0x00, 0x5C, 0x52, 0x00, 0x3A, 0x16, 0xC0, 0x0F, 0x3B, 0x12, 0xC0, 0x0B, 0x3B, 0x11, 0xC0, 0x07, 0x3B, 0x01, 0xC0, 0x03, 0x90, 0x70, 0x55, 0x44, 0x00, 0x51, 0x4D, 0x78, 0x53, 0x45, 0x51, 0x4E, 0x12, 0x4C, 0x74, 0x53, 0x32, 0x5C, 0x52, 0x00, 0x3A, 0x16, 0xC0, 0x10, 0x3B, 0x01, 0xC0, 0x0C, 0x78, 0x3B, 0xF0, 0xC0, 0x07, 0x3B, 0xEF, 0xC0, 0x03, 0x90, 0x4B, 0x9F, 0xE8
+ }
+ },
+ {
+ 44,
+ 79,
+ 0x39,
+ 0x0057,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x57, 0x55, 0x45, 0x00, 0x51, 0x4C, 0x78, 0x53, 0x44, 0x53, 0x32, 0x5C, 0x52, 0x00, 0x3A, 0x16, 0xC0, 0x10, 0x3B, 0x11, 0xC0, 0x0C, 0x3B, 0x10, 0xC0, 0x08, 0x78, 0x3B, 0xFF, 0xC0, 0x03, 0x90, 0x2B, 0x51, 0x4D, 0x53, 0x45, 0x51, 0x4C, 0x53, 0x44, 0x51, 0x4E, 0x7A, 0x44, 0x7A, 0x45, 0x53, 0x32, 0x5C, 0x52, 0x00, 0x3A, 0x16, 0xC0, 0x10, 0x78, 0x3B, 0xFF, 0xC0, 0x0B, 0x3B, 0xEF, 0xC0, 0x07, 0x3B, 0x21
+ }
+ },
+ {
+ 45,
+ 79,
+ 0x39,
+ 0x0058,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x58, 0x3B, 0xEE, 0xC0, 0x03, 0x90, 0x05, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x51, 0x43, 0x01, 0x03, 0x3A, 0x0E, 0xC0, 0x0F, 0x51, 0x45, 0x3F, 0x34, 0x51, 0x44, 0x3F, 0x34, 0x51, 0x32, 0x3F, 0x34, 0x76, 0x0E, 0x7F, 0x84, 0x88, 0x8C, 0x90, 0x94, 0x98, 0x9C, 0x9C, 0x9C, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x20, 0x40, 0x62, 0xD0, 0x00, 0x55, 0x4C, 0x11, 0x55, 0x4D, 0x09, 0x55, 0x4E, 0x98, 0xAB, 0x02
+ }
+ },
+ {
+ 46,
+ 79,
+ 0x39,
+ 0x0059,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x59, 0x55, 0x4F, 0x03, 0x55, 0x50, 0x97, 0x55, 0x51, 0x01, 0x55, 0x52, 0xDF, 0x55, 0x15, 0x08, 0x55, 0x16, 0x08, 0x55, 0x17, 0x08, 0x55, 0x42, 0x1C, 0x55, 0x43, 0x04, 0x55, 0xA2, 0x00, 0x55, 0xA3, 0x00, 0x55, 0xA4, 0x48, 0x55, 0xA5, 0x04, 0x55, 0xA6, 0x08, 0x55, 0xA9, 0x01, 0x55, 0xA7, 0x0C, 0x55, 0xA8, 0x05, 0x55, 0x18, 0x04, 0x55, 0xAD, 0x02, 0x55, 0x40, 0x00, 0x55, 0x3F, 0x00, 0x51, 0xE1, 0x6F
+ }
+ },
+ {
+ 47,
+ 79,
+ 0x39,
+ 0x005A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x5A, 0xA9, 0xA0, 0x08, 0x51, 0xA7, 0x58, 0xA8, 0x7C, 0x18, 0xF9, 0x70, 0xBF, 0x62, 0xD3, 0x01, 0x57, 0x3F, 0x50, 0x09, 0x28, 0x54, 0xA0, 0x79, 0xDF, 0xF9, 0x70, 0x3F, 0x71, 0xC0, 0x5D, 0xFC, 0x70, 0xCF, 0x71, 0x10, 0x62, 0x76, 0x07, 0x43, 0xE2, 0x08, 0x70, 0xCF, 0x71, 0x20, 0x62, 0xA4, 0x01, 0x62, 0xC0, 0x00, 0x39, 0x04, 0xD0, 0x04, 0x43, 0xC8, 0x04, 0x7C, 0x19, 0x41, 0x70, 0xCF, 0x71, 0x3B, 0x24
+ }
+ },
+ {
+ 48,
+ 79,
+ 0x39,
+ 0x005B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x5B, 0x20, 0x43, 0x81, 0x0E, 0x43, 0x85, 0x0E, 0x43, 0x89, 0x0E, 0x43, 0x8D, 0x0E, 0x43, 0x91, 0x0E, 0x43, 0x95, 0x0E, 0x43, 0x99, 0x0E, 0x43, 0x9D, 0x0E, 0x70, 0xCF, 0x55, 0x9A, 0x07, 0x55, 0x9C, 0x02, 0x55, 0x9E, 0x06, 0x55, 0x9D, 0x00, 0x50, 0x48, 0x57, 0x00, 0x7C, 0x18, 0xB7, 0x71, 0x30, 0x62, 0x1B, 0x40, 0x70, 0xCF, 0x62, 0xA2, 0x10, 0x7C, 0x2A, 0xD8, 0x50, 0x04, 0x7C, 0x18, 0xE7, 0x6B, 0x85
+ }
+ },
+ {
+ 49,
+ 79,
+ 0x39,
+ 0x005C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x5C, 0x70, 0xCF, 0x7C, 0x19, 0x4E, 0x7F, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x00, 0x03, 0x06, 0x09, 0x0C, 0x0F, 0x12, 0x15, 0x18, 0x62, 0xD0, 0x00, 0x70, 0xCF, 0x71, 0x10, 0x51, 0x3D, 0xF0, 0x60, 0x5C, 0x51, 0x3D, 0xF0, 0x75, 0x73, 0x53, 0x09, 0x5E, 0x00, 0x22, 0x09, 0x61, 0x00, 0x70, 0xCF, 0x71, 0x20, 0x51, 0x3D, 0xFE, 0xE9, 0x5C, 0x51, 0x3D, 0xFE, 0xED, 0x53, 0x09, 0xBF, 0x2E
+ }
+ },
+ {
+ 50,
+ 79,
+ 0x39,
+ 0x005D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x5D, 0x5E, 0x00, 0x2A, 0x09, 0x61, 0x00, 0x70, 0xCF, 0x51, 0x3D, 0xFF, 0xBA, 0x53, 0xA0, 0x51, 0x3D, 0xFF, 0xBD, 0x53, 0xA1, 0x7F, 0x70, 0xCF, 0x71, 0x20, 0x51, 0x3D, 0xFE, 0xC5, 0x5C, 0x51, 0x3D, 0xFE, 0xC9, 0x73, 0x53, 0x09, 0x5E, 0x00, 0x22, 0x09, 0x61, 0x00, 0x70, 0xCF, 0x71, 0x10, 0x51, 0x3D, 0xF0, 0x10, 0x5C, 0x51, 0x3D, 0xF0, 0x25, 0x53, 0x09, 0x5E, 0x00, 0x2A, 0x09, 0x61, 0x00, 0x4E, 0x4D
+ }
+ },
+ {
+ 51,
+ 79,
+ 0x39,
+ 0x005E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x5E, 0x70, 0xCF, 0x7F, 0x0C, 0x0C, 0x00, 0x10, 0x10, 0x08, 0x00, 0x04, 0x08, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x00, 0x04, 0x08, 0x00, 0x00, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x01, 0x80, 0x10, 0x01, 0x80, 0x01, 0x40, 0x04, 0x02, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x40, 0x08, 0x80, 0x20, 0x80, 0x08, 0x04, 0x02, 0x40, 0x20, 0x62, 0xD0, 0x00, 0x55, 0x9D, 0x00, 0x51, 0xA6, 0x91, 0x11, 0xD4
+ }
+ },
+ {
+ 52,
+ 79,
+ 0x39,
+ 0x005F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x5F, 0x76, 0x51, 0xA4, 0x58, 0xA3, 0x7C, 0x18, 0xB7, 0x51, 0xA5, 0x7C, 0x18, 0xE7, 0x70, 0xCF, 0x71, 0x20, 0x50, 0x00, 0x60, 0x80, 0x60, 0x84, 0x60, 0x88, 0x60, 0x8C, 0x60, 0x90, 0x60, 0x94, 0x60, 0x98, 0x60, 0x9C, 0x60, 0x82, 0x60, 0x86, 0x60, 0x8A, 0x60, 0x8E, 0x60, 0x92, 0x60, 0x96, 0x60, 0x9A, 0x60, 0x9E, 0x60, 0xC0, 0x43, 0x81, 0x04, 0x43, 0x85, 0x04, 0x43, 0x89, 0x04, 0x43, 0x8D, 0x86, 0xBF
+ }
+ },
+ {
+ 53,
+ 79,
+ 0x39,
+ 0x0060,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x60, 0x04, 0x43, 0x91, 0x04, 0x43, 0x95, 0x04, 0x43, 0x99, 0x04, 0x43, 0x9D, 0x04, 0x71, 0x30, 0x71, 0x30, 0x62, 0x1F, 0x00, 0x62, 0x1B, 0x70, 0x62, 0x13, 0x87, 0x70, 0xCF, 0x71, 0x10, 0x55, 0x09, 0x19, 0x51, 0x09, 0xFF, 0x5E, 0x5C, 0x51, 0x09, 0xFF, 0x73, 0x53, 0x45, 0x5E, 0x00, 0x2A, 0x45, 0x61, 0x00, 0x7A, 0x09, 0xDF, 0xEC, 0x70, 0xCF, 0x41, 0xA2, 0x3F, 0x55, 0x40, 0x00, 0x55, 0x3F, 0xDC, 0x6C
+ }
+ },
+ {
+ 54,
+ 79,
+ 0x39,
+ 0x0061,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x61, 0x00, 0x51, 0xA9, 0xA0, 0x08, 0x51, 0xA7, 0x58, 0xA8, 0x7C, 0x18, 0xF9, 0x7F, 0x41, 0xE0, 0xFB, 0x71, 0x30, 0x41, 0x1B, 0xBF, 0x70, 0xCF, 0x71, 0x20, 0x41, 0x81, 0xFD, 0x41, 0x85, 0xFD, 0x41, 0x89, 0xFD, 0x41, 0x8D, 0xFD, 0x41, 0x91, 0xFD, 0x41, 0x95, 0xFD, 0x41, 0x99, 0xFD, 0x41, 0x9D, 0xFD, 0x70, 0xCF, 0x41, 0xA2, 0xEF, 0x7C, 0x19, 0x5A, 0x70, 0xCF, 0x71, 0x10, 0x41, 0xE2, 0xF7, 0x90, 0xD5
+ }
+ },
+ {
+ 55,
+ 79,
+ 0x39,
+ 0x0062,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x62, 0x70, 0xCF, 0x7F, 0x7C, 0x19, 0x41, 0x70, 0xCF, 0x71, 0x10, 0x43, 0xE2, 0x08, 0x71, 0x30, 0x43, 0x1B, 0x40, 0x70, 0xCF, 0x71, 0x20, 0x43, 0x81, 0x02, 0x43, 0x85, 0x02, 0x43, 0x89, 0x02, 0x43, 0x8D, 0x02, 0x43, 0x91, 0x02, 0x43, 0x95, 0x02, 0x43, 0x99, 0x02, 0x43, 0x9D, 0x02, 0x70, 0xCF, 0x43, 0xA2, 0x10, 0x7C, 0x19, 0x4E, 0x7F, 0x62, 0xD0, 0x00, 0x53, 0x49, 0x5A, 0x48, 0x53, 0x9B, 0x24, 0xFE
+ }
+ },
+ {
+ 56,
+ 79,
+ 0x39,
+ 0x0063,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x63, 0x5B, 0x21, 0x01, 0xA0, 0x06, 0x2E, 0x9E, 0x01, 0x80, 0x04, 0x26, 0x9E, 0xFE, 0x68, 0x48, 0x6E, 0x49, 0x51, 0x49, 0x78, 0x70, 0xCF, 0x71, 0x20, 0x60, 0xC9, 0x70, 0xCF, 0x7C, 0x2A, 0xBA, 0x7F, 0x00, 0x04, 0x0C, 0x1C, 0x3C, 0x7C, 0xFC, 0x62, 0xD0, 0x00, 0x53, 0x3E, 0x76, 0x3E, 0xFF, 0xF0, 0x26, 0x9C, 0x03, 0x2C, 0x9C, 0x7C, 0x2A, 0xBA, 0x7F, 0x62, 0xD0, 0x00, 0x53, 0xA7, 0x5A, 0xA8, 0xA6, 0x03
+ }
+ },
+ {
+ 57,
+ 79,
+ 0x39,
+ 0x0064,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x64, 0x90, 0x01, 0x7F, 0x62, 0xD0, 0x00, 0x08, 0x5A, 0x3E, 0x55, 0x40, 0xFF, 0x55, 0x3F, 0x01, 0x78, 0xA0, 0x0A, 0x06, 0x40, 0xFF, 0x0E, 0x3F, 0x01, 0x78, 0xBF, 0xF8, 0x51, 0x3E, 0x68, 0x3F, 0x6E, 0x40, 0x78, 0xDF, 0xFA, 0x16, 0x40, 0x7F, 0x1E, 0x3F, 0x00, 0x18, 0x78, 0x64, 0x64, 0x26, 0x9C, 0x03, 0x2C, 0x9C, 0x7C, 0x2A, 0xBA, 0x7F, 0x62, 0xD0, 0x00, 0x78, 0x53, 0x9A, 0x7C, 0x2A, 0xBA, 0x11, 0xDA
+ }
+ },
+ {
+ 58,
+ 79,
+ 0x39,
+ 0x0065,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x65, 0x7F, 0x70, 0xCF, 0x71, 0x20, 0x62, 0xA7, 0x89, 0x62, 0xA7, 0x49, 0x70, 0xCF, 0x7F, 0x70, 0xCF, 0x71, 0x20, 0x49, 0xC8, 0x08, 0xAF, 0xFC, 0x70, 0xCF, 0x7F, 0x70, 0xCF, 0x71, 0x20, 0x62, 0xA7, 0x09, 0x70, 0xCF, 0x7F, 0x70, 0xBF, 0x62, 0xD0, 0x00, 0x55, 0x41, 0x00, 0x93, 0xA8, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x70, 0xBF, 0x62, 0xD0, 0x00, 0x55, 0x41, 0x02, 0x93, 0x99, 0x70, 0x3F, 0x71, 0xB9, 0x2B
+ }
+ },
+ {
+ 59,
+ 79,
+ 0x39,
+ 0x0066,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x66, 0xC0, 0x7F, 0x57, 0x98, 0x50, 0x0A, 0x28, 0x21, 0xE0, 0xB0, 0x04, 0x79, 0xDF, 0xF7, 0x7F, 0x70, 0xCF, 0x71, 0x10, 0x64, 0xE0, 0x01, 0x80, 0x09, 0x80, 0x75, 0x80, 0xE1, 0x81, 0x3D, 0x81, 0x49, 0x41, 0x00, 0xFD, 0x41, 0x0C, 0xF7, 0x41, 0x0C, 0xBF, 0x41, 0x00, 0x7F, 0x41, 0x10, 0xF7, 0x41, 0x10, 0xBF, 0x70, 0xCF, 0x71, 0x20, 0x5D, 0xF7, 0x53, 0x9F, 0x70, 0xFE, 0x43, 0x80, 0x04, 0x52, 0xE2, 0x7E
+ }
+ },
+ {
+ 60,
+ 79,
+ 0x39,
+ 0x0067,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x67, 0x06, 0x60, 0x83, 0x06, 0x68, 0x06, 0x2E, 0x70, 0x01, 0x43, 0x84, 0x08, 0x52, 0x03, 0x60, 0x87, 0x06, 0x69, 0x03, 0x2E, 0x71, 0x01, 0x43, 0x88, 0x04, 0x52, 0x00, 0x60, 0x8B, 0x06, 0x6A, 0x00, 0x2E, 0x72, 0x01, 0x43, 0x8C, 0x02, 0x52, 0x09, 0x60, 0x8F, 0x06, 0x6B, 0x09, 0x2E, 0x73, 0x01, 0x43, 0x90, 0x01, 0x52, 0x0C, 0x60, 0x93, 0x06, 0x6C, 0x0C, 0x2E, 0x74, 0x01, 0x43, 0x94, 0x02, 0x8C, 0xD3
+ }
+ },
+ {
+ 61,
+ 79,
+ 0x39,
+ 0x0068,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x68, 0x52, 0x0F, 0x60, 0x97, 0x06, 0x6D, 0x0F, 0x2E, 0x75, 0x01, 0x43, 0xA3, 0x3F, 0x7F, 0x41, 0x04, 0xBF, 0x41, 0x0C, 0xFB, 0x41, 0x0C, 0xDF, 0x41, 0x00, 0xDF, 0x41, 0x10, 0xFB, 0x41, 0x10, 0xDF, 0x70, 0xCF, 0x71, 0x20, 0x5D, 0xF7, 0x53, 0x9F, 0x70, 0xFE, 0x43, 0x80, 0x02, 0x52, 0x07, 0x60, 0x83, 0x06, 0x68, 0x07, 0x2E, 0x70, 0x01, 0x43, 0x84, 0x04, 0x52, 0x04, 0x60, 0x87, 0x06, 0x69, 0x46, 0x48
+ }
+ },
+ {
+ 62,
+ 79,
+ 0x39,
+ 0x0069,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x69, 0x04, 0x2E, 0x71, 0x01, 0x43, 0x88, 0x02, 0x52, 0x01, 0x60, 0x8B, 0x06, 0x6A, 0x01, 0x2E, 0x72, 0x01, 0x43, 0x8C, 0x04, 0x52, 0x0A, 0x60, 0x8F, 0x06, 0x6B, 0x0A, 0x2E, 0x73, 0x01, 0x43, 0x90, 0x02, 0x52, 0x0D, 0x60, 0x93, 0x06, 0x6C, 0x0D, 0x2E, 0x74, 0x01, 0x43, 0x94, 0x04, 0x52, 0x10, 0x60, 0x97, 0x06, 0x6D, 0x10, 0x2E, 0x75, 0x01, 0x43, 0xA3, 0x3F, 0x7F, 0x41, 0x08, 0xF7, 0x41, 0xC5, 0x47
+ }
+ },
+ {
+ 63,
+ 79,
+ 0x39,
+ 0x006A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x6A, 0x0C, 0xFD, 0x41, 0x0C, 0xEF, 0x41, 0x08, 0x7F, 0x41, 0x10, 0xFD, 0x70, 0xCF, 0x71, 0x20, 0x5D, 0xF7, 0x53, 0x9F, 0x70, 0xFE, 0x43, 0x80, 0x01, 0x52, 0x08, 0x60, 0x83, 0x06, 0x68, 0x08, 0x2E, 0x70, 0x01, 0x43, 0x84, 0x02, 0x52, 0x05, 0x60, 0x87, 0x06, 0x69, 0x05, 0x2E, 0x71, 0x01, 0x43, 0x88, 0x01, 0x52, 0x02, 0x60, 0x8B, 0x06, 0x6A, 0x02, 0x2E, 0x72, 0x01, 0x43, 0x8C, 0x08, 0x52, 0x57, 0x6C
+ }
+ },
+ {
+ 64,
+ 79,
+ 0x39,
+ 0x006B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x6B, 0x0B, 0x60, 0x8F, 0x06, 0x6B, 0x0B, 0x2E, 0x73, 0x01, 0x43, 0x90, 0x04, 0x52, 0x0E, 0x60, 0x93, 0x06, 0x6C, 0x0E, 0x2E, 0x74, 0x01, 0x43, 0xA3, 0x1F, 0x7F, 0x70, 0xCF, 0x71, 0x20, 0x5D, 0xF7, 0x53, 0x9F, 0x70, 0xFE, 0x43, 0xA3, 0x00, 0x7F, 0x7F, 0x70, 0xCF, 0x71, 0x10, 0x64, 0xE0, 0x01, 0x80, 0x09, 0x80, 0x34, 0x80, 0x5F, 0x80, 0x84, 0x80, 0x8B, 0x43, 0x00, 0x02, 0x43, 0x0C, 0x08, 0x1D, 0xF9
+ }
+ },
+ {
+ 65,
+ 79,
+ 0x39,
+ 0x006C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x6C, 0x43, 0x0C, 0x40, 0x43, 0x00, 0x80, 0x43, 0x10, 0x08, 0x43, 0x10, 0x40, 0x70, 0xCF, 0x71, 0x20, 0x41, 0x80, 0xFB, 0x41, 0x84, 0xF7, 0x41, 0x88, 0xFB, 0x41, 0x8C, 0xFD, 0x41, 0x90, 0xFE, 0x41, 0x94, 0xFD, 0x62, 0xA3, 0x00, 0x80, 0x5E, 0x43, 0x04, 0x40, 0x43, 0x0C, 0x04, 0x43, 0x0C, 0x20, 0x43, 0x00, 0x20, 0x43, 0x10, 0x04, 0x43, 0x10, 0x20, 0x70, 0xCF, 0x71, 0x20, 0x41, 0x80, 0xFD, 0x9E, 0xFC
+ }
+ },
+ {
+ 66,
+ 79,
+ 0x39,
+ 0x006D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x6D, 0x41, 0x84, 0xFB, 0x41, 0x88, 0xFD, 0x41, 0x8C, 0xFB, 0x41, 0x90, 0xFD, 0x41, 0x94, 0xFB, 0x62, 0xA3, 0x00, 0x80, 0x31, 0x43, 0x08, 0x08, 0x43, 0x0C, 0x02, 0x43, 0x0C, 0x10, 0x43, 0x08, 0x80, 0x43, 0x10, 0x02, 0x70, 0xCF, 0x71, 0x20, 0x41, 0x80, 0xFE, 0x41, 0x84, 0xFD, 0x41, 0x88, 0xFE, 0x41, 0x8C, 0xF7, 0x41, 0x90, 0xFB, 0x62, 0xA3, 0x00, 0x80, 0x0A, 0x70, 0xCF, 0x71, 0x20, 0x62, 0x2E, 0x1D
+ }
+ },
+ {
+ 67,
+ 79,
+ 0x39,
+ 0x006E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x6E, 0xA3, 0x00, 0x80, 0x01, 0x70, 0xCF, 0x7F, 0x62, 0xD3, 0x00, 0x57, 0x07, 0x52, 0x70, 0x54, 0x80, 0x52, 0x68, 0x54, 0x78, 0x51, 0xA0, 0x56, 0x70, 0x00, 0x54, 0x68, 0x79, 0xDF, 0xEF, 0x7F, 0x62, 0xD5, 0x00, 0x62, 0xD3, 0x00, 0x58, 0xA0, 0x55, 0x09, 0x88, 0x50, 0x0A, 0x28, 0x21, 0x1F, 0x3F, 0x09, 0x75, 0x3C, 0x09, 0x99, 0xCF, 0xF4, 0x7F, 0x62, 0xD0, 0x00, 0x55, 0xAA, 0x00, 0x55, 0xAC, 0xE5, 0x8C
+ }
+ },
+ {
+ 68,
+ 79,
+ 0x39,
+ 0x006F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x6F, 0x00, 0x57, 0x07, 0x62, 0xD3, 0x00, 0x5B, 0x3D, 0x80, 0x00, 0xA0, 0x5A, 0x10, 0x64, 0x5C, 0x52, 0x58, 0x53, 0x56, 0x52, 0x59, 0x53, 0x57, 0x51, 0x3E, 0x6E, 0x56, 0x6E, 0x57, 0x78, 0xDF, 0xFA, 0x51, 0x40, 0x14, 0x57, 0x51, 0x3F, 0x1C, 0x56, 0xA0, 0x0E, 0xD0, 0x06, 0x55, 0x57, 0x00, 0x80, 0x04, 0x55, 0x57, 0xFF, 0x55, 0x56, 0x00, 0x20, 0x10, 0x52, 0x78, 0x5C, 0x62, 0xD3, 0x02, 0x51, 0x6C, 0x9B
+ }
+ },
+ {
+ 69,
+ 79,
+ 0x39,
+ 0x0070,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x70, 0x57, 0x73, 0x54, 0x00, 0x39, 0xDC, 0xD0, 0x05, 0x39, 0x23, 0xD0, 0x04, 0x55, 0xAB, 0x01, 0x62, 0xD3, 0x08, 0x13, 0x00, 0xC0, 0x07, 0x39, 0x0F, 0xD0, 0x0B, 0x80, 0x05, 0x39, 0xF1, 0xC0, 0x05, 0x04, 0xAA, 0x76, 0xAC, 0x20, 0x79, 0xDF, 0x9C, 0x51, 0xAC, 0x47, 0xAA, 0x80, 0xA0, 0x03, 0x76, 0xAA, 0x68, 0xAA, 0x39, 0x02, 0xC0, 0x18, 0x47, 0xAA, 0x80, 0xA0, 0x03, 0x76, 0xAA, 0x68, 0xAA, 0x67, 0x92
+ }
+ },
+ {
+ 70,
+ 79,
+ 0x39,
+ 0x0071,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x71, 0x67, 0x39, 0x02, 0xC0, 0x0A, 0x47, 0xAA, 0x80, 0xA0, 0x03, 0x76, 0xAA, 0x68, 0xAA, 0x57, 0x07, 0x62, 0xD3, 0x00, 0x3D, 0x80, 0x00, 0xA0, 0x33, 0x10, 0x52, 0x78, 0x5C, 0x62, 0xD3, 0x02, 0x52, 0x00, 0x53, 0x47, 0x47, 0x42, 0x10, 0xA0, 0x1B, 0x51, 0xAA, 0x15, 0x00, 0xD0, 0x0B, 0x47, 0xAA, 0x80, 0xB0, 0x0E, 0x56, 0x00, 0x00, 0x80, 0x09, 0x47, 0xAA, 0x80, 0xA0, 0x04, 0x56, 0x00, 0xFF, 0xE5, 0x8F
+ }
+ },
+ {
+ 71,
+ 79,
+ 0x39,
+ 0x0072,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x72, 0x52, 0x00, 0x73, 0x53, 0x57, 0x5B, 0x7C, 0x10, 0xC0, 0x20, 0x79, 0xDF, 0xC4, 0x7F, 0x62, 0xD0, 0x00, 0x70, 0xCF, 0x71, 0x20, 0x49, 0xC4, 0x01, 0xAF, 0xFC, 0x41, 0xA4, 0xF7, 0x41, 0xC4, 0xFE, 0x5D, 0xA8, 0x53, 0x59, 0x5D, 0xA9, 0x53, 0x58, 0x5D, 0xAB, 0x53, 0x5B, 0x5D, 0xAC, 0x53, 0x5A, 0x5D, 0xAE, 0x53, 0x5D, 0x5D, 0xAF, 0x53, 0x5C, 0x5D, 0xB1, 0x53, 0x5F, 0x5D, 0xB2, 0x53, 0x5E, 0x2F, 0x24
+ }
+ },
+ {
+ 72,
+ 79,
+ 0x39,
+ 0x0073,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x73, 0x5D, 0xB4, 0x53, 0x61, 0x5D, 0xB5, 0x53, 0x60, 0x5D, 0xB7, 0x53, 0x63, 0x5D, 0xB8, 0x53, 0x62, 0x5D, 0xBA, 0x53, 0x65, 0x5D, 0xBB, 0x53, 0x64, 0x5D, 0xBD, 0x53, 0x67, 0x5D, 0xBE, 0x53, 0x66, 0x70, 0xCF, 0x7F, 0x62, 0xD3, 0x00, 0x57, 0x07, 0x5B, 0x3D, 0x70, 0x00, 0xA0, 0x25, 0x10, 0x64, 0x5C, 0x51, 0x3E, 0x6F, 0x58, 0x6F, 0x59, 0x78, 0xDF, 0xFA, 0x51, 0x40, 0x15, 0x59, 0x51, 0x3F, 0x50, 0x67
+ }
+ },
+ {
+ 73,
+ 79,
+ 0x39,
+ 0x0074,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x74, 0x1D, 0x58, 0xA0, 0x0E, 0xD0, 0x06, 0x56, 0x59, 0x00, 0x80, 0x04, 0x56, 0x59, 0xFF, 0x56, 0x58, 0x00, 0x20, 0x79, 0xDF, 0xD4, 0x7F, 0x55, 0x3D, 0x00, 0x55, 0x37, 0x01, 0x7C, 0x17, 0x18, 0x9E, 0x7E, 0x58, 0xA1, 0x62, 0xD3, 0x01, 0x52, 0xA0, 0x60, 0xFD, 0x52, 0xC5, 0x70, 0xCF, 0x71, 0x20, 0x60, 0xA5, 0x70, 0xCF, 0x9E, 0x51, 0x50, 0x00, 0x57, 0x88, 0x9C, 0x53, 0x43, 0xA4, 0x08, 0x47, 0x25, 0x12
+ }
+ },
+ {
+ 74,
+ 79,
+ 0x39,
+ 0x0075,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x75, 0x9F, 0x01, 0xA0, 0x03, 0x71, 0x01, 0x70, 0xCF, 0x51, 0x3D, 0xA0, 0x05, 0x9E, 0x6A, 0x51, 0x3D, 0x9F, 0x3C, 0x50, 0x00, 0x9D, 0x93, 0x62, 0xD3, 0x01, 0x58, 0xA1, 0x52, 0xA1, 0x60, 0xFD, 0x52, 0xC6, 0x70, 0xCF, 0x71, 0x20, 0x60, 0xA5, 0x70, 0xCF, 0x9E, 0x1C, 0x50, 0x01, 0x57, 0x88, 0x9C, 0x1E, 0x43, 0xA4, 0x08, 0x47, 0x9F, 0x01, 0xA0, 0x03, 0x71, 0x01, 0x70, 0xCF, 0x9E, 0x39, 0x9F, 0x07, 0xD7
+ }
+ },
+ {
+ 75,
+ 79,
+ 0x39,
+ 0x0076,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x76, 0x0D, 0x50, 0x01, 0x9D, 0x64, 0x62, 0xD3, 0x01, 0x58, 0xA1, 0x52, 0xA2, 0x60, 0xFD, 0x52, 0xC7, 0x70, 0xCF, 0x71, 0x20, 0x60, 0xA5, 0x70, 0xCF, 0x9D, 0xED, 0x50, 0x02, 0x57, 0x88, 0x9B, 0xEF, 0x43, 0xA4, 0x08, 0x47, 0x9F, 0x01, 0xA0, 0x03, 0x71, 0x01, 0x70, 0xCF, 0x9E, 0x0A, 0x9E, 0xDE, 0x50, 0x02, 0x9D, 0x35, 0x7C, 0x17, 0x55, 0x76, 0x3D, 0x3C, 0x3D, 0x09, 0xCF, 0x5F, 0x62, 0xD3, 0x43, 0x50
+ }
+ },
+ {
+ 76,
+ 79,
+ 0x39,
+ 0x0077,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x77, 0x00, 0x9D, 0xC4, 0x9D, 0xF3, 0x7C, 0x14, 0x1F, 0x55, 0x37, 0x00, 0x7F, 0x43, 0xE0, 0x08, 0x7F, 0x41, 0xE0, 0xF7, 0x7F, 0x62, 0xE6, 0x04, 0x62, 0xD0, 0x00, 0x5A, 0x53, 0x53, 0x54, 0x10, 0x08, 0x51, 0x55, 0x08, 0x38, 0x03, 0x4F, 0x50, 0x00, 0x54, 0xFE, 0x54, 0xFD, 0x01, 0x08, 0x54, 0xFF, 0x48, 0xFC, 0x01, 0xA0, 0x09, 0x52, 0xFB, 0x05, 0xFE, 0x52, 0xFA, 0x0D, 0xFD, 0x6F, 0xFD, 0x6F, 0xCC, 0x63
+ }
+ },
+ {
+ 77,
+ 79,
+ 0x39,
+ 0x0078,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x78, 0xFE, 0x6F, 0xFC, 0x7B, 0xFF, 0xBF, 0xEA, 0x52, 0xFC, 0x60, 0xE8, 0x52, 0xFE, 0x60, 0xE7, 0x62, 0xE6, 0x00, 0x62, 0xE6, 0x01, 0x38, 0xFA, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x5D, 0xF7, 0x08, 0x70, 0xFE, 0x57, 0xF0, 0x50, 0x00, 0x62, 0xE6, 0x04, 0x62, 0xE8, 0x01, 0x62, 0xE7, 0x00, 0x62, 0xE6, 0x00, 0x62, 0xE6, 0x01, 0x62, 0xDA, 0xF7, 0x49, 0xDA, 0x08, 0xAF, 0xFC, 0x62, 0xDA, 0xF7, 0x08, 0xF1, 0xAE
+ }
+ },
+ {
+ 78,
+ 79,
+ 0x39,
+ 0x0079,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x79, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x51, 0x00, 0x18, 0x49, 0xDA, 0x08, 0xB0, 0x04, 0x40, 0x80, 0x05, 0x74, 0x62, 0xDA, 0xF7, 0x79, 0xBF, 0xE0, 0x49, 0xDA, 0x08, 0xA0, 0x02, 0x74, 0x62, 0xE6, 0x04, 0x60, 0xE8, 0x62, 0xE7, 0x00, 0x62, 0xE6, 0x00, 0x62, 0xE6, 0x01, 0x62, 0xD0, 0x00, 0x53, 0x55, 0x55, 0x53, 0x00, 0x55, 0x54, 0x01, 0x7E, 0x55, 0x77
+ }
+ },
+ {
+ 79,
+ 79,
+ 0x39,
+ 0x007A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x7A, 0x5D, 0xF7, 0x08, 0x70, 0xFE, 0x62, 0xD0, 0x00, 0x51, 0x05, 0x58, 0x04, 0x7E, 0x5D, 0xF7, 0x08, 0x70, 0xFE, 0x62, 0xD0, 0x00, 0x51, 0x01, 0x58, 0x00, 0x7E, 0x5D, 0xF7, 0x08, 0x70, 0xFE, 0x62, 0xD0, 0x00, 0x51, 0x03, 0x58, 0x02, 0x7E, 0x5D, 0xF7, 0x08, 0x70, 0xFE, 0x62, 0xD0, 0x00, 0x51, 0x07, 0x58, 0x06, 0x7E, 0x08, 0x08, 0x10, 0x4F, 0x5D, 0xF7, 0x54, 0xFD, 0x70, 0x3F, 0x71, 0xC0, 0x9C, 0x06
+ }
+ },
+ {
+ 80,
+ 79,
+ 0x39,
+ 0x007B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x7B, 0x20, 0x18, 0x70, 0xFE, 0x62, 0xD0, 0x00, 0x53, 0x05, 0x5A, 0x04, 0x7E, 0x08, 0x08, 0x10, 0x4F, 0x5D, 0xF7, 0x54, 0xFD, 0x70, 0x3F, 0x71, 0xC0, 0x20, 0x18, 0x70, 0xFE, 0x62, 0xD0, 0x00, 0x53, 0x01, 0x5A, 0x00, 0x7E, 0x08, 0x08, 0x10, 0x4F, 0x5D, 0xF7, 0x54, 0xFD, 0x70, 0x3F, 0x71, 0xC0, 0x20, 0x18, 0x70, 0xFE, 0x62, 0xD0, 0x00, 0x53, 0x03, 0x5A, 0x02, 0x7E, 0x0E, 0x1E, 0x3D, 0x7A, 0xE3, 0x95
+ }
+ },
+ {
+ 81,
+ 79,
+ 0x39,
+ 0x007C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x7C, 0x07, 0x03, 0x00, 0x00, 0x07, 0x0E, 0x1E, 0x3D, 0x03, 0x01, 0x00, 0x00, 0x1E, 0x3D, 0x7A, 0xF6, 0x0E, 0x07, 0x01, 0x00, 0x58, 0x45, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x79, 0xDF, 0xF6, 0x7A, 0x44, 0xBF, 0xF0, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x08, 0x10, 0x70, 0x3F, 0x71, 0x80, 0x5D, 0xD3, 0x08, 0x5D, 0xD0, 0x08, 0x62, 0xD0, 0x00, 0x51, 0xB6, 0x60, 0xD3, 0x2E, 0xB3, 0x80, 0x48, 0x60
+ }
+ },
+ {
+ 82,
+ 79,
+ 0x39,
+ 0x007D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x7D, 0x49, 0xD7, 0x08, 0xA0, 0x09, 0x26, 0xB3, 0xF0, 0x2E, 0xB3, 0x00, 0x80, 0x08, 0x49, 0xD7, 0x20, 0xA0, 0x03, 0x80, 0xA6, 0x51, 0xB3, 0x21, 0x0E, 0xE0, 0x01, 0x80, 0x11, 0x80, 0x67, 0x80, 0x79, 0x80, 0x47, 0x80, 0x96, 0x80, 0x94, 0x80, 0x92, 0x80, 0x90, 0x80, 0x97, 0x5D, 0xD8, 0x21, 0xFE, 0x39, 0x48, 0xA0, 0x06, 0x62, 0xD7, 0x00, 0x80, 0x8A, 0x49, 0xD8, 0x01, 0xB0, 0x0F, 0x55, 0xBA, 0x69, 0xA3
+ }
+ },
+ {
+ 83,
+ 79,
+ 0x39,
+ 0x007E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x7E, 0x02, 0x26, 0xB3, 0xF0, 0x2E, 0xB3, 0x02, 0x62, 0xD7, 0x10, 0x80, 0x77, 0x55, 0xBA, 0x01, 0x26, 0xB3, 0xF0, 0x2E, 0xB3, 0x06, 0x5F, 0xB5, 0xB4, 0x51, 0xB7, 0x02, 0xB5, 0x5C, 0x52, 0x00, 0x60, 0xD8, 0x76, 0xB5, 0x62, 0xD7, 0x14, 0x80, 0x5B, 0x51, 0xB8, 0x78, 0x3A, 0xB5, 0xC0, 0x0F, 0x51, 0xB7, 0x02, 0xB5, 0x5C, 0x52, 0x00, 0x60, 0xD8, 0x76, 0xB5, 0x2E, 0xB3, 0x20, 0x60, 0xD8, 0x62, 0x18, 0x02
+ }
+ },
+ {
+ 84,
+ 79,
+ 0x39,
+ 0x007F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x7F, 0xD7, 0x04, 0x80, 0x3F, 0x5D, 0xD8, 0x3A, 0xB8, 0xD0, 0x2B, 0xA0, 0x29, 0x53, 0xB5, 0x53, 0xB4, 0x26, 0xB3, 0xF0, 0x2E, 0xB3, 0x04, 0x80, 0x18, 0x51, 0xB9, 0x78, 0x3A, 0xB5, 0xC0, 0x16, 0x51, 0xB7, 0x02, 0xB5, 0x5C, 0x5D, 0xD8, 0x54, 0x00, 0x2E, 0xB3, 0x10, 0x76, 0xB5, 0x80, 0x01, 0x62, 0xD7, 0x10, 0x80, 0x0F, 0x62, 0xD7, 0x00, 0x80, 0x0A, 0x26, 0xB3, 0xF0, 0x2E, 0xB3, 0x00, 0x55, 0xFC, 0xCB
+ }
+ },
+ {
+ 85,
+ 79,
+ 0x39,
+ 0x0080,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x80, 0xBA, 0x00, 0x18, 0x60, 0xD0, 0x18, 0x60, 0xD3, 0x20, 0x18, 0x7E, 0x62, 0xD0, 0x00, 0x70, 0xCF, 0x71, 0x10, 0x41, 0x04, 0x5F, 0x43, 0x05, 0xA0, 0x70, 0xCF, 0x26, 0xAF, 0x5F, 0x51, 0xAF, 0x60, 0x04, 0x55, 0xBA, 0x00, 0x90, 0x1F, 0x90, 0x24, 0x40, 0x40, 0x40, 0x40, 0x40, 0x50, 0x00, 0x53, 0xB4, 0x70, 0xCF, 0x71, 0x10, 0x43, 0x04, 0xA0, 0x43, 0x05, 0xA0, 0x70, 0xCF, 0x2E, 0xAF, 0xA0, 0xAC, 0x2C
+ }
+ },
+ {
+ 86,
+ 79,
+ 0x39,
+ 0x0081,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x81, 0x51, 0xAF, 0x60, 0x04, 0x7F, 0x41, 0xE0, 0x7F, 0x43, 0xE0, 0x80, 0x7F, 0x43, 0xD6, 0x31, 0x7F, 0x41, 0xE0, 0x7F, 0x41, 0xD6, 0xFE, 0x7F, 0x62, 0xD0, 0x00, 0x4F, 0x52, 0xFD, 0x53, 0xB8, 0x52, 0xFC, 0x53, 0xB9, 0x52, 0xFB, 0x53, 0xB7, 0x52, 0xFA, 0x53, 0xB6, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x76, 0xBB, 0xD0, 0x04, 0x55, 0xBB, 0xFF, 0x7E, 0x43, 0xE1, 0x01, 0x7F, 0x41, 0xE1, 0xFE, 0x7F, 0xB7, 0x43
+ }
+ },
+ {
+ 87,
+ 79,
+ 0x39,
+ 0x0082,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x82, 0x43, 0x23, 0x01, 0x7F, 0x54, 0x00, 0x70, 0xFE, 0x41, 0x23, 0xFE, 0x18, 0x60, 0x22, 0x18, 0x60, 0x23, 0x18, 0x70, 0x3F, 0x71, 0xC0, 0x7E, 0x30, 0x62, 0xD0, 0x00, 0x53, 0xF8, 0x5D, 0xF7, 0x08, 0x21, 0xC0, 0xB0, 0x07, 0x56, 0x01, 0x00, 0x55, 0xF8, 0x00, 0x51, 0xF8, 0x70, 0x3F, 0x71, 0x80, 0x60, 0xD3, 0x55, 0xFD, 0x01, 0x3C, 0xFD, 0x01, 0xB0, 0xAE, 0x70, 0xCF, 0x71, 0x10, 0x5D, 0xE0, 0xFE, 0xD2
+ }
+ },
+ {
+ 88,
+ 79,
+ 0x39,
+ 0x0083,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x83, 0x08, 0x21, 0xF8, 0x49, 0xFE, 0x08, 0xB0, 0x0A, 0x49, 0xFE, 0x10, 0xB0, 0x09, 0x29, 0x01, 0x80, 0x07, 0x29, 0x02, 0x80, 0x03, 0x29, 0x00, 0x60, 0xE0, 0x70, 0xCF, 0x80, 0x01, 0x65, 0xFD, 0x3C, 0xFD, 0x02, 0xB0, 0x84, 0x65, 0xFD, 0x70, 0xCF, 0x71, 0x10, 0x49, 0xE4, 0x08, 0xA0, 0x05, 0x70, 0xCF, 0x80, 0x20, 0x70, 0xCF, 0x52, 0x00, 0x53, 0xFA, 0x51, 0xFD, 0x39, 0x04, 0xB0, 0x69, 0x08, 0xF8, 0xC7
+ }
+ },
+ {
+ 89,
+ 79,
+ 0x39,
+ 0x0084,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x84, 0x10, 0x50, 0x03, 0x55, 0xF8, 0x3A, 0x7C, 0x00, 0x60, 0x20, 0x18, 0x53, 0xFD, 0x3C, 0xF8, 0x00, 0xA0, 0x09, 0x55, 0xFF, 0x00, 0x55, 0xFD, 0x10, 0x80, 0x37, 0x65, 0xFD, 0x52, 0x00, 0x53, 0xFA, 0x52, 0x02, 0x53, 0xFB, 0x52, 0x01, 0x60, 0xD4, 0x52, 0x05, 0x53, 0xFC, 0x55, 0xFE, 0x56, 0x51, 0xFD, 0x39, 0x08, 0xB0, 0x33, 0x08, 0x10, 0x50, 0x02, 0x55, 0xF8, 0x3A, 0x7C, 0x00, 0x60, 0x20, 0x70, 0xB8
+ }
+ },
+ {
+ 90,
+ 79,
+ 0x39,
+ 0x0085,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x85, 0x18, 0x53, 0xFD, 0x55, 0xFF, 0x01, 0x3C, 0xF8, 0x00, 0xA0, 0x04, 0x55, 0xFF, 0x00, 0x65, 0xFD, 0x3C, 0xFD, 0x10, 0xB0, 0x13, 0x18, 0x70, 0xCF, 0x71, 0x10, 0x60, 0xE0, 0x70, 0xCF, 0x65, 0xFD, 0x51, 0xFF, 0x3C, 0xFD, 0x20, 0xA0, 0x04, 0x30, 0x8F, 0xFE, 0x62, 0xD0, 0x00, 0x62, 0xD5, 0x00, 0x62, 0xD4, 0x00, 0x7E, 0x30, 0x30, 0x30, 0x51, 0xF8, 0x70, 0x3F, 0x71, 0x80, 0x60, 0xD3, 0x52, 0x35, 0x43
+ }
+ },
+ {
+ 91,
+ 79,
+ 0x39,
+ 0x0086,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x86, 0x02, 0x53, 0xFB, 0x52, 0x01, 0x60, 0xD5, 0x52, 0x03, 0x74, 0x53, 0xFD, 0x52, 0x04, 0x53, 0xFE, 0x50, 0x00, 0x6C, 0x00, 0x6A, 0x6C, 0x00, 0x6A, 0x6C, 0x00, 0x6A, 0x6C, 0x00, 0x6A, 0x6C, 0x00, 0x6A, 0x6C, 0x00, 0x6A, 0x6C, 0x00, 0x6A, 0x08, 0x52, 0x00, 0x5C, 0x18, 0x08, 0x28, 0x3F, 0xFB, 0x18, 0x75, 0xB0, 0x02, 0x74, 0x7A, 0xFE, 0xB0, 0x05, 0x7A, 0xFD, 0xA0, 0x0F, 0x3C, 0xFB, 0x00, 0x37, 0x48
+ }
+ },
+ {
+ 92,
+ 79,
+ 0x39,
+ 0x0087,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x87, 0xBF, 0xEB, 0x08, 0x5D, 0xD5, 0x74, 0x60, 0xD5, 0x18, 0x8F, 0xE2, 0x62, 0xD0, 0x00, 0x62, 0xD5, 0x00, 0x7E, 0x70, 0xBF, 0x62, 0xD0, 0x00, 0x47, 0x36, 0x40, 0xB0, 0x0F, 0x47, 0x36, 0x80, 0xA0, 0x0A, 0x26, 0x36, 0x3F, 0x51, 0x36, 0x3A, 0x0E, 0xA0, 0x01, 0x70, 0xBF, 0x51, 0x0E, 0xA1, 0x1A, 0x55, 0xBE, 0x00, 0x3C, 0x0E, 0x02, 0xC0, 0x04, 0x55, 0xBE, 0x01, 0x5F, 0x36, 0x0E, 0x62, 0xD4, 0xE5, 0xA5
+ }
+ },
+ {
+ 93,
+ 79,
+ 0x39,
+ 0x0088,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x88, 0x02, 0x62, 0xD5, 0x01, 0x55, 0x0E, 0x00, 0x55, 0x35, 0x99, 0x55, 0x34, 0xE0, 0x3E, 0x35, 0x53, 0x45, 0x3E, 0x35, 0x53, 0x44, 0x3E, 0x35, 0x53, 0x32, 0x3C, 0x45, 0x02, 0xC0, 0x94, 0x51, 0x4D, 0x11, 0x03, 0x3A, 0x45, 0xC0, 0x8C, 0x3C, 0x44, 0x02, 0xC0, 0x87, 0x51, 0x4C, 0x11, 0x03, 0x3A, 0x44, 0xC0, 0x7F, 0x62, 0xD3, 0x02, 0x58, 0x32, 0x52, 0xFE, 0x53, 0x23, 0x52, 0xFF, 0x53, 0x24, 0x10, 0xFC
+ }
+ },
+ {
+ 94,
+ 79,
+ 0x39,
+ 0x0089,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x89, 0x52, 0x00, 0x53, 0x25, 0x52, 0x01, 0x53, 0x26, 0x52, 0x02, 0x53, 0x27, 0x5B, 0x12, 0x4C, 0x5C, 0x52, 0xFE, 0x53, 0x1E, 0x52, 0xFF, 0x53, 0x1F, 0x52, 0x00, 0x53, 0x20, 0x52, 0x01, 0x53, 0x21, 0x52, 0x02, 0x53, 0x22, 0x5B, 0x12, 0x4C, 0x5C, 0x52, 0xFE, 0x53, 0x19, 0x52, 0xFF, 0x53, 0x1A, 0x52, 0x00, 0x53, 0x1B, 0x52, 0x01, 0x53, 0x1C, 0x52, 0x02, 0x53, 0x1D, 0x51, 0x32, 0x02, 0x4C, 0xF8, 0xCD
+ }
+ },
+ {
+ 95,
+ 79,
+ 0x39,
+ 0x008A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x8A, 0x5C, 0x52, 0xFE, 0x53, 0x28, 0x52, 0xFF, 0x53, 0x29, 0x52, 0x00, 0x53, 0x2A, 0x52, 0x01, 0x53, 0x2B, 0x52, 0x02, 0x53, 0x2C, 0x5B, 0x02, 0x4C, 0x5C, 0x52, 0xFE, 0x53, 0x2D, 0x52, 0xFF, 0x53, 0x2E, 0x52, 0x00, 0x53, 0x2F, 0x52, 0x01, 0x53, 0x30, 0x52, 0x02, 0x53, 0x31, 0x90, 0x62, 0x80, 0x44, 0x7C, 0x25, 0x70, 0x90, 0x5B, 0x55, 0xBD, 0x00, 0x51, 0x45, 0xA0, 0x18, 0x51, 0x4D, 0x78, 0xB8, 0x4E
+ }
+ },
+ {
+ 96,
+ 79,
+ 0x39,
+ 0x008B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x8B, 0x3A, 0x45, 0xA0, 0x11, 0x51, 0x44, 0xA0, 0x1A, 0x51, 0x4C, 0x78, 0x3A, 0x44, 0xA0, 0x13, 0x7C, 0x26, 0x0E, 0x80, 0x21, 0x51, 0x44, 0xA0, 0x17, 0x51, 0x4C, 0x78, 0x3A, 0x44, 0xA0, 0x10, 0x80, 0x11, 0x51, 0x45, 0xA0, 0x0A, 0x51, 0x4D, 0x78, 0x3A, 0x45, 0xA0, 0x03, 0x80, 0x04, 0x55, 0xBD, 0x01, 0x7C, 0x26, 0x94, 0x51, 0x0E, 0x3A, 0x43, 0xC0, 0x05, 0x50, 0xFF, 0x80, 0x0C, 0x7C, 0x23, 0x96, 0x0B
+ }
+ },
+ {
+ 97,
+ 79,
+ 0x39,
+ 0x008C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x8C, 0x48, 0x7A, 0x36, 0x51, 0x36, 0xBF, 0x07, 0x51, 0x0E, 0x55, 0x36, 0x00, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x55, 0x13, 0x00, 0x51, 0x1F, 0x02, 0x20, 0x0E, 0x13, 0x00, 0x02, 0x21, 0x0E, 0x13, 0x00, 0x02, 0x24, 0x0E, 0x13, 0x00, 0x02, 0x25, 0x0E, 0x13, 0x00, 0x02, 0x26, 0x0E, 0x13, 0x00, 0x02, 0x29, 0x0E, 0x13, 0x00, 0x02, 0x2A, 0x0E, 0x13, 0x00, 0x02, 0x2B, 0x0E, 0x13, 0x00, 0x3C, 0x13, 0xFB, 0xD6
+ }
+ },
+ {
+ 98,
+ 79,
+ 0x39,
+ 0x008D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x8D, 0x00, 0xA0, 0x03, 0x50, 0xFF, 0x53, 0xBC, 0x7F, 0x3C, 0xBE, 0x01, 0xB0, 0x23, 0x50, 0x00, 0x53, 0x19, 0x53, 0x1A, 0x53, 0x1B, 0x53, 0x1C, 0x53, 0x1D, 0x53, 0x1E, 0x53, 0x22, 0x53, 0x23, 0x53, 0x27, 0x53, 0x28, 0x53, 0x2C, 0x53, 0x2D, 0x53, 0x2E, 0x53, 0x2F, 0x53, 0x30, 0x53, 0x31, 0x62, 0xD5, 0x01, 0x06, 0x34, 0x03, 0x50, 0x00, 0x53, 0x0F, 0x53, 0x10, 0x53, 0x12, 0x53, 0x13, 0x62, 0xD5, 0x8B
+ }
+ },
+ {
+ 99,
+ 79,
+ 0x39,
+ 0x008E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x8E, 0xD3, 0x00, 0x10, 0x51, 0x31, 0x57, 0x17, 0x03, 0x19, 0x0E, 0x13, 0x00, 0x79, 0xDF, 0xF9, 0x53, 0x14, 0x20, 0x51, 0xBC, 0x80, 0x08, 0x3C, 0x13, 0x00, 0xA0, 0x03, 0x50, 0xFF, 0x3F, 0x34, 0x51, 0x31, 0x02, 0x2C, 0x0E, 0x10, 0x00, 0x02, 0x27, 0x0E, 0x10, 0x00, 0x02, 0x22, 0x0E, 0x10, 0x00, 0x02, 0x1D, 0x0E, 0x10, 0x00, 0x12, 0x19, 0x1E, 0x10, 0x00, 0x12, 0x1E, 0x1E, 0x10, 0x00, 0x12, 0x8E, 0xFE
+ }
+ },
+ {
+ 100,
+ 79,
+ 0x39,
+ 0x008F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x8F, 0x23, 0x1E, 0x10, 0x00, 0x12, 0x28, 0x1E, 0x10, 0x00, 0x12, 0x2D, 0x1E, 0x10, 0x00, 0x64, 0x6B, 0x10, 0x02, 0x30, 0x0E, 0x10, 0x00, 0x02, 0x2B, 0x0E, 0x10, 0x00, 0x02, 0x26, 0x0E, 0x10, 0x00, 0x02, 0x21, 0x0E, 0x10, 0x00, 0x02, 0x1C, 0x0E, 0x10, 0x00, 0x12, 0x1A, 0x1E, 0x10, 0x00, 0x12, 0x1F, 0x1E, 0x10, 0x00, 0x12, 0x24, 0x1E, 0x10, 0x00, 0x12, 0x29, 0x1E, 0x10, 0x00, 0x12, 0x2E, 0x29, 0x35
+ }
+ },
+ {
+ 101,
+ 79,
+ 0x39,
+ 0x0090,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x90, 0x1E, 0x10, 0x00, 0x53, 0x11, 0x7C, 0x11, 0x4D, 0x51, 0x44, 0x06, 0x12, 0x80, 0x0C, 0x11, 0x0E, 0x10, 0x00, 0x47, 0x10, 0x80, 0xA0, 0x0A, 0x55, 0x10, 0x00, 0x55, 0x11, 0x00, 0x55, 0x12, 0x00, 0x7C, 0x12, 0x26, 0x47, 0x42, 0x08, 0xA0, 0x36, 0x62, 0xD3, 0x01, 0x4D, 0x34, 0x51, 0x48, 0x3B, 0x00, 0xC0, 0x1E, 0xB0, 0x09, 0x51, 0x49, 0x3B, 0x01, 0xA0, 0x21, 0xC0, 0x14, 0x51, 0x48, 0x3A, 0x02, 0xE8
+ }
+ },
+ {
+ 102,
+ 79,
+ 0x39,
+ 0x0091,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x91, 0x4F, 0xB0, 0x07, 0x51, 0x49, 0x3A, 0x50, 0xA0, 0x13, 0x7A, 0x49, 0x1E, 0x48, 0x00, 0x80, 0x0C, 0x51, 0x48, 0x2A, 0x49, 0xA0, 0x06, 0x76, 0x49, 0x0E, 0x48, 0x00, 0x4D, 0x34, 0x51, 0x48, 0x3A, 0x4F, 0xC0, 0x0B, 0xB0, 0x13, 0x51, 0x49, 0x3A, 0x50, 0xC0, 0x03, 0xB0, 0x0B, 0x51, 0x48, 0x3F, 0x34, 0x51, 0x49, 0x3F, 0x34, 0x80, 0x09, 0x51, 0x4F, 0x3F, 0x34, 0x51, 0x50, 0x3F, 0x34, 0x50, 0x45, 0x6F
+ }
+ },
+ {
+ 103,
+ 79,
+ 0x39,
+ 0x0092,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x92, 0x00, 0x53, 0x10, 0x53, 0x12, 0x51, 0x2D, 0x02, 0x2E, 0x0E, 0x10, 0x00, 0x02, 0x2F, 0x0E, 0x10, 0x00, 0x02, 0x30, 0x0E, 0x10, 0x00, 0x02, 0x31, 0x0E, 0x10, 0x00, 0x12, 0x19, 0x1E, 0x10, 0x00, 0x12, 0x1A, 0x1E, 0x10, 0x00, 0x12, 0x1B, 0x1E, 0x10, 0x00, 0x12, 0x1C, 0x1E, 0x10, 0x00, 0x12, 0x1D, 0x1E, 0x10, 0x00, 0x64, 0x6B, 0x10, 0x02, 0x28, 0x0E, 0x10, 0x00, 0x02, 0x29, 0x0E, 0x10, 0xBB, 0x5C
+ }
+ },
+ {
+ 104,
+ 79,
+ 0x39,
+ 0x0093,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x93, 0x00, 0x02, 0x2A, 0x0E, 0x10, 0x00, 0x02, 0x2B, 0x0E, 0x10, 0x00, 0x02, 0x2C, 0x0E, 0x10, 0x00, 0x12, 0x1E, 0x1E, 0x10, 0x00, 0x12, 0x1F, 0x1E, 0x10, 0x00, 0x12, 0x20, 0x1E, 0x10, 0x00, 0x12, 0x21, 0x1E, 0x10, 0x00, 0x12, 0x22, 0x1E, 0x10, 0x00, 0x53, 0x11, 0x7C, 0x11, 0x4D, 0x51, 0x45, 0x06, 0x12, 0x80, 0x0C, 0x11, 0x0E, 0x10, 0x00, 0x47, 0x10, 0x80, 0xA0, 0x0A, 0x55, 0x10, 0x00, 0x4E, 0x83
+ }
+ },
+ {
+ 105,
+ 79,
+ 0x39,
+ 0x0094,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x94, 0x55, 0x11, 0x00, 0x55, 0x12, 0x00, 0x7C, 0x11, 0xB3, 0x47, 0x42, 0x08, 0xA0, 0x36, 0x62, 0xD3, 0x01, 0x4D, 0x34, 0x51, 0x48, 0x3B, 0x00, 0xC0, 0x1E, 0xB0, 0x09, 0x51, 0x49, 0x3B, 0x01, 0xA0, 0x21, 0xC0, 0x14, 0x51, 0x48, 0x3A, 0x51, 0xB0, 0x07, 0x51, 0x49, 0x3A, 0x52, 0xA0, 0x13, 0x7A, 0x49, 0x1E, 0x48, 0x00, 0x80, 0x0C, 0x51, 0x48, 0x2A, 0x49, 0xA0, 0x06, 0x76, 0x49, 0x0E, 0x48, 0x31, 0x4A
+ }
+ },
+ {
+ 106,
+ 79,
+ 0x39,
+ 0x0095,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x95, 0x00, 0x4D, 0x34, 0x51, 0x48, 0x3A, 0x51, 0xC0, 0x0B, 0xB0, 0x13, 0x51, 0x49, 0x3A, 0x52, 0xC0, 0x03, 0xB0, 0x0B, 0x51, 0x48, 0x3F, 0x34, 0x51, 0x49, 0x3F, 0x34, 0x80, 0x09, 0x51, 0x51, 0x3F, 0x34, 0x51, 0x52, 0x3F, 0x34, 0x62, 0xD3, 0x02, 0x76, 0x0E, 0x51, 0x0E, 0x55, 0xBC, 0x00, 0x7F, 0x55, 0x12, 0x00, 0x5F, 0x11, 0x45, 0x06, 0x11, 0xFE, 0x5F, 0x10, 0x44, 0x06, 0x10, 0xFE, 0x51, 0x97, 0x17
+ }
+ },
+ {
+ 107,
+ 79,
+ 0x39,
+ 0x0096,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x96, 0x32, 0x08, 0x51, 0x4C, 0x14, 0x32, 0x14, 0x32, 0x16, 0x32, 0x02, 0x55, 0x0F, 0x06, 0x7A, 0x0F, 0x51, 0x0F, 0xA0, 0x74, 0x47, 0x11, 0x80, 0xB0, 0x44, 0x51, 0x4D, 0x78, 0x3A, 0x11, 0xC0, 0x3D, 0x55, 0x13, 0x06, 0x7A, 0x13, 0x51, 0x13, 0xA0, 0x4F, 0x47, 0x10, 0x80, 0xB0, 0x1E, 0x51, 0x4C, 0x78, 0x3A, 0x10, 0xC0, 0x17, 0x58, 0x32, 0x62, 0xD3, 0x02, 0x52, 0x00, 0x58, 0x12, 0x62, 0xD3, 0x19, 0x1C
+ }
+ },
+ {
+ 108,
+ 79,
+ 0x39,
+ 0x0097,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x97, 0x00, 0x54, 0x19, 0x76, 0x12, 0x76, 0x10, 0x76, 0x32, 0x8F, 0xD9, 0x58, 0x12, 0x62, 0xD3, 0x00, 0x56, 0x19, 0x00, 0x75, 0x5A, 0x12, 0x76, 0x10, 0x76, 0x32, 0x8F, 0xC8, 0x58, 0x12, 0x62, 0xD3, 0x00, 0x50, 0x00, 0x54, 0x19, 0x75, 0x54, 0x19, 0x75, 0x54, 0x19, 0x75, 0x54, 0x19, 0x75, 0x54, 0x19, 0x75, 0x5A, 0x12, 0x06, 0x32, 0x05, 0x76, 0x11, 0x5F, 0x10, 0x44, 0x06, 0x10, 0xFE, 0x51, 0xA0, 0x2B
+ }
+ },
+ {
+ 109,
+ 79,
+ 0x39,
+ 0x0098,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x98, 0x4C, 0x11, 0x05, 0x04, 0x32, 0x8F, 0x88, 0x62, 0xD3, 0x02, 0x18, 0x53, 0x32, 0x7F, 0x62, 0xD3, 0x00, 0x3C, 0x45, 0x01, 0xB0, 0x1B, 0x57, 0x05, 0x52, 0x19, 0x6D, 0x6D, 0x6D, 0x21, 0x1F, 0x53, 0x0F, 0x6D, 0x21, 0x7F, 0x02, 0x0F, 0x54, 0x14, 0x75, 0x5B, 0x39, 0x0A, 0xBF, 0xEB, 0x80, 0x21, 0x51, 0x4D, 0x11, 0x02, 0x3A, 0x45, 0xB0, 0x19, 0x57, 0x0F, 0x52, 0x19, 0x6D, 0x6D, 0x6D, 0x21, 0x4A, 0x80
+ }
+ },
+ {
+ 110,
+ 79,
+ 0x39,
+ 0x0099,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x99, 0x1F, 0x53, 0x0F, 0x6D, 0x21, 0x7F, 0x02, 0x0F, 0x54, 0x1E, 0x75, 0x5B, 0x39, 0x14, 0xBF, 0xEB, 0x3C, 0x44, 0x01, 0xB0, 0x1D, 0x57, 0x01, 0x52, 0x19, 0x6D, 0x6D, 0x6D, 0x21, 0x1F, 0x53, 0x0F, 0x6D, 0x21, 0x7F, 0x02, 0x0F, 0x54, 0x18, 0x5B, 0x01, 0x05, 0x5C, 0x39, 0x15, 0xBF, 0xE9, 0x80, 0x23, 0x51, 0x4C, 0x11, 0x02, 0x3A, 0x44, 0xB0, 0x1B, 0x57, 0x03, 0x52, 0x19, 0x6D, 0x6D, 0x6D, 0xB7, 0x5B
+ }
+ },
+ {
+ 111,
+ 79,
+ 0x39,
+ 0x009A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x9A, 0x21, 0x1F, 0x53, 0x0F, 0x6D, 0x21, 0x7F, 0x02, 0x0F, 0x54, 0x1A, 0x5B, 0x01, 0x05, 0x5C, 0x39, 0x17, 0xBF, 0xE9, 0x7F, 0x62, 0xD3, 0x00, 0x51, 0x45, 0xB0, 0x94, 0x55, 0x19, 0x04, 0x55, 0x1A, 0x10, 0x55, 0x1B, 0x10, 0x55, 0x1C, 0x10, 0x55, 0x1D, 0x04, 0x51, 0xBD, 0xB0, 0x23, 0x51, 0x25, 0xA0, 0x0D, 0x51, 0x24, 0x5F, 0x12, 0x26, 0x5F, 0x14, 0x25, 0x92, 0x47, 0x53, 0x1B, 0x51, 0x2A, 0x43, 0x74
+ }
+ },
+ {
+ 112,
+ 79,
+ 0x39,
+ 0x009B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x9B, 0xA0, 0x0F, 0x51, 0x29, 0x5F, 0x12, 0x2B, 0x5F, 0x14, 0x2A, 0x92, 0x37, 0x53, 0x1A, 0x53, 0x1C, 0x57, 0x04, 0x52, 0x23, 0x53, 0x4A, 0x52, 0x19, 0x53, 0x4B, 0x7C, 0x29, 0x2D, 0x50, 0x04, 0x6E, 0x4A, 0x6E, 0x4B, 0x78, 0xBF, 0xFA, 0x52, 0x28, 0x14, 0x4B, 0x1E, 0x4A, 0x00, 0x47, 0x4A, 0x80, 0xA0, 0x07, 0x55, 0x4A, 0x00, 0x55, 0x4B, 0x00, 0x47, 0x4A, 0x7F, 0xA0, 0x04, 0x55, 0x4B, 0xFF, 0xD0, 0x8F
+ }
+ },
+ {
+ 113,
+ 79,
+ 0x39,
+ 0x009C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x9C, 0x51, 0x4B, 0x3C, 0xAD, 0x02, 0xA0, 0x0D, 0x3C, 0xAD, 0x03, 0xA0, 0x03, 0x80, 0x10, 0x6D, 0x21, 0x7F, 0x80, 0x0B, 0x6D, 0x21, 0x7F, 0x53, 0x4B, 0x6D, 0x21, 0x7F, 0x02, 0x4B, 0x54, 0x1E, 0x6D, 0x6D, 0x6D, 0x21, 0x1F, 0x54, 0x19, 0x6D, 0x21, 0x7F, 0x05, 0x19, 0x79, 0xDF, 0xA5, 0x51, 0x4D, 0x11, 0x01, 0x3A, 0x45, 0xB0, 0x94, 0x55, 0x2D, 0x04, 0x55, 0x2E, 0x10, 0x55, 0x2F, 0x10, 0x55, 0xF3, 0xD6
+ }
+ },
+ {
+ 114,
+ 79,
+ 0x39,
+ 0x009D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x9D, 0x30, 0x10, 0x55, 0x31, 0x04, 0x51, 0xBD, 0xB0, 0x23, 0x51, 0x25, 0xA0, 0x0D, 0x51, 0x24, 0x5F, 0x12, 0x26, 0x5F, 0x14, 0x25, 0x91, 0xAC, 0x53, 0x2F, 0x51, 0x20, 0xA0, 0x0F, 0x51, 0x1F, 0x5F, 0x12, 0x21, 0x5F, 0x14, 0x20, 0x91, 0x9C, 0x53, 0x2E, 0x53, 0x30, 0x57, 0x04, 0x52, 0x23, 0x53, 0x4A, 0x52, 0x2D, 0x53, 0x4B, 0x7C, 0x29, 0x2D, 0x50, 0x04, 0x6E, 0x4A, 0x6E, 0x4B, 0x78, 0xBF, 0x6F, 0xCF
+ }
+ },
+ {
+ 115,
+ 79,
+ 0x39,
+ 0x009E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x9E, 0xFA, 0x52, 0x1E, 0x14, 0x4B, 0x1E, 0x4A, 0x00, 0x47, 0x4A, 0x80, 0xA0, 0x07, 0x55, 0x4A, 0x00, 0x55, 0x4B, 0x00, 0x47, 0x4A, 0x7F, 0xA0, 0x04, 0x55, 0x4B, 0xFF, 0x51, 0x4B, 0x3C, 0xAD, 0x02, 0xA0, 0x0D, 0x3C, 0xAD, 0x03, 0xA0, 0x03, 0x80, 0x10, 0x6D, 0x21, 0x7F, 0x80, 0x0B, 0x6D, 0x21, 0x7F, 0x53, 0x4B, 0x6D, 0x21, 0x7F, 0x02, 0x4B, 0x54, 0x28, 0x6D, 0x6D, 0x6D, 0x21, 0x1F, 0x54, 0xC2, 0x76
+ }
+ },
+ {
+ 116,
+ 79,
+ 0x39,
+ 0x009F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x9F, 0x2D, 0x6D, 0x21, 0x7F, 0x05, 0x2D, 0x79, 0xDF, 0xA5, 0x3C, 0x44, 0x00, 0xB0, 0x97, 0x55, 0x19, 0x04, 0x55, 0x1E, 0x10, 0x55, 0x23, 0x10, 0x55, 0x28, 0x10, 0x55, 0x2D, 0x04, 0x51, 0xBD, 0xB0, 0x23, 0x51, 0x25, 0xA0, 0x0D, 0x51, 0x20, 0x5F, 0x12, 0x2A, 0x5F, 0x14, 0x25, 0x91, 0x14, 0x53, 0x23, 0x51, 0x26, 0xA0, 0x0F, 0x51, 0x21, 0x5F, 0x12, 0x2B, 0x5F, 0x14, 0x26, 0x91, 0x04, 0x53, 0x38, 0x63
+ }
+ },
+ {
+ 117,
+ 79,
+ 0x39,
+ 0x00A0,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xA0, 0x1E, 0x53, 0x28, 0x57, 0x14, 0x52, 0x1B, 0x53, 0x4A, 0x52, 0x19, 0x53, 0x4B, 0x7C, 0x29, 0x2D, 0x50, 0x04, 0x6E, 0x4A, 0x6E, 0x4B, 0x78, 0xBF, 0xFA, 0x52, 0x1C, 0x14, 0x4B, 0x1E, 0x4A, 0x00, 0x47, 0x4A, 0x80, 0xA0, 0x07, 0x55, 0x4A, 0x00, 0x55, 0x4B, 0x00, 0x47, 0x4A, 0x7F, 0xA0, 0x04, 0x55, 0x4B, 0xFF, 0x51, 0x4B, 0x3C, 0xAD, 0x02, 0xA0, 0x0D, 0x3C, 0xAD, 0x03, 0xA0, 0x03, 0x80, 0xA1, 0x36
+ }
+ },
+ {
+ 118,
+ 79,
+ 0x39,
+ 0x00A1,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xA1, 0x10, 0x6D, 0x21, 0x7F, 0x80, 0x0B, 0x6D, 0x21, 0x7F, 0x53, 0x4B, 0x6D, 0x21, 0x7F, 0x02, 0x4B, 0x54, 0x1A, 0x6D, 0x6D, 0x6D, 0x21, 0x1F, 0x54, 0x19, 0x6D, 0x21, 0x7F, 0x05, 0x19, 0x5B, 0x11, 0x05, 0x5C, 0xDF, 0xA2, 0x51, 0x4C, 0x11, 0x01, 0x3A, 0x44, 0xB0, 0x97, 0x55, 0x1D, 0x04, 0x55, 0x22, 0x10, 0x55, 0x27, 0x10, 0x55, 0x2C, 0x10, 0x55, 0x31, 0x04, 0x51, 0xBD, 0xB0, 0x23, 0x51, 0xD2, 0x99
+ }
+ },
+ {
+ 119,
+ 79,
+ 0x39,
+ 0x00A2,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xA2, 0x25, 0xA0, 0x0D, 0x51, 0x20, 0x5F, 0x12, 0x2A, 0x5F, 0x14, 0x25, 0x90, 0x76, 0x53, 0x27, 0x51, 0x24, 0xA0, 0x0F, 0x51, 0x1F, 0x5F, 0x12, 0x29, 0x5F, 0x14, 0x24, 0x90, 0x66, 0x53, 0x22, 0x53, 0x2C, 0x57, 0x14, 0x52, 0x1B, 0x53, 0x4A, 0x52, 0x1D, 0x53, 0x4B, 0x7C, 0x29, 0x2D, 0x50, 0x04, 0x6E, 0x4A, 0x6E, 0x4B, 0x78, 0xBF, 0xFA, 0x52, 0x1A, 0x14, 0x4B, 0x1E, 0x4A, 0x00, 0x47, 0x4A, 0xB3, 0x5C
+ }
+ },
+ {
+ 120,
+ 79,
+ 0x39,
+ 0x00A3,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xA3, 0x80, 0xA0, 0x07, 0x55, 0x4A, 0x00, 0x55, 0x4B, 0x00, 0x47, 0x4A, 0x7F, 0xA0, 0x04, 0x55, 0x4B, 0xFF, 0x51, 0x4B, 0x3C, 0xAD, 0x02, 0xA0, 0x0D, 0x3C, 0xAD, 0x03, 0xA0, 0x03, 0x80, 0x10, 0x6D, 0x21, 0x7F, 0x80, 0x0B, 0x6D, 0x21, 0x7F, 0x53, 0x4B, 0x6D, 0x21, 0x7F, 0x02, 0x4B, 0x54, 0x1C, 0x6D, 0x6D, 0x6D, 0x21, 0x1F, 0x54, 0x1D, 0x6D, 0x21, 0x7F, 0x05, 0x1D, 0x5B, 0x11, 0x05, 0x5C, 0x0D, 0x11
+ }
+ },
+ {
+ 121,
+ 79,
+ 0x39,
+ 0x00A4,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xA4, 0xDF, 0xA2, 0x7F, 0x55, 0x11, 0x00, 0x04, 0x12, 0x0E, 0x11, 0x00, 0x65, 0x12, 0x6B, 0x11, 0x65, 0x12, 0x6B, 0x11, 0x65, 0x12, 0x6B, 0x11, 0x65, 0x12, 0x6B, 0x11, 0x55, 0x10, 0x00, 0x55, 0x13, 0x00, 0x7C, 0x11, 0x4D, 0x51, 0x12, 0x39, 0x10, 0xD0, 0x03, 0x50, 0x10, 0x7F, 0x12, 0x4B, 0x55, 0x10, 0x08, 0x47, 0x4B, 0x01, 0xA0, 0x03, 0x02, 0x4A, 0x6D, 0x6E, 0x4B, 0x7A, 0x10, 0xBF, 0xF3, 0x1A, 0x2C
+ }
+ },
+ {
+ 122,
+ 79,
+ 0x39,
+ 0x00A5,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xA5, 0x53, 0x4A, 0x7F, 0x62, 0xD0, 0x00, 0x3C, 0x0E, 0x02, 0xC0, 0x0E, 0x55, 0x36, 0x00, 0x90, 0x09, 0x47, 0x36, 0x40, 0xA0, 0x04, 0x7C, 0x14, 0x1F, 0x7F, 0x70, 0xBF, 0x62, 0xD4, 0x02, 0x62, 0xD3, 0x02, 0x50, 0x00, 0x53, 0x32, 0x53, 0x35, 0x53, 0x44, 0x53, 0x45, 0x55, 0x34, 0x99, 0x3E, 0x34, 0x53, 0x19, 0x3E, 0x34, 0x53, 0x1A, 0x3E, 0x34, 0x53, 0x1B, 0x76, 0x45, 0x51, 0x45, 0x3A, 0x0E, 0x9D, 0x33
+ }
+ },
+ {
+ 123,
+ 79,
+ 0x39,
+ 0x00A6,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xA6, 0xD1, 0x1F, 0x3E, 0x34, 0x53, 0x1C, 0x3E, 0x34, 0x53, 0x1D, 0x3E, 0x34, 0x53, 0x1E, 0x51, 0x19, 0x12, 0x1C, 0xD0, 0x03, 0x73, 0x74, 0x53, 0x1F, 0x51, 0x1A, 0x12, 0x1D, 0xD0, 0x03, 0x73, 0x74, 0x53, 0x20, 0x51, 0x1F, 0xA0, 0x07, 0x39, 0x02, 0xA0, 0x03, 0x80, 0x2D, 0x51, 0x20, 0xA0, 0x05, 0x39, 0x02, 0xB0, 0x25, 0x51, 0x19, 0x3A, 0x1C, 0xC0, 0x0B, 0xA0, 0x11, 0x51, 0x1B, 0x12, 0x4C, 0xEF, 0xD8
+ }
+ },
+ {
+ 124,
+ 79,
+ 0x39,
+ 0x00A7,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xA7, 0x53, 0x21, 0x80, 0x0C, 0x51, 0x1B, 0x02, 0x4C, 0x53, 0x21, 0x80, 0x04, 0x5F, 0x21, 0x1B, 0x51, 0x1A, 0x12, 0x1D, 0x67, 0x14, 0x21, 0x80, 0x8D, 0x3C, 0x1F, 0x02, 0xB0, 0x41, 0x3C, 0x20, 0x01, 0xB0, 0x3C, 0x51, 0x19, 0x3A, 0x1C, 0xC0, 0x0B, 0xA0, 0x11, 0x51, 0x1B, 0x12, 0x4C, 0x53, 0x21, 0x80, 0x0C, 0x51, 0x1B, 0x02, 0x4C, 0x53, 0x21, 0x80, 0x04, 0x5F, 0x21, 0x1B, 0x51, 0x1A, 0x3A, 0x1F, 0x39
+ }
+ },
+ {
+ 125,
+ 79,
+ 0x39,
+ 0x00A8,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xA8, 0x1D, 0xC0, 0x0E, 0x58, 0x21, 0x52, 0x00, 0x79, 0x3B, 0x00, 0xD0, 0x10, 0x7A, 0x21, 0x80, 0x0C, 0x58, 0x21, 0x52, 0x00, 0x75, 0x3B, 0x00, 0xD0, 0x03, 0x76, 0x21, 0x80, 0x48, 0x3C, 0x1F, 0x01, 0xB0, 0x41, 0x3C, 0x20, 0x02, 0xB0, 0x3C, 0x51, 0x1A, 0x3A, 0x1D, 0xC0, 0x08, 0x51, 0x1B, 0x78, 0x53, 0x21, 0x80, 0x06, 0x51, 0x1B, 0x74, 0x53, 0x21, 0x51, 0x19, 0x3A, 0x1C, 0xC0, 0x0B, 0xA0, 0x9C, 0x34
+ }
+ },
+ {
+ 126,
+ 79,
+ 0x39,
+ 0x00A9,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xA9, 0x11, 0x51, 0x21, 0x12, 0x4C, 0x53, 0x1F, 0x80, 0x0C, 0x51, 0x21, 0x02, 0x4C, 0x53, 0x1F, 0x80, 0x04, 0x55, 0x1F, 0x00, 0x58, 0x21, 0x52, 0x00, 0x58, 0x1F, 0x3B, 0x00, 0xD0, 0x03, 0x5A, 0x21, 0x80, 0x03, 0x8F, 0x17, 0x58, 0x1B, 0x52, 0x00, 0x58, 0x21, 0x13, 0x00, 0xCF, 0x0D, 0x3A, 0x18, 0xDF, 0x09, 0x58, 0x1E, 0x52, 0x00, 0x58, 0x21, 0x13, 0x00, 0xCE, 0xFF, 0x3A, 0x18, 0xDE, 0xFB, 0xB0, 0x5D
+ }
+ },
+ {
+ 127,
+ 79,
+ 0x39,
+ 0x00AA,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xAA, 0x58, 0x1B, 0x52, 0x00, 0x58, 0x1E, 0x3B, 0x00, 0xD0, 0x0A, 0x52, 0x00, 0x01, 0x01, 0x55, 0x36, 0x40, 0x80, 0x06, 0x01, 0x01, 0x55, 0x36, 0x40, 0x58, 0x21, 0x54, 0x00, 0x76, 0x32, 0x8E, 0xDB, 0x76, 0x44, 0x5F, 0x45, 0x44, 0x06, 0x35, 0x03, 0x51, 0x35, 0x55, 0x34, 0x99, 0x04, 0x34, 0x51, 0x44, 0x3A, 0x0E, 0xCE, 0xBA, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x62, 0xD0, 0x00, 0x70, 0xCF, 0x71, 0x06, 0x0A
+ }
+ },
+ {
+ 128,
+ 79,
+ 0x39,
+ 0x00AB,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xAB, 0x20, 0x51, 0x9A, 0x60, 0xA0, 0x51, 0x9C, 0x60, 0xA2, 0x51, 0x9B, 0x60, 0xA1, 0x51, 0x9E, 0x60, 0xC7, 0x51, 0x9D, 0x60, 0xA4, 0x70, 0xCF, 0x7F, 0x62, 0xD0, 0x00, 0x62, 0xD5, 0x00, 0x62, 0xD4, 0x00, 0x62, 0xD3, 0x00, 0x55, 0xFA, 0x00, 0x50, 0x06, 0x55, 0xF8, 0x3A, 0x7C, 0x00, 0x60, 0x3C, 0xF8, 0x05, 0xB0, 0x12, 0x70, 0xCF, 0x71, 0x20, 0x62, 0xA6, 0x00, 0x71, 0x30, 0x62, 0x1B, 0x30, 0xAA, 0x53
+ }
+ },
+ {
+ 129,
+ 79,
+ 0x39,
+ 0x00AC,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xAC, 0x43, 0x1B, 0x40, 0x70, 0xCF, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x62, 0xD0, 0x03, 0x51, 0xE1, 0x54, 0x01, 0x51, 0xE0, 0x54, 0x00, 0x38, 0xFE, 0x20, 0x7F, 0x7F, 0x7F, 0x10, 0x4F, 0x20, 0x7F, 0x10, 0x4F, 0x20, 0x7F, 0x62, 0xD0, 0x00, 0x26, 0xAF, 0xFD, 0x7C, 0x72, 0x51, 0x26, 0xAE, 0xFB, 0x51, 0xAE, 0x60, 0x00, 0x7F, 0x10, 0x4F, 0x20, 0x7F, 0x10, 0x4F, 0x20, 0x7F, 0x10, 0x4F, 0x20, 0x7F, 0xEF, 0xDE
+ }
+ },
+ {
+ 130,
+ 79,
+ 0x39,
+ 0x00AD,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xAD, 0x10, 0x4F, 0x20, 0x7F, 0x10, 0x4F, 0x20, 0x7F, 0x10, 0x4F, 0x20, 0x7F, 0x10, 0x4F, 0x62, 0xD0, 0x00, 0x51, 0xAF, 0x29, 0x02, 0x7C, 0x6F, 0x20, 0x62, 0xD0, 0x00, 0x51, 0xAE, 0x29, 0x04, 0x53, 0xAE, 0x51, 0xAE, 0x60, 0x00, 0x20, 0x7F, 0x7F, 0x7F, 0x08, 0x62, 0xD0, 0x00, 0x55, 0xFA, 0x00, 0x62, 0xD5, 0x00, 0x62, 0xD4, 0x00, 0x4F, 0x5B, 0x01, 0x03, 0x53, 0xF9, 0x55, 0xF8, 0x3A, 0x50, 0xE3, 0xC7
+ }
+ },
+ {
+ 131,
+ 79,
+ 0x39,
+ 0x00AE,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xAE, 0x06, 0x00, 0x20, 0x70, 0xBF, 0x62, 0xD3, 0x00, 0x52, 0xF8, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x62, 0xD0, 0x00, 0x55, 0xFA, 0x00, 0x62, 0xD5, 0x00, 0x62, 0xD4, 0x00, 0x4F, 0x5B, 0x01, 0x03, 0x53, 0xF9, 0x55, 0xF8, 0x3A, 0x50, 0x06, 0x00, 0x7F, 0x11, 0x04, 0x4B, 0xD0, 0x04, 0x78, 0xC0, 0x09, 0x3A, 0x80, 0x40, 0x79, 0x19, 0x00, 0xDF, 0xF9, 0x7F, 0x71, 0x40, 0xA0, 0x05, 0x70, 0xCF, 0x71, 0xD5, 0xAC
+ }
+ },
+ {
+ 132,
+ 79,
+ 0x39,
+ 0x00AF,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xAF, 0x10, 0x5E, 0x00, 0x70, 0xCF, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x56, 0x00, 0x00, 0x80, 0x13, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0xC0, 0x7C, 0x6F, 0x54, 0x52, 0x00, 0x3F, 0xE8, 0x77, 0x00, 0x3D, 0x00, 0x04, 0xCF, 0xEA, 0x62, 0xD0, 0x04, 0x55, 0xB6, 0x00, 0x62, 0xD0, 0x04, 0x55, 0xB5, 0x00, 0x7C, 0x73, 0x74, 0x38, 0xFF, 0x20, 0x7F, 0x7F, 0x10, 0x4F, 0xBC, 0x7B
+ }
+ },
+ {
+ 133,
+ 79,
+ 0x39,
+ 0x00B0,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xB0, 0x38, 0x01, 0x10, 0x7C, 0x11, 0x47, 0x62, 0xD0, 0x00, 0x20, 0x54, 0x00, 0x50, 0x0F, 0x08, 0x10, 0x7C, 0x2B, 0x38, 0x38, 0xFE, 0x52, 0x00, 0x62, 0xD0, 0x00, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x56, 0x01, 0x00, 0x9F, 0xD7, 0x62, 0xD0, 0x00, 0x54, 0x00, 0x52, 0x00, 0x08, 0x7C, 0x47, 0x34, 0x38, 0xFF, 0x52, 0x00, 0x08, 0x90, 0x46, 0x52, 0x00, 0x08, 0x62, 0xD0, 0x04, 0x51, 0x2E, 0x60
+ }
+ },
+ {
+ 134,
+ 79,
+ 0x39,
+ 0x00B1,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xB1, 0xB5, 0x08, 0x7C, 0x3A, 0x9B, 0x38, 0xFD, 0x62, 0xD0, 0x00, 0x54, 0x01, 0x5A, 0xE8, 0x06, 0xE8, 0x01, 0x50, 0x0F, 0x08, 0x51, 0xE8, 0x08, 0x52, 0x00, 0x08, 0x91, 0x47, 0x62, 0xD0, 0x00, 0x5A, 0xE8, 0x06, 0xE8, 0x01, 0x50, 0x0F, 0x08, 0x51, 0xE8, 0x08, 0x7C, 0x2B, 0x3C, 0x38, 0xFB, 0x52, 0x00, 0x62, 0xD0, 0x04, 0x53, 0xB5, 0x52, 0x01, 0x62, 0xD0, 0x00, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0xF0, 0xE5
+ }
+ },
+ {
+ 135,
+ 79,
+ 0x39,
+ 0x00B2,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xB2, 0x4F, 0x38, 0x06, 0x50, 0x04, 0x3B, 0xFC, 0xD0, 0x04, 0x56, 0xFC, 0x04, 0x56, 0x05, 0x00, 0x56, 0x04, 0x00, 0x80, 0x67, 0x56, 0x02, 0xE0, 0x56, 0x01, 0x01, 0x56, 0x00, 0x00, 0x80, 0x23, 0x7C, 0x6F, 0x4C, 0x52, 0x01, 0x7C, 0x70, 0xCD, 0x7C, 0x6F, 0x44, 0x06, 0xE8, 0xC4, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x3B, 0x03, 0xB0, 0x03, 0x80, 0x0F, 0x07, 0x02, 0x08, 0x0F, 0x01, 0x00, 0x77, 0x09, 0x18
+ }
+ },
+ {
+ 136,
+ 79,
+ 0x39,
+ 0x00B3,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xB3, 0x00, 0x52, 0x00, 0x3B, 0xFC, 0xCF, 0xD9, 0x52, 0x00, 0x3B, 0xFC, 0xA0, 0x2C, 0x62, 0xD0, 0x00, 0x7C, 0x6F, 0x18, 0x06, 0xE8, 0xC0, 0x7C, 0x6F, 0x54, 0x52, 0x00, 0x3F, 0xE8, 0x7C, 0x6F, 0x18, 0x06, 0xE8, 0xC4, 0x7C, 0x6F, 0x54, 0x52, 0x03, 0x3F, 0xE8, 0x52, 0x02, 0x53, 0xE8, 0x52, 0x01, 0x60, 0xD5, 0x50, 0xFF, 0x3F, 0xE8, 0x77, 0x05, 0x77, 0x04, 0x62, 0xD0, 0x04, 0x52, 0x04, 0x3A, 0xDB, 0xBD
+ }
+ },
+ {
+ 137,
+ 79,
+ 0x39,
+ 0x00B4,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xB4, 0xB6, 0xCF, 0x92, 0x52, 0x05, 0x62, 0xD0, 0x04, 0x53, 0xB6, 0x3D, 0x05, 0x04, 0xD0, 0x55, 0x56, 0x02, 0xE0, 0x56, 0x01, 0x01, 0x56, 0x00, 0x00, 0x80, 0x44, 0x7C, 0x6F, 0x4C, 0x52, 0x01, 0x7C, 0x70, 0xCD, 0x3D, 0x03, 0xFF, 0xA0, 0x2F, 0x62, 0xD0, 0x04, 0x51, 0xB6, 0x7C, 0x70, 0x0E, 0x06, 0xE8, 0xC0, 0x7C, 0x6F, 0x54, 0x52, 0x00, 0x7C, 0x72, 0xE6, 0x7C, 0x70, 0x0E, 0x06, 0xE8, 0xC4, 0x09, 0x1A
+ }
+ },
+ {
+ 138,
+ 79,
+ 0x39,
+ 0x00B5,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xB5, 0x7C, 0x6F, 0x54, 0x52, 0x03, 0x7C, 0x72, 0xE6, 0x01, 0x01, 0x53, 0xB6, 0x62, 0xD0, 0x00, 0x39, 0x04, 0xC0, 0x03, 0x80, 0x0F, 0x07, 0x02, 0x08, 0x0F, 0x01, 0x00, 0x77, 0x00, 0x52, 0x00, 0x3B, 0xFC, 0xCF, 0xB8, 0x56, 0x04, 0x00, 0x80, 0x32, 0x62, 0xD0, 0x00, 0x7C, 0x6F, 0x44, 0x06, 0xE8, 0xC4, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x7C, 0x72, 0x31, 0x06, 0xE6, 0xC0, 0x0E, 0x76, 0xF5
+ }
+ },
+ {
+ 139,
+ 79,
+ 0x39,
+ 0x00B6,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xB6, 0xE7, 0x03, 0x51, 0xE7, 0x60, 0xD4, 0x3E, 0xE6, 0x7C, 0x6E, 0xB6, 0x7C, 0x70, 0x1E, 0x06, 0xE6, 0xE0, 0x0E, 0xE7, 0x01, 0x7C, 0x6D, 0xEA, 0x77, 0x04, 0x52, 0x04, 0x3B, 0x05, 0xCF, 0xCA, 0x38, 0xFA, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x3D, 0xFC, 0x00, 0xB0, 0x06, 0x7C, 0x73, 0x74, 0x80, 0x28, 0x90, 0x29, 0x54, 0x00, 0x3D, 0x00, 0x00, 0xA0, 0x1F, 0x62, 0xD0, 0x04, 0x3C, 0xB4, 0x00, 0xF5, 0xF4
+ }
+ },
+ {
+ 140,
+ 79,
+ 0x39,
+ 0x00B7,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xB7, 0xB0, 0x10, 0x62, 0xD0, 0x00, 0x52, 0xFB, 0x53, 0xE8, 0x52, 0xFA, 0x60, 0xD5, 0x50, 0x01, 0x3F, 0xE8, 0x52, 0x00, 0x62, 0xD0, 0x04, 0x53, 0xB4, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x7C, 0x6F, 0xC9, 0x80, 0x22, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0x00, 0x0E, 0xE9, 0x02, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x62, 0xD0, 0x00, 0x51, 0x16, 0x62, 0xD0, 0x00, 0x3A, 0xE9, 0x04, 0x13
+ }
+ },
+ {
+ 141,
+ 79,
+ 0x39,
+ 0x00B8,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xB8, 0xD0, 0x03, 0x77, 0x01, 0x77, 0x00, 0x3D, 0x00, 0x99, 0xD0, 0x07, 0x50, 0x28, 0x3B, 0x01, 0xDF, 0xD5, 0x50, 0x28, 0x3B, 0x01, 0xD0, 0x08, 0x62, 0xD0, 0x00, 0x50, 0x10, 0x80, 0x06, 0x62, 0xD0, 0x00, 0x50, 0x00, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x7C, 0x6F, 0x2F, 0xB0, 0x0A, 0x3D, 0xFC, 0x00, 0xA0, 0x4E, 0x91, 0x78, 0x80, 0x4A, 0x3D, 0x00, 0x10, 0xB0, 0x03, 0x80, 0x43, 0xFB, 0x02
+ }
+ },
+ {
+ 142,
+ 79,
+ 0x39,
+ 0x00B9,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xB9, 0x3D, 0x00, 0x20, 0xB0, 0x2B, 0x62, 0xD0, 0x04, 0x51, 0xB5, 0x21, 0x0F, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x62, 0xD0, 0x04, 0x51, 0xB4, 0x21, 0xF0, 0x62, 0xD0, 0x00, 0x2A, 0xE9, 0x62, 0xD0, 0x03, 0x53, 0x9A, 0x51, 0x9A, 0x08, 0x50, 0x02, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x80, 0x14, 0x3D, 0x00, 0x30, 0xB0, 0x05, 0x90, 0x10, 0x80, 0x0B, 0x62, 0xD0, 0x03, 0x47, 0x99, 0x40, 0xA0, 0x03, 0xDB, 0xC3
+ }
+ },
+ {
+ 143,
+ 79,
+ 0x39,
+ 0x00BA,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xBA, 0x90, 0xE4, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x04, 0x62, 0xD0, 0x04, 0x51, 0xB5, 0x08, 0x50, 0x23, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x62, 0xD0, 0x04, 0x50, 0x04, 0x3A, 0xB5, 0xC0, 0xB7, 0x56, 0x03, 0x00, 0x80, 0xA9, 0x62, 0xD0, 0x00, 0x52, 0x03, 0x7C, 0x6D, 0x8A, 0x51, 0xE8, 0x01, 0xE0, 0x54, 0x02, 0x51, 0xE9, 0x09, 0x01, 0x54, 0x01, 0x52, 0x03, 0x64, 0x64, 0x64, 0x01, 0x8B, 0x24
+ }
+ },
+ {
+ 144,
+ 79,
+ 0x39,
+ 0x00BB,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xBB, 0x03, 0x54, 0x00, 0x7C, 0x6F, 0xF6, 0x08, 0x52, 0x00, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x52, 0x02, 0x01, 0x01, 0x53, 0xE8, 0x52, 0x01, 0x09, 0x00, 0x7C, 0x6D, 0xE3, 0x3E, 0xE8, 0x53, 0xE8, 0x51, 0xE9, 0x08, 0x51, 0xE8, 0x08, 0x52, 0x00, 0x01, 0x01, 0x08, 0x7C, 0x32, 0x52, 0x62, 0xD0, 0x00, 0x52, 0x02, 0x01, 0x03, 0x7C, 0x6E, 0xA3, 0x08, 0x52, 0x00, 0x01, 0x03, 0x2A, 0x63
+ }
+ },
+ {
+ 145,
+ 79,
+ 0x39,
+ 0x00BC,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xBC, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFB, 0x62, 0xD0, 0x00, 0x52, 0x02, 0x01, 0x04, 0x53, 0xE8, 0x52, 0x01, 0x09, 0x00, 0x7C, 0x6D, 0xE3, 0x3E, 0xE8, 0x53, 0xE8, 0x51, 0xE9, 0x08, 0x51, 0xE8, 0x08, 0x52, 0x00, 0x01, 0x04, 0x08, 0x7C, 0x32, 0x52, 0x62, 0xD0, 0x00, 0x52, 0x02, 0x01, 0x06, 0x53, 0xE8, 0x52, 0x01, 0x09, 0x00, 0x7C, 0x6D, 0xE3, 0x3E, 0xE8, 0x53, 0xE8, 0x51, 0xE9, 0x08, 0x51, 0x0A, 0x24
+ }
+ },
+ {
+ 146,
+ 79,
+ 0x39,
+ 0x00BD,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xBD, 0xE8, 0x08, 0x52, 0x00, 0x01, 0x06, 0x08, 0x7C, 0x32, 0x52, 0x38, 0xFA, 0x77, 0x03, 0x62, 0xD0, 0x04, 0x52, 0x03, 0x3A, 0xB5, 0xCF, 0x50, 0x50, 0x00, 0x08, 0x50, 0x25, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x38, 0xFC, 0x20, 0x7F, 0x62, 0xD0, 0x04, 0x51, 0xB5, 0x21, 0x0F, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x62, 0xD0, 0x04, 0x51, 0xB4, 0x21, 0xF0, 0x62, 0xD0, 0x00, 0x2A, 0xE9, 0x62, 0xD0, 0xCB, 0xA7
+ }
+ },
+ {
+ 147,
+ 79,
+ 0x39,
+ 0x00BE,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xBE, 0x03, 0x53, 0x9A, 0x51, 0x9A, 0x08, 0x50, 0x02, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x62, 0xD0, 0x01, 0x51, 0xE6, 0x08, 0x51, 0xE7, 0x08, 0x50, 0x03, 0x08, 0x7C, 0x32, 0x52, 0x62, 0xD0, 0x01, 0x51, 0xE4, 0x08, 0x51, 0xE5, 0x08, 0x50, 0x05, 0x08, 0x7C, 0x32, 0x52, 0x38, 0xFA, 0x7F, 0x10, 0x4F, 0x38, 0x07, 0x62, 0xD0, 0x04, 0x51, 0xB5, 0x21, 0x0F, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x62, 0xD0, 0xB2
+ }
+ },
+ {
+ 148,
+ 79,
+ 0x39,
+ 0x00BF,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xBF, 0xD0, 0x04, 0x51, 0xB4, 0x21, 0xF0, 0x62, 0xD0, 0x00, 0x2A, 0xE9, 0x62, 0xD0, 0x03, 0x53, 0x9A, 0x51, 0x9A, 0x08, 0x50, 0x02, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x56, 0x00, 0x00, 0x80, 0xCA, 0x56, 0x04, 0x00, 0x62, 0xD0, 0x04, 0x52, 0x00, 0x3A, 0xB5, 0xD0, 0x12, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0xC0, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x54, 0x04, 0x62, 0xD0, 0x00, 0x3F, 0x91
+ }
+ },
+ {
+ 149,
+ 79,
+ 0x39,
+ 0x00C0,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xC0, 0x52, 0x04, 0x7C, 0x6D, 0x8A, 0x51, 0xE8, 0x01, 0xE0, 0x54, 0x02, 0x51, 0xE9, 0x09, 0x01, 0x54, 0x01, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0x81, 0x0E, 0xE9, 0x0D, 0x7C, 0x6F, 0x5C, 0x54, 0x03, 0x52, 0x02, 0x01, 0x06, 0x53, 0xE8, 0x52, 0x01, 0x09, 0x00, 0x7C, 0x6D, 0xE3, 0x3E, 0xE8, 0x53, 0xE8, 0x51, 0xE9, 0x08, 0x51, 0xE8, 0x08, 0x52, 0x03, 0x08, 0x7C, 0x32, 0x52, 0x38, 0xFD, 0x62, 0xD0, 0xD7, 0xC2
+ }
+ },
+ {
+ 150,
+ 79,
+ 0x39,
+ 0x00C1,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xC1, 0x00, 0x52, 0x02, 0x01, 0x04, 0x53, 0xE8, 0x52, 0x01, 0x09, 0x00, 0x7C, 0x6D, 0xE3, 0x3E, 0xE8, 0x53, 0xE8, 0x51, 0xE9, 0x08, 0x51, 0xE8, 0x08, 0x52, 0x03, 0x01, 0x02, 0x08, 0x7C, 0x32, 0x52, 0x62, 0xD0, 0x00, 0x52, 0x02, 0x01, 0x03, 0x7C, 0x6E, 0xA3, 0x08, 0x52, 0x03, 0x01, 0x04, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFB, 0x7C, 0x6F, 0x4C, 0x52, 0x01, 0x60, 0xD4, 0x3E, 0xE8, 0x54, 0x05, 0xAB, 0x6B
+ }
+ },
+ {
+ 151,
+ 79,
+ 0x39,
+ 0x00C2,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xC2, 0x48, 0x00, 0x01, 0xA0, 0x18, 0x52, 0x05, 0x21, 0x0F, 0x53, 0xE9, 0x52, 0x06, 0x2A, 0xE9, 0x08, 0x52, 0x03, 0x11, 0x01, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x80, 0x0C, 0x52, 0x05, 0x62, 0xD0, 0x00, 0x64, 0x64, 0x64, 0x64, 0x54, 0x06, 0x77, 0x00, 0x3D, 0x00, 0x04, 0xCF, 0x33, 0x38, 0xF9, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x71, 0x10, 0x41, 0x04, 0x5F, 0x70, 0xCF, 0x62, 0xD0, 0x00, 0x4D, 0xB0
+ }
+ },
+ {
+ 152,
+ 79,
+ 0x39,
+ 0x00C3,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xC3, 0x51, 0xAF, 0x29, 0xA0, 0x7C, 0x6F, 0x20, 0x10, 0x7C, 0x20, 0x0B, 0x7C, 0x20, 0x50, 0x20, 0x10, 0x50, 0x01, 0x08, 0x50, 0x00, 0x08, 0x50, 0xA0, 0x08, 0x08, 0x7C, 0x20, 0x57, 0x38, 0xFC, 0x20, 0x62, 0xC8, 0x0B, 0x62, 0xCA, 0x24, 0x43, 0xD6, 0x01, 0x62, 0xCD, 0x00, 0x56, 0x00, 0x20, 0x80, 0x06, 0x62, 0xCF, 0x00, 0x7B, 0x00, 0x3D, 0x00, 0x00, 0xBF, 0xF7, 0x41, 0xD6, 0xFE, 0x38, 0xFF, 0x54, 0xBF
+ }
+ },
+ {
+ 153,
+ 79,
+ 0x39,
+ 0x00C4,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xC4, 0x20, 0x7F, 0x10, 0x4F, 0x3D, 0xFC, 0x21, 0xD0, 0x0C, 0x41, 0xD6, 0xEF, 0x41, 0xE0, 0x7F, 0x62, 0xC8, 0x0B, 0x80, 0x0A, 0x62, 0xC8, 0x00, 0x43, 0xD6, 0x10, 0x43, 0xE0, 0x80, 0x20, 0x7F, 0x43, 0xD6, 0x01, 0x40, 0x62, 0xD0, 0x00, 0x51, 0xAF, 0x29, 0xA0, 0x7C, 0x6F, 0x20, 0x71, 0x10, 0x43, 0x04, 0xA0, 0x70, 0xCF, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x5D, 0xF7, 0x54, 0x00, 0x70, 0xFE, 0x7C, 0xDE, 0xD4
+ }
+ },
+ {
+ 154,
+ 79,
+ 0x39,
+ 0x00C5,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xC5, 0x70, 0xF8, 0xB0, 0x13, 0x7C, 0x73, 0x90, 0xBF, 0xFC, 0x71, 0x01, 0x40, 0x70, 0xFE, 0x62, 0xE3, 0x38, 0x41, 0xD6, 0xFE, 0x80, 0x06, 0x10, 0x7C, 0x33, 0x60, 0x20, 0x71, 0x10, 0x41, 0x04, 0x5F, 0x70, 0xCF, 0x62, 0xD0, 0x00, 0x51, 0xAF, 0x29, 0xA0, 0x7C, 0x6F, 0x20, 0x48, 0x00, 0x01, 0xA0, 0x03, 0x71, 0x01, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x7C, 0x33, 0x60, 0x20, 0x71, 0x10, 0x41, 0x04, 0x7F, 0x17
+ }
+ },
+ {
+ 155,
+ 79,
+ 0x39,
+ 0x00C6,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xC6, 0x5F, 0x70, 0xCF, 0x62, 0xD0, 0x00, 0x51, 0xAF, 0x29, 0xA0, 0x7C, 0x6F, 0x20, 0x71, 0x10, 0x43, 0xEC, 0x02, 0x70, 0xCF, 0x62, 0xDA, 0x7F, 0x43, 0xE0, 0x80, 0x9F, 0x83, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x9F, 0x92, 0x71, 0x10, 0x43, 0xEC, 0x02, 0x70, 0xCF, 0x62, 0xDA, 0x7F, 0x43, 0xE0, 0x80, 0x9F, 0x6D, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x7C, 0x73, 0x89, 0x38, 0xFF, 0x20, 0xF5, 0x04
+ }
+ },
+ {
+ 156,
+ 79,
+ 0x39,
+ 0x00C7,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xC7, 0x7F, 0x7C, 0x73, 0x89, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x5D, 0xC8, 0x39, 0x00, 0xB0, 0x18, 0x7C, 0x73, 0x90, 0xA0, 0x09, 0x56, 0x01, 0x01, 0x56, 0x00, 0x00, 0x80, 0x04, 0x7C, 0x6F, 0xC9, 0x62, 0xD0, 0x00, 0x52, 0x01, 0x80, 0x1D, 0x5D, 0xC9, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x47, 0xE9, 0x01, 0xA0, 0x09, 0x56, 0x01, 0x01, 0x56, 0x00, 0x00, 0x80, 0x04, 0x7C, 0x6F, 0xC9, 0x62, 0xD0, 0x00, 0xEB, 0xF1
+ }
+ },
+ {
+ 157,
+ 79,
+ 0x39,
+ 0x00C8,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xC8, 0x52, 0x01, 0x38, 0xFE, 0x20, 0x7F, 0x62, 0xD0, 0x00, 0x50, 0x00, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x7C, 0x70, 0xF8, 0xA0, 0x25, 0x5D, 0xD6, 0x53, 0xE9, 0x2E, 0xE9, 0xFE, 0x51, 0xE9, 0x54, 0x00, 0x43, 0xD6, 0x01, 0x52, 0xFC, 0x60, 0xCD, 0x52, 0xFB, 0x60, 0xCF, 0x5D, 0xD6, 0x53, 0xE9, 0x52, 0x00, 0x24, 0xE9, 0x51, 0xE9, 0x60, 0xD6, 0x80, 0x16, 0x3D, 0xFC, 0xA0, 0xD0, 0x11, 0x7C, 0x6F, 0x06, 0x28
+ }
+ },
+ {
+ 158,
+ 79,
+ 0x39,
+ 0x00C9,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xC9, 0xB9, 0x55, 0xE9, 0x00, 0x06, 0xE8, 0x00, 0x7C, 0x71, 0x08, 0x52, 0xFB, 0x3F, 0xE8, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x03, 0x52, 0xFB, 0x54, 0x01, 0x52, 0xFA, 0x54, 0x00, 0x7C, 0x70, 0xF8, 0xA0, 0x1C, 0x7C, 0x71, 0x65, 0x60, 0xCD, 0x52, 0x00, 0x60, 0xCF, 0x52, 0x01, 0x60, 0xCF, 0x5D, 0xD6, 0x53, 0xE9, 0x52, 0x02, 0x24, 0xE9, 0x51, 0xE9, 0x60, 0xD6, 0x80, 0x26, 0x3D, 0xFC, 0x41, 0x9F
+ }
+ },
+ {
+ 159,
+ 79,
+ 0x39,
+ 0x00CA,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xCA, 0x9F, 0xD0, 0x21, 0x7C, 0x6F, 0xB9, 0x55, 0xE9, 0x00, 0x06, 0xE8, 0x00, 0x0E, 0xE9, 0x01, 0x7C, 0x6F, 0xD9, 0x52, 0xFC, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x06, 0xE8, 0x01, 0x7C, 0x71, 0x08, 0x52, 0x01, 0x3F, 0xE8, 0x38, 0xFD, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x7C, 0x70, 0xF8, 0xA0, 0x29, 0x5D, 0xD6, 0x53, 0xE9, 0x2E, 0xE9, 0xFE, 0x51, 0xE9, 0x54, 0x01, 0x43, 0xD6, 0x01, 0x10, 0x52, 0xEA, 0xF2
+ }
+ },
+ {
+ 160,
+ 79,
+ 0x39,
+ 0x00CB,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xCB, 0xFC, 0x7C, 0x33, 0x49, 0x62, 0xD0, 0x00, 0x20, 0x54, 0x00, 0x5D, 0xD6, 0x53, 0xE9, 0x52, 0x01, 0x24, 0xE9, 0x51, 0xE9, 0x60, 0xD6, 0x80, 0x17, 0x3D, 0xFC, 0xA0, 0xD0, 0x12, 0x7C, 0x6F, 0xB9, 0x55, 0xE9, 0x00, 0x06, 0xE8, 0x00, 0x0E, 0xE9, 0x01, 0x7C, 0x6D, 0x83, 0x54, 0x00, 0x52, 0x00, 0x62, 0xD0, 0x00, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x03, 0x7C, 0x70, 0xF8, 0xA0, 0x1B, 0x45, 0xA9
+ }
+ },
+ {
+ 161,
+ 79,
+ 0x39,
+ 0x00CC,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xCC, 0x7C, 0x71, 0x65, 0x08, 0x7C, 0x33, 0x53, 0x38, 0xFF, 0x7C, 0x72, 0x25, 0x5D, 0xD6, 0x53, 0xE9, 0x52, 0x02, 0x24, 0xE9, 0x51, 0xE9, 0x60, 0xD6, 0x80, 0x29, 0x3D, 0xFC, 0x9F, 0xD0, 0x24, 0x7C, 0x6F, 0xB9, 0x55, 0xE9, 0x00, 0x06, 0xE8, 0x00, 0x0E, 0xE9, 0x01, 0x7C, 0x6D, 0x83, 0x54, 0x00, 0x52, 0xFC, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x06, 0xE8, 0x01, 0x0E, 0xE9, 0x01, 0x7C, 0x6D, 0x83, 0xFD, 0x1A
+ }
+ },
+ {
+ 162,
+ 79,
+ 0x39,
+ 0x00CD,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xCD, 0x54, 0x01, 0x7C, 0x71, 0x2E, 0x38, 0xFD, 0x20, 0x7F, 0x60, 0xCD, 0x5D, 0xF7, 0x08, 0x70, 0xFE, 0x5D, 0xCF, 0x7E, 0x60, 0xCD, 0x5D, 0xF7, 0x08, 0x70, 0xFE, 0x5D, 0xCF, 0x5C, 0x5D, 0xCF, 0x7E, 0x49, 0xC9, 0x01, 0xBF, 0xFC, 0x41, 0xD6, 0xFE, 0x7F, 0x41, 0x05, 0xF7, 0x7C, 0x73, 0x82, 0x62, 0xD0, 0x00, 0x51, 0xAF, 0x29, 0x08, 0x7C, 0x6F, 0x20, 0x71, 0x10, 0x43, 0x05, 0x08, 0x43, 0x04, 0xA4, 0x69
+ }
+ },
+ {
+ 163,
+ 79,
+ 0x39,
+ 0x00CE,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xCE, 0x08, 0x70, 0xCF, 0x62, 0xD0, 0x04, 0x55, 0xB9, 0x00, 0x62, 0xD0, 0x03, 0x55, 0x99, 0x04, 0x55, 0x9A, 0x00, 0x55, 0x9B, 0xF8, 0x55, 0x9C, 0x00, 0x55, 0x9E, 0x64, 0x55, 0x9D, 0x32, 0x55, 0x9F, 0x00, 0x55, 0xA0, 0x00, 0x7C, 0x30, 0xB2, 0x90, 0x10, 0x7C, 0x6F, 0x64, 0x10, 0x57, 0x01, 0x50, 0xF4, 0x7C, 0x2B, 0xA8, 0x20, 0x7C, 0x6E, 0xE8, 0x7F, 0x10, 0x4F, 0x38, 0x03, 0x7C, 0x31, 0x35, 0x13, 0x48
+ }
+ },
+ {
+ 164,
+ 79,
+ 0x39,
+ 0x00CF,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xCF, 0x7C, 0x6F, 0x2F, 0xB0, 0x06, 0x56, 0x01, 0x20, 0x80, 0x04, 0x56, 0x01, 0xA0, 0x52, 0x01, 0x08, 0x7C, 0x31, 0x02, 0x38, 0xFF, 0x62, 0xD0, 0x03, 0x51, 0x99, 0x21, 0xFC, 0x62, 0xD0, 0x00, 0x08, 0x50, 0x00, 0x08, 0x7C, 0x32, 0x0C, 0x50, 0x20, 0x08, 0x50, 0x01, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x3D, 0x00, 0x00, 0xB0, 0x28, 0x62, 0xD0, 0x04, 0x51, 0xB9, 0x08, 0x50, 0x01, 0x08, 0x7C, 0x7C, 0x1B
+ }
+ },
+ {
+ 165,
+ 79,
+ 0x39,
+ 0x00D0,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xD0, 0x32, 0x0C, 0x38, 0xFE, 0x50, 0x00, 0x08, 0x50, 0x02, 0x08, 0x7C, 0x32, 0x0C, 0x62, 0xD0, 0x03, 0x51, 0x9B, 0x08, 0x50, 0x1E, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x82, 0x52, 0x3D, 0x00, 0x10, 0xB1, 0x87, 0x50, 0x00, 0x08, 0x50, 0x02, 0x08, 0x7C, 0x32, 0x0C, 0x7C, 0x40, 0x1F, 0x62, 0xD0, 0x00, 0x08, 0x50, 0x01, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x50, 0xC0, 0x08, 0x50, 0x03, 0x08, 0x01, 0x26
+ }
+ },
+ {
+ 166,
+ 79,
+ 0x39,
+ 0x00D1,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xD1, 0x7C, 0x32, 0x0C, 0x50, 0xC1, 0x08, 0x50, 0x04, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x50, 0xC2, 0x08, 0x50, 0x05, 0x08, 0x7C, 0x32, 0x0C, 0x50, 0x00, 0x08, 0x50, 0x06, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x10, 0x50, 0x00, 0x7C, 0x2B, 0x69, 0x62, 0xD0, 0x00, 0x20, 0x08, 0x50, 0x07, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x10, 0x50, 0x01, 0x7C, 0x2B, 0x69, 0x62, 0xD0, 0x00, 0x20, 0x08, 0xD6, 0xD1
+ }
+ },
+ {
+ 167,
+ 79,
+ 0x39,
+ 0x00D2,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xD2, 0x50, 0x08, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x10, 0x50, 0x02, 0x7C, 0x2B, 0x69, 0x62, 0xD0, 0x00, 0x20, 0x08, 0x50, 0x09, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x10, 0x50, 0x03, 0x7C, 0x2B, 0x69, 0x62, 0xD0, 0x00, 0x20, 0x08, 0x50, 0x0A, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x10, 0x50, 0x04, 0x7C, 0x2B, 0x69, 0x62, 0xD0, 0x00, 0x20, 0x08, 0x50, 0x0B, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xAF, 0x84
+ }
+ },
+ {
+ 168,
+ 79,
+ 0x39,
+ 0x00D3,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xD3, 0xFE, 0x10, 0x50, 0x05, 0x7C, 0x2B, 0x69, 0x62, 0xD0, 0x00, 0x20, 0x08, 0x50, 0x0C, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x10, 0x50, 0x06, 0x7C, 0x2B, 0x69, 0x62, 0xD0, 0x00, 0x20, 0x08, 0x50, 0x0D, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x10, 0x50, 0x07, 0x7C, 0x2B, 0x69, 0x62, 0xD0, 0x00, 0x20, 0x08, 0x50, 0x0E, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x50, 0x07, 0x10, 0x06, 0x33
+ }
+ },
+ {
+ 169,
+ 79,
+ 0x39,
+ 0x00D4,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xD4, 0x08, 0x57, 0xA0, 0x28, 0x53, 0xE9, 0x18, 0x75, 0x09, 0x00, 0x28, 0x53, 0xE8, 0x20, 0x51, 0xE9, 0x08, 0x51, 0xE8, 0x08, 0x50, 0x0F, 0x08, 0x7C, 0x32, 0x52, 0x38, 0xFD, 0x50, 0x10, 0x08, 0x50, 0x12, 0x08, 0x50, 0x11, 0x08, 0x7C, 0x32, 0x52, 0x50, 0xA0, 0x08, 0x50, 0x02, 0x08, 0x50, 0x13, 0x08, 0x7C, 0x32, 0x52, 0x38, 0xFA, 0x50, 0x04, 0x08, 0x50, 0x00, 0x08, 0x50, 0x15, 0x08, 0x7C, 0x62, 0xEC
+ }
+ },
+ {
+ 170,
+ 79,
+ 0x39,
+ 0x00D5,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xD5, 0x32, 0x52, 0x50, 0x00, 0x08, 0x50, 0x17, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFB, 0x50, 0x00, 0x08, 0x50, 0x18, 0x08, 0x7C, 0x32, 0x0C, 0x50, 0x00, 0x08, 0x50, 0x19, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x50, 0x00, 0x08, 0x50, 0x1A, 0x08, 0x7C, 0x32, 0x0C, 0x50, 0x00, 0x08, 0x50, 0x1B, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x50, 0x00, 0x08, 0x50, 0x1C, 0x08, 0x7C, 0x32, 0x0C, 0x62, 0xD0, 0x66, 0xF5
+ }
+ },
+ {
+ 171,
+ 79,
+ 0x39,
+ 0x00D6,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xD6, 0x03, 0x51, 0x9C, 0x08, 0x50, 0x1D, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x62, 0xD0, 0x03, 0x51, 0x9E, 0x08, 0x50, 0x1E, 0x08, 0x7C, 0x32, 0x0C, 0x62, 0xD0, 0x03, 0x51, 0x9D, 0x08, 0x50, 0x1F, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x80, 0xC7, 0x3D, 0x00, 0x20, 0xB0, 0x03, 0x80, 0xC0, 0x3D, 0x00, 0x30, 0xB0, 0xBB, 0x50, 0x01, 0x08, 0x50, 0x00, 0x08, 0x7C, 0x32, 0x0C, 0x50, 0x04, 0x08, 0x7D, 0x24
+ }
+ },
+ {
+ 172,
+ 79,
+ 0x39,
+ 0x00D7,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xD7, 0x50, 0x01, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x50, 0x01, 0x08, 0x50, 0x02, 0x08, 0x7C, 0x32, 0x0C, 0x62, 0xD0, 0x03, 0x51, 0x9F, 0x08, 0x50, 0x29, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x50, 0x04, 0x08, 0x50, 0x2A, 0x08, 0x7C, 0x32, 0x0C, 0x50, 0x08, 0x08, 0x50, 0x2B, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x50, 0x08, 0x08, 0x50, 0x2C, 0x08, 0x7C, 0x32, 0x0C, 0x50, 0x00, 0x08, 0x50, 0xFF, 0x29
+ }
+ },
+ {
+ 173,
+ 79,
+ 0x39,
+ 0x00D8,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xD8, 0x48, 0x08, 0x50, 0x2D, 0x08, 0x7C, 0x32, 0x52, 0x38, 0xFB, 0x50, 0x1C, 0x08, 0x50, 0x2F, 0x08, 0x7C, 0x32, 0x0C, 0x50, 0x00, 0x08, 0x50, 0x30, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x50, 0x08, 0x08, 0x50, 0x31, 0x08, 0x7C, 0x32, 0x0C, 0x50, 0x08, 0x08, 0x50, 0x32, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x50, 0x5A, 0x08, 0x50, 0x33, 0x08, 0x7C, 0x32, 0x0C, 0x50, 0x00, 0x08, 0x50, 0x34, 0xD9, 0xDE
+ }
+ },
+ {
+ 174,
+ 79,
+ 0x39,
+ 0x00D9,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xD9, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x50, 0x04, 0x08, 0x50, 0x35, 0x08, 0x7C, 0x32, 0x0C, 0x50, 0x0C, 0x08, 0x50, 0x36, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x50, 0x05, 0x08, 0x50, 0x37, 0x08, 0x7C, 0x32, 0x0C, 0x50, 0x01, 0x08, 0x50, 0x38, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x7C, 0x2B, 0x1A, 0x7C, 0x31, 0x1F, 0x38, 0xFD, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x7C, 0x32, 0x06, 0x7C, 0x20, 0x6D
+ }
+ },
+ {
+ 175,
+ 79,
+ 0x39,
+ 0x00DA,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xDA, 0x6F, 0x3C, 0x54, 0x00, 0x3D, 0x00, 0x30, 0xB0, 0x05, 0x90, 0xE8, 0x80, 0x03, 0x90, 0x4B, 0x62, 0xD0, 0x03, 0x51, 0x99, 0x21, 0x01, 0x62, 0xD0, 0x00, 0x39, 0x01, 0xB0, 0x19, 0x7C, 0x31, 0x35, 0x62, 0xD4, 0x00, 0x62, 0xD5, 0x00, 0x62, 0xD1, 0x00, 0x62, 0xD3, 0x00, 0x62, 0xD0, 0x00, 0x62, 0xE3, 0x38, 0x50, 0x00, 0x00, 0x7C, 0x6F, 0x3C, 0x54, 0x01, 0x52, 0x01, 0x3B, 0x00, 0xA0, 0x17, 0xE4, 0xF6
+ }
+ },
+ {
+ 176,
+ 79,
+ 0x39,
+ 0x00DB,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xDB, 0x52, 0x01, 0x08, 0x52, 0x00, 0x08, 0x7C, 0x2B, 0x1B, 0x9C, 0xEE, 0x52, 0x01, 0x08, 0x52, 0x00, 0x08, 0x7C, 0x2B, 0x1F, 0x38, 0xFC, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x7C, 0x6F, 0x2F, 0xB0, 0x30, 0x50, 0x00, 0x08, 0x7C, 0x32, 0xA7, 0x62, 0xD0, 0x03, 0x53, 0x99, 0x50, 0x1E, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFE, 0x62, 0xD0, 0x03, 0x53, 0x9B, 0x47, 0x99, 0x02, 0xA0, 0x70, 0xFB, 0x25
+ }
+ },
+ {
+ 177,
+ 79,
+ 0x39,
+ 0x00DC,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xDC, 0x51, 0x99, 0x21, 0xFD, 0x62, 0xD0, 0x00, 0x08, 0x50, 0x00, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x80, 0x5E, 0x3D, 0x00, 0x10, 0xB0, 0x33, 0x50, 0x00, 0x08, 0x7C, 0x32, 0xA7, 0x62, 0xD0, 0x03, 0x53, 0x99, 0x50, 0x1D, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFE, 0x62, 0xD0, 0x03, 0x53, 0x9C, 0x50, 0x1F, 0x08, 0x7C, 0x32, 0xA7, 0x62, 0xD0, 0x03, 0x53, 0x9D, 0x50, 0x1E, 0x08, 0x7C, 0x32, 0xA7, 0x46, 0xBC
+ }
+ },
+ {
+ 178,
+ 79,
+ 0x39,
+ 0x00DD,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xDD, 0x38, 0xFE, 0x62, 0xD0, 0x03, 0x53, 0x9E, 0x80, 0x27, 0x3D, 0x00, 0x20, 0xB0, 0x10, 0x50, 0x00, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFF, 0x62, 0xD0, 0x03, 0x53, 0x99, 0x80, 0x13, 0x48, 0x00, 0x40, 0xA0, 0x0E, 0x50, 0x00, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFF, 0x62, 0xD0, 0x03, 0x53, 0x99, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x04, 0x50, 0x00, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFF, 0x62, 0xAA, 0x85
+ }
+ },
+ {
+ 179,
+ 79,
+ 0x39,
+ 0x00DE,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xDE, 0xD0, 0x00, 0x54, 0x00, 0x3D, 0x00, 0x01, 0xA0, 0x1F, 0x52, 0x00, 0x21, 0x70, 0x39, 0x30, 0xB0, 0x0E, 0x50, 0x01, 0x08, 0x50, 0x00, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x80, 0xE7, 0x52, 0x00, 0x62, 0xD0, 0x03, 0x53, 0x99, 0x80, 0xDE, 0x50, 0x29, 0x08, 0x7C, 0x32, 0xA7, 0x62, 0xD0, 0x03, 0x53, 0x9F, 0x50, 0x02, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x39, 0x81, 0xB0, 0x82, 0x36
+ }
+ },
+ {
+ 180,
+ 79,
+ 0x39,
+ 0x00DF,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xDF, 0xC4, 0x50, 0x2A, 0x08, 0x7C, 0x32, 0xA7, 0x62, 0xD0, 0x00, 0x53, 0xA5, 0x50, 0x2B, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x53, 0x15, 0x50, 0x2C, 0x08, 0x7C, 0x32, 0xA7, 0x62, 0xD0, 0x00, 0x53, 0x16, 0x50, 0x2D, 0x08, 0x7C, 0x32, 0xF7, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x00, 0x53, 0xA3, 0x18, 0x53, 0xA4, 0x50, 0x2F, 0x08, 0x7C, 0x28, 0x83
+ }
+ },
+ {
+ 181,
+ 79,
+ 0x39,
+ 0x00E0,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xE0, 0x32, 0xA7, 0x38, 0xFF, 0x62, 0xD0, 0x00, 0x53, 0x42, 0x50, 0x30, 0x08, 0x7C, 0x32, 0xA7, 0x62, 0xD0, 0x04, 0x53, 0xB7, 0x50, 0x31, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x53, 0xA6, 0x50, 0x32, 0x08, 0x7C, 0x32, 0xA7, 0x62, 0xD0, 0x00, 0x53, 0x17, 0x50, 0x36, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x53, 0xA7, 0x50, 0x37, 0x08, 0x7C, 0x32, 0xA7, 0x62, 0x39, 0xA6
+ }
+ },
+ {
+ 182,
+ 79,
+ 0x39,
+ 0x00E1,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xE1, 0xD0, 0x00, 0x53, 0xA8, 0x50, 0x38, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x53, 0xA9, 0x10, 0x7C, 0x18, 0x83, 0x7C, 0x17, 0xB7, 0x20, 0x80, 0x04, 0x62, 0xE3, 0x38, 0x7C, 0x31, 0xC5, 0x62, 0xD0, 0x00, 0x39, 0x00, 0xBF, 0xF4, 0x7C, 0x71, 0x10, 0x7C, 0x49, 0x07, 0x62, 0xE3, 0x38, 0x52, 0x01, 0x71, 0x10, 0x60, 0xE0, 0x50, 0x01, 0x08, 0x50, 0x02, 0x08, 0x70, 0xCF, 0x7C, 0xFE, 0x31
+ }
+ },
+ {
+ 183,
+ 79,
+ 0x39,
+ 0x00E2,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xE2, 0x32, 0x0C, 0x38, 0xFE, 0x38, 0xFC, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x7C, 0x6F, 0x2F, 0xB0, 0x06, 0x3D, 0xFC, 0x00, 0xB0, 0x0B, 0x3D, 0x00, 0x20, 0xA0, 0x06, 0x48, 0x00, 0x40, 0xA0, 0x26, 0x62, 0xD0, 0x04, 0x06, 0xB9, 0x40, 0x51, 0xB9, 0x29, 0x20, 0x62, 0xD0, 0x00, 0x08, 0x50, 0x01, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x80, 0x04, 0x62, 0xE3, 0x38, 0x7C, 0x31, 0xC5, 0x62, 0xD0, 0xA4, 0x7E
+ }
+ },
+ {
+ 184,
+ 79,
+ 0x39,
+ 0x00E3,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xE3, 0x00, 0x39, 0x00, 0xBF, 0xF4, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x7C, 0x6F, 0x2F, 0xB0, 0x06, 0x3D, 0xFC, 0x00, 0xB0, 0x0B, 0x3D, 0x00, 0x20, 0xA0, 0x06, 0x48, 0x00, 0x40, 0xA0, 0x0F, 0x62, 0xD0, 0x04, 0x51, 0xB9, 0x08, 0x50, 0x01, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x50, 0x00, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFF, 0x21, 0x80, 0x62, 0xD0, 0x04, 0x53, 0xB8, 0x38, 0xFF, 0xE6, 0x03
+ }
+ },
+ {
+ 185,
+ 79,
+ 0x39,
+ 0x00E4,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xE4, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x7C, 0x6F, 0x2F, 0xB0, 0x0A, 0x3D, 0xFC, 0x01, 0xB0, 0x19, 0x90, 0xC1, 0x80, 0x15, 0x3D, 0x00, 0x10, 0xB0, 0x05, 0x90, 0x63, 0x80, 0x0C, 0x3D, 0x00, 0x30, 0xB0, 0x05, 0x90, 0x21, 0x80, 0x03, 0x90, 0x56, 0x52, 0xFC, 0x08, 0x7C, 0x2B, 0x4C, 0x38, 0xFF, 0x38, 0xFF, 0x20, 0x7F, 0x62, 0xD0, 0x04, 0x51, 0xB9, 0x62, 0xD0, 0x00, 0x67, 0x67, 0x67, 0x67, 0x15, 0x62
+ }
+ },
+ {
+ 186,
+ 79,
+ 0x39,
+ 0x00E5,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xE5, 0x67, 0x67, 0x21, 0x03, 0x7F, 0x50, 0x84, 0x08, 0x50, 0x01, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x7C, 0x6F, 0x64, 0x7C, 0x32, 0x06, 0x62, 0xD0, 0x00, 0x62, 0xE3, 0x38, 0x50, 0x01, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFF, 0x62, 0xD0, 0x00, 0x39, 0x04, 0xA0, 0x10, 0x50, 0x00, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFF, 0x62, 0xD0, 0x00, 0x39, 0x01, 0xAF, 0xDA, 0x7C, 0x6E, 0xE8, 0x7F, 0x10, 0x4F, 0xD5, 0xE3
+ }
+ },
+ {
+ 187,
+ 79,
+ 0x39,
+ 0x00E6,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xE6, 0x38, 0x02, 0x7C, 0x6F, 0x64, 0x56, 0x01, 0xFA, 0x56, 0x00, 0x00, 0x80, 0x36, 0x7C, 0x32, 0x06, 0x62, 0xD0, 0x00, 0x50, 0x00, 0x08, 0x7C, 0x32, 0xA7, 0x38, 0xFF, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x26, 0xE9, 0x80, 0x62, 0xD0, 0x04, 0x51, 0xB8, 0x62, 0xD0, 0x00, 0x3A, 0xE9, 0xA0, 0x03, 0x80, 0x1C, 0x10, 0x57, 0x03, 0x50, 0xE3, 0x7C, 0x2B, 0xA8, 0x20, 0x62, 0xE3, 0x38, 0x7B, 0x01, 0x1F, 0xA4, 0x82
+ }
+ },
+ {
+ 188,
+ 79,
+ 0x39,
+ 0x00E7,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xE7, 0x00, 0x00, 0x3D, 0x00, 0x00, 0xBF, 0xC7, 0x3D, 0x01, 0x00, 0xBF, 0xC2, 0x7C, 0x6E, 0xE8, 0x38, 0xFE, 0x20, 0x7F, 0x7C, 0x6F, 0x64, 0x10, 0x57, 0x01, 0x50, 0xF4, 0x7C, 0x2B, 0xA8, 0x20, 0x7C, 0x6E, 0xE8, 0x7C, 0x32, 0x06, 0x62, 0xD0, 0x00, 0x7F, 0x7C, 0x31, 0x77, 0x7F, 0x7C, 0x31, 0xC1, 0x7F, 0x43, 0x05, 0x08, 0x62, 0xD0, 0x00, 0x26, 0xB0, 0xFB, 0x51, 0xB0, 0x60, 0x00, 0x62, 0xDA, 0x4A, 0xCF
+ }
+ },
+ {
+ 189,
+ 79,
+ 0x39,
+ 0x00E8,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xE8, 0xEF, 0x43, 0xE0, 0x10, 0x7C, 0x31, 0x9D, 0x7F, 0x7C, 0x31, 0xB6, 0x7C, 0x73, 0x82, 0x41, 0x05, 0xF7, 0x62, 0xD0, 0x00, 0x51, 0xB0, 0x29, 0x04, 0x53, 0xB0, 0x51, 0xB0, 0x60, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x62, 0xD0, 0x00, 0x50, 0x00, 0x7F, 0x10, 0x4F, 0x20, 0x7F, 0x7F, 0x10, 0x4F, 0x20, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xC3, 0x00, 0x62, 0xD0, 0x04, 0x55, 0xC2, 0x00, 0x62, 0xD0, 0x04, 0x09, 0x4E
+ }
+ },
+ {
+ 190,
+ 79,
+ 0x39,
+ 0x00E9,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xE9, 0x55, 0xC1, 0x00, 0x7C, 0x3A, 0x1F, 0x10, 0x7C, 0x49, 0x5B, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x62, 0xD0, 0x03, 0x51, 0x9B, 0x21, 0xF0, 0x62, 0xD0, 0x04, 0x53, 0xC2, 0x7C, 0x6F, 0x2F, 0xA0, 0x06, 0x3D, 0x00, 0x30, 0xB0, 0x0B, 0x7C, 0x73, 0x26, 0x62, 0xD0, 0x00, 0x53, 0x39, 0x80, 0x07, 0x62, 0xD0, 0x00, 0x55, 0x39, 0x00, 0x62, 0xD0, 0x00, 0x51, 0x39, 0x62, 0xD0, 0x00, 0x53, 0x3A, 0x4C, 0xD5
+ }
+ },
+ {
+ 191,
+ 79,
+ 0x39,
+ 0x00EA,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xEA, 0x62, 0xD0, 0x00, 0x51, 0x39, 0x62, 0xD0, 0x00, 0x53, 0x3B, 0x62, 0xD0, 0x00, 0x51, 0x39, 0x62, 0xD0, 0x00, 0x53, 0x3C, 0x7C, 0x3A, 0x21, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x62, 0xD0, 0x04, 0x51, 0xCF, 0x54, 0x01, 0x10, 0x52, 0xFB, 0x7C, 0x49, 0x92, 0x20, 0x62, 0xD0, 0x04, 0x53, 0xC3, 0x3C, 0xC3, 0x00, 0xB0, 0x4F, 0x52, 0xFB, 0x3B, 0xFC, 0xA0, 0x49, 0x52, 0xFC, 0x3B, 0xFE, 0x3A
+ }
+ },
+ {
+ 192,
+ 79,
+ 0x39,
+ 0x00EB,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xEB, 0xFB, 0xD0, 0x09, 0x62, 0xD0, 0x04, 0x55, 0xC3, 0x2F, 0x80, 0x21, 0x62, 0xD0, 0x04, 0x55, 0xC3, 0x4F, 0x3D, 0xFB, 0x00, 0xB0, 0x16, 0x7C, 0x3A, 0x2C, 0x7C, 0x3A, 0x22, 0x62, 0xD0, 0x00, 0x39, 0x00, 0xA0, 0x09, 0x7C, 0x3A, 0x22, 0x62, 0xD0, 0x04, 0x53, 0xC3, 0x62, 0xD0, 0x04, 0x51, 0xC1, 0x62, 0xD0, 0x04, 0x3A, 0xC3, 0xB0, 0x0C, 0x62, 0xD0, 0x04, 0x52, 0x01, 0x01, 0x01, 0x53, 0xCF, 0x63, 0x05
+ }
+ },
+ {
+ 193,
+ 79,
+ 0x39,
+ 0x00EC,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xEC, 0x80, 0x04, 0x7C, 0x70, 0x5B, 0x62, 0xD0, 0x04, 0x3C, 0xC3, 0x00, 0xA0, 0x09, 0x52, 0xFB, 0x08, 0x7C, 0x3A, 0x28, 0x38, 0xFF, 0x62, 0xD0, 0x04, 0x51, 0xC3, 0x08, 0x52, 0xFB, 0x08, 0x91, 0x86, 0x38, 0xFE, 0x39, 0x00, 0xA0, 0x21, 0x62, 0xD0, 0x04, 0x55, 0xC3, 0xFF, 0x62, 0xD0, 0x04, 0x51, 0xC1, 0x62, 0xD0, 0x04, 0x3A, 0xC3, 0xB0, 0x0C, 0x62, 0xD0, 0x04, 0x52, 0x01, 0x01, 0x01, 0x53, 0x63, 0x06
+ }
+ },
+ {
+ 194,
+ 79,
+ 0x39,
+ 0x00ED,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xED, 0xCF, 0x80, 0x04, 0x7C, 0x70, 0x5B, 0x62, 0xD0, 0x04, 0x3C, 0xC3, 0x00, 0xA0, 0x06, 0x56, 0x00, 0x01, 0x80, 0x04, 0x56, 0x00, 0x00, 0x52, 0xFB, 0x08, 0x52, 0xFC, 0x08, 0x50, 0x04, 0x08, 0x50, 0xC3, 0x08, 0x62, 0xD0, 0x00, 0x50, 0x0F, 0x08, 0x10, 0x7C, 0x2B, 0x40, 0x38, 0xFA, 0x62, 0xD0, 0x04, 0x3C, 0xC3, 0x00, 0xA0, 0x2B, 0x90, 0x31, 0x62, 0xD0, 0x04, 0x3C, 0xC3, 0x00, 0xA0, 0x21, 0x41, 0xC3
+ }
+ },
+ {
+ 195,
+ 79,
+ 0x39,
+ 0x00EE,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xEE, 0x62, 0xD0, 0x04, 0x3C, 0xCF, 0x00, 0xB0, 0x0F, 0x62, 0xD0, 0x04, 0x3C, 0xC3, 0xFF, 0xA0, 0x07, 0x62, 0xD0, 0x04, 0x55, 0xCF, 0x80, 0x62, 0xD0, 0x04, 0x51, 0xC3, 0x62, 0xD0, 0x04, 0x53, 0xC1, 0x52, 0x00, 0x62, 0xD0, 0x00, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x62, 0xD0, 0x04, 0x51, 0xC3, 0x54, 0x00, 0x3C, 0xC3, 0x00, 0xA0, 0x0B, 0x7C, 0x6F, 0x3C, 0x62, 0xD0, 0x00, 0x39, 0x14, 0x6A
+ }
+ },
+ {
+ 196,
+ 79,
+ 0x39,
+ 0x00EF,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xEF, 0x30, 0xB0, 0x03, 0x80, 0xB1, 0x50, 0x10, 0x08, 0x50, 0x29, 0x08, 0x50, 0x28, 0x08, 0x90, 0xA9, 0x50, 0x20, 0x08, 0x50, 0x3F, 0x08, 0x50, 0x30, 0x08, 0x90, 0x9E, 0x38, 0xFA, 0x50, 0x40, 0x08, 0x50, 0x49, 0x08, 0x50, 0x48, 0x08, 0x90, 0x91, 0x50, 0x80, 0x08, 0x50, 0x9F, 0x08, 0x50, 0x90, 0x08, 0x90, 0x86, 0x38, 0xFA, 0x62, 0xD0, 0x04, 0x51, 0xC3, 0x3B, 0x00, 0xA0, 0x6E, 0x3D, 0x00, 0x76, 0x2F
+ }
+ },
+ {
+ 197,
+ 79,
+ 0x39,
+ 0x00F0,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xF0, 0x28, 0xC0, 0x69, 0x50, 0x29, 0x3B, 0x00, 0xC0, 0x63, 0x62, 0xD0, 0x04, 0x51, 0xDF, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x65, 0xE9, 0x51, 0xE9, 0x01, 0x10, 0x62, 0xD0, 0x04, 0x53, 0xC3, 0x62, 0xD0, 0x04, 0x51, 0xC1, 0x62, 0xD0, 0x04, 0x3A, 0xC3, 0xB0, 0x0F, 0x62, 0xD0, 0x04, 0x51, 0xBF, 0x01, 0x01, 0x62, 0xD0, 0x04, 0x53, 0xCF, 0x80, 0x04, 0x7C, 0x70, 0x5B, 0x50, 0x10, 0x08, 0x50, 0x29, 0x67, 0x12
+ }
+ },
+ {
+ 198,
+ 79,
+ 0x39,
+ 0x00F1,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xF1, 0x08, 0x50, 0x28, 0x08, 0x90, 0x33, 0x50, 0x20, 0x08, 0x50, 0x3F, 0x08, 0x50, 0x30, 0x08, 0x90, 0x28, 0x38, 0xFA, 0x50, 0x40, 0x08, 0x50, 0x49, 0x08, 0x50, 0x48, 0x08, 0x90, 0x1B, 0x50, 0x80, 0x08, 0x50, 0x9F, 0x08, 0x50, 0x90, 0x08, 0x90, 0x10, 0x38, 0xFA, 0x62, 0xD0, 0x04, 0x51, 0xCF, 0x62, 0xD0, 0x04, 0x53, 0xBF, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x62, 0xD0, 0x04, 0x51, 0xC3, 0xF6, 0x31
+ }
+ },
+ {
+ 199,
+ 79,
+ 0x39,
+ 0x00F2,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xF2, 0x3B, 0xFC, 0xC0, 0x21, 0x62, 0xD0, 0x04, 0x52, 0xFB, 0x3A, 0xC3, 0xC0, 0x18, 0x62, 0xD0, 0x04, 0x51, 0xC2, 0x23, 0xFA, 0x39, 0x00, 0xB0, 0x0D, 0x62, 0xD0, 0x04, 0x55, 0xC3, 0x00, 0x62, 0xD0, 0x04, 0x55, 0xCF, 0x00, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x0A, 0x50, 0x02, 0x3B, 0xFC, 0xD1, 0xA6, 0x7C, 0x73, 0x26, 0x54, 0x03, 0x56, 0x00, 0x00, 0x80, 0xCA, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x80, 0x46
+ }
+ },
+ {
+ 200,
+ 79,
+ 0x39,
+ 0x00F3,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xF3, 0x06, 0xE8, 0xC0, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x7C, 0x6D, 0x8A, 0x51, 0xE8, 0x01, 0xE0, 0x54, 0x02, 0x51, 0xE9, 0x09, 0x01, 0x54, 0x01, 0x7C, 0x6D, 0xA5, 0x65, 0xE8, 0x6B, 0xE9, 0x06, 0xE8, 0xDD, 0x0E, 0xE9, 0x02, 0x7C, 0x6D, 0x83, 0x7C, 0x6E, 0xE1, 0x52, 0x02, 0x53, 0xE6, 0x52, 0x01, 0x60, 0xD4, 0x3E, 0xE6, 0x53, 0xE6, 0x50, 0x00, 0x3A, 0xE9, 0xB0, 0x07, 0x51, 0xE6, 0x3A, 0xC6, 0xD3
+ }
+ },
+ {
+ 201,
+ 79,
+ 0x39,
+ 0x00F4,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xF4, 0xE8, 0xA0, 0x03, 0x80, 0x84, 0x62, 0xD0, 0x00, 0x52, 0x02, 0x01, 0x06, 0x7C, 0x6E, 0xA3, 0x54, 0x04, 0x3E, 0xE8, 0x54, 0x05, 0x52, 0x02, 0x01, 0x04, 0x7C, 0x6E, 0xA3, 0x54, 0x06, 0x3E, 0xE8, 0x54, 0x07, 0x7C, 0x6D, 0xA5, 0x65, 0xE8, 0x6B, 0xE9, 0x06, 0xE8, 0xF5, 0x0E, 0xE9, 0x02, 0x7C, 0x6D, 0x83, 0x7C, 0x6E, 0xE1, 0x51, 0xE9, 0x08, 0x51, 0xE8, 0x08, 0x52, 0x04, 0x08, 0x52, 0x05, 0xBB, 0xBE
+ }
+ },
+ {
+ 202,
+ 79,
+ 0x39,
+ 0x00F5,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xF5, 0x08, 0x91, 0x1B, 0x38, 0xFC, 0x62, 0xD0, 0x00, 0x52, 0x03, 0x7C, 0x71, 0xD1, 0xC0, 0x31, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x65, 0xE8, 0x6B, 0xE9, 0x06, 0xE8, 0xA1, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x7C, 0x6E, 0xE1, 0x51, 0xE9, 0x08, 0x51, 0xE8, 0x08, 0x52, 0x06, 0x08, 0x52, 0x07, 0x08, 0x90, 0xEB, 0x38, 0xFC, 0x62, 0xD0, 0x00, 0x52, 0x03, 0x7C, 0x71, 0xD1, 0xD0, 0x03, 0x80, 0xCA, 0xDD
+ }
+ },
+ {
+ 203,
+ 79,
+ 0x39,
+ 0x00F6,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xF6, 0x08, 0x77, 0x00, 0x7C, 0x72, 0x41, 0xCF, 0x33, 0x50, 0x04, 0x3B, 0xFC, 0xD0, 0x09, 0x62, 0xD0, 0x04, 0x55, 0xC0, 0x04, 0x80, 0x08, 0x52, 0xFC, 0x62, 0xD0, 0x04, 0x53, 0xC0, 0x7C, 0x72, 0x41, 0xA0, 0xAD, 0x56, 0x00, 0x00, 0x80, 0x89, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0xC0, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x7C, 0x6D, 0x8A, 0x51, 0xE8, 0x01, 0xE0, 0x54, 0x02, 0x51, 0x65, 0x14
+ }
+ },
+ {
+ 204,
+ 79,
+ 0x39,
+ 0x00F7,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xF7, 0xE9, 0x09, 0x01, 0x54, 0x01, 0x7C, 0x6F, 0xF6, 0x53, 0xE8, 0x7C, 0x6E, 0xAE, 0x65, 0xE6, 0x6B, 0xE7, 0x06, 0xE6, 0xDD, 0x0E, 0xE7, 0x02, 0x51, 0xE7, 0x60, 0xD5, 0x50, 0x00, 0x3F, 0xE6, 0x51, 0xE8, 0x3F, 0xE6, 0x52, 0x02, 0x01, 0x06, 0x53, 0xE8, 0x52, 0x01, 0x09, 0x00, 0x7C, 0x6D, 0xE3, 0x3E, 0xE8, 0x53, 0xE8, 0x7C, 0x6E, 0xAE, 0x65, 0xE6, 0x6B, 0xE7, 0x06, 0xE6, 0xF5, 0x0E, 0xE7, 0xC3, 0xD1
+ }
+ },
+ {
+ 205,
+ 79,
+ 0x39,
+ 0x00F8,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xF8, 0x02, 0x7C, 0x6D, 0xEA, 0x51, 0xE8, 0x3F, 0xE6, 0x52, 0x02, 0x01, 0x04, 0x53, 0xE8, 0x52, 0x01, 0x09, 0x00, 0x7C, 0x6D, 0xE3, 0x3E, 0xE8, 0x53, 0xE8, 0x7C, 0x6E, 0xAE, 0x65, 0xE6, 0x6B, 0xE7, 0x06, 0xE6, 0xA1, 0x0E, 0xE7, 0x03, 0x7C, 0x6D, 0xEA, 0x51, 0xE8, 0x3F, 0xE6, 0x77, 0x00, 0x7C, 0x72, 0x41, 0xCF, 0x74, 0x3D, 0xFB, 0x00, 0xB0, 0x09, 0x56, 0x09, 0x01, 0x56, 0x08, 0x00, 0x80, 0x53, 0xF2
+ }
+ },
+ {
+ 206,
+ 79,
+ 0x39,
+ 0x00F9,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xF9, 0x07, 0x56, 0x09, 0x00, 0x56, 0x08, 0x00, 0x62, 0xD0, 0x00, 0x52, 0x09, 0x80, 0x0D, 0x62, 0xD0, 0x00, 0x50, 0x00, 0x80, 0x06, 0x62, 0xD0, 0x00, 0x50, 0x00, 0x38, 0xF6, 0x20, 0x7F, 0x10, 0x4F, 0x52, 0xFC, 0x13, 0xFA, 0x52, 0xFB, 0x1B, 0xF9, 0xC0, 0x12, 0x62, 0xD0, 0x00, 0x52, 0xFC, 0x13, 0xFA, 0x53, 0xE8, 0x52, 0xFB, 0x1B, 0xF9, 0x53, 0xE9, 0x80, 0x10, 0x62, 0xD0, 0x00, 0x52, 0xFA, 0x95, 0x77
+ }
+ },
+ {
+ 207,
+ 79,
+ 0x39,
+ 0x00FA,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xFA, 0x13, 0xFC, 0x53, 0xE8, 0x52, 0xF9, 0x1B, 0xFB, 0x53, 0xE9, 0x20, 0x7F, 0x10, 0x4F, 0x7C, 0x72, 0x93, 0xB0, 0x22, 0x3D, 0xFC, 0x01, 0xB0, 0x32, 0x62, 0xD0, 0x04, 0x51, 0xCF, 0x08, 0x50, 0x0E, 0x08, 0x7C, 0x32, 0x0C, 0x62, 0xD0, 0x04, 0x51, 0xC3, 0x08, 0x50, 0x0F, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x80, 0x16, 0x7C, 0x6F, 0x3C, 0x39, 0x30, 0xB0, 0x0F, 0x62, 0xD0, 0x04, 0x51, 0xC3, 0xA8, 0x9E
+ }
+ },
+ {
+ 208,
+ 79,
+ 0x39,
+ 0x00FB,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xFB, 0x08, 0x50, 0x24, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x52, 0xFC, 0x08, 0x7C, 0x3A, 0x2D, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x62, 0xE3, 0x38, 0x7C, 0x2B, 0x06, 0x71, 0x01, 0x90, 0x67, 0x90, 0xC5, 0x80, 0x5D, 0x62, 0xD0, 0x00, 0x26, 0xAE, 0xFB, 0x51, 0xAE, 0x60, 0x00, 0x7C, 0x70, 0x4B, 0x51, 0xAE, 0x29, 0x04, 0x53, 0xAE, 0x51, 0xAE, 0x60, 0x00, 0x7C, 0x70, 0x4B, 0x26, 0x61, 0x11
+ }
+ },
+ {
+ 209,
+ 79,
+ 0x39,
+ 0x00FC,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xFC, 0xAF, 0xFD, 0x51, 0xAF, 0x60, 0x04, 0x7C, 0x70, 0x4B, 0x51, 0xAF, 0x29, 0x02, 0x7C, 0x6F, 0x20, 0x56, 0x01, 0x00, 0x80, 0x03, 0x77, 0x01, 0x3D, 0x01, 0x0A, 0xCF, 0xFA, 0x62, 0xE3, 0x38, 0x90, 0x9D, 0x62, 0xD0, 0x04, 0x3C, 0xC4, 0x00, 0xA0, 0x0C, 0x7C, 0x45, 0x53, 0x7C, 0x2C, 0x1E, 0x62, 0xD0, 0x00, 0x54, 0x00, 0x52, 0x00, 0x08, 0x90, 0x9B, 0x52, 0x00, 0x08, 0x7C, 0x39, 0x02, 0x38, 0x9A, 0x84
+ }
+ },
+ {
+ 210,
+ 79,
+ 0x39,
+ 0x00FD,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xFD, 0xFE, 0x8F, 0xA3, 0x38, 0xFE, 0x20, 0x8F, 0xFF, 0x10, 0x4F, 0x38, 0x01, 0x10, 0x7C, 0x16, 0x34, 0x20, 0x10, 0x57, 0x13, 0x50, 0x88, 0x7C, 0x2B, 0xA8, 0x20, 0x62, 0xD0, 0x04, 0x55, 0xC4, 0x01, 0x62, 0xD0, 0x00, 0x55, 0xA7, 0x0C, 0x62, 0xD0, 0x00, 0x55, 0xA8, 0x05, 0x62, 0xD0, 0x00, 0x55, 0xA9, 0x01, 0x10, 0x7C, 0x17, 0xB7, 0x7C, 0x19, 0x82, 0x62, 0xD0, 0x00, 0x20, 0x39, 0x00, 0xA0, 0xEE, 0x2D
+ }
+ },
+ {
+ 211,
+ 79,
+ 0x39,
+ 0x00FE,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xFE, 0x1F, 0x71, 0x10, 0x5D, 0xE0, 0x54, 0x00, 0x41, 0xE0, 0xE7, 0x43, 0xE0, 0x18, 0x70, 0xCF, 0x62, 0xE3, 0x38, 0x7C, 0x49, 0x07, 0x62, 0xE3, 0x38, 0x52, 0x00, 0x7C, 0x72, 0xB2, 0x80, 0x06, 0x10, 0x7C, 0x10, 0x74, 0x20, 0x38, 0xFF, 0x20, 0x7F, 0x7C, 0x33, 0x69, 0x7C, 0x40, 0x59, 0x7C, 0x45, 0x51, 0x7C, 0x2B, 0xCA, 0x7C, 0x3A, 0x31, 0x7C, 0x40, 0x10, 0x7C, 0x2B, 0x19, 0x7F, 0x7C, 0x40, 0x55, 0xFC
+ }
+ },
+ {
+ 212,
+ 79,
+ 0x39,
+ 0x00FF,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0xFF, 0x98, 0x7C, 0x36, 0x78, 0x7C, 0x45, 0x52, 0x7C, 0x2B, 0xFD, 0x7C, 0x3A, 0x4C, 0x7C, 0x40, 0x1E, 0x7C, 0x2B, 0x23, 0x7F, 0x10, 0x4F, 0x52, 0xFC, 0x08, 0x7C, 0x38, 0x88, 0x52, 0xFC, 0x08, 0x7C, 0x45, 0x4D, 0x38, 0xFE, 0x52, 0xFC, 0x08, 0x7C, 0x45, 0x76, 0x52, 0xFC, 0x08, 0x7C, 0x2E, 0x27, 0x38, 0xFE, 0x52, 0xFC, 0x08, 0x7C, 0x3E, 0x8C, 0x52, 0xFC, 0x08, 0x7C, 0x40, 0x28, 0x38, 0xFE, 0x1F, 0x91
+ }
+ },
+ {
+ 213,
+ 79,
+ 0x39,
+ 0x0100,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x00, 0x52, 0xFC, 0x08, 0x7C, 0x2B, 0x48, 0x52, 0xFC, 0x08, 0x7C, 0x38, 0xC9, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x62, 0xD0, 0x04, 0x55, 0xC5, 0x04, 0x38, 0xFF, 0x20, 0x7F, 0x7F, 0x62, 0xD0, 0x04, 0x51, 0xC5, 0x62, 0xD0, 0x00, 0x7F, 0x10, 0x4F, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x62, 0xD0, 0x00, 0x51, 0x54, 0x54, 0x01, 0x51, 0x53, 0x54, 0x00, 0x70, 0xFE, 0x10, 0x7C, 0x1E, 0xFE, 0x51
+ }
+ },
+ {
+ 214,
+ 79,
+ 0x39,
+ 0x0101,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x01, 0x1C, 0x62, 0xD0, 0x00, 0x20, 0x10, 0x52, 0x00, 0x08, 0x52, 0x01, 0x20, 0x7C, 0x1D, 0xD4, 0x20, 0x62, 0xDA, 0xF7, 0x71, 0x01, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0x7C, 0x1E, 0x1C, 0x20, 0x70, 0xFE, 0x62, 0xD0, 0x00, 0x55, 0x0D, 0x00, 0x55, 0x0C, 0x00, 0x7C, 0x72, 0x19, 0x92, 0x21, 0x7C, 0x73, 0x6D, 0x10, 0x7C, 0x1D, 0xCC, 0x7C, 0x20, 0x80, 0x7C, 0x20, 0x78, 0x20, 0x62, 0xD0, 0x00, 0x55, 0xFD, 0x50
+ }
+ },
+ {
+ 215,
+ 79,
+ 0x39,
+ 0x0102,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x02, 0xEF, 0x00, 0x55, 0xEE, 0x00, 0x62, 0xD0, 0x03, 0x55, 0xC8, 0x00, 0x55, 0xC9, 0x00, 0x55, 0xCA, 0x00, 0x55, 0xCB, 0x00, 0x7C, 0x2B, 0x67, 0x7F, 0x10, 0x4F, 0x38, 0x03, 0x7C, 0x72, 0x93, 0xB0, 0xF9, 0x7C, 0x70, 0xE8, 0x54, 0x01, 0x51, 0x0C, 0x54, 0x00, 0x71, 0x01, 0x62, 0xD0, 0x03, 0x47, 0x99, 0x02, 0xA0, 0x3F, 0x93, 0x58, 0x9F, 0x74, 0x7C, 0x70, 0xE8, 0x08, 0x51, 0x0C, 0x62, 0xD0, 0xDD, 0x11
+ }
+ },
+ {
+ 216,
+ 79,
+ 0x39,
+ 0x0103,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x03, 0x00, 0x53, 0xEE, 0x18, 0x53, 0xEF, 0x71, 0x01, 0x62, 0xD0, 0x03, 0x55, 0xC8, 0x00, 0x55, 0xC9, 0x00, 0x55, 0xCA, 0x00, 0x55, 0xCB, 0x00, 0x7C, 0x2B, 0x67, 0x10, 0x7C, 0x18, 0x83, 0x20, 0x10, 0x57, 0x13, 0x50, 0x88, 0x7C, 0x2B, 0xA8, 0x7C, 0x10, 0x74, 0x20, 0x91, 0x3B, 0x7C, 0x6F, 0xEA, 0x81, 0x33, 0x62, 0xD0, 0x03, 0x51, 0x9A, 0x21, 0x0F, 0x54, 0x02, 0x62, 0xD0, 0x04, 0x3C, 0xCB, 0x0A, 0x6C
+ }
+ },
+ {
+ 217,
+ 79,
+ 0x39,
+ 0x0104,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x04, 0xF1, 0xB0, 0x45, 0x62, 0xD0, 0x03, 0x3C, 0x9C, 0x00, 0xA0, 0x03, 0x93, 0x67, 0x3D, 0x02, 0x00, 0xA0, 0x06, 0x7C, 0x6F, 0xEA, 0x80, 0x97, 0x7C, 0x73, 0x2E, 0xA0, 0x27, 0x62, 0xD0, 0x03, 0x52, 0x01, 0x12, 0xE5, 0x62, 0xD0, 0x00, 0x53, 0xE8, 0x52, 0x00, 0x62, 0xD0, 0x03, 0x1A, 0xE4, 0x7C, 0x72, 0x49, 0x62, 0xD0, 0x03, 0x12, 0xDB, 0x7C, 0x70, 0xA1, 0x1A, 0xDA, 0xC0, 0x70, 0x91, 0x2A, 0x7B, 0x4F
+ }
+ },
+ {
+ 218,
+ 79,
+ 0x39,
+ 0x0105,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x05, 0x80, 0x6C, 0x7C, 0x6F, 0xEA, 0x80, 0x67, 0x62, 0xD0, 0x04, 0x3C, 0xCB, 0xF2, 0xB0, 0x1E, 0x3D, 0x02, 0x00, 0xB0, 0x06, 0x7C, 0x73, 0x2E, 0xB0, 0x08, 0x90, 0xCD, 0x7C, 0x6F, 0xEA, 0x80, 0x4E, 0x62, 0xD0, 0x03, 0x3C, 0x9D, 0x00, 0xA0, 0x46, 0x93, 0x0A, 0x80, 0x42, 0x9E, 0xBE, 0x7C, 0x70, 0xE8, 0x08, 0x51, 0x0C, 0x62, 0xD0, 0x00, 0x53, 0xEE, 0x18, 0x53, 0xEF, 0x71, 0x01, 0x62, 0xD0, 0xC8, 0xEA
+ }
+ },
+ {
+ 219,
+ 79,
+ 0x39,
+ 0x0106,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x06, 0x03, 0x55, 0xC8, 0x00, 0x55, 0xC9, 0x00, 0x55, 0xCA, 0x00, 0x55, 0xCB, 0x00, 0x7C, 0x2B, 0x67, 0x90, 0xFD, 0x90, 0x94, 0x7C, 0x6F, 0xEA, 0x80, 0x15, 0x62, 0xD0, 0x04, 0x3C, 0xCB, 0xF4, 0xA0, 0x0D, 0x10, 0x57, 0x00, 0x50, 0x01, 0x7C, 0x1D, 0xD4, 0x20, 0x7C, 0x73, 0x6D, 0x7C, 0x72, 0x93, 0xB0, 0x70, 0x7C, 0x70, 0xE8, 0x54, 0x01, 0x51, 0x0C, 0x54, 0x00, 0x71, 0x01, 0x62, 0xD0, 0x00, 0x44, 0xE3
+ }
+ },
+ {
+ 220,
+ 79,
+ 0x39,
+ 0x0107,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x07, 0x52, 0x01, 0x12, 0xEF, 0x62, 0xD0, 0x00, 0x53, 0xE8, 0x52, 0x00, 0x62, 0xD0, 0x00, 0x1A, 0xEE, 0x7C, 0x72, 0x49, 0x53, 0xE6, 0x51, 0xE9, 0x53, 0xE7, 0x51, 0xE6, 0x62, 0xD0, 0x03, 0x04, 0xCB, 0x62, 0xD0, 0x00, 0x51, 0xE7, 0x62, 0xD0, 0x03, 0x0C, 0xCA, 0x0E, 0xC9, 0x00, 0x0E, 0xC8, 0x00, 0x62, 0xD0, 0x00, 0x52, 0x01, 0x53, 0xEF, 0x52, 0x00, 0x53, 0xEE, 0x62, 0xD0, 0x03, 0x51, 0xCB, 0x39, 0xCE
+ }
+ },
+ {
+ 221,
+ 79,
+ 0x39,
+ 0x0108,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x08, 0x11, 0x30, 0x51, 0xCA, 0x19, 0x75, 0x51, 0xC9, 0x19, 0x00, 0x51, 0xC8, 0x19, 0x00, 0xC0, 0x12, 0x9E, 0x1A, 0x62, 0xD0, 0x03, 0x55, 0xC8, 0x00, 0x55, 0xC9, 0x00, 0x55, 0xCA, 0x00, 0x55, 0xCB, 0x00, 0x7C, 0x2B, 0x68, 0x38, 0xFD, 0x20, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xCB, 0xF1, 0x62, 0xD0, 0x03, 0x51, 0x9C, 0x08, 0x62, 0xD0, 0x03, 0x55, 0xD8, 0x00, 0x18, 0x53, 0xD9, 0x62, 0xD0, 0x03, 0xB7, 0xCB
+ }
+ },
+ {
+ 222,
+ 79,
+ 0x39,
+ 0x0109,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x09, 0x3C, 0x9C, 0x00, 0xA0, 0x14, 0x10, 0x62, 0xD0, 0x03, 0x51, 0xD8, 0x08, 0x51, 0xD9, 0x20, 0x7C, 0x1D, 0xD4, 0x20, 0x7C, 0x70, 0xAA, 0x80, 0x0F, 0x10, 0x57, 0x00, 0x50, 0x01, 0x7C, 0x1D, 0xD4, 0x20, 0x70, 0xFE, 0x7C, 0x72, 0x19, 0x7C, 0x71, 0x54, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xCB, 0xF2, 0x62, 0xD0, 0x03, 0x51, 0xD7, 0x08, 0x51, 0xD6, 0x62, 0xD0, 0x03, 0x53, 0xD8, 0x18, 0x53, 0xD9, 0xF0, 0x3E
+ }
+ },
+ {
+ 223,
+ 79,
+ 0x39,
+ 0x010A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x0A, 0x10, 0x51, 0xD8, 0x08, 0x51, 0xD9, 0x20, 0x7C, 0x1D, 0xD4, 0x20, 0x7C, 0x70, 0xAA, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x62, 0xD0, 0x03, 0x50, 0x78, 0x3A, 0x9D, 0xD0, 0x07, 0x62, 0xD0, 0x03, 0x55, 0x9D, 0x78, 0x7C, 0x71, 0xD8, 0x53, 0xE9, 0x65, 0xE9, 0x7C, 0x71, 0xD8, 0x64, 0x64, 0x64, 0x02, 0xE9, 0x54, 0x00, 0x80, 0x09, 0x62, 0xD0, 0x03, 0x76, 0x9D, 0x07, 0x00, 0x0A, 0x62, 0xD0, 0x03, 0xA5, 0xA9
+ }
+ },
+ {
+ 224,
+ 79,
+ 0x39,
+ 0x010B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x0B, 0x3C, 0x9D, 0x1A, 0xD0, 0x0A, 0x62, 0xD0, 0x03, 0x52, 0x00, 0x3A, 0x9C, 0xCF, 0xE8, 0x62, 0xD0, 0x03, 0x51, 0x9D, 0x08, 0x62, 0xD0, 0x03, 0x55, 0xD6, 0x00, 0x18, 0x53, 0xD7, 0x62, 0xD0, 0x03, 0x51, 0x9D, 0x7C, 0x70, 0x0E, 0x7C, 0x6D, 0x9C, 0x62, 0xD0, 0x03, 0x51, 0xD7, 0x62, 0xD0, 0x00, 0x04, 0xE8, 0x62, 0xD0, 0x03, 0x51, 0xD6, 0x62, 0xD0, 0x00, 0x0C, 0xE9, 0x7C, 0x70, 0x17, 0x08, 0x59, 0x12
+ }
+ },
+ {
+ 225,
+ 79,
+ 0x39,
+ 0x010C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x0C, 0x51, 0xE9, 0x62, 0xD0, 0x03, 0x53, 0xD6, 0x18, 0x53, 0xD7, 0x62, 0xD0, 0x03, 0x51, 0x9E, 0x08, 0x62, 0xD0, 0x03, 0x55, 0xDA, 0x00, 0x18, 0x53, 0xDB, 0x51, 0xDB, 0x08, 0x51, 0xDA, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x18, 0x53, 0xE8, 0x7C, 0x6D, 0x9C, 0x62, 0xD0, 0x03, 0x51, 0xDB, 0x62, 0xD0, 0x00, 0x04, 0xE8, 0x62, 0xD0, 0x03, 0x51, 0xDA, 0x62, 0xD0, 0x00, 0x0C, 0xE9, 0x7C, 0x70, 0x17, 0x5E, 0x1D
+ }
+ },
+ {
+ 226,
+ 79,
+ 0x39,
+ 0x010D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x0D, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x03, 0x53, 0xDA, 0x18, 0x53, 0xDB, 0x38, 0xFF, 0x20, 0x7F, 0x62, 0xD0, 0x00, 0x51, 0xAE, 0x21, 0x0D, 0x60, 0x00, 0x62, 0xD0, 0x00, 0x51, 0xAF, 0x21, 0xBB, 0x60, 0x04, 0x62, 0xD0, 0x00, 0x51, 0xB0, 0x21, 0x74, 0x7C, 0x73, 0x1E, 0x21, 0x00, 0x7C, 0x73, 0x16, 0x21, 0x10, 0x60, 0x10, 0x71, 0x10, 0x5D, 0x00, 0x70, 0xCF, 0x62, 0xD0, 0x04, 0x53, 0xCA, 0x71, 0x6E, 0x3E
+ }
+ },
+ {
+ 227,
+ 79,
+ 0x39,
+ 0x010E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x0E, 0x10, 0x5D, 0x04, 0x70, 0xCF, 0x62, 0xD0, 0x04, 0x53, 0xC9, 0x71, 0x10, 0x5D, 0x08, 0x70, 0xCF, 0x62, 0xD0, 0x04, 0x53, 0xC8, 0x71, 0x10, 0x5D, 0x0C, 0x70, 0xCF, 0x62, 0xD0, 0x04, 0x53, 0xC7, 0x71, 0x10, 0x5D, 0x10, 0x70, 0xCF, 0x62, 0xD0, 0x04, 0x53, 0xC6, 0x71, 0x10, 0x43, 0x00, 0xF2, 0x43, 0x04, 0x44, 0x43, 0x08, 0x8B, 0x43, 0x0C, 0xFF, 0x43, 0x10, 0xEF, 0x70, 0xCF, 0x7F, 0x62, 0x34, 0xCB
+ }
+ },
+ {
+ 228,
+ 79,
+ 0x39,
+ 0x010F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x0F, 0xD0, 0x04, 0x51, 0xCA, 0x71, 0x10, 0x60, 0x00, 0x70, 0xCF, 0x62, 0xD0, 0x04, 0x51, 0xC9, 0x71, 0x10, 0x60, 0x04, 0x70, 0xCF, 0x62, 0xD0, 0x04, 0x51, 0xC8, 0x71, 0x10, 0x60, 0x08, 0x70, 0xCF, 0x62, 0xD0, 0x04, 0x51, 0xC7, 0x71, 0x10, 0x60, 0x0C, 0x70, 0xCF, 0x62, 0xD0, 0x04, 0x51, 0xC6, 0x71, 0x10, 0x60, 0x10, 0x70, 0xCF, 0x62, 0xD0, 0x00, 0x51, 0xAE, 0x60, 0x00, 0x62, 0xD0, 0x00, 0xB4, 0xCC
+ }
+ },
+ {
+ 229,
+ 79,
+ 0x39,
+ 0x0110,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x10, 0x7C, 0x72, 0x51, 0x51, 0xB0, 0x7C, 0x73, 0x1E, 0x7C, 0x73, 0x16, 0x60, 0x10, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x71, 0x10, 0x43, 0xEC, 0x01, 0x70, 0xFE, 0x70, 0xCF, 0x9F, 0x32, 0x7C, 0x31, 0xC5, 0x62, 0xD0, 0x00, 0x39, 0x00, 0xB0, 0x3A, 0x7C, 0x72, 0xCB, 0x10, 0x70, 0xCF, 0x7C, 0x1D, 0xD0, 0x7C, 0x20, 0x7C, 0x20, 0x62, 0xDB, 0xFE, 0x7C, 0x39, 0xF1, 0x71, 0x10, 0x43, 0xD7, 0x20, 0x43, 0x58, 0x15
+ }
+ },
+ {
+ 230,
+ 79,
+ 0x39,
+ 0x0111,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x11, 0xC9, 0x80, 0x70, 0xCF, 0x43, 0xFF, 0x08, 0x71, 0x10, 0x41, 0xC9, 0x7F, 0x41, 0xD7, 0xDF, 0x40, 0x7C, 0x73, 0x7B, 0x70, 0xCF, 0x7C, 0x3A, 0x08, 0x10, 0x7C, 0x20, 0x78, 0x7C, 0x1D, 0xCC, 0x20, 0x62, 0xD0, 0x00, 0x55, 0xBB, 0xFF, 0x62, 0xD0, 0x03, 0x26, 0x99, 0xFD, 0x9F, 0x51, 0x71, 0x01, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x56, 0x00, 0x00, 0x71, 0x10, 0x41, 0xEC, 0xFE, 0x27, 0xB4
+ }
+ },
+ {
+ 231,
+ 79,
+ 0x39,
+ 0x0112,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x12, 0x70, 0xFE, 0x70, 0xCF, 0x9E, 0xC9, 0x7C, 0x71, 0x10, 0x80, 0x6B, 0x7C, 0x32, 0x06, 0x62, 0xD0, 0x00, 0x7C, 0x31, 0xC5, 0x39, 0x00, 0xB0, 0x5A, 0x3D, 0x00, 0x00, 0xB0, 0x55, 0x62, 0xD0, 0x00, 0x3C, 0xBB, 0xFF, 0xA0, 0x4D, 0x7C, 0x39, 0xE9, 0x62, 0xD0, 0x03, 0x51, 0xD9, 0x11, 0x02, 0x62, 0xD0, 0x00, 0x53, 0xE8, 0x62, 0xD0, 0x03, 0x51, 0xD8, 0x19, 0x00, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x50, 0x07
+ }
+ },
+ {
+ 232,
+ 79,
+ 0x39,
+ 0x0113,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x13, 0x62, 0xD0, 0x00, 0x51, 0xBB, 0x62, 0xD0, 0x00, 0x7C, 0x70, 0xBF, 0xC0, 0x22, 0x7C, 0x72, 0xCB, 0x56, 0x00, 0x01, 0x10, 0x70, 0xCF, 0x7C, 0x20, 0x7C, 0x20, 0x62, 0xDB, 0xFE, 0x10, 0x7C, 0x0C, 0x80, 0x20, 0x71, 0x10, 0x7C, 0x73, 0x7B, 0x10, 0x70, 0xCF, 0x7C, 0x20, 0x78, 0x20, 0x7C, 0x39, 0xED, 0x71, 0x01, 0x70, 0xFE, 0x62, 0xD0, 0x00, 0x51, 0x0D, 0x62, 0xD0, 0x03, 0x12, 0xD5, 0x62, 0x05, 0x72
+ }
+ },
+ {
+ 233,
+ 79,
+ 0x39,
+ 0x0114,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x14, 0xD0, 0x00, 0x53, 0xE8, 0x62, 0xD0, 0x00, 0x51, 0x0C, 0x62, 0xD0, 0x03, 0x1A, 0xD4, 0x7C, 0x72, 0x49, 0x62, 0xD0, 0x03, 0x12, 0xD9, 0x7C, 0x70, 0xA1, 0x1A, 0xD8, 0xCF, 0x6F, 0x52, 0x01, 0x7C, 0x72, 0xB2, 0x9E, 0x9B, 0x7C, 0x71, 0x54, 0x71, 0x01, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x62, 0xD0, 0x04, 0x3C, 0xCB, 0xF2, 0xB0, 0x09, 0x56, 0x01, 0x01, 0x56, 0x00, 0x00, 0x80, 0x34, 0xD1
+ }
+ },
+ {
+ 234,
+ 79,
+ 0x39,
+ 0x0115,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x15, 0x04, 0x7C, 0x6F, 0xC9, 0x62, 0xD0, 0x00, 0x52, 0x01, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0x4F, 0x20, 0x7F, 0x7F, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x56, 0x00, 0x00, 0x10, 0x7C, 0x18, 0x83, 0x7C, 0x19, 0x64, 0x20, 0x56, 0x00, 0x01, 0x52, 0x00, 0x08, 0x7C, 0x2B, 0x34, 0x38, 0xFF, 0x10, 0x7C, 0x18, 0x4D, 0x20, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x04, 0x7C, 0x6F, 0x3C, 0x54, 0x01, 0x3D, 0x3A, 0xDE
+ }
+ },
+ {
+ 235,
+ 79,
+ 0x39,
+ 0x0116,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x16, 0x01, 0x50, 0xB0, 0x29, 0x56, 0x00, 0x00, 0x80, 0x1D, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0x00, 0x0E, 0xE9, 0x02, 0x7C, 0x6D, 0x83, 0x08, 0x52, 0x00, 0x01, 0x07, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x77, 0x00, 0x3D, 0x00, 0x99, 0xCF, 0xE0, 0x81, 0x85, 0x3D, 0x01, 0x40, 0xB0, 0x29, 0x56, 0x00, 0x00, 0x80, 0x1D, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0x00, 0x0E, 0x92, 0x8F
+ }
+ },
+ {
+ 236,
+ 79,
+ 0x39,
+ 0x0117,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x17, 0xE9, 0x05, 0x7C, 0x6D, 0x83, 0x08, 0x52, 0x00, 0x01, 0x07, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x77, 0x00, 0x3D, 0x00, 0x99, 0xCF, 0xE0, 0x81, 0x58, 0x3D, 0x01, 0x70, 0xB0, 0x61, 0x7C, 0x39, 0x34, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x26, 0xE9, 0x01, 0x3C, 0xE9, 0x01, 0xB0, 0x29, 0x56, 0x00, 0x00, 0x80, 0x1D, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0x00, 0x0E, 0xE9, 0x05, 0x7C, 0xC7, 0xFA
+ }
+ },
+ {
+ 237,
+ 79,
+ 0x39,
+ 0x0118,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x18, 0x6D, 0x83, 0x08, 0x52, 0x00, 0x01, 0x07, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x77, 0x00, 0x3D, 0x00, 0x99, 0xCF, 0xE0, 0x81, 0x1B, 0x56, 0x00, 0x00, 0x80, 0x1D, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0x00, 0x0E, 0xE9, 0x08, 0x7C, 0x6D, 0x83, 0x08, 0x52, 0x00, 0x01, 0x07, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x77, 0x00, 0x3D, 0x00, 0x99, 0xCF, 0xE0, 0x80, 0xF3, 0x3D, 0x01, 0xF5, 0x57
+ }
+ },
+ {
+ 238,
+ 79,
+ 0x39,
+ 0x0119,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x19, 0x60, 0xB0, 0x95, 0x7C, 0x39, 0x34, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x26, 0xE9, 0x01, 0x3C, 0xE9, 0x01, 0xB0, 0x5D, 0x50, 0x1B, 0x08, 0x50, 0x07, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x56, 0x00, 0x00, 0x80, 0x1D, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0x00, 0x0E, 0xE9, 0x09, 0x7C, 0x6F, 0x5C, 0x08, 0x52, 0x00, 0x01, 0x08, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x77, 0x00, 0x3D, 0xF8, 0x5E
+ }
+ },
+ {
+ 239,
+ 79,
+ 0x39,
+ 0x011A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x1A, 0x00, 0x1B, 0xCF, 0xE0, 0x56, 0x02, 0x23, 0x56, 0x00, 0x00, 0x80, 0x1D, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0x25, 0x0E, 0xE9, 0x09, 0x7C, 0x6F, 0x5C, 0x08, 0x52, 0x02, 0x03, 0x00, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x77, 0x00, 0x3D, 0x00, 0x1B, 0xCF, 0xE0, 0x80, 0x82, 0x56, 0x00, 0x00, 0x80, 0x1D, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0x00, 0x0E, 0xE9, 0x0A, 0xCB, 0x05
+ }
+ },
+ {
+ 240,
+ 79,
+ 0x39,
+ 0x011B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x1B, 0x7C, 0x6F, 0x5C, 0x08, 0x52, 0x00, 0x01, 0x07, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x77, 0x00, 0x3D, 0x00, 0x99, 0xCF, 0xE0, 0x80, 0x5A, 0x3D, 0x01, 0x30, 0xB0, 0x55, 0x62, 0xD0, 0x03, 0x3C, 0x9F, 0x99, 0xD0, 0x4D, 0x62, 0xD0, 0x03, 0x51, 0x9F, 0x7C, 0x70, 0x0E, 0x06, 0xE8, 0x00, 0x0E, 0xE9, 0x08, 0x7C, 0x6D, 0x83, 0x08, 0x50, 0x26, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFE, 0x62, 0xD0, 0xD0, 0x10
+ }
+ },
+ {
+ 241,
+ 79,
+ 0x39,
+ 0x011C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x1C, 0x03, 0x51, 0x9F, 0x7C, 0x70, 0x0E, 0x06, 0xE8, 0x00, 0x0E, 0xE9, 0x02, 0x7C, 0x6D, 0x83, 0x08, 0x50, 0x27, 0x08, 0x7C, 0x32, 0x0C, 0x62, 0xD0, 0x03, 0x51, 0x9F, 0x7C, 0x70, 0x0E, 0x06, 0xE8, 0x00, 0x0E, 0xE9, 0x05, 0x7C, 0x6D, 0x83, 0x08, 0x50, 0x28, 0x08, 0x7C, 0x32, 0x0C, 0x38, 0xFC, 0x38, 0xFC, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x03, 0x56, 0x00, 0x00, 0x80, 0x5A, 0x62, 0xD0, 0x00, 0x3B, 0xE7
+ }
+ },
+ {
+ 242,
+ 79,
+ 0x39,
+ 0x011D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x1D, 0x52, 0x00, 0x7C, 0x6D, 0x8A, 0x06, 0xE8, 0xE6, 0x0E, 0xE9, 0x01, 0x7C, 0x6D, 0x83, 0x54, 0x01, 0x3E, 0xE8, 0x54, 0x02, 0x7C, 0x70, 0x01, 0x7C, 0x70, 0xD4, 0x52, 0x02, 0x53, 0xE9, 0x7C, 0x6E, 0xAE, 0x06, 0xE6, 0xB8, 0x0E, 0xE7, 0x03, 0x7C, 0x6D, 0xEA, 0x52, 0x00, 0x7C, 0x6D, 0x8A, 0x06, 0xE8, 0xE4, 0x0E, 0xE9, 0x01, 0x7C, 0x6D, 0x83, 0x54, 0x01, 0x3E, 0xE8, 0x54, 0x02, 0x7C, 0x70, 0xCA, 0x06
+ }
+ },
+ {
+ 243,
+ 79,
+ 0x39,
+ 0x011E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x1E, 0xD4, 0x7C, 0x70, 0x01, 0x52, 0x02, 0x53, 0xE9, 0x7C, 0x6E, 0xAE, 0x06, 0xE6, 0xB4, 0x0E, 0xE7, 0x03, 0x7C, 0x6D, 0xEA, 0x77, 0x00, 0x7C, 0x6F, 0xC1, 0xCF, 0xA3, 0x52, 0xFC, 0x08, 0x7C, 0x5F, 0x91, 0x38, 0xFF, 0x38, 0xFD, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x7C, 0x6F, 0xB9, 0x52, 0xFB, 0x60, 0xD5, 0x50, 0x04, 0x3F, 0xE8, 0x52, 0xFC, 0x01, 0x01, 0x7C, 0x71, 0x76, 0x50, 0x01, 0x3F, 0x32, 0xD7
+ }
+ },
+ {
+ 244,
+ 79,
+ 0x39,
+ 0x011F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x1F, 0xE8, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x03, 0x7C, 0x6F, 0xB9, 0x52, 0xFB, 0x7C, 0x6D, 0xE3, 0x47, 0xE9, 0x80, 0xBF, 0xF4, 0x52, 0xFC, 0x53, 0xE8, 0x52, 0xFB, 0x60, 0xD4, 0x3E, 0xE8, 0x39, 0x04, 0xB0, 0x73, 0x56, 0x00, 0x00, 0x80, 0x3F, 0x62, 0xD0, 0x00, 0x52, 0x00, 0x7C, 0x6D, 0x8A, 0x52, 0xFC, 0x01, 0x02, 0x53, 0xE6, 0x52, 0xFB, 0x09, 0x00, 0x53, 0xE7, 0x51, 0xE8, 0x02, 0x69, 0x46
+ }
+ },
+ {
+ 245,
+ 79,
+ 0x39,
+ 0x0120,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x20, 0xE6, 0x53, 0xE6, 0x51, 0xE9, 0x0A, 0xE7, 0x53, 0xE7, 0x06, 0xE8, 0xE0, 0x0E, 0xE9, 0x01, 0x51, 0xE9, 0x60, 0xD4, 0x51, 0xE7, 0x60, 0xD5, 0x10, 0x57, 0x08, 0x62, 0xD0, 0x00, 0x3E, 0xE8, 0x3F, 0xE6, 0x79, 0xBF, 0xF7, 0x20, 0x77, 0x00, 0x7C, 0x6F, 0xC1, 0xCF, 0xBE, 0x62, 0xD0, 0x00, 0x52, 0xFC, 0x01, 0x22, 0x7C, 0x71, 0x76, 0x52, 0xF9, 0x3F, 0xE8, 0x52, 0xFC, 0x01, 0x23, 0x7C, 0x71, 0xE7, 0x43
+ }
+ },
+ {
+ 246,
+ 79,
+ 0x39,
+ 0x0121,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x21, 0x76, 0x52, 0xFA, 0x3F, 0xE8, 0x52, 0xFC, 0x01, 0x24, 0x7C, 0x71, 0x76, 0x62, 0xD0, 0x00, 0x51, 0xA2, 0x62, 0xD0, 0x00, 0x3F, 0xE8, 0x7C, 0x6F, 0xB9, 0x52, 0xFB, 0x60, 0xD5, 0x50, 0x84, 0x3F, 0xE8, 0x38, 0xFD, 0x20, 0x7F, 0x10, 0x4F, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x62, 0xD0, 0x03, 0x55, 0xAC, 0x19, 0x55, 0xAB, 0x00, 0x55, 0xAA, 0x02, 0x62, 0xD0, 0x00, 0x55, 0xE8, 0x00, 0x55, 0xDD, 0x30
+ }
+ },
+ {
+ 247,
+ 79,
+ 0x39,
+ 0x0122,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x22, 0xE9, 0x0A, 0x7C, 0x6D, 0xAD, 0x7C, 0x6D, 0xC6, 0x51, 0xE8, 0x62, 0xD0, 0x03, 0x53, 0xA9, 0x10, 0x50, 0x03, 0x08, 0x50, 0xA9, 0x5C, 0x18, 0x7C, 0x20, 0x98, 0x20, 0x62, 0xD0, 0x03, 0x50, 0x00, 0x01, 0x80, 0x53, 0xAB, 0x50, 0x02, 0x09, 0x00, 0x53, 0xAA, 0x62, 0xD0, 0x00, 0x55, 0xE8, 0x00, 0x55, 0xE9, 0x0A, 0x7C, 0x6D, 0xC6, 0x7C, 0x6D, 0xAD, 0x7C, 0x73, 0x3C, 0x51, 0xE8, 0x62, 0xD0, 0xBC, 0xEF
+ }
+ },
+ {
+ 248,
+ 79,
+ 0x39,
+ 0x0123,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x23, 0x03, 0x53, 0xA9, 0x10, 0x50, 0x03, 0x08, 0x50, 0xA9, 0x5C, 0x18, 0x7C, 0x20, 0x98, 0x20, 0x62, 0xD0, 0x03, 0x55, 0xAB, 0xA0, 0x55, 0xAA, 0x01, 0x62, 0xD0, 0x00, 0x55, 0xE8, 0x00, 0x55, 0xE9, 0x0A, 0x7C, 0x6D, 0xC6, 0x7C, 0x6D, 0xAD, 0x16, 0xE8, 0x02, 0x1E, 0xE9, 0x00, 0x51, 0xE8, 0x62, 0xD0, 0x03, 0x53, 0xA9, 0x10, 0x50, 0x03, 0x08, 0x50, 0xA9, 0x5C, 0x18, 0x7C, 0x20, 0x98, 0x62, 0xDB, 0x2E
+ }
+ },
+ {
+ 249,
+ 79,
+ 0x39,
+ 0x0124,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x24, 0xD0, 0x00, 0x20, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0x50, 0x99, 0x7C, 0x12, 0x90, 0x20, 0x9F, 0x59, 0x10, 0x7C, 0x10, 0x74, 0x20, 0x7F, 0x10, 0x4F, 0x10, 0x52, 0xFB, 0x08, 0x52, 0xFC, 0x20, 0x7C, 0x13, 0xEA, 0x20, 0x9F, 0x44, 0x10, 0x7C, 0x10, 0x74, 0x20, 0x20, 0x7F, 0x10, 0x4F, 0x10, 0x52, 0xFC, 0x7C, 0x13, 0xFB, 0x20, 0x9F, 0x32, 0x10, 0x7C, 0x10, 0x74, 0x20, 0x20, 0x7F, 0x10, 0x4F, 0x86, 0x85
+ }
+ },
+ {
+ 250,
+ 79,
+ 0x39,
+ 0x0125,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x25, 0x10, 0x52, 0xFC, 0x7C, 0x14, 0x0D, 0x20, 0x9F, 0x20, 0x10, 0x7C, 0x10, 0x74, 0x20, 0x20, 0x7F, 0x10, 0x4F, 0x52, 0xFC, 0x62, 0xD0, 0x00, 0x53, 0xA9, 0x20, 0x7F, 0x62, 0xD0, 0x00, 0x55, 0x39, 0x08, 0x55, 0x3A, 0x08, 0x55, 0x3B, 0x08, 0x55, 0x3C, 0x08, 0x55, 0x01, 0x00, 0x55, 0x00, 0x00, 0x55, 0x03, 0x00, 0x55, 0x02, 0x00, 0x55, 0x05, 0x00, 0x55, 0x04, 0x00, 0x55, 0x07, 0x00, 0x55, 0x71, 0x5C
+ }
+ },
+ {
+ 251,
+ 79,
+ 0x39,
+ 0x0126,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x26, 0x06, 0x00, 0x55, 0x55, 0x20, 0x55, 0x54, 0x01, 0x55, 0x53, 0x00, 0x43, 0xE6, 0x01, 0x43, 0xE0, 0x08, 0x7F, 0x49, 0xE0, 0x08, 0xB0, 0x05, 0x50, 0x00, 0x80, 0x07, 0x08, 0x7C, 0x54, 0x59, 0x38, 0xFF, 0x7F, 0x08, 0x7C, 0x54, 0xA4, 0x38, 0xFF, 0x7F, 0x08, 0x7C, 0x54, 0xB5, 0x38, 0xFF, 0x7F, 0x08, 0x7C, 0x54, 0xE2, 0x38, 0xFF, 0x7F, 0x08, 0x7C, 0x54, 0xF3, 0x38, 0xFF, 0x7F, 0x08, 0x7C, 0x84, 0x83
+ }
+ },
+ {
+ 252,
+ 79,
+ 0x39,
+ 0x0127,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x27, 0x55, 0x04, 0x38, 0xFF, 0x7F, 0x08, 0x7C, 0x55, 0x15, 0x38, 0xFF, 0x7F, 0x08, 0x7C, 0x5B, 0xE0, 0x38, 0xFF, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x50, 0x00, 0x3D, 0xF9, 0x80, 0xC0, 0x06, 0x7C, 0x4A, 0x8B, 0x50, 0xC0, 0x3D, 0xF5, 0x80, 0xC0, 0x0C, 0x10, 0x4B, 0x11, 0x04, 0x4B, 0x7C, 0x4A, 0x8B, 0x31, 0x80, 0x20, 0x08, 0x7C, 0x4A, 0x28, 0x18, 0x6A, 0xD0, 0x04, 0x7C, 0x4A, 0x8B, 0x6A, 0xD0, 0x1F, 0xBA
+ }
+ },
+ {
+ 253,
+ 79,
+ 0x39,
+ 0x0128,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x28, 0x08, 0x4B, 0x11, 0x04, 0x4B, 0x7C, 0x4A, 0x8B, 0x38, 0xFF, 0x20, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x10, 0x4F, 0x5D, 0xD0, 0x08, 0x62, 0xD0, 0x00, 0x7C, 0x4A, 0xA3, 0x51, 0xE1, 0x54, 0xFB, 0x18, 0x60, 0xD0, 0x20, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x5D, 0xD0, 0x08, 0x62, 0xD0, 0x00, 0x51, 0xE9, 0x08, 0x50, 0x00, 0x53, 0xE9, 0x53, 0xE1, 0x53, 0xE0, 0x53, 0xDF, 0x56, 0x00, 0x20, 0x66, 0xFC, 0xD7, 0x2B
+ }
+ },
+ {
+ 254,
+ 79,
+ 0x39,
+ 0x0129,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x29, 0x6C, 0xFB, 0x6C, 0xFA, 0x6C, 0xF9, 0x6B, 0xDF, 0x6B, 0xE0, 0x6B, 0xE1, 0x6B, 0xE9, 0x51, 0xDF, 0x1B, 0xF8, 0x51, 0xE0, 0x1B, 0xF7, 0x51, 0xE1, 0x1B, 0xF6, 0x51, 0xE9, 0x1B, 0xF5, 0xC0, 0x11, 0x53, 0xE9, 0x52, 0xF8, 0x14, 0xDF, 0x52, 0xF7, 0x1C, 0xE0, 0x52, 0xF6, 0x1C, 0xE1, 0x77, 0xFC, 0x7B, 0x00, 0xBF, 0xCB, 0x51, 0xDF, 0x54, 0xF8, 0x51, 0xE0, 0x54, 0xF7, 0x51, 0xE1, 0x54, 0xF6, 0x3A, 0xF2
+ }
+ },
+ {
+ 255,
+ 79,
+ 0x39,
+ 0x012A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x2A, 0x51, 0xE9, 0x54, 0xF5, 0x18, 0x53, 0xE9, 0x18, 0x60, 0xD0, 0x7F, 0x37, 0xFC, 0xFF, 0x77, 0xFC, 0x37, 0xFB, 0xFF, 0x0F, 0xFB, 0x00, 0x37, 0xFA, 0xFF, 0x0F, 0xFA, 0x00, 0x37, 0xF9, 0xFF, 0x0F, 0xF9, 0x00, 0x7F, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x08, 0x66, 0xFC, 0x6B, 0xE1, 0x51, 0xE1, 0x1B, 0xFB, 0xC0, 0x05, 0x53, 0xE1, 0x77, 0xFC, 0x7A, 0xE0, 0xBF, 0xEF, 0x7F, 0x08, 0x10, 0x4F, 0x50, 0x80, 0x7F
+ }
+ },
+ {
+ 256,
+ 79,
+ 0x39,
+ 0x012B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x2B, 0x00, 0x6F, 0xFF, 0xD0, 0x03, 0x03, 0xFE, 0x66, 0xFE, 0xBF, 0xF7, 0x38, 0xFE, 0x70, 0x3F, 0x71, 0xC0, 0x7F, 0x7C, 0x6E, 0x82, 0x7C, 0x6E, 0xC0, 0x7F, 0x62, 0xD0, 0x01, 0x51, 0xE7, 0x08, 0x51, 0xE6, 0x62, 0xD0, 0x03, 0x53, 0xFE, 0x18, 0x53, 0xFF, 0x62, 0xD0, 0x01, 0x51, 0xE5, 0x08, 0x51, 0xE4, 0x62, 0xD0, 0x03, 0x53, 0xFC, 0x18, 0x53, 0xFD, 0x62, 0xD0, 0x01, 0x51, 0xEF, 0x08, 0x51, 0x7E, 0x7C
+ }
+ },
+ {
+ 257,
+ 79,
+ 0x39,
+ 0x012C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x2C, 0xEE, 0x62, 0xD0, 0x03, 0x53, 0xFA, 0x18, 0x53, 0xFB, 0x62, 0xD0, 0x01, 0x51, 0xED, 0x08, 0x51, 0xEC, 0x62, 0xD0, 0x03, 0x53, 0xF8, 0x18, 0x53, 0xF9, 0x7F, 0x62, 0xD0, 0x01, 0x51, 0xE7, 0x02, 0xEF, 0x62, 0xD0, 0x00, 0x53, 0xE8, 0x62, 0xD0, 0x01, 0x51, 0xE6, 0x0A, 0xEE, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x7C, 0x6D, 0xF3, 0x51, 0xE8, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x04, 0x53, 0xA3, 0x18, 0x23, 0xC7
+ }
+ },
+ {
+ 258,
+ 79,
+ 0x39,
+ 0x012D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x2D, 0x53, 0xA4, 0x62, 0xD0, 0x01, 0x51, 0xE5, 0x02, 0xED, 0x62, 0xD0, 0x00, 0x53, 0xE8, 0x62, 0xD0, 0x01, 0x51, 0xE4, 0x0A, 0xEC, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x7C, 0x6D, 0xF3, 0x7C, 0x71, 0xC3, 0x7F, 0x10, 0x4F, 0x52, 0xFA, 0x13, 0xFC, 0x52, 0xF9, 0x1B, 0xFB, 0xD0, 0x12, 0x62, 0xD0, 0x00, 0x52, 0xFC, 0x13, 0xFA, 0x53, 0xE8, 0x52, 0xFB, 0x1B, 0xF9, 0x53, 0xE9, 0x80, 0x10, 0x62, 0xD0, 0xB7, 0xF0
+ }
+ },
+ {
+ 259,
+ 79,
+ 0x39,
+ 0x012E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x2E, 0x00, 0x52, 0xFA, 0x13, 0xFC, 0x53, 0xE8, 0x52, 0xF9, 0x1B, 0xFB, 0x53, 0xE9, 0x20, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xCD, 0x00, 0x7C, 0x70, 0x41, 0x7F, 0x62, 0xD0, 0x03, 0x51, 0xEC, 0x08, 0x51, 0xED, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xE6, 0x08, 0x51, 0xE7, 0x08, 0x9F, 0xB4, 0x38, 0xFC, 0x7C, 0x6F, 0xA8, 0x62, 0xD0, 0x03, 0x51, 0xE8, 0x08, 0x51, 0xE9, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xEE, 0x8C, 0x9B
+ }
+ },
+ {
+ 260,
+ 79,
+ 0x39,
+ 0x012F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x2F, 0x08, 0x51, 0xEF, 0x08, 0x9F, 0x9B, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x62, 0xD0, 0x04, 0x04, 0xA0, 0x7C, 0x71, 0x7F, 0x0C, 0x9F, 0x62, 0xD0, 0x03, 0x51, 0xEA, 0x08, 0x51, 0xEB, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xE4, 0x08, 0x51, 0xE5, 0x08, 0x9F, 0x78, 0x38, 0xF8, 0x7C, 0x6F, 0x76, 0x62, 0xD0, 0x03, 0x51, 0xE6, 0x08, 0x51, 0xE7, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xEC, 0x08, 0x51, 0xED, 0x08, 0x6A, 0x58
+ }
+ },
+ {
+ 261,
+ 79,
+ 0x39,
+ 0x0130,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x30, 0x9F, 0x5F, 0x38, 0xFC, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x62, 0xD0, 0x04, 0x04, 0x9E, 0x7C, 0x71, 0x7F, 0x0C, 0x9D, 0x7F, 0x10, 0x7C, 0x1E, 0x80, 0x62, 0xD0, 0x00, 0x5A, 0xE9, 0x20, 0x7C, 0x71, 0x22, 0x51, 0xAE, 0x62, 0xD0, 0x03, 0x12, 0xDD, 0x62, 0xD0, 0x04, 0x53, 0xA6, 0x62, 0xD0, 0x04, 0x51, 0xAD, 0x62, 0xD0, 0x03, 0x1A, 0xDC, 0x62, 0xD0, 0x04, 0x53, 0xA5, 0x62, 0xD0, 0x04, 0x51, 0x3D, 0xFF
+ }
+ },
+ {
+ 262,
+ 79,
+ 0x39,
+ 0x0131,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x31, 0xAE, 0x08, 0x51, 0xAD, 0x62, 0xD0, 0x03, 0x53, 0xDC, 0x18, 0x53, 0xDD, 0x62, 0xD0, 0x04, 0x51, 0xA6, 0x62, 0xD0, 0x00, 0x53, 0xE6, 0x62, 0xD0, 0x04, 0x51, 0xA5, 0x62, 0xD0, 0x00, 0x53, 0xE7, 0x62, 0xD0, 0x04, 0x51, 0xA0, 0x08, 0x62, 0xD0, 0x00, 0x18, 0x53, 0xE5, 0x55, 0xE4, 0x00, 0x65, 0xE5, 0x65, 0xE4, 0x6B, 0xE5, 0x51, 0xE4, 0x53, 0xE2, 0x51, 0xE5, 0x53, 0xE3, 0x50, 0x00, 0x08, 0x8B, 0x9C
+ }
+ },
+ {
+ 263,
+ 79,
+ 0x39,
+ 0x0132,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x32, 0x08, 0x51, 0xE7, 0x08, 0x51, 0xE6, 0x08, 0x50, 0x00, 0x08, 0x08, 0x51, 0xE3, 0x08, 0x51, 0xE2, 0x08, 0x7C, 0x49, 0xD3, 0x18, 0x53, 0xE6, 0x18, 0x53, 0xE7, 0x18, 0x18, 0x38, 0xFC, 0x51, 0xE6, 0x53, 0xE8, 0x51, 0xE7, 0x53, 0xE9, 0x51, 0xE8, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x04, 0x53, 0x9B, 0x18, 0x53, 0x9C, 0x62, 0xD0, 0x04, 0x51, 0xA6, 0x62, 0xD0, 0x00, 0x53, 0xE6, 0x62, 0xD0, 0x04, 0x57, 0x35
+ }
+ },
+ {
+ 264,
+ 79,
+ 0x39,
+ 0x0133,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x33, 0x51, 0xA5, 0x62, 0xD0, 0x00, 0x53, 0xE7, 0x62, 0xD0, 0x04, 0x51, 0x9E, 0x08, 0x62, 0xD0, 0x00, 0x18, 0x53, 0xE5, 0x55, 0xE4, 0x00, 0x65, 0xE5, 0x65, 0xE4, 0x6B, 0xE5, 0x51, 0xE4, 0x53, 0xE2, 0x51, 0xE5, 0x53, 0xE3, 0x50, 0x00, 0x08, 0x08, 0x51, 0xE7, 0x08, 0x51, 0xE6, 0x08, 0x50, 0x00, 0x08, 0x08, 0x51, 0xE3, 0x08, 0x51, 0xE2, 0x08, 0x7C, 0x49, 0xD3, 0x18, 0x53, 0xE6, 0x18, 0x53, 0x0D, 0xA2
+ }
+ },
+ {
+ 265,
+ 79,
+ 0x39,
+ 0x0134,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x34, 0xE7, 0x18, 0x18, 0x38, 0xFC, 0x51, 0xE6, 0x53, 0xE8, 0x51, 0xE7, 0x53, 0xE9, 0x51, 0xE8, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x04, 0x53, 0x99, 0x18, 0x53, 0x9A, 0x7C, 0x6E, 0x82, 0x7F, 0x10, 0x4F, 0x38, 0x08, 0x62, 0xD0, 0x04, 0x55, 0xDE, 0x00, 0x62, 0xD0, 0x04, 0x55, 0xDD, 0x00, 0x52, 0xFC, 0x03, 0xFA, 0x54, 0x01, 0x52, 0xFB, 0x0B, 0xF9, 0x54, 0x00, 0x52, 0xF8, 0x03, 0xF6, 0x54, 0x03, 0x0D, 0xA3
+ }
+ },
+ {
+ 266,
+ 79,
+ 0x39,
+ 0x0135,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x35, 0x52, 0xF7, 0x0B, 0xF5, 0x54, 0x02, 0x52, 0xFC, 0x03, 0xF6, 0x54, 0x05, 0x52, 0xFB, 0x0B, 0xF5, 0x54, 0x04, 0x52, 0xFA, 0x03, 0xF8, 0x54, 0x07, 0x52, 0xF9, 0x0B, 0xF7, 0x54, 0x06, 0x52, 0xFC, 0x13, 0xF8, 0x52, 0xFB, 0x1B, 0xF7, 0xC0, 0x43, 0x7C, 0x72, 0xD4, 0xD0, 0x1E, 0x62, 0xD0, 0x04, 0x55, 0xDE, 0x01, 0x52, 0x01, 0x13, 0x03, 0x52, 0x00, 0x1B, 0x02, 0xD0, 0x06, 0x7C, 0x73, 0x66, 0x05, 0x94
+ }
+ },
+ {
+ 267,
+ 79,
+ 0x39,
+ 0x0136,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x36, 0x80, 0x69, 0x62, 0xD0, 0x04, 0x55, 0xDD, 0x02, 0x80, 0x61, 0x62, 0xD0, 0x04, 0x55, 0xDE, 0x02, 0x52, 0x07, 0x13, 0x05, 0x52, 0x06, 0x1B, 0x04, 0xD0, 0x09, 0x62, 0xD0, 0x04, 0x55, 0xDD, 0x02, 0x80, 0x49, 0x62, 0xD0, 0x04, 0x55, 0xDD, 0x03, 0x80, 0x41, 0x7C, 0x72, 0xD4, 0xC0, 0x21, 0x62, 0xD0, 0x04, 0x55, 0xDE, 0x03, 0x52, 0x03, 0x13, 0x01, 0x52, 0x02, 0x1B, 0x00, 0xD0, 0x09, 0x62, 0xE1, 0x4D
+ }
+ },
+ {
+ 268,
+ 79,
+ 0x39,
+ 0x0137,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x37, 0xD0, 0x04, 0x55, 0xDD, 0x03, 0x80, 0x24, 0x62, 0xD0, 0x04, 0x55, 0xDD, 0x04, 0x80, 0x1C, 0x62, 0xD0, 0x04, 0x55, 0xDE, 0x04, 0x52, 0x05, 0x13, 0x07, 0x52, 0x04, 0x1B, 0x06, 0xD0, 0x09, 0x62, 0xD0, 0x04, 0x55, 0xDD, 0x04, 0x80, 0x04, 0x7C, 0x73, 0x66, 0x62, 0xD0, 0x04, 0x3C, 0xDD, 0x01, 0xB0, 0x29, 0x62, 0xD0, 0x00, 0x52, 0xF3, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x52, 0xFA, 0x02, 0xE8, 0x77, 0x7A
+ }
+ },
+ {
+ 269,
+ 79,
+ 0x39,
+ 0x0138,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x38, 0x53, 0xE8, 0x52, 0xF9, 0x0A, 0xE9, 0x53, 0xE9, 0x51, 0xE8, 0x13, 0xF6, 0x51, 0xE9, 0x1B, 0xF5, 0xD0, 0x09, 0x62, 0xD0, 0x04, 0x55, 0xE0, 0x01, 0x80, 0x97, 0x62, 0xD0, 0x04, 0x3C, 0xDD, 0x02, 0xB0, 0x29, 0x62, 0xD0, 0x00, 0x52, 0xF4, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x52, 0xF8, 0x02, 0xE8, 0x53, 0xE8, 0x52, 0xF7, 0x0A, 0xE9, 0x53, 0xE9, 0x51, 0xE8, 0x13, 0xFC, 0x51, 0xE9, 0x1B, 0xFB, 0x37, 0xFB
+ }
+ },
+ {
+ 270,
+ 79,
+ 0x39,
+ 0x0139,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x39, 0xD0, 0x09, 0x62, 0xD0, 0x04, 0x55, 0xE0, 0x02, 0x80, 0x67, 0x62, 0xD0, 0x04, 0x3C, 0xDD, 0x03, 0xB0, 0x29, 0x62, 0xD0, 0x00, 0x52, 0xF3, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x52, 0xF6, 0x02, 0xE8, 0x53, 0xE8, 0x52, 0xF5, 0x0A, 0xE9, 0x53, 0xE9, 0x51, 0xE8, 0x13, 0xFA, 0x51, 0xE9, 0x1B, 0xF9, 0xD0, 0x09, 0x62, 0xD0, 0x04, 0x55, 0xE0, 0x03, 0x80, 0x37, 0x62, 0xD0, 0x04, 0x3C, 0xDD, 0x04, 0x10, 0xAE
+ }
+ },
+ {
+ 271,
+ 79,
+ 0x39,
+ 0x013A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x3A, 0xB0, 0x29, 0x62, 0xD0, 0x00, 0x52, 0xF4, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x52, 0xFC, 0x02, 0xE8, 0x53, 0xE8, 0x52, 0xFB, 0x0A, 0xE9, 0x53, 0xE9, 0x51, 0xE8, 0x13, 0xF8, 0x51, 0xE9, 0x1B, 0xF7, 0xD0, 0x09, 0x62, 0xD0, 0x04, 0x55, 0xE0, 0x04, 0x80, 0x07, 0x62, 0xD0, 0x04, 0x55, 0xE0, 0x00, 0x62, 0xD0, 0x04, 0x3C, 0xDE, 0x04, 0xB0, 0x15, 0x62, 0xD0, 0x04, 0x3C, 0xDD, 0x01, 0xB0, 0x0D, 0xA9, 0xE1
+ }
+ },
+ {
+ 272,
+ 79,
+ 0x39,
+ 0x013B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x3B, 0x62, 0xD0, 0x04, 0x51, 0xDE, 0x01, 0x03, 0x62, 0xD0, 0x00, 0x80, 0x15, 0x62, 0xD0, 0x04, 0x51, 0xDE, 0x62, 0xD0, 0x04, 0x02, 0xDD, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x16, 0xE9, 0x02, 0x51, 0xE9, 0x38, 0xF8, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x09, 0x52, 0xF7, 0x3B, 0xFB, 0xB0, 0x1B, 0x52, 0xF8, 0x3B, 0xFC, 0xB0, 0x15, 0x52, 0xF5, 0x3B, 0xF9, 0xB0, 0x0F, 0x52, 0xF6, 0x3B, 0xFA, 0xB0, 0x09, 0xC2, 0x14
+ }
+ },
+ {
+ 273,
+ 79,
+ 0x39,
+ 0x013C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x3C, 0x62, 0xD0, 0x04, 0x55, 0xDF, 0xFE, 0x81, 0x17, 0x52, 0xF7, 0x3B, 0xFB, 0xB0, 0x07, 0x52, 0xF8, 0x3B, 0xFC, 0xA0, 0x0D, 0x52, 0xF5, 0x3B, 0xF9, 0xB0, 0x4E, 0x52, 0xF6, 0x3B, 0xFA, 0xB0, 0x48, 0x62, 0xD0, 0x04, 0x3C, 0xCE, 0x00, 0xA0, 0x06, 0x3C, 0xCE, 0x07, 0xB0, 0x09, 0x62, 0xD0, 0x04, 0x55, 0xDF, 0x00, 0x80, 0xEA, 0x62, 0xD0, 0x04, 0x3C, 0xCE, 0x01, 0xA0, 0x06, 0x3C, 0xCE, 0x02, 0xC9, 0x23
+ }
+ },
+ {
+ 274,
+ 79,
+ 0x39,
+ 0x013D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x3D, 0xB0, 0x09, 0x62, 0xD0, 0x04, 0x55, 0xDF, 0x02, 0x80, 0xD5, 0x62, 0xD0, 0x04, 0x3C, 0xCE, 0x03, 0xA0, 0x06, 0x3C, 0xCE, 0x04, 0xB0, 0x09, 0x62, 0xD0, 0x04, 0x55, 0xDF, 0x04, 0x80, 0xC0, 0x62, 0xD0, 0x04, 0x55, 0xDF, 0x06, 0x80, 0xB8, 0x52, 0xFB, 0x08, 0x52, 0xFC, 0x08, 0x52, 0xF7, 0x08, 0x52, 0xF8, 0x08, 0x9B, 0xEC, 0x7C, 0x72, 0x25, 0x52, 0xF9, 0x08, 0x52, 0xFA, 0x08, 0x52, 0xF5, 0x56, 0x3E
+ }
+ },
+ {
+ 275,
+ 79,
+ 0x39,
+ 0x013E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x3E, 0x08, 0x52, 0xF6, 0x08, 0x9B, 0xDB, 0x38, 0xF8, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x54, 0x03, 0x51, 0xE9, 0x54, 0x02, 0x52, 0x01, 0x13, 0x03, 0x52, 0x00, 0x1B, 0x02, 0xD0, 0x23, 0x7C, 0x71, 0x2E, 0x7C, 0x70, 0x17, 0x7C, 0x73, 0x4A, 0xD0, 0x09, 0x56, 0x06, 0x01, 0x56, 0x05, 0x00, 0x80, 0x07, 0x56, 0x06, 0x00, 0x56, 0x05, 0x00, 0x62, 0xD0, 0x00, 0x52, 0x06, 0x54, 0x04, 0x80, 0x2C, 0x62, 0x31, 0xF5
+ }
+ },
+ {
+ 276,
+ 79,
+ 0x39,
+ 0x013F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x3F, 0xD0, 0x00, 0x52, 0x03, 0x53, 0xE8, 0x52, 0x02, 0x53, 0xE9, 0x7C, 0x70, 0x17, 0x13, 0x01, 0x51, 0xE9, 0x1B, 0x00, 0xD0, 0x09, 0x56, 0x08, 0x01, 0x56, 0x07, 0x00, 0x80, 0x07, 0x56, 0x08, 0x00, 0x56, 0x07, 0x00, 0x62, 0xD0, 0x00, 0x52, 0x08, 0x54, 0x04, 0x62, 0xD0, 0x04, 0x47, 0xCE, 0x01, 0xB0, 0x1B, 0x62, 0xD0, 0x00, 0x52, 0x04, 0x31, 0x01, 0x53, 0xE9, 0x62, 0xD0, 0x04, 0x51, 0xCE, 0x79, 0x86
+ }
+ },
+ {
+ 277,
+ 79,
+ 0x39,
+ 0x0140,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x40, 0x62, 0xD0, 0x00, 0x02, 0xE9, 0x62, 0xD0, 0x04, 0x53, 0xDF, 0x80, 0x0D, 0x62, 0xD0, 0x04, 0x51, 0xCE, 0x03, 0x04, 0x62, 0xD0, 0x04, 0x53, 0xDF, 0x62, 0xD0, 0x04, 0x26, 0xDF, 0x07, 0x62, 0xD0, 0x04, 0x51, 0xDF, 0x01, 0x01, 0x62, 0xD0, 0x00, 0x38, 0xF7, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x04, 0x56, 0x00, 0x00, 0x7C, 0x72, 0xAB, 0x10, 0x7C, 0x1E, 0x80, 0x62, 0xD0, 0x00, 0x5A, 0xE9, 0x20, 0xC9, 0x27
+ }
+ },
+ {
+ 278,
+ 79,
+ 0x39,
+ 0x0141,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x41, 0x7C, 0x71, 0x22, 0x3D, 0xFC, 0x01, 0xA0, 0x62, 0x3D, 0xFC, 0x00, 0xB0, 0x41, 0x62, 0xD0, 0x04, 0x55, 0xD0, 0x00, 0x62, 0xD0, 0x04, 0x7C, 0x71, 0xEE, 0x3C, 0xAD, 0x00, 0xB0, 0x06, 0x3C, 0xAE, 0x00, 0xA0, 0x22, 0x62, 0xD0, 0x04, 0x51, 0xAE, 0x08, 0x51, 0xAD, 0x62, 0xD0, 0x04, 0x53, 0xAF, 0x18, 0x53, 0xB0, 0x10, 0x50, 0x00, 0x5C, 0x7C, 0x1E, 0xB4, 0x20, 0x62, 0xD0, 0x03, 0x55, 0xDD, 0x4B, 0x2C
+ }
+ },
+ {
+ 279,
+ 79,
+ 0x39,
+ 0x0142,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x42, 0x00, 0x55, 0xDC, 0x00, 0x62, 0xD0, 0x04, 0x55, 0xA6, 0x00, 0x55, 0xA5, 0x00, 0x7C, 0x72, 0x85, 0x62, 0xD0, 0x03, 0x55, 0xE3, 0x00, 0x55, 0xE2, 0x00, 0x7C, 0x73, 0x5F, 0x62, 0xD0, 0x04, 0x55, 0xD4, 0x00, 0x62, 0xD0, 0x00, 0x50, 0x00, 0x83, 0xAD, 0x62, 0xD0, 0x04, 0x3C, 0xDC, 0x01, 0xA0, 0x2A, 0x62, 0xD0, 0x01, 0x51, 0xE7, 0x08, 0x51, 0xE6, 0x62, 0xD0, 0x03, 0x53, 0xFE, 0x18, 0x53, 0x86, 0xA3
+ }
+ },
+ {
+ 280,
+ 79,
+ 0x39,
+ 0x0143,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x43, 0xFF, 0x62, 0xD0, 0x01, 0x51, 0xE5, 0x08, 0x51, 0xE4, 0x62, 0xD0, 0x03, 0x53, 0xFC, 0x18, 0x53, 0xFD, 0x7C, 0x6E, 0x82, 0x62, 0xD0, 0x04, 0x55, 0xDC, 0x01, 0x62, 0xD0, 0x01, 0x51, 0xE7, 0x08, 0x51, 0xE6, 0x62, 0xD0, 0x03, 0x53, 0xF6, 0x18, 0x53, 0xF7, 0x62, 0xD0, 0x01, 0x51, 0xE5, 0x08, 0x51, 0xE4, 0x62, 0xD0, 0x03, 0x53, 0xF4, 0x18, 0x53, 0xF5, 0x62, 0xD0, 0x00, 0x51, 0x3A, 0x08, 0x36, 0x04
+ }
+ },
+ {
+ 281,
+ 79,
+ 0x39,
+ 0x0144,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x44, 0x62, 0xD0, 0x00, 0x51, 0x39, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xEA, 0x08, 0x51, 0xEB, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xEC, 0x08, 0x51, 0xED, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xE4, 0x08, 0x51, 0xE5, 0x08, 0x51, 0xE6, 0x08, 0x51, 0xE7, 0x08, 0x9B, 0xF5, 0x38, 0xF6, 0x7C, 0x71, 0x88, 0x54, 0x00, 0x3D, 0x00, 0x00, 0xA1, 0x23, 0x3D, 0xFB, 0x00, 0xA1, 0x1E, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0xAC, 0xF1
+ }
+ },
+ {
+ 282,
+ 79,
+ 0x39,
+ 0x0145,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x45, 0x62, 0xD0, 0x03, 0x51, 0xE3, 0x21, 0x0F, 0x62, 0xD0, 0x00, 0x53, 0xE6, 0x62, 0xD0, 0x03, 0x51, 0xE2, 0x21, 0x00, 0x62, 0xD0, 0x00, 0x3A, 0xE9, 0xB0, 0x07, 0x51, 0xE6, 0x3A, 0xE8, 0xA0, 0xA4, 0x62, 0xD0, 0x03, 0x65, 0xE3, 0x6B, 0xE2, 0x65, 0xE3, 0x6B, 0xE2, 0x65, 0xE3, 0x6B, 0xE2, 0x65, 0xE3, 0x6B, 0xE2, 0x52, 0x00, 0x2C, 0xE3, 0x3C, 0xE2, 0x12, 0xB0, 0x06, 0x3C, 0xE3, 0x34, 0xA0, 0xF9, 0x8C
+ }
+ },
+ {
+ 283,
+ 79,
+ 0x39,
+ 0x0146,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x46, 0x28, 0x62, 0xD0, 0x03, 0x3C, 0xE2, 0x23, 0xB0, 0x06, 0x3C, 0xE3, 0x41, 0xA0, 0x1B, 0x62, 0xD0, 0x03, 0x3C, 0xE2, 0x34, 0xB0, 0x06, 0x3C, 0xE3, 0x12, 0xA0, 0x0E, 0x62, 0xD0, 0x03, 0x3C, 0xE2, 0x41, 0xB0, 0x14, 0x3C, 0xE3, 0x23, 0xB0, 0x0F, 0x62, 0xD0, 0x04, 0x55, 0xD2, 0x01, 0x62, 0xD0, 0x04, 0x55, 0xD3, 0x01, 0x80, 0x49, 0x62, 0xD0, 0x03, 0x3C, 0xE2, 0x43, 0xB0, 0x06, 0x3C, 0xE3, 0xD5, 0x45
+ }
+ },
+ {
+ 284,
+ 79,
+ 0x39,
+ 0x0147,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x47, 0x21, 0xA0, 0x28, 0x62, 0xD0, 0x03, 0x3C, 0xE2, 0x32, 0xB0, 0x06, 0x3C, 0xE3, 0x14, 0xA0, 0x1B, 0x62, 0xD0, 0x03, 0x3C, 0xE2, 0x21, 0xB0, 0x06, 0x3C, 0xE3, 0x43, 0xA0, 0x0E, 0x62, 0xD0, 0x03, 0x3C, 0xE2, 0x14, 0xB0, 0x14, 0x3C, 0xE3, 0x32, 0xB0, 0x0F, 0x62, 0xD0, 0x04, 0x55, 0xD2, 0x00, 0x62, 0xD0, 0x04, 0x55, 0xD3, 0x01, 0x80, 0x07, 0x62, 0xD0, 0x04, 0x55, 0xD3, 0x00, 0x7C, 0x72, 0x16, 0xC8
+ }
+ },
+ {
+ 285,
+ 79,
+ 0x39,
+ 0x0148,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x48, 0x85, 0x80, 0x3D, 0x7C, 0x73, 0x0E, 0x39, 0x00, 0xA0, 0x36, 0x62, 0xD0, 0x04, 0x3C, 0xD3, 0x01, 0xB0, 0x2E, 0x62, 0xD0, 0x00, 0x7C, 0x73, 0x0E, 0x53, 0xE9, 0x62, 0xD0, 0x04, 0x51, 0xD1, 0x62, 0xD0, 0x00, 0x3A, 0xE9, 0xA0, 0x08, 0x62, 0xD0, 0x04, 0x76, 0xD1, 0x80, 0x13, 0x62, 0xD0, 0x03, 0x55, 0xE3, 0x00, 0x55, 0xE2, 0x00, 0x7C, 0x72, 0x85, 0x62, 0xD0, 0x04, 0x55, 0xD3, 0x00, 0x62, 0x19, 0xCF
+ }
+ },
+ {
+ 286,
+ 79,
+ 0x39,
+ 0x0149,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x49, 0xD0, 0x04, 0x3C, 0xD3, 0x01, 0xB0, 0x11, 0x62, 0xD0, 0x04, 0x3C, 0xD2, 0x01, 0xB0, 0x06, 0x56, 0x00, 0x28, 0x80, 0x04, 0x56, 0x00, 0x29, 0x3D, 0x00, 0x00, 0xA0, 0x3E, 0x62, 0xD0, 0x03, 0x51, 0xEA, 0x08, 0x51, 0xEB, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xEC, 0x08, 0x51, 0xED, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xE4, 0x08, 0x51, 0xE5, 0x08, 0x51, 0xE6, 0x08, 0x51, 0xE7, 0x08, 0x9C, 0x65, 0x38, 0x1E, 0xDA
+ }
+ },
+ {
+ 287,
+ 79,
+ 0x39,
+ 0x014A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x4A, 0xF8, 0x54, 0x03, 0x3D, 0xFB, 0x00, 0xA0, 0x09, 0x62, 0xD0, 0x04, 0x3C, 0xD3, 0x00, 0xB0, 0x0A, 0x52, 0x03, 0x54, 0x00, 0x66, 0x00, 0x07, 0x00, 0x0E, 0x7C, 0x72, 0xF6, 0x39, 0x00, 0xA1, 0x5B, 0x3D, 0x00, 0x00, 0xA1, 0x56, 0x3D, 0x00, 0x28, 0xA1, 0x51, 0x3D, 0x00, 0x29, 0xA1, 0x4C, 0x62, 0xD0, 0x03, 0x51, 0xEC, 0x08, 0x51, 0xED, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xE6, 0x08, 0x51, 0xE7, 0xB4, 0x07
+ }
+ },
+ {
+ 288,
+ 79,
+ 0x39,
+ 0x014B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x4B, 0x08, 0x7C, 0x4B, 0x61, 0x38, 0xFC, 0x7C, 0x6F, 0xA8, 0x62, 0xD0, 0x03, 0x51, 0xEA, 0x08, 0x51, 0xEB, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xE4, 0x08, 0x51, 0xE5, 0x08, 0x7C, 0x4B, 0x61, 0x38, 0xFC, 0x7C, 0x6F, 0x76, 0x62, 0xD0, 0x04, 0x52, 0x00, 0x3A, 0xD4, 0xB0, 0x04, 0x56, 0x01, 0x01, 0x3D, 0x01, 0x00, 0xB0, 0xD4, 0x62, 0xD0, 0x00, 0x3C, 0x39, 0x00, 0xB0, 0x73, 0x62, 0xD0, 0x00, 0x3C, 0xBA, 0x14
+ }
+ },
+ {
+ 289,
+ 79,
+ 0x39,
+ 0x014C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x4C, 0x3A, 0x00, 0xB0, 0x6B, 0x62, 0xD0, 0x04, 0x3C, 0x9F, 0x00, 0xB0, 0x06, 0x3C, 0xA0, 0x00, 0xA0, 0x0E, 0x62, 0xD0, 0x04, 0x3C, 0x9D, 0x00, 0xB0, 0x56, 0x3C, 0x9E, 0x00, 0xB0, 0x51, 0x3D, 0x00, 0x10, 0xB0, 0x13, 0x62, 0xD0, 0x04, 0x3C, 0xD4, 0x14, 0xA0, 0x06, 0x3C, 0xD4, 0x1C, 0xB0, 0x3F, 0x56, 0x01, 0x01, 0x80, 0x3A, 0x3D, 0x00, 0x1C, 0xB0, 0x13, 0x62, 0xD0, 0x04, 0x3C, 0xD4, 0x18, 0x4D, 0x3B
+ }
+ },
+ {
+ 290,
+ 79,
+ 0x39,
+ 0x014D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x4D, 0xA0, 0x06, 0x3C, 0xD4, 0x10, 0xB0, 0x28, 0x56, 0x01, 0x01, 0x80, 0x23, 0x3D, 0x00, 0x18, 0xA0, 0x06, 0x3D, 0x00, 0x14, 0xB0, 0x19, 0x62, 0xD0, 0x00, 0x52, 0x00, 0x11, 0x04, 0x7C, 0x70, 0x27, 0xA0, 0x0A, 0x52, 0x00, 0x01, 0x04, 0x7C, 0x70, 0x27, 0xB0, 0x04, 0x56, 0x01, 0x01, 0x3D, 0x00, 0x10, 0xB0, 0x18, 0x62, 0xD0, 0x04, 0x3C, 0xD4, 0x10, 0xA0, 0x0B, 0x3C, 0xD4, 0x1E, 0xA0, 0x06, 0x64, 0x6A
+ }
+ },
+ {
+ 291,
+ 79,
+ 0x39,
+ 0x014E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x4E, 0x3C, 0xD4, 0x12, 0xB0, 0x43, 0x56, 0x01, 0x01, 0x80, 0x3E, 0x3D, 0x00, 0x1E, 0xB0, 0x18, 0x62, 0xD0, 0x04, 0x3C, 0xD4, 0x1E, 0xA0, 0x0B, 0x3C, 0xD4, 0x10, 0xA0, 0x06, 0x3C, 0xD4, 0x1C, 0xB0, 0x27, 0x56, 0x01, 0x01, 0x80, 0x22, 0x62, 0xD0, 0x04, 0x51, 0xD4, 0x3B, 0x00, 0xA0, 0x16, 0x62, 0xD0, 0x00, 0x52, 0x00, 0x11, 0x02, 0x7C, 0x70, 0x27, 0xA0, 0x0A, 0x52, 0x00, 0x01, 0x02, 0x7C, 0x91, 0xC5
+ }
+ },
+ {
+ 292,
+ 79,
+ 0x39,
+ 0x014F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x4F, 0x70, 0x27, 0xB0, 0x04, 0x56, 0x01, 0x01, 0x3D, 0x01, 0x01, 0xB0, 0x22, 0x62, 0xD0, 0x00, 0x7C, 0x72, 0xF6, 0x53, 0xE9, 0x62, 0xD0, 0x04, 0x51, 0xD5, 0x62, 0xD0, 0x00, 0x3A, 0xE9, 0xA0, 0x1B, 0x7C, 0x6E, 0x82, 0x62, 0xD0, 0x04, 0x76, 0xD5, 0x56, 0x00, 0x00, 0x80, 0x0E, 0x7C, 0x73, 0x5F, 0x52, 0x00, 0x62, 0xD0, 0x04, 0x53, 0xD4, 0x56, 0x00, 0x00, 0x3D, 0x00, 0x00, 0xA0, 0x52, 0x62, 0x27, 0xF2
+ }
+ },
+ {
+ 293,
+ 79,
+ 0x39,
+ 0x0150,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x50, 0xD0, 0x03, 0x51, 0xEC, 0x08, 0x51, 0xED, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xE6, 0x08, 0x51, 0xE7, 0x08, 0x7C, 0x4B, 0x61, 0x38, 0xFC, 0x7C, 0x6F, 0xA8, 0x62, 0xD0, 0x03, 0x51, 0xEA, 0x08, 0x51, 0xEB, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xE4, 0x08, 0x51, 0xE5, 0x08, 0x7C, 0x4B, 0x61, 0x38, 0xFC, 0x7C, 0x6F, 0x76, 0x7C, 0x4C, 0x14, 0x62, 0xD0, 0x04, 0x52, 0x00, 0x3A, 0xD0, 0xB0, 0x08, 0x62, 0xAE, 0x01
+ }
+ },
+ {
+ 294,
+ 79,
+ 0x39,
+ 0x0151,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x51, 0xD0, 0x04, 0x76, 0xCF, 0x80, 0x04, 0x7C, 0x70, 0x5B, 0x52, 0x00, 0x62, 0xD0, 0x04, 0x53, 0xD0, 0x52, 0x00, 0x62, 0xD0, 0x00, 0x38, 0xFC, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x03, 0x7C, 0x72, 0xAB, 0x56, 0x00, 0x00, 0x52, 0xFC, 0x08, 0x7C, 0x5B, 0xE0, 0x38, 0xFF, 0x62, 0xD0, 0x00, 0x54, 0x00, 0x52, 0xFC, 0x08, 0x90, 0x6D, 0x62, 0xD0, 0x00, 0x54, 0x01, 0x52, 0xFC, 0x08, 0x90, 0x96, 0x38, 0xC7, 0x34
+ }
+ },
+ {
+ 295,
+ 79,
+ 0x39,
+ 0x0152,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x52, 0xFE, 0x62, 0xD0, 0x00, 0x54, 0x02, 0x3D, 0x00, 0x00, 0xA0, 0x05, 0x52, 0x00, 0x80, 0x12, 0x3D, 0x01, 0x00, 0xA0, 0x08, 0x52, 0x01, 0x62, 0xD0, 0x00, 0x80, 0x06, 0x52, 0x02, 0x62, 0xD0, 0x00, 0x38, 0xFD, 0x20, 0x7F, 0x10, 0x4F, 0x50, 0x00, 0x08, 0x52, 0xFC, 0x08, 0x9B, 0x7E, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x01, 0x56, 0x00, 0x00, 0x50, 0x01, 0x08, 0x52, 0x5D, 0x61
+ }
+ },
+ {
+ 296,
+ 79,
+ 0x39,
+ 0x0153,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x53, 0xFC, 0x08, 0x9B, 0x68, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x54, 0x00, 0x3D, 0x00, 0x28, 0xA0, 0x0A, 0x3D, 0x00, 0x29, 0xA0, 0x05, 0x50, 0x00, 0x80, 0x06, 0x52, 0x00, 0x62, 0xD0, 0x00, 0x38, 0xFF, 0x20, 0x7F, 0x10, 0x4F, 0x50, 0x01, 0x08, 0x52, 0xFC, 0x08, 0x9B, 0x40, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x20, 0x7F, 0x10, 0x4F, 0x50, 0x00, 0x08, 0x52, 0xFC, 0x08, 0x90, 0x29, 0x38, 0xFE, 0x62, 0x5B, 0x5E
+ }
+ },
+ {
+ 297,
+ 79,
+ 0x39,
+ 0x0154,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x54, 0xD0, 0x00, 0x20, 0x7F, 0x10, 0x4F, 0x50, 0x01, 0x08, 0x52, 0xFC, 0x08, 0x90, 0x18, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x20, 0x7F, 0x10, 0x4F, 0x50, 0x02, 0x08, 0x52, 0xFC, 0x08, 0x90, 0x07, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x0F, 0x56, 0x00, 0x00, 0x56, 0x04, 0x00, 0x7C, 0x72, 0xAB, 0x56, 0x03, 0x00, 0x10, 0x7C, 0x1E, 0x80, 0x62, 0xD0, 0x00, 0x5A, 0xE9, 0x20, 0xE0, 0x69
+ }
+ },
+ {
+ 298,
+ 79,
+ 0x39,
+ 0x0155,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x55, 0x7C, 0x71, 0x22, 0x10, 0x7C, 0x1E, 0x8D, 0x62, 0xD0, 0x00, 0x5A, 0xE9, 0x20, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x04, 0x53, 0xAB, 0x18, 0x53, 0xAC, 0x3D, 0xFC, 0x02, 0xD0, 0x61, 0x3D, 0xFC, 0x00, 0xB0, 0x41, 0x62, 0xD0, 0x04, 0x55, 0xD0, 0x00, 0x62, 0xD0, 0x04, 0x7C, 0x71, 0xEE, 0x3C, 0xAD, 0x00, 0xB0, 0x06, 0x3C, 0xAE, 0x00, 0xA0, 0x22, 0x62, 0xD0, 0x04, 0x51, 0xAE, 0x08, 0x51, 0xAD, 0xF0, 0x8A
+ }
+ },
+ {
+ 299,
+ 79,
+ 0x39,
+ 0x0156,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x56, 0x62, 0xD0, 0x04, 0x53, 0xAF, 0x18, 0x53, 0xB0, 0x10, 0x50, 0x00, 0x5C, 0x7C, 0x1E, 0xB4, 0x20, 0x62, 0xD0, 0x03, 0x55, 0xDD, 0x00, 0x55, 0xDC, 0x00, 0x62, 0xD0, 0x04, 0x55, 0xA6, 0x00, 0x55, 0xA5, 0x00, 0x62, 0xD0, 0x04, 0x55, 0xDB, 0x00, 0x7C, 0x73, 0x58, 0x7C, 0x73, 0x51, 0x10, 0x50, 0x00, 0x5C, 0x7C, 0x1E, 0xCC, 0x20, 0x62, 0xD0, 0x00, 0x50, 0x00, 0x83, 0x71, 0x3D, 0xFC, 0x02, 0x20, 0xEB
+ }
+ },
+ {
+ 300,
+ 79,
+ 0x39,
+ 0x0157,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x57, 0xB3, 0x0F, 0x62, 0xD0, 0x04, 0x3C, 0xDC, 0x02, 0xD0, 0x55, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x7C, 0x72, 0x01, 0x20, 0x3C, 0xE9, 0x00, 0xB0, 0x05, 0x39, 0x00, 0xA0, 0x33, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x7C, 0x72, 0x01, 0x53, 0xE8, 0x20, 0x62, 0xD0, 0x04, 0x51, 0xAC, 0x62, 0xD0, 0x00, 0x12, 0xE8, 0x62, 0xD0, 0x04, 0x51, 0xAB, 0x62, 0xD0, 0x00, 0x1A, 0xE9, 0xD0, 0x1A, 0x7C, 0xE0, 0x6C
+ }
+ },
+ {
+ 301,
+ 79,
+ 0x39,
+ 0x0158,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x58, 0x4A, 0xD9, 0x7C, 0x4A, 0xD2, 0x7C, 0x4B, 0x1A, 0x62, 0xD0, 0x00, 0x50, 0x00, 0x83, 0x1F, 0x7C, 0x4A, 0xD9, 0x7C, 0x4A, 0xD2, 0x7C, 0x4B, 0x1A, 0x62, 0xD0, 0x04, 0x55, 0xDC, 0x02, 0x3D, 0xFB, 0x01, 0xA0, 0x06, 0x3D, 0xFB, 0x02, 0xB1, 0x49, 0x62, 0xD0, 0x01, 0x51, 0xEE, 0x08, 0x51, 0xEF, 0x08, 0x51, 0xE6, 0x08, 0x51, 0xE7, 0x08, 0x7C, 0x4B, 0x61, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x54, 0x7C, 0xA5
+ }
+ },
+ {
+ 302,
+ 79,
+ 0x39,
+ 0x0159,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x59, 0x08, 0x51, 0xE9, 0x54, 0x07, 0x62, 0xD0, 0x01, 0x51, 0xEC, 0x08, 0x51, 0xED, 0x08, 0x51, 0xE4, 0x08, 0x51, 0xE5, 0x08, 0x7C, 0x4B, 0x61, 0x38, 0xF8, 0x7C, 0x71, 0xF5, 0x62, 0xD0, 0x03, 0x51, 0xE8, 0x08, 0x51, 0xE9, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xEC, 0x08, 0x51, 0xED, 0x08, 0x7C, 0x4B, 0x61, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x54, 0x0C, 0x51, 0xE9, 0x54, 0x0B, 0x62, 0xD0, 0x03, 0x51, 0x9A, 0xE2
+ }
+ },
+ {
+ 303,
+ 79,
+ 0x39,
+ 0x015A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x5A, 0xE6, 0x08, 0x51, 0xE7, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xEA, 0x08, 0x51, 0xEB, 0x08, 0x7C, 0x4B, 0x61, 0x38, 0xF8, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x54, 0x0E, 0x51, 0xE9, 0x54, 0x0D, 0x52, 0x08, 0x13, 0x0C, 0x54, 0x06, 0x52, 0x07, 0x1B, 0x0B, 0x54, 0x05, 0x62, 0xD0, 0x00, 0x51, 0x3B, 0x62, 0xD0, 0x00, 0x13, 0x06, 0x52, 0x05, 0x31, 0x80, 0x53, 0xE1, 0x50, 0x00, 0x31, 0x80, 0x1A, 0xE1, 0x96, 0xDB
+ }
+ },
+ {
+ 304,
+ 79,
+ 0x39,
+ 0x015B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x5B, 0xD0, 0x06, 0x56, 0x00, 0x48, 0x80, 0x41, 0x52, 0x06, 0x11, 0x00, 0x52, 0x05, 0x31, 0x80, 0x19, 0x80, 0xD0, 0x35, 0x62, 0xD0, 0x00, 0x52, 0x06, 0x73, 0x53, 0xE8, 0x52, 0x05, 0x73, 0x53, 0xE9, 0x51, 0xE8, 0x01, 0x01, 0x54, 0x06, 0x51, 0xE9, 0x09, 0x00, 0x54, 0x05, 0x62, 0xD0, 0x00, 0x51, 0x3B, 0x62, 0xD0, 0x00, 0x13, 0x06, 0x52, 0x05, 0x31, 0x80, 0x53, 0xE1, 0x50, 0x00, 0x31, 0x80, 0xF9, 0xA2
+ }
+ },
+ {
+ 305,
+ 79,
+ 0x39,
+ 0x015C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x5C, 0x1A, 0xE1, 0xD0, 0x04, 0x56, 0x00, 0x49, 0x52, 0x0A, 0x13, 0x0E, 0x54, 0x06, 0x52, 0x09, 0x1B, 0x0D, 0x54, 0x05, 0x62, 0xD0, 0x00, 0x51, 0x3C, 0x62, 0xD0, 0x00, 0x13, 0x06, 0x52, 0x05, 0x31, 0x80, 0x53, 0xE1, 0x50, 0x00, 0x31, 0x80, 0x1A, 0xE1, 0xD0, 0x06, 0x56, 0x00, 0x48, 0x80, 0x41, 0x52, 0x06, 0x11, 0x00, 0x52, 0x05, 0x31, 0x80, 0x19, 0x80, 0xD0, 0x35, 0x62, 0xD0, 0x00, 0x52, 0x2B, 0x07
+ }
+ },
+ {
+ 306,
+ 79,
+ 0x39,
+ 0x015D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x5D, 0x06, 0x73, 0x53, 0xE8, 0x52, 0x05, 0x73, 0x53, 0xE9, 0x51, 0xE8, 0x01, 0x01, 0x54, 0x06, 0x51, 0xE9, 0x09, 0x00, 0x54, 0x05, 0x62, 0xD0, 0x00, 0x51, 0x3C, 0x62, 0xD0, 0x00, 0x13, 0x06, 0x52, 0x05, 0x31, 0x80, 0x53, 0xE1, 0x50, 0x00, 0x31, 0x80, 0x1A, 0xE1, 0xD0, 0x04, 0x56, 0x00, 0x49, 0x3D, 0xFB, 0x00, 0xA0, 0x06, 0x3D, 0xFB, 0x02, 0xB1, 0x57, 0x62, 0xD0, 0x00, 0x51, 0x3A, 0x08, 0x85, 0xBC
+ }
+ },
+ {
+ 307,
+ 79,
+ 0x39,
+ 0x015E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x5E, 0x62, 0xD0, 0x00, 0x51, 0x39, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xEA, 0x08, 0x51, 0xEB, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xEC, 0x08, 0x51, 0xED, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xE4, 0x08, 0x51, 0xE5, 0x08, 0x51, 0xE6, 0x08, 0x51, 0xE7, 0x08, 0x7C, 0x4D, 0x1E, 0x7C, 0x71, 0x88, 0x54, 0x01, 0x62, 0xD0, 0x03, 0x51, 0xEA, 0x08, 0x51, 0xEB, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xEC, 0x08, 0x51, 0xED, 0x92, 0xD7
+ }
+ },
+ {
+ 308,
+ 79,
+ 0x39,
+ 0x015F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x5F, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xE4, 0x08, 0x51, 0xE5, 0x08, 0x51, 0xE6, 0x08, 0x51, 0xE7, 0x08, 0x7C, 0x4E, 0xE4, 0x38, 0xEE, 0x54, 0x02, 0x62, 0xD0, 0x00, 0x51, 0x3A, 0x08, 0x62, 0xD0, 0x00, 0x51, 0x39, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xE6, 0x08, 0x51, 0xE7, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xE8, 0x08, 0x51, 0xE9, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xEC, 0x08, 0x51, 0xED, 0x08, 0x51, 0xEE, 0x51, 0x56
+ }
+ },
+ {
+ 309,
+ 79,
+ 0x39,
+ 0x0160,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x60, 0x08, 0x51, 0xEF, 0x08, 0x7C, 0x4D, 0x1E, 0x7C, 0x71, 0x88, 0x05, 0x01, 0x62, 0xD0, 0x03, 0x51, 0xE6, 0x08, 0x51, 0xE7, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xE8, 0x08, 0x51, 0xE9, 0x08, 0x62, 0xD0, 0x01, 0x51, 0xEC, 0x08, 0x51, 0xED, 0x08, 0x51, 0xEE, 0x08, 0x51, 0xEF, 0x08, 0x7C, 0x4E, 0xE4, 0x38, 0xEE, 0x62, 0xD0, 0x00, 0x54, 0x03, 0x3D, 0x01, 0x00, 0xA0, 0x95, 0x3D, 0x02, 0xFF, 0xA0, 0x19, 0xE7
+ }
+ },
+ {
+ 310,
+ 79,
+ 0x39,
+ 0x0161,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x61, 0x90, 0x3D, 0x03, 0xFF, 0xA0, 0x8B, 0x52, 0x02, 0x3B, 0x03, 0xA0, 0x0B, 0x3D, 0x02, 0x08, 0xB0, 0x0B, 0x3D, 0x03, 0x01, 0xB0, 0x06, 0x7C, 0x71, 0xB9, 0x80, 0x76, 0x3D, 0x03, 0x08, 0xB0, 0x11, 0x3D, 0x02, 0x01, 0xB0, 0x0C, 0x52, 0x03, 0x03, 0x03, 0x54, 0x00, 0x07, 0x00, 0x2E, 0x80, 0x61, 0x52, 0x03, 0x3B, 0x02, 0xD0, 0x2C, 0x62, 0xD0, 0x00, 0x52, 0x02, 0x13, 0x03, 0x39, 0x01, 0xB0, 0xAA, 0x0A
+ }
+ },
+ {
+ 311,
+ 79,
+ 0x39,
+ 0x0162,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x62, 0x21, 0x50, 0x02, 0x08, 0x52, 0x02, 0x08, 0x7C, 0x4A, 0x10, 0x38, 0xFF, 0x18, 0x39, 0x00, 0xB0, 0x06, 0x7C, 0x71, 0xB9, 0x80, 0x3B, 0x52, 0x03, 0x03, 0x03, 0x54, 0x00, 0x07, 0x00, 0x2E, 0x80, 0x30, 0x52, 0x02, 0x3B, 0x03, 0xD0, 0x2A, 0x62, 0xD0, 0x00, 0x52, 0x03, 0x13, 0x02, 0x39, 0x01, 0xB0, 0x1F, 0x50, 0x02, 0x08, 0x52, 0x03, 0x08, 0x7C, 0x4A, 0x10, 0x38, 0xFF, 0x18, 0x39, 0x00, 0x26, 0x03
+ }
+ },
+ {
+ 312,
+ 79,
+ 0x39,
+ 0x0163,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x63, 0xB0, 0x0C, 0x52, 0x03, 0x03, 0x03, 0x54, 0x00, 0x07, 0x00, 0x2E, 0x80, 0x04, 0x7C, 0x71, 0xB9, 0x3D, 0x00, 0x00, 0xA0, 0x54, 0x3D, 0xFB, 0x01, 0xB0, 0x0D, 0x52, 0x00, 0x08, 0x90, 0x52, 0x38, 0xFF, 0x62, 0xD0, 0x00, 0x80, 0x48, 0x3D, 0xFB, 0x00, 0xB0, 0x12, 0x62, 0xD0, 0x00, 0x52, 0x00, 0x29, 0x30, 0x08, 0x91, 0x16, 0x38, 0xFF, 0x62, 0xD0, 0x00, 0x80, 0x32, 0x3D, 0xFB, 0x02, 0xB0, 0xE9, 0x8A
+ }
+ },
+ {
+ 313,
+ 79,
+ 0x39,
+ 0x0164,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x64, 0x28, 0x3D, 0x00, 0x48, 0xA0, 0x06, 0x3D, 0x00, 0x49, 0xB0, 0x0D, 0x52, 0x00, 0x08, 0x90, 0x21, 0x38, 0xFF, 0x62, 0xD0, 0x00, 0x80, 0x17, 0x62, 0xD0, 0x00, 0x52, 0x00, 0x29, 0x30, 0x08, 0x90, 0xEA, 0x38, 0xFF, 0x62, 0xD0, 0x00, 0x80, 0x06, 0x62, 0xD0, 0x00, 0x50, 0x00, 0x38, 0xF1, 0x20, 0x7F, 0x10, 0x4F, 0x7C, 0x72, 0xEE, 0x39, 0x00, 0xA0, 0x43, 0x3D, 0xFC, 0x00, 0xA0, 0x3E, 0x62, 0x09, 0xCB
+ }
+ },
+ {
+ 314,
+ 79,
+ 0x39,
+ 0x0165,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x65, 0xD0, 0x04, 0x52, 0xFC, 0x3A, 0xD7, 0xB0, 0x2C, 0x62, 0xD0, 0x00, 0x7C, 0x72, 0xEE, 0x53, 0xE9, 0x62, 0xD0, 0x04, 0x51, 0xD8, 0x62, 0xD0, 0x00, 0x3A, 0xE9, 0xA0, 0x21, 0x7C, 0x72, 0x39, 0x39, 0x00, 0xA0, 0x04, 0x7C, 0x72, 0x8C, 0x7C, 0x4A, 0xD2, 0x62, 0xD0, 0x04, 0x76, 0xD8, 0x56, 0xFC, 0x00, 0x80, 0x0A, 0x62, 0xD0, 0x04, 0x55, 0xD8, 0x00, 0x7C, 0x72, 0x59, 0x7C, 0x72, 0x39, 0x39, 0x4E, 0x56
+ }
+ },
+ {
+ 315,
+ 79,
+ 0x39,
+ 0x0166,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x66, 0x00, 0xA0, 0x4D, 0x3D, 0xFC, 0x00, 0xA0, 0x48, 0x62, 0xD0, 0x04, 0x3C, 0xDB, 0x00, 0xA0, 0x3D, 0x3C, 0xDB, 0x48, 0xA0, 0x38, 0x3C, 0xDB, 0x49, 0xA0, 0x33, 0x62, 0xD0, 0x04, 0x52, 0xFC, 0x3A, 0xD7, 0xB0, 0x22, 0x62, 0xD0, 0x00, 0x7C, 0x72, 0x39, 0x53, 0xE9, 0x62, 0xD0, 0x04, 0x51, 0xD6, 0x62, 0xD0, 0x00, 0x3A, 0xE9, 0xA0, 0x19, 0x7C, 0x4A, 0xD2, 0x62, 0xD0, 0x04, 0x76, 0xD6, 0x56, 0x79, 0xAD
+ }
+ },
+ {
+ 316,
+ 79,
+ 0x39,
+ 0x0167,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x67, 0xFC, 0x00, 0x80, 0x0C, 0x7C, 0x72, 0x8C, 0x7C, 0x72, 0x59, 0x80, 0x04, 0x7C, 0x72, 0x8C, 0x3D, 0xFC, 0x00, 0xA0, 0x31, 0x7C, 0x4B, 0x1A, 0x7C, 0x4B, 0x99, 0x7C, 0x4C, 0x14, 0x7C, 0x6E, 0xC0, 0x62, 0xD0, 0x04, 0x52, 0xFC, 0x3A, 0xD0, 0xB0, 0x08, 0x62, 0xD0, 0x04, 0x76, 0xCF, 0x80, 0x04, 0x7C, 0x70, 0x5B, 0x52, 0xFC, 0x62, 0xD0, 0x04, 0x53, 0xD0, 0x52, 0xFC, 0x62, 0xD0, 0x04, 0x53, 0x22, 0x00
+ }
+ },
+ {
+ 317,
+ 79,
+ 0x39,
+ 0x0168,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x68, 0xDB, 0x7C, 0x73, 0x58, 0x52, 0xFC, 0x62, 0xD0, 0x00, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x05, 0x7C, 0x72, 0x64, 0x39, 0x00, 0xA1, 0x10, 0x56, 0x00, 0x00, 0x3D, 0xFC, 0x00, 0xA1, 0x08, 0x7C, 0x4B, 0x99, 0x62, 0xD0, 0x04, 0x52, 0xFC, 0x3A, 0xD9, 0xB0, 0x04, 0x56, 0x00, 0x01, 0x3D, 0x00, 0x00, 0xB0, 0xC1, 0x62, 0xD0, 0x00, 0x3C, 0x39, 0x00, 0xB0, 0x73, 0x62, 0xD0, 0x00, 0x3C, 0x3A, 0x00, 0x73, 0xA3
+ }
+ },
+ {
+ 318,
+ 79,
+ 0x39,
+ 0x0169,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x69, 0xB0, 0x6B, 0x62, 0xD0, 0x04, 0x3C, 0x9F, 0x00, 0xB0, 0x06, 0x3C, 0xA0, 0x00, 0xA0, 0x0E, 0x62, 0xD0, 0x04, 0x3C, 0x9D, 0x00, 0xB0, 0x56, 0x3C, 0x9E, 0x00, 0xB0, 0x51, 0x3D, 0xFC, 0x30, 0xB0, 0x13, 0x62, 0xD0, 0x04, 0x3C, 0xD9, 0x34, 0xA0, 0x06, 0x3C, 0xD9, 0x3C, 0xB0, 0x3F, 0x56, 0x00, 0x01, 0x80, 0x3A, 0x3D, 0xFC, 0x3C, 0xB0, 0x13, 0x62, 0xD0, 0x04, 0x3C, 0xD9, 0x38, 0xA0, 0x06, 0x5F, 0x7C
+ }
+ },
+ {
+ 319,
+ 79,
+ 0x39,
+ 0x016A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x6A, 0x3C, 0xD9, 0x30, 0xB0, 0x28, 0x56, 0x00, 0x01, 0x80, 0x23, 0x3D, 0xFC, 0x38, 0xA0, 0x06, 0x3D, 0xFC, 0x34, 0xB0, 0x19, 0x62, 0xD0, 0x00, 0x52, 0xFC, 0x11, 0x04, 0x7C, 0x70, 0x34, 0xA0, 0x0A, 0x52, 0xFC, 0x01, 0x04, 0x7C, 0x70, 0x34, 0xB0, 0x04, 0x56, 0x00, 0x01, 0x3D, 0xFC, 0x30, 0xB0, 0x13, 0x62, 0xD0, 0x04, 0x3C, 0xD9, 0x3E, 0xA0, 0x06, 0x3C, 0xD9, 0x32, 0xB0, 0x35, 0x56, 0x00, 0x1E, 0xFB
+ }
+ },
+ {
+ 320,
+ 79,
+ 0x39,
+ 0x016B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x6B, 0x01, 0x80, 0x30, 0x3D, 0xFC, 0x3E, 0xB0, 0x13, 0x62, 0xD0, 0x04, 0x3C, 0xD9, 0x30, 0xA0, 0x06, 0x3C, 0xD9, 0x3C, 0xB0, 0x1E, 0x56, 0x00, 0x01, 0x80, 0x19, 0x62, 0xD0, 0x00, 0x52, 0xFC, 0x11, 0x02, 0x7C, 0x70, 0x34, 0xA0, 0x0A, 0x52, 0xFC, 0x01, 0x02, 0x7C, 0x70, 0x34, 0xB0, 0x04, 0x56, 0x00, 0x01, 0x3D, 0x00, 0x01, 0xB0, 0x1F, 0x7C, 0x72, 0x64, 0x53, 0xE9, 0x62, 0xD0, 0x04, 0x51, 0x16, 0xEC
+ }
+ },
+ {
+ 321,
+ 79,
+ 0x39,
+ 0x016C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x6C, 0xDA, 0x62, 0xD0, 0x00, 0x3A, 0xE9, 0xA0, 0x1E, 0x7C, 0x4A, 0xD2, 0x62, 0xD0, 0x04, 0x76, 0xDA, 0x56, 0xFC, 0x00, 0x80, 0x11, 0x62, 0xD0, 0x04, 0x55, 0xDA, 0x00, 0x52, 0xFC, 0x62, 0xD0, 0x04, 0x53, 0xD9, 0x56, 0xFC, 0x00, 0x3D, 0xFC, 0x00, 0xA0, 0xAE, 0x7C, 0x4B, 0x1A, 0x62, 0xD0, 0x03, 0x51, 0xED, 0x62, 0xD0, 0x03, 0x02, 0xE9, 0x62, 0xD0, 0x00, 0x53, 0xE8, 0x62, 0xD0, 0x03, 0x51, 0x43, 0x47
+ }
+ },
+ {
+ 322,
+ 79,
+ 0x39,
+ 0x016D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x6D, 0xEC, 0x62, 0xD0, 0x03, 0x0A, 0xE8, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x7C, 0x6D, 0xF3, 0x51, 0xE8, 0x54, 0x02, 0x51, 0xE9, 0x54, 0x01, 0x62, 0xD0, 0x03, 0x51, 0xEB, 0x62, 0xD0, 0x03, 0x02, 0xE7, 0x62, 0xD0, 0x00, 0x53, 0xE8, 0x62, 0xD0, 0x03, 0x51, 0xEA, 0x62, 0xD0, 0x03, 0x0A, 0xE6, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x7C, 0x6D, 0xF3, 0x51, 0xE8, 0x54, 0x04, 0x51, 0xE9, 0x54, 0x03, 0x52, 0xCA, 0x56
+ }
+ },
+ {
+ 323,
+ 79,
+ 0x39,
+ 0x016E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x6E, 0x01, 0x08, 0x52, 0x02, 0x08, 0x62, 0xD0, 0x04, 0x51, 0xA3, 0x08, 0x51, 0xA4, 0x08, 0x7C, 0x4B, 0x61, 0x38, 0xFC, 0x7C, 0x6F, 0xA8, 0x52, 0x03, 0x08, 0x52, 0x04, 0x08, 0x62, 0xD0, 0x04, 0x51, 0xA1, 0x08, 0x51, 0xA2, 0x08, 0x7C, 0x4B, 0x61, 0x38, 0xFC, 0x7C, 0x6F, 0x76, 0x7C, 0x4C, 0x14, 0x7C, 0x6E, 0xC0, 0x62, 0xD0, 0x04, 0x52, 0xFC, 0x3A, 0xD0, 0xB0, 0x08, 0x62, 0xD0, 0x04, 0x76, 0x9E, 0xFF
+ }
+ },
+ {
+ 324,
+ 79,
+ 0x39,
+ 0x016F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x6F, 0xCF, 0x80, 0x04, 0x7C, 0x70, 0x5B, 0x52, 0xFC, 0x62, 0xD0, 0x04, 0x53, 0xD0, 0x52, 0xFC, 0x62, 0xD0, 0x04, 0x53, 0xDB, 0x7C, 0x73, 0x51, 0x52, 0xFC, 0x62, 0xD0, 0x00, 0x38, 0xFB, 0x20, 0x7F, 0x10, 0x4F, 0x50, 0x00, 0x08, 0x52, 0xFC, 0x08, 0x90, 0x07, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x04, 0x7C, 0x6F, 0xC9, 0x3D, 0xFB, 0x00, 0xA0, 0x37, 0x62, 0xD0, 0x04, 0xC4, 0x4C
+ }
+ },
+ {
+ 325,
+ 79,
+ 0x39,
+ 0x0170,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x70, 0x55, 0xCD, 0x00, 0x7C, 0x70, 0x62, 0x50, 0x0D, 0x10, 0x08, 0x57, 0x8D, 0x28, 0x53, 0xE7, 0x18, 0x75, 0x09, 0x00, 0x28, 0x20, 0x02, 0xE8, 0x53, 0xE8, 0x51, 0xE7, 0x0A, 0xE9, 0x10, 0x08, 0x51, 0xE8, 0x20, 0x7C, 0x1E, 0xE4, 0x20, 0x7C, 0x73, 0x43, 0x7C, 0x70, 0x41, 0x52, 0xFB, 0x62, 0xD0, 0x00, 0x83, 0x5B, 0x3D, 0xFC, 0x00, 0xB2, 0xB8, 0x7C, 0x70, 0x5B, 0x10, 0x7C, 0x1E, 0x9A, 0x62, 0xB4, 0x2D
+ }
+ },
+ {
+ 326,
+ 79,
+ 0x39,
+ 0x0171,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x71, 0xD0, 0x00, 0x5A, 0xE9, 0x20, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x04, 0x53, 0xA9, 0x18, 0x53, 0xAA, 0x10, 0x7C, 0x1E, 0xA7, 0x62, 0xD0, 0x00, 0x5A, 0xE9, 0x20, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x04, 0x53, 0xA7, 0x18, 0x53, 0xA8, 0x62, 0xD0, 0x04, 0x3C, 0xA9, 0x00, 0xB0, 0x06, 0x3C, 0xAA, 0x00, 0xA1, 0x37, 0x62, 0xD0, 0x04, 0x3C, 0xCC, 0x01, 0xB0, 0xFB, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x3F, 0x44
+ }
+ },
+ {
+ 327,
+ 79,
+ 0x39,
+ 0x0172,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x72, 0x08, 0x57, 0x8F, 0x28, 0x53, 0xE9, 0x18, 0x75, 0x09, 0x00, 0x28, 0x20, 0x62, 0xD0, 0x04, 0x12, 0xAA, 0x7C, 0x71, 0x7F, 0x1A, 0xA9, 0xD0, 0xDD, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x08, 0x57, 0x8D, 0x28, 0x53, 0xE9, 0x18, 0x75, 0x09, 0x00, 0x28, 0x53, 0xE8, 0x20, 0x7C, 0x70, 0x77, 0xD0, 0xC4, 0x7C, 0x72, 0xB9, 0x3A, 0xFE, 0xB0, 0x08, 0x7C, 0x72, 0xC2, 0x3A, 0xFF, 0xA0, 0x96, 0x62, 0x15, 0xF1
+ }
+ },
+ {
+ 328,
+ 79,
+ 0x39,
+ 0x0173,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x73, 0xD0, 0x03, 0x51, 0xF4, 0x62, 0xD0, 0x03, 0x3A, 0xFC, 0xB0, 0x0D, 0x62, 0xD0, 0x03, 0x51, 0xF5, 0x62, 0xD0, 0x03, 0x3A, 0xFD, 0xA0, 0x7E, 0x62, 0xD0, 0x03, 0x51, 0xF6, 0x08, 0x51, 0xF7, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xFE, 0x08, 0x51, 0xFF, 0x08, 0x7C, 0x4B, 0x61, 0x38, 0xFC, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x57, 0x96, 0x28, 0x20, 0x7C, 0x71, 0xD1, 0xC0, 0x27, 0x62, 0xD0, 0x03, 0x07, 0xD6
+ }
+ },
+ {
+ 329,
+ 79,
+ 0x39,
+ 0x0174,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x74, 0x51, 0xF4, 0x08, 0x51, 0xF5, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xFC, 0x08, 0x51, 0xFD, 0x08, 0x7C, 0x4B, 0x61, 0x38, 0xFC, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x57, 0x97, 0x28, 0x20, 0x7C, 0x71, 0xD1, 0xD0, 0x32, 0x56, 0x01, 0x01, 0x62, 0xD0, 0x04, 0x55, 0xCD, 0x00, 0x7C, 0x70, 0x41, 0x62, 0xD0, 0x03, 0x50, 0x0D, 0x10, 0x08, 0x57, 0x9D, 0x28, 0x53, 0xBC, 0x18, 0x75, 0x09, 0x00, 0x28, 0xDC, 0x81
+ }
+ },
+ {
+ 330,
+ 79,
+ 0x39,
+ 0x0175,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x75, 0x53, 0xBD, 0x20, 0x50, 0x0D, 0x10, 0x08, 0x57, 0x9F, 0x28, 0x53, 0xBE, 0x18, 0x75, 0x09, 0x00, 0x28, 0x53, 0xBF, 0x20, 0x3D, 0x01, 0x00, 0xB0, 0x1C, 0x62, 0xD0, 0x04, 0x3C, 0xCD, 0x00, 0xB0, 0x07, 0x7C, 0x6F, 0x87, 0x56, 0x00, 0x20, 0x62, 0xD0, 0x04, 0x76, 0xCD, 0x3C, 0xCD, 0x01, 0xB0, 0x04, 0x7C, 0x71, 0x3A, 0x62, 0xD0, 0x04, 0x3C, 0xCC, 0x02, 0xB0, 0x2D, 0x62, 0xD0, 0x00, 0x50, 0xA9, 0x1C
+ }
+ },
+ {
+ 331,
+ 79,
+ 0x39,
+ 0x0176,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x76, 0x0D, 0x10, 0x08, 0x57, 0x8B, 0x28, 0x53, 0xE9, 0x18, 0x75, 0x09, 0x00, 0x28, 0x20, 0x62, 0xD0, 0x04, 0x12, 0xAA, 0x7C, 0x71, 0x7F, 0x1A, 0xA9, 0xD0, 0x0F, 0x7C, 0x70, 0x62, 0x7C, 0x70, 0x77, 0xD0, 0x07, 0x56, 0x00, 0x40, 0x7C, 0x4B, 0x8F, 0x62, 0xD0, 0x03, 0x3C, 0xEE, 0x00, 0xB0, 0x06, 0x3C, 0xEF, 0x00, 0xA1, 0x26, 0x62, 0xD0, 0x04, 0x3C, 0xCC, 0x00, 0xB0, 0x42, 0x62, 0xD0, 0x04, 0x2A, 0x1F
+ }
+ },
+ {
+ 332,
+ 79,
+ 0x39,
+ 0x0177,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x77, 0x3C, 0xCD, 0x01, 0xB0, 0x3A, 0x62, 0xD0, 0x03, 0x51, 0xEF, 0x62, 0xD0, 0x04, 0x12, 0xA8, 0x62, 0xD0, 0x03, 0x51, 0xEE, 0x62, 0xD0, 0x04, 0x1A, 0xA7, 0xD0, 0x0D, 0x7C, 0x72, 0x6F, 0x54, 0x03, 0x7C, 0x72, 0x7A, 0x54, 0x02, 0x80, 0x04, 0x7C, 0x70, 0x41, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x7C, 0x72, 0x0D, 0x20, 0x7C, 0x73, 0x4A, 0xD0, 0xEA, 0x7C, 0x4B, 0x8F, 0x80, 0xE5, 0x62, 0xD0, 0x5E, 0x88
+ }
+ },
+ {
+ 333,
+ 79,
+ 0x39,
+ 0x0178,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x78, 0x04, 0x3C, 0xCC, 0x01, 0xB0, 0xDD, 0x7C, 0x73, 0x35, 0xB0, 0xD8, 0x62, 0xD0, 0x03, 0x51, 0xEF, 0x62, 0xD0, 0x04, 0x12, 0xA8, 0x62, 0xD0, 0x03, 0x51, 0xEE, 0x62, 0xD0, 0x04, 0x1A, 0xA7, 0xD0, 0x0D, 0x7C, 0x72, 0x6F, 0x53, 0xEF, 0x7C, 0x72, 0x7A, 0x53, 0xEE, 0x80, 0x04, 0x7C, 0x70, 0x41, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x08, 0x57, 0x93, 0x28, 0x53, 0xE9, 0x18, 0x75, 0x09, 0x00, 0x77, 0xBB
+ }
+ },
+ {
+ 334,
+ 79,
+ 0x39,
+ 0x0179,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x79, 0x28, 0x20, 0x62, 0xD0, 0x03, 0x12, 0xEF, 0x7C, 0x70, 0xA1, 0x1A, 0xEE, 0xD0, 0x88, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x7C, 0x72, 0x0D, 0x53, 0xE8, 0x20, 0x62, 0xD0, 0x03, 0x51, 0xEF, 0x62, 0xD0, 0x00, 0x12, 0xE8, 0x62, 0xD0, 0x03, 0x51, 0xEE, 0x62, 0xD0, 0x00, 0x1A, 0xE9, 0xD0, 0x66, 0x62, 0xD0, 0x03, 0x51, 0xF6, 0x08, 0x51, 0xF7, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xBC, 0x08, 0x51, 0x4F, 0x6C
+ }
+ },
+ {
+ 335,
+ 79,
+ 0x39,
+ 0x017A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x7A, 0xBD, 0x08, 0x7C, 0x4B, 0x61, 0x38, 0xFC, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x57, 0x95, 0x28, 0x20, 0x7C, 0x70, 0xBF, 0xD0, 0x2F, 0x62, 0xD0, 0x03, 0x51, 0xF4, 0x08, 0x51, 0xF5, 0x08, 0x62, 0xD0, 0x03, 0x51, 0xBE, 0x08, 0x51, 0xBF, 0x08, 0x7C, 0x4B, 0x61, 0x38, 0xFC, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x57, 0x95, 0x28, 0x20, 0x7C, 0x70, 0xBF, 0xD0, 0x09, 0x56, 0x00, 0x22, 0x7C, 0x79, 0xC1
+ }
+ },
+ {
+ 336,
+ 79,
+ 0x39,
+ 0x017B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x7B, 0x4B, 0x8F, 0x80, 0x1F, 0x7C, 0x6F, 0x87, 0x62, 0xD0, 0x04, 0x55, 0xCD, 0x01, 0x7C, 0x71, 0x3A, 0x56, 0x00, 0x20, 0x80, 0x0E, 0x7C, 0x4B, 0x8F, 0x80, 0x09, 0x7C, 0x73, 0x35, 0xB0, 0x04, 0x7C, 0x4B, 0x8F, 0x10, 0x50, 0x00, 0x5C, 0x7C, 0x1E, 0xE4, 0x20, 0x7C, 0x73, 0x43, 0x80, 0x53, 0x62, 0xD0, 0x04, 0x3C, 0xCC, 0x00, 0xB0, 0x04, 0x7C, 0x4A, 0xD9, 0x52, 0xFC, 0x62, 0xD0, 0x04, 0x53, 0x43, 0x56
+ }
+ },
+ {
+ 337,
+ 79,
+ 0x39,
+ 0x017C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x7C, 0xCC, 0x62, 0xD0, 0x01, 0x51, 0xE7, 0x08, 0x51, 0xE6, 0x62, 0xD0, 0x03, 0x53, 0xF6, 0x18, 0x53, 0xF7, 0x62, 0xD0, 0x01, 0x51, 0xE5, 0x08, 0x51, 0xE4, 0x62, 0xD0, 0x03, 0x53, 0xF4, 0x18, 0x53, 0xF5, 0x62, 0xD0, 0x01, 0x51, 0xEF, 0x08, 0x51, 0xEE, 0x62, 0xD0, 0x03, 0x53, 0xF2, 0x18, 0x53, 0xF3, 0x62, 0xD0, 0x01, 0x51, 0xED, 0x08, 0x51, 0xEC, 0x62, 0xD0, 0x03, 0x53, 0xF0, 0x18, 0x53, 0x03, 0xD7
+ }
+ },
+ {
+ 338,
+ 79,
+ 0x39,
+ 0x017D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x7D, 0xF1, 0x3D, 0x00, 0x40, 0xB0, 0x43, 0x7C, 0x72, 0xC2, 0x02, 0xF3, 0x62, 0xD0, 0x00, 0x53, 0xE8, 0x7C, 0x72, 0xB9, 0x0A, 0xF2, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x7C, 0x6D, 0xF3, 0x51, 0xE8, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x04, 0x53, 0xA3, 0x18, 0x53, 0xA4, 0x62, 0xD0, 0x03, 0x51, 0xF5, 0x02, 0xF5, 0x62, 0xD0, 0x00, 0x53, 0xE8, 0x62, 0xD0, 0x03, 0x51, 0xF4, 0x0A, 0xF4, 0x62, 0xD0, 0x00, 0x9F, 0x10
+ }
+ },
+ {
+ 339,
+ 79,
+ 0x39,
+ 0x017E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x7E, 0x53, 0xE9, 0x7C, 0x6D, 0xF3, 0x7C, 0x71, 0xC3, 0x52, 0x00, 0x62, 0xD0, 0x00, 0x38, 0xFC, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x06, 0x62, 0xD0, 0x00, 0x3C, 0x0E, 0x00, 0xA0, 0x06, 0x3D, 0xFC, 0xFF, 0xB0, 0x09, 0x62, 0xD0, 0x04, 0x55, 0xE2, 0x01, 0x85, 0xED, 0x62, 0xD0, 0x04, 0x3C, 0xE1, 0x00, 0xA0, 0x06, 0x3C, 0xE1, 0xFF, 0xB0, 0x74, 0x56, 0x00, 0x00, 0x56, 0x00, 0x00, 0x80, 0x65, 0x62, 0xDB, 0x89
+ }
+ },
+ {
+ 340,
+ 79,
+ 0x39,
+ 0x017F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x7F, 0xD0, 0x00, 0x52, 0x00, 0x7C, 0x6D, 0x8A, 0x06, 0xE8, 0xE0, 0x7C, 0x71, 0x08, 0x62, 0xD0, 0x04, 0x51, 0xE2, 0x62, 0xD0, 0x00, 0x3F, 0xE8, 0x52, 0x00, 0x7C, 0x6D, 0x8A, 0x06, 0xE8, 0xE1, 0x7C, 0x71, 0x08, 0x7C, 0x72, 0x9A, 0x62, 0xD0, 0x04, 0x76, 0xE2, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0xB8, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x7C, 0x6E, 0xAE, 0x06, 0xE6, 0x45, 0x5E
+ }
+ },
+ {
+ 341,
+ 79,
+ 0x39,
+ 0x0180,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x80, 0xB0, 0x0E, 0xE7, 0x03, 0x7C, 0x6D, 0xEA, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0xB4, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x7C, 0x6E, 0xAE, 0x06, 0xE6, 0xEA, 0x0E, 0xE7, 0x00, 0x7C, 0x6D, 0xEA, 0x77, 0x00, 0x7C, 0x6F, 0xC1, 0xCF, 0x98, 0x85, 0x6D, 0x62, 0xD0, 0x04, 0x50, 0x03, 0x3A, 0xE1, 0xC0, 0x0A, 0x62, 0xD0, 0x00, 0x50, 0x03, 0x3A, 0x0E, 0xD4, 0xAD, 0x7C, 0x71, 0x93, 0xC2, 0xFD, 0xCF
+ }
+ },
+ {
+ 342,
+ 79,
+ 0x39,
+ 0x0181,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x81, 0x0D, 0x7C, 0x6F, 0xC9, 0x80, 0x13, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0xCC, 0x7C, 0x6F, 0x54, 0x50, 0xFF, 0x3F, 0xE8, 0x77, 0x00, 0x7C, 0x71, 0xB1, 0xCF, 0xEA, 0x56, 0x00, 0x00, 0x80, 0x51, 0x56, 0x02, 0x00, 0x80, 0x41, 0x62, 0xD0, 0x00, 0x7C, 0x6F, 0x27, 0x06, 0xE8, 0xCC, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x47, 0xE9, 0x0F, 0xA0, 0x29, 0x52, 0x02, 0x08, 0x95, 0x00
+ }
+ },
+ {
+ 343,
+ 79,
+ 0x39,
+ 0x0182,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x82, 0x52, 0x00, 0x08, 0x95, 0xA1, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x54, 0x03, 0x50, 0x0D, 0x10, 0x57, 0x85, 0x28, 0x20, 0x3B, 0x03, 0xC0, 0x0F, 0x52, 0x02, 0x08, 0x52, 0x00, 0x08, 0x95, 0x0D, 0x38, 0xFE, 0x77, 0x01, 0x80, 0x0C, 0x77, 0x02, 0x62, 0xD0, 0x04, 0x52, 0x02, 0x3A, 0xE1, 0xCF, 0xB8, 0x77, 0x00, 0x7C, 0x6F, 0xC1, 0xCF, 0xAC, 0x7C, 0x71, 0xE1, 0x3D, 0x00, 0x02, 0xA0, 0x06, 0x3D, 0xB2, 0x3B
+ }
+ },
+ {
+ 344,
+ 79,
+ 0x39,
+ 0x0183,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x83, 0x00, 0x03, 0xB1, 0x09, 0x7C, 0x68, 0xBB, 0x52, 0x01, 0x08, 0x7C, 0x66, 0xDE, 0x52, 0x01, 0x08, 0x7C, 0x6A, 0x7F, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x51, 0x0E, 0x13, 0x01, 0x62, 0xD0, 0x00, 0x54, 0x00, 0x56, 0x02, 0x00, 0x80, 0xDF, 0x62, 0xD0, 0x00, 0x7C, 0x6F, 0x27, 0x55, 0xE6, 0x03, 0x55, 0xE7, 0x00, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x00, 0x3C, 0xE7, 0x00, 0xB0, 0x06, 0x3C, 0xE6, 0x00, 0x73, 0xBE
+ }
+ },
+ {
+ 345,
+ 79,
+ 0x39,
+ 0x0184,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x84, 0xA0, 0x1A, 0x70, 0xFB, 0x6E, 0xE7, 0x6E, 0xE6, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x04, 0xE1, 0x51, 0xE9, 0x0C, 0xE0, 0x65, 0xE8, 0x6B, 0xE9, 0x8F, 0xDE, 0x5F, 0xE8, 0xE1, 0x5F, 0xE9, 0xE0, 0x62, 0xD0, 0x00, 0x06, 0xE8, 0xCE, 0x0E, 0xE9, 0x02, 0x7C, 0x6D, 0x83, 0x54, 0x04, 0x7C, 0x6F, 0x27, 0x06, 0xE8, 0xFD, 0x0E, 0xE9, 0x02, 0x7C, 0x6D, 0x83, 0x54, 0x03, 0x7C, 0x71, 0x00, 0xCF, 0x77
+ }
+ },
+ {
+ 346,
+ 79,
+ 0x39,
+ 0x0185,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x85, 0x55, 0xE6, 0x03, 0x55, 0xE7, 0x00, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x00, 0x3C, 0xE7, 0x00, 0xB0, 0x06, 0x3C, 0xE6, 0x00, 0xA0, 0x1A, 0x70, 0xFB, 0x6E, 0xE7, 0x6E, 0xE6, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x04, 0xE1, 0x51, 0xE9, 0x0C, 0xE0, 0x65, 0xE8, 0x6B, 0xE9, 0x8F, 0xDE, 0x5F, 0xE8, 0xE1, 0x5F, 0xE9, 0xE0, 0x62, 0xD0, 0x00, 0x06, 0xE8, 0xC5, 0x0E, 0xE9, 0x02, 0x7C, 0x6D, 0x25, 0x24
+ }
+ },
+ {
+ 347,
+ 79,
+ 0x39,
+ 0x0186,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x86, 0x83, 0x54, 0x03, 0x52, 0x03, 0x7C, 0x6D, 0x8A, 0x06, 0xE8, 0xE0, 0x0E, 0xE9, 0x01, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x7C, 0x72, 0x31, 0x06, 0xE6, 0xD0, 0x0E, 0xE7, 0x03, 0x7C, 0x6D, 0xEA, 0x52, 0x03, 0x7C, 0x6D, 0x8A, 0x06, 0xE8, 0xE1, 0x0E, 0xE9, 0x01, 0x7C, 0x6D, 0x83, 0x7C, 0x6E, 0xE1, 0x52, 0x04, 0x7C, 0x6E, 0xB6, 0x06, 0xE6, 0xD5, 0x0E, 0xE7, 0x02, 0x7C, 0x6D, 0xEA, 0x51, 0xE8, 0x36, 0x47
+ }
+ },
+ {
+ 348,
+ 79,
+ 0x39,
+ 0x0187,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x87, 0x3F, 0xE6, 0x77, 0x02, 0x52, 0x02, 0x3B, 0x00, 0xCF, 0x1D, 0x83, 0x3A, 0x56, 0x00, 0x00, 0x80, 0x76, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0xCC, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x47, 0xE9, 0xF0, 0xA0, 0x5E, 0x56, 0x03, 0x00, 0x56, 0x04, 0xFF, 0x56, 0x02, 0x00, 0x80, 0x3B, 0x62, 0xD0, 0x00, 0x7C, 0x6F, 0x27, 0x06, 0xE8, 0xCC, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x02, 0xE0
+ }
+ },
+ {
+ 349,
+ 79,
+ 0x39,
+ 0x0188,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x88, 0x83, 0x53, 0xE9, 0x47, 0xE9, 0x0F, 0xA0, 0x23, 0x52, 0x02, 0x08, 0x52, 0x00, 0x08, 0x94, 0x16, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x54, 0x05, 0x3D, 0x03, 0x00, 0xB0, 0x06, 0x7C, 0x71, 0x4B, 0x80, 0x0A, 0x52, 0x05, 0x3B, 0x03, 0xD0, 0x04, 0x7C, 0x71, 0x4B, 0x77, 0x02, 0x62, 0xD0, 0x04, 0x52, 0x02, 0x3A, 0xE1, 0xCF, 0xBE, 0x3D, 0x04, 0xFF, 0xA0, 0x0B, 0x52, 0x04, 0x08, 0x52, 0x00, 0x08, 0x89, 0xEF
+ }
+ },
+ {
+ 350,
+ 79,
+ 0x39,
+ 0x0189,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x89, 0x93, 0x6A, 0x38, 0xFE, 0x77, 0x00, 0x7C, 0x6F, 0xC1, 0xCF, 0x87, 0x82, 0xB9, 0x7C, 0x6F, 0xC9, 0x80, 0x13, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0xCC, 0x7C, 0x6F, 0x54, 0x50, 0xFF, 0x3F, 0xE8, 0x77, 0x00, 0x7C, 0x6F, 0xC1, 0xCF, 0xEA, 0x56, 0x00, 0x00, 0x80, 0x51, 0x56, 0x02, 0x00, 0x80, 0x41, 0x62, 0xD0, 0x00, 0x7C, 0x6F, 0x27, 0x06, 0xE8, 0xCC, 0x0E, 0xE9, 0x03, 0x7C, 0xED, 0xB8
+ }
+ },
+ {
+ 351,
+ 79,
+ 0x39,
+ 0x018A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x8A, 0x6D, 0x83, 0x53, 0xE9, 0x47, 0xE9, 0xF0, 0xA0, 0x29, 0x52, 0x00, 0x08, 0x52, 0x02, 0x08, 0x93, 0x95, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x54, 0x03, 0x50, 0x0D, 0x10, 0x57, 0x85, 0x28, 0x20, 0x3B, 0x03, 0xC0, 0x0F, 0x52, 0x00, 0x08, 0x52, 0x02, 0x08, 0x93, 0x01, 0x38, 0xFE, 0x77, 0x01, 0x80, 0x0C, 0x77, 0x02, 0x62, 0xD0, 0x00, 0x52, 0x02, 0x3A, 0x0E, 0xCF, 0xB8, 0x77, 0x00, 0x7C, 0x71, 0x06, 0xEB
+ }
+ },
+ {
+ 352,
+ 79,
+ 0x39,
+ 0x018B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x8B, 0xB1, 0xCF, 0xAC, 0x7C, 0x71, 0xE1, 0x50, 0x00, 0x3B, 0x00, 0xC0, 0x06, 0x3D, 0x00, 0x04, 0xD1, 0x24, 0x62, 0xD0, 0x00, 0x51, 0x0E, 0x13, 0x01, 0x62, 0xD0, 0x00, 0x39, 0x04, 0xD1, 0x16, 0x7C, 0x68, 0xBB, 0x52, 0x01, 0x08, 0x93, 0xF7, 0x52, 0x01, 0x08, 0x7C, 0x6B, 0x94, 0x38, 0xFE, 0x56, 0x02, 0x00, 0x80, 0xF9, 0x62, 0xD0, 0x00, 0x7C, 0x6F, 0x27, 0x55, 0xE6, 0x03, 0x55, 0xE7, 0x00, 0x9B, 0x16
+ }
+ },
+ {
+ 353,
+ 79,
+ 0x39,
+ 0x018C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x8C, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x00, 0x3C, 0xE7, 0x00, 0xB0, 0x06, 0x3C, 0xE6, 0x00, 0xA0, 0x1A, 0x70, 0xFB, 0x6E, 0xE7, 0x6E, 0xE6, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x04, 0xE1, 0x51, 0xE9, 0x0C, 0xE0, 0x65, 0xE8, 0x6B, 0xE9, 0x8F, 0xDE, 0x5F, 0xE8, 0xE1, 0x5F, 0xE9, 0xE0, 0x62, 0xD0, 0x00, 0x06, 0xE8, 0xC5, 0x0E, 0xE9, 0x02, 0x7C, 0x6D, 0x83, 0x54, 0x04, 0x7C, 0x6F, 0x27, 0x98, 0x11
+ }
+ },
+ {
+ 354,
+ 79,
+ 0x39,
+ 0x018D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x8D, 0x06, 0xE8, 0xFD, 0x0E, 0xE9, 0x02, 0x7C, 0x6D, 0x83, 0x54, 0x03, 0x7C, 0x6F, 0x44, 0x06, 0xE8, 0xCC, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x7A, 0xE8, 0x53, 0xE7, 0x26, 0xE7, 0xF0, 0x7C, 0x6F, 0xD0, 0x7C, 0x71, 0x00, 0x55, 0xE6, 0x03, 0x55, 0xE7, 0x00, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x00, 0x3C, 0xE7, 0x00, 0xB0, 0x06, 0x3C, 0xE6, 0x00, 0xA0, 0x1A, 0x70, 0xFB, 0x6E, 0xE7, 0x6E, 0xE6, 0xE5, 0xAC
+ }
+ },
+ {
+ 355,
+ 79,
+ 0x39,
+ 0x018E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x8E, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x04, 0xE1, 0x51, 0xE9, 0x0C, 0xE0, 0x65, 0xE8, 0x6B, 0xE9, 0x8F, 0xDE, 0x5F, 0xE8, 0xE1, 0x5F, 0xE9, 0xE0, 0x62, 0xD0, 0x00, 0x06, 0xE8, 0xCE, 0x0E, 0xE9, 0x02, 0x7C, 0x6D, 0x83, 0x54, 0x03, 0x52, 0x04, 0x7C, 0x6D, 0x8A, 0x06, 0xE8, 0xE0, 0x0E, 0xE9, 0x01, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x52, 0x03, 0x53, 0xE6, 0x55, 0xE7, 0x00, 0x06, 0xE6, 0x47, 0x71
+ }
+ },
+ {
+ 356,
+ 79,
+ 0x39,
+ 0x018F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x8F, 0xD0, 0x0E, 0xE7, 0x03, 0x7C, 0x6D, 0xEA, 0x52, 0x04, 0x7C, 0x6D, 0x8A, 0x06, 0xE8, 0xE1, 0x0E, 0xE9, 0x01, 0x7C, 0x6D, 0x83, 0x7C, 0x6E, 0xE1, 0x52, 0x03, 0x7C, 0x6E, 0xB6, 0x06, 0xE6, 0xD5, 0x0E, 0xE7, 0x02, 0x7C, 0x6D, 0xEA, 0x51, 0xE8, 0x3F, 0xE6, 0x77, 0x02, 0x52, 0x02, 0x3B, 0x00, 0xCF, 0x03, 0x80, 0x80, 0x56, 0x00, 0x00, 0x80, 0x76, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0x2C, 0x3C
+ }
+ },
+ {
+ 357,
+ 79,
+ 0x39,
+ 0x0190,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x90, 0xE8, 0xCC, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x47, 0xE9, 0x0F, 0xA0, 0x5E, 0x56, 0x03, 0x00, 0x56, 0x04, 0xFF, 0x56, 0x02, 0x00, 0x80, 0x3B, 0x62, 0xD0, 0x00, 0x7C, 0x6F, 0x27, 0x06, 0xE8, 0xCC, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x47, 0xE9, 0xF0, 0xA0, 0x23, 0x52, 0x00, 0x08, 0x52, 0x02, 0x08, 0x91, 0xEE, 0x38, 0xFE, 0x62, 0xD0, 0x00, 0x54, 0x05, 0x3D, 0x0E, 0x01
+ }
+ },
+ {
+ 358,
+ 79,
+ 0x39,
+ 0x0191,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x91, 0x03, 0x00, 0xB0, 0x06, 0x7C, 0x71, 0x4B, 0x80, 0x0A, 0x52, 0x05, 0x3B, 0x03, 0xD0, 0x04, 0x7C, 0x71, 0x4B, 0x77, 0x02, 0x62, 0xD0, 0x00, 0x52, 0x02, 0x3A, 0x0E, 0xCF, 0xBE, 0x3D, 0x04, 0xFF, 0xA0, 0x0B, 0x52, 0x00, 0x08, 0x52, 0x04, 0x08, 0x91, 0x42, 0x38, 0xFE, 0x77, 0x00, 0x7C, 0x71, 0xB1, 0xCF, 0x87, 0x7C, 0x71, 0x93, 0xD0, 0x8E, 0x7C, 0x72, 0xDD, 0x12, 0xE1, 0x62, 0xD0, 0x00, 0xD5, 0x90
+ }
+ },
+ {
+ 359,
+ 79,
+ 0x39,
+ 0x0192,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x92, 0x54, 0x00, 0x56, 0x02, 0x00, 0x80, 0x57, 0x62, 0xD0, 0x00, 0x7C, 0x6F, 0x27, 0x06, 0xE8, 0xCC, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x26, 0xE9, 0xF0, 0x3C, 0xE9, 0xF0, 0xB0, 0x35, 0x7C, 0x6F, 0x27, 0x06, 0xE8, 0xD0, 0x7C, 0x6F, 0x54, 0x62, 0xD0, 0x04, 0x51, 0xE2, 0x62, 0xD0, 0x00, 0x3F, 0xE8, 0x52, 0x02, 0x7C, 0x6D, 0xD9, 0x06, 0xE8, 0xD5, 0x7C, 0x6F, 0xE2, 0x7C, 0x72, 0x81, 0xE9
+ }
+ },
+ {
+ 360,
+ 79,
+ 0x39,
+ 0x0193,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x93, 0x9A, 0x62, 0xD0, 0x04, 0x51, 0xE2, 0x08, 0x91, 0xCC, 0x38, 0xFF, 0x62, 0xD0, 0x04, 0x53, 0xE2, 0x7B, 0x00, 0x80, 0x08, 0x3D, 0x00, 0x00, 0xB0, 0x03, 0x80, 0x2B, 0x77, 0x02, 0x62, 0xD0, 0x00, 0x52, 0x02, 0x3A, 0x0E, 0xCF, 0xA2, 0x80, 0x1E, 0x50, 0x00, 0x08, 0x91, 0xF1, 0x38, 0xFF, 0x7C, 0x71, 0x93, 0xC0, 0x0A, 0x50, 0x00, 0x08, 0x95, 0x86, 0x38, 0xFF, 0x80, 0x09, 0x50, 0x00, 0x08, 0xE4, 0xB0
+ }
+ },
+ {
+ 361,
+ 79,
+ 0x39,
+ 0x0194,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x94, 0x7C, 0x6B, 0x94, 0x38, 0xFF, 0x56, 0x00, 0x00, 0x80, 0x88, 0x62, 0xD0, 0x00, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0xD0, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x7C, 0x6E, 0xAE, 0x65, 0xE6, 0x6B, 0xE7, 0x7C, 0x70, 0x1E, 0x06, 0xE6, 0xE0, 0x0E, 0xE7, 0x01, 0x7C, 0x6D, 0xEA, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0xB8, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x7C, 0x6E, 0xAE, 0x06, 0x78, 0xD9
+ }
+ },
+ {
+ 362,
+ 79,
+ 0x39,
+ 0x0195,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x95, 0xE6, 0xB0, 0x0E, 0xE7, 0x03, 0x7C, 0x6D, 0xEA, 0x7C, 0x6D, 0xA5, 0x06, 0xE8, 0xB4, 0x0E, 0xE9, 0x03, 0x7C, 0x6D, 0x83, 0x53, 0xE9, 0x7C, 0x6E, 0xAE, 0x06, 0xE6, 0xEA, 0x0E, 0xE7, 0x00, 0x7C, 0x6D, 0xEA, 0x7C, 0x6D, 0xA5, 0x65, 0xE8, 0x6B, 0xE9, 0x06, 0xE8, 0xD5, 0x0E, 0xE9, 0x02, 0x7C, 0x6D, 0x83, 0x7C, 0x6E, 0xE1, 0x7C, 0x73, 0x3C, 0x7C, 0x6E, 0xAE, 0x65, 0xE6, 0x6B, 0xE7, 0x7C, 0x67, 0xB8
+ }
+ },
+ {
+ 363,
+ 79,
+ 0x39,
+ 0x0196,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x96, 0x70, 0x1E, 0x06, 0xE6, 0xE1, 0x0E, 0xE7, 0x01, 0x7C, 0x6D, 0xEA, 0x51, 0xE8, 0x3F, 0xE6, 0x77, 0x00, 0x7C, 0x6F, 0xC1, 0xCF, 0x75, 0x3D, 0xFC, 0xFF, 0xA0, 0x08, 0x7C, 0x72, 0xDD, 0x53, 0xE1, 0x80, 0x07, 0x62, 0xD0, 0x04, 0x55, 0xE1, 0xFF, 0x38, 0xFA, 0x20, 0x7F, 0x10, 0x4F, 0x62, 0xD0, 0x00, 0x52, 0xFB, 0x97, 0xD5, 0x40, 0x06, 0xE8, 0xE0, 0x0E, 0xE9, 0x01, 0x97, 0xC5, 0x40, 0x53, 0xCA, 0x7F
+ }
+ },
+ {
+ 364,
+ 79,
+ 0x39,
+ 0x0197,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x97, 0xE9, 0x52, 0xFC, 0x53, 0xE6, 0x55, 0xE7, 0x00, 0x06, 0xE6, 0xD0, 0x0E, 0xE7, 0x03, 0x7C, 0x6D, 0xEA, 0x52, 0xFB, 0x97, 0xB5, 0x40, 0x06, 0xE8, 0xE1, 0x0E, 0xE9, 0x01, 0x97, 0xA5, 0x40, 0x7C, 0x6E, 0xE1, 0x52, 0xFC, 0x7C, 0x6E, 0xB6, 0x06, 0xE6, 0xD5, 0x0E, 0xE7, 0x02, 0x97, 0xFB, 0x40, 0x51, 0xE8, 0x3F, 0xE6, 0x7C, 0x70, 0xF0, 0x06, 0xE8, 0xCC, 0x0E, 0xE9, 0x03, 0x97, 0x84, 0x40, 0xDB, 0xA2
+ }
+ },
+ {
+ 365,
+ 79,
+ 0x39,
+ 0x0198,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x98, 0x7A, 0xE8, 0x53, 0xE7, 0x26, 0xE7, 0xF0, 0x7C, 0x6F, 0xD0, 0x52, 0xFC, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x06, 0xE8, 0xCC, 0x0E, 0xE9, 0x03, 0x97, 0x6A, 0x40, 0x7A, 0xE8, 0x53, 0xE7, 0x26, 0xE7, 0x0F, 0x7C, 0x6F, 0xD0, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x03, 0x7C, 0x6F, 0xB9, 0x55, 0xE9, 0x00, 0x06, 0xE8, 0xB8, 0x0E, 0xE9, 0x03, 0x97, 0x4B, 0x40, 0x54, 0x00, 0x7C, 0x70, 0xF0, 0x06, 0xE8, 0x7E, 0xE9
+ }
+ },
+ {
+ 366,
+ 79,
+ 0x39,
+ 0x0199,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x99, 0xB0, 0x0E, 0xE9, 0x03, 0x97, 0x3D, 0x40, 0x54, 0x01, 0x52, 0x00, 0x3B, 0x01, 0xD0, 0x08, 0x7C, 0x73, 0x06, 0x54, 0x02, 0x80, 0x06, 0x7C, 0x72, 0xFE, 0x54, 0x02, 0x7C, 0x6F, 0xB9, 0x55, 0xE9, 0x00, 0x06, 0xE8, 0xB4, 0x0E, 0xE9, 0x03, 0x97, 0x1A, 0x40, 0x54, 0x00, 0x7C, 0x70, 0xF0, 0x06, 0xE8, 0xEA, 0x0E, 0xE9, 0x00, 0x97, 0x0C, 0x40, 0x54, 0x01, 0x52, 0x00, 0x3B, 0x01, 0xD0, 0x08, 0x98, 0x1E
+ }
+ },
+ {
+ 367,
+ 79,
+ 0x39,
+ 0x019A,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x9A, 0x7C, 0x73, 0x06, 0x05, 0x02, 0x80, 0x06, 0x7C, 0x72, 0xFE, 0x05, 0x02, 0x52, 0x02, 0x62, 0xD0, 0x00, 0x38, 0xFD, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x77, 0xFC, 0xB0, 0x03, 0x77, 0xFC, 0x50, 0x0F, 0x3B, 0xFC, 0xD0, 0x04, 0x56, 0xFC, 0x01, 0x52, 0xFC, 0x54, 0x01, 0x56, 0x00, 0x00, 0x80, 0x1A, 0x62, 0xD0, 0x00, 0x52, 0x00, 0x96, 0xD2, 0x40, 0x06, 0xE8, 0xE0, 0x0E, 0xE9, 0x01, 0x96, 0xD9, 0xA1
+ }
+ },
+ {
+ 368,
+ 79,
+ 0x39,
+ 0x019B,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x9B, 0xC2, 0x40, 0x3B, 0xFC, 0xB0, 0x03, 0x77, 0xFC, 0x77, 0x00, 0x7C, 0x6F, 0xC1, 0xCF, 0xE3, 0x52, 0xFC, 0x3B, 0x01, 0xBF, 0xD4, 0x52, 0xFC, 0x62, 0xD0, 0x00, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x0B, 0x3D, 0xFC, 0x00, 0xB0, 0x11, 0x62, 0xD0, 0x04, 0x51, 0xE1, 0x54, 0x03, 0x62, 0xD0, 0x00, 0x51, 0x0E, 0x54, 0x02, 0x80, 0x0D, 0x62, 0xD0, 0x04, 0x51, 0xE1, 0x13, 0xFC, 0x54, 0x03, 0x43, 0x76
+ }
+ },
+ {
+ 369,
+ 79,
+ 0x39,
+ 0x019C,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x9C, 0x7C, 0x70, 0xDB, 0x56, 0x00, 0x00, 0x56, 0x01, 0x00, 0x81, 0xA7, 0x56, 0x04, 0x00, 0x81, 0x97, 0x3D, 0xFC, 0x00, 0xB0, 0x22, 0x62, 0xD0, 0x00, 0x7C, 0x6F, 0x44, 0x06, 0xE8, 0xB8, 0x0E, 0xE9, 0x03, 0x96, 0x60, 0x40, 0x54, 0x05, 0x96, 0x7D, 0x40, 0x06, 0xE8, 0xB0, 0x0E, 0xE9, 0x03, 0x96, 0x52, 0x40, 0x54, 0x06, 0x80, 0x54, 0x62, 0xD0, 0x00, 0x52, 0x04, 0x96, 0xBD, 0x40, 0x96, 0x43, 0xDE, 0xAD
+ }
+ },
+ {
+ 370,
+ 79,
+ 0x39,
+ 0x019D,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x9D, 0x40, 0x54, 0x05, 0x96, 0x60, 0x40, 0x55, 0xE6, 0x03, 0x55, 0xE7, 0x00, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x00, 0x3C, 0xE7, 0x00, 0xB0, 0x06, 0x3C, 0xE6, 0x00, 0xA0, 0x1A, 0x70, 0xFB, 0x6E, 0xE7, 0x6E, 0xE6, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x04, 0xE1, 0x51, 0xE9, 0x0C, 0xE0, 0x65, 0xE8, 0x6B, 0xE9, 0x8F, 0xDE, 0x5F, 0xE8, 0xE1, 0x5F, 0xE9, 0xE0, 0x62, 0xD0, 0x00, 0x06, 0xE8, 0x4D, 0x8C
+ }
+ },
+ {
+ 371,
+ 79,
+ 0x39,
+ 0x019E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x9E, 0xC3, 0x0E, 0xE9, 0x02, 0x95, 0xFD, 0x40, 0x54, 0x06, 0x52, 0x05, 0x3B, 0x06, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x52, 0x06, 0x13, 0x05, 0x54, 0x07, 0x80, 0x0A, 0x62, 0xD0, 0x00, 0x52, 0x05, 0x13, 0x06, 0x54, 0x07, 0x3D, 0xFC, 0x00, 0xB0, 0x22, 0x62, 0xD0, 0x00, 0x97, 0x97, 0x40, 0x06, 0xE8, 0xB4, 0x0E, 0xE9, 0x03, 0x95, 0xCD, 0x40, 0x54, 0x05, 0x95, 0xEA, 0x40, 0x06, 0xE8, 0xEA, 0x0E, 0xC7, 0x81
+ }
+ },
+ {
+ 372,
+ 79,
+ 0x39,
+ 0x019F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0x9F, 0xE9, 0x00, 0x95, 0xBF, 0x40, 0x54, 0x06, 0x80, 0x54, 0x62, 0xD0, 0x00, 0x52, 0x04, 0x96, 0x6E, 0x40, 0x95, 0xB0, 0x40, 0x54, 0x05, 0x95, 0xCD, 0x40, 0x55, 0xE6, 0x03, 0x55, 0xE7, 0x00, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x00, 0x3C, 0xE7, 0x00, 0xB0, 0x06, 0x3C, 0xE6, 0x00, 0xA0, 0x1A, 0x70, 0xFB, 0x6E, 0xE7, 0x6E, 0xE6, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x04, 0xE1, 0x51, 0xE9, 0x0B, 0x0A
+ }
+ },
+ {
+ 373,
+ 79,
+ 0x39,
+ 0x01A0,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xA0, 0x0C, 0xE0, 0x65, 0xE8, 0x6B, 0xE9, 0x8F, 0xDE, 0x5F, 0xE8, 0xE1, 0x5F, 0xE9, 0xE0, 0x62, 0xD0, 0x00, 0x06, 0xE8, 0xC4, 0x0E, 0xE9, 0x02, 0x95, 0x6A, 0x40, 0x54, 0x06, 0x52, 0x05, 0x3B, 0x06, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x52, 0x06, 0x13, 0x05, 0x54, 0x08, 0x80, 0x0A, 0x62, 0xD0, 0x00, 0x52, 0x05, 0x13, 0x06, 0x54, 0x08, 0x62, 0xD0, 0x00, 0x52, 0x07, 0x53, 0xE8, 0x50, 0x00, 0x08, 0xD8, 0xA5
+ }
+ },
+ {
+ 374,
+ 79,
+ 0x39,
+ 0x01A1,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xA1, 0x51, 0xE8, 0x08, 0x52, 0x07, 0x08, 0x95, 0x13, 0x7C, 0x71, 0xF5, 0x52, 0x08, 0x53, 0xE6, 0x50, 0x00, 0x08, 0x51, 0xE6, 0x08, 0x52, 0x08, 0x08, 0x95, 0x01, 0x38, 0xFA, 0x62, 0xD0, 0x00, 0x52, 0x0A, 0x02, 0xE8, 0x62, 0xD0, 0x03, 0x53, 0xDF, 0x52, 0x09, 0x62, 0xD0, 0x00, 0x0A, 0xE9, 0x62, 0xD0, 0x03, 0x53, 0xDE, 0x62, 0xD0, 0x00, 0x96, 0xCB, 0x40, 0x52, 0x01, 0x02, 0xE8, 0x53, 0xE8, 0x90, 0x16
+ }
+ },
+ {
+ 375,
+ 79,
+ 0x39,
+ 0x01A2,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xA2, 0x50, 0x00, 0x0A, 0xE9, 0x53, 0xE9, 0x65, 0xE8, 0x6B, 0xE9, 0x06, 0xE8, 0xB1, 0x97, 0x53, 0x40, 0x62, 0xD0, 0x03, 0x51, 0xDE, 0x62, 0xD0, 0x00, 0x3F, 0xE8, 0x62, 0xD0, 0x03, 0x51, 0xDF, 0x62, 0xD0, 0x00, 0x3F, 0xE8, 0x77, 0x04, 0x52, 0x04, 0x3B, 0x02, 0xCE, 0x65, 0x77, 0x00, 0x07, 0x01, 0x03, 0x52, 0x00, 0x3B, 0x03, 0xCE, 0x55, 0x38, 0xF5, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x97, 0xD6, 0xA3
+ }
+ },
+ {
+ 376,
+ 79,
+ 0x39,
+ 0x01A3,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xA3, 0x08, 0x40, 0x80, 0x95, 0x62, 0xD0, 0x00, 0x94, 0xDC, 0x40, 0x06, 0xE8, 0xCC, 0x0E, 0xE9, 0x03, 0x94, 0xB1, 0x40, 0x53, 0xE9, 0x47, 0xE9, 0xF0, 0xA0, 0x7D, 0x52, 0x01, 0x95, 0x1C, 0x40, 0x95, 0xCD, 0x40, 0x06, 0xE6, 0xB8, 0x0E, 0xE7, 0x03, 0x51, 0xE7, 0x60, 0xD4, 0x3E, 0xE6, 0x53, 0xE7, 0x96, 0xDE, 0x40, 0x52, 0x01, 0x95, 0x47, 0x40, 0x95, 0xB4, 0x40, 0x06, 0xE6, 0xB4, 0x0E, 0xE7, 0x7E, 0xF4
+ }
+ },
+ {
+ 377,
+ 79,
+ 0x39,
+ 0x01A4,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xA4, 0x03, 0x51, 0xE7, 0x60, 0xD4, 0x3E, 0xE6, 0x53, 0xE7, 0x96, 0xC5, 0x40, 0x52, 0x01, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x55, 0xE6, 0x03, 0x55, 0xE7, 0x00, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x00, 0x3C, 0xE7, 0x00, 0xB0, 0x06, 0x3C, 0xE6, 0x00, 0xA0, 0x1A, 0x70, 0xFB, 0x6E, 0xE7, 0x6E, 0xE6, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x04, 0xE1, 0x51, 0xE9, 0x0C, 0xE0, 0x65, 0xE8, 0x6B, 0xE9, 0xD5, 0xA3
+ }
+ },
+ {
+ 378,
+ 79,
+ 0x39,
+ 0x01A5,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xA5, 0x8F, 0xDE, 0x5F, 0xE8, 0xE1, 0x5F, 0xE9, 0xE0, 0x62, 0xD0, 0x00, 0x06, 0xE8, 0xCE, 0x0E, 0xE9, 0x02, 0x96, 0x86, 0x40, 0x77, 0x01, 0x77, 0x00, 0x96, 0x67, 0x40, 0xCF, 0x68, 0x96, 0x6A, 0x40, 0x81, 0x15, 0x62, 0xD0, 0x00, 0x94, 0x3E, 0x40, 0x06, 0xE8, 0xCC, 0x0E, 0xE9, 0x03, 0x94, 0x13, 0x40, 0x53, 0xE9, 0x47, 0xE9, 0x0F, 0xA0, 0xFD, 0x52, 0x01, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x55, 0x51, 0x9C
+ }
+ },
+ {
+ 379,
+ 79,
+ 0x39,
+ 0x01A6,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xA6, 0xE6, 0x03, 0x55, 0xE7, 0x00, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x00, 0x3C, 0xE7, 0x00, 0xB0, 0x06, 0x3C, 0xE6, 0x00, 0xA0, 0x1A, 0x70, 0xFB, 0x6E, 0xE7, 0x6E, 0xE6, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x04, 0xE1, 0x51, 0xE9, 0x0C, 0xE0, 0x65, 0xE8, 0x6B, 0xE9, 0x8F, 0xDE, 0x5F, 0xE8, 0xE1, 0x5F, 0xE9, 0xE0, 0x62, 0xD0, 0x00, 0x06, 0xE8, 0xC3, 0x0E, 0xE9, 0x02, 0x94, 0xEF, 0x40, 0xA8, 0x4B
+ }
+ },
+ {
+ 380,
+ 79,
+ 0x39,
+ 0x01A7,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xA7, 0x06, 0xE6, 0xB0, 0x0E, 0xE7, 0x03, 0x51, 0xE7, 0x60, 0xD4, 0x3E, 0xE6, 0x53, 0xE7, 0x96, 0x00, 0x40, 0x52, 0x01, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x55, 0xE6, 0x03, 0x55, 0xE7, 0x00, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x00, 0x3C, 0xE7, 0x00, 0xB0, 0x06, 0x3C, 0xE6, 0x00, 0xA0, 0x1A, 0x70, 0xFB, 0x6E, 0xE7, 0x6E, 0xE6, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x04, 0xE1, 0x51, 0xE9, 0x0C, 0x20, 0x3C
+ }
+ },
+ {
+ 381,
+ 79,
+ 0x39,
+ 0x01A8,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xA8, 0xE0, 0x65, 0xE8, 0x6B, 0xE9, 0x8F, 0xDE, 0x5F, 0xE8, 0xE1, 0x5F, 0xE9, 0xE0, 0x62, 0xD0, 0x00, 0x06, 0xE8, 0xC4, 0x0E, 0xE9, 0x02, 0x94, 0x96, 0x40, 0x06, 0xE6, 0xEA, 0x0E, 0xE7, 0x00, 0x51, 0xE7, 0x60, 0xD4, 0x3E, 0xE6, 0x53, 0xE7, 0x95, 0xA7, 0x40, 0x52, 0x01, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x55, 0xE6, 0x03, 0x55, 0xE7, 0x00, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x00, 0x3C, 0xE7, 0x00, 0x6A, 0xD1
+ }
+ },
+ {
+ 382,
+ 79,
+ 0x39,
+ 0x01A9,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xA9, 0xB0, 0x06, 0x3C, 0xE6, 0x00, 0xA0, 0x1A, 0x70, 0xFB, 0x6E, 0xE7, 0x6E, 0xE6, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x04, 0xE1, 0x51, 0xE9, 0x0C, 0xE0, 0x65, 0xE8, 0x6B, 0xE9, 0x8F, 0xDE, 0x5F, 0xE8, 0xE1, 0x5F, 0xE9, 0xE0, 0x62, 0xD0, 0x00, 0x06, 0xE8, 0xC5, 0x0E, 0xE9, 0x02, 0x95, 0x68, 0x40, 0x77, 0x01, 0x77, 0x00, 0x97, 0x39, 0x40, 0xCE, 0xE8, 0x38, 0xFE, 0x20, 0x7F, 0x10, 0x0B, 0x14
+ }
+ },
+ {
+ 383,
+ 79,
+ 0x39,
+ 0x01AA,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xAA, 0x4F, 0x38, 0x07, 0x3D, 0xFC, 0x00, 0xB0, 0x11, 0x62, 0xD0, 0x04, 0x51, 0xE1, 0x54, 0x05, 0x62, 0xD0, 0x00, 0x51, 0x0E, 0x54, 0x02, 0x80, 0x0D, 0x62, 0xD0, 0x04, 0x51, 0xE1, 0x13, 0xFC, 0x54, 0x05, 0x96, 0x38, 0x40, 0x62, 0xD0, 0x00, 0x94, 0x6F, 0x40, 0x06, 0xE8, 0x5E, 0x0E, 0xE9, 0x0F, 0x94, 0xAA, 0x40, 0x54, 0x04, 0x56, 0x03, 0x00, 0x56, 0x01, 0x00, 0x97, 0xE4, 0x40, 0x80, 0xCB, 0xEE, 0xDB
+ }
+ },
+ {
+ 384,
+ 79,
+ 0x39,
+ 0x01AB,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xAB, 0x62, 0xD0, 0x03, 0x55, 0xDF, 0x00, 0x55, 0xDE, 0x00, 0x56, 0x06, 0x00, 0x80, 0x34, 0x96, 0xCE, 0x40, 0x52, 0x01, 0x94, 0x2B, 0x40, 0x10, 0x57, 0x03, 0x7C, 0x4A, 0xBC, 0x20, 0x03, 0x06, 0x54, 0x00, 0x92, 0xC2, 0x40, 0x65, 0xE8, 0x6B, 0xE9, 0x06, 0xE8, 0xB1, 0x0E, 0xE9, 0x02, 0x92, 0x93, 0x40, 0x53, 0xE9, 0x3E, 0xE8, 0x62, 0xD0, 0x03, 0x04, 0xDF, 0x95, 0xA5, 0x40, 0x0C, 0xDE, 0x77, 0x92, 0x24
+ }
+ },
+ {
+ 385,
+ 79,
+ 0x39,
+ 0x01AC,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xAC, 0x06, 0x52, 0x06, 0x3B, 0x02, 0xCF, 0xC8, 0x95, 0x83, 0x40, 0xD0, 0x7A, 0x62, 0xD0, 0x03, 0x51, 0xDF, 0x08, 0x51, 0xDE, 0x62, 0xD0, 0x04, 0x53, 0xB1, 0x18, 0x53, 0xB2, 0x56, 0x06, 0x00, 0x80, 0x5F, 0x96, 0x7B, 0x40, 0x52, 0x01, 0x93, 0xD8, 0x40, 0x54, 0x00, 0x3D, 0xFC, 0x00, 0xB0, 0x42, 0x52, 0x00, 0x92, 0x56, 0x40, 0x06, 0xE8, 0xE0, 0x0E, 0xE9, 0x01, 0x92, 0x46, 0x40, 0x53, 0xE9, 0x64, 0xC9
+ }
+ },
+ {
+ 386,
+ 79,
+ 0x39,
+ 0x01AD,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xAD, 0x96, 0x67, 0x40, 0x06, 0xE6, 0xD0, 0x0E, 0xE7, 0x03, 0x92, 0x9F, 0x40, 0x52, 0x00, 0x92, 0x3A, 0x40, 0x06, 0xE8, 0xE1, 0x0E, 0xE9, 0x01, 0x92, 0x2A, 0x40, 0x93, 0x85, 0x40, 0x52, 0x06, 0x93, 0x55, 0x40, 0x06, 0xE6, 0xD5, 0x0E, 0xE7, 0x02, 0x92, 0x80, 0x40, 0x51, 0xE8, 0x3F, 0xE6, 0x80, 0x0D, 0x96, 0x2B, 0x40, 0x06, 0xE8, 0xFD, 0x0E, 0xE9, 0x02, 0x94, 0x5D, 0x40, 0x77, 0x06, 0x52, 0x35, 0x6C
+ }
+ },
+ {
+ 387,
+ 79,
+ 0x39,
+ 0x01AE,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xAE, 0x06, 0x3B, 0x02, 0xCF, 0x9D, 0x77, 0x03, 0x07, 0x01, 0x03, 0x52, 0x03, 0x3B, 0x04, 0xCF, 0x31, 0x38, 0xF9, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x07, 0x3D, 0xFC, 0x00, 0xB0, 0x11, 0x62, 0xD0, 0x04, 0x51, 0xE1, 0x54, 0x01, 0x62, 0xD0, 0x00, 0x51, 0x0E, 0x54, 0x02, 0x80, 0x0D, 0x62, 0xD0, 0x04, 0x51, 0xE1, 0x13, 0xFC, 0x54, 0x01, 0x95, 0x23, 0x40, 0x62, 0xD0, 0x00, 0x93, 0x69, 0x40, 0x06, 0x99, 0x35
+ }
+ },
+ {
+ 388,
+ 79,
+ 0x39,
+ 0x01AF,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xAF, 0xE8, 0x5E, 0x0E, 0xE9, 0x0F, 0x93, 0x95, 0x40, 0x54, 0x04, 0x56, 0x03, 0x00, 0x56, 0x00, 0x00, 0x96, 0xCF, 0x40, 0x81, 0x6E, 0x62, 0xD0, 0x03, 0x55, 0xDF, 0x00, 0x55, 0xDE, 0x00, 0x56, 0x05, 0x00, 0x80, 0x39, 0x62, 0xD0, 0x00, 0x93, 0x30, 0x40, 0x52, 0x00, 0x93, 0x13, 0x40, 0x53, 0xE9, 0x10, 0x52, 0x05, 0x57, 0x03, 0x7C, 0x4A, 0xBC, 0x20, 0x02, 0xE9, 0x54, 0x06, 0x52, 0x06, 0x91, 0x39, 0x76
+ }
+ },
+ {
+ 389,
+ 79,
+ 0x39,
+ 0x01B0,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xB0, 0xD8, 0x40, 0x06, 0xE8, 0xB1, 0x0E, 0xE9, 0x02, 0x91, 0x79, 0x40, 0x53, 0xE9, 0x3E, 0xE8, 0x62, 0xD0, 0x03, 0x04, 0xDF, 0x94, 0x8B, 0x40, 0x0C, 0xDE, 0x77, 0x05, 0x52, 0x05, 0x3B, 0x01, 0xCF, 0xC3, 0x94, 0x69, 0x40, 0xD1, 0x18, 0x62, 0xD0, 0x03, 0x51, 0xDF, 0x08, 0x51, 0xDE, 0x62, 0xD0, 0x04, 0x53, 0xB1, 0x18, 0x53, 0xB2, 0x56, 0x05, 0x00, 0x80, 0x2A, 0x3D, 0xFC, 0x00, 0xB0, 0x13, 0x78, 0xF5
+ }
+ },
+ {
+ 390,
+ 79,
+ 0x39,
+ 0x01B1,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xB1, 0x62, 0xD0, 0x00, 0x92, 0xD3, 0x40, 0x06, 0xE8, 0xD0, 0x93, 0x09, 0x40, 0x50, 0x00, 0x3F, 0xE8, 0x80, 0x11, 0x62, 0xD0, 0x00, 0x92, 0xC1, 0x40, 0x06, 0xE8, 0xFD, 0x93, 0x85, 0x40, 0x50, 0xFF, 0x3F, 0xE8, 0x77, 0x05, 0x52, 0x05, 0x3B, 0x02, 0xCF, 0xD2, 0x56, 0x05, 0x00, 0x80, 0x66, 0x62, 0xD0, 0x00, 0x92, 0xA4, 0x40, 0x52, 0x00, 0x92, 0x87, 0x40, 0x54, 0x06, 0x3D, 0xFC, 0x00, 0xB0, 0x7F, 0x04
+ }
+ },
+ {
+ 391,
+ 79,
+ 0x39,
+ 0x01B2,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xB2, 0x42, 0x52, 0x05, 0x91, 0x05, 0x40, 0x06, 0xE8, 0xE0, 0x0E, 0xE9, 0x01, 0x90, 0xF5, 0x40, 0x53, 0xE9, 0x95, 0x16, 0x40, 0x06, 0xE6, 0xD0, 0x0E, 0xE7, 0x03, 0x91, 0x4E, 0x40, 0x52, 0x05, 0x90, 0xE9, 0x40, 0x06, 0xE8, 0xE1, 0x0E, 0xE9, 0x01, 0x90, 0xD9, 0x40, 0x92, 0x34, 0x40, 0x52, 0x06, 0x92, 0x04, 0x40, 0x06, 0xE6, 0xD5, 0x0E, 0xE7, 0x02, 0x91, 0x2F, 0x40, 0x51, 0xE8, 0x3F, 0xE6, 0xBE, 0x83
+ }
+ },
+ {
+ 392,
+ 79,
+ 0x39,
+ 0x01B3,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xB3, 0x80, 0x11, 0x62, 0xD0, 0x00, 0x92, 0x51, 0x40, 0x06, 0xE8, 0xFD, 0x93, 0x15, 0x40, 0x52, 0x06, 0x3F, 0xE8, 0x77, 0x05, 0x52, 0x05, 0x3B, 0x01, 0xCF, 0x96, 0x3D, 0xFC, 0x00, 0xB0, 0x5F, 0x62, 0xD0, 0x04, 0x51, 0xE2, 0x62, 0xD0, 0x04, 0x53, 0xE3, 0x56, 0x05, 0x00, 0x80, 0x4A, 0x62, 0xD0, 0x00, 0x92, 0x25, 0x40, 0x06, 0xE8, 0xD0, 0x0E, 0xE9, 0x03, 0x90, 0x87, 0x40, 0x39, 0x00, 0xB0, 0x0F, 0x26
+ }
+ },
+ {
+ 393,
+ 79,
+ 0x39,
+ 0x01B4,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xB4, 0x35, 0x92, 0x15, 0x40, 0x06, 0xE8, 0xD0, 0x92, 0x4B, 0x40, 0x62, 0xD0, 0x04, 0x51, 0xE3, 0x62, 0xD0, 0x00, 0x3F, 0xE8, 0x62, 0xD0, 0x04, 0x51, 0xE3, 0x08, 0x7C, 0x66, 0x95, 0x38, 0xFF, 0x62, 0xD0, 0x04, 0x53, 0xE3, 0x62, 0xD0, 0x00, 0x52, 0x05, 0x90, 0xAE, 0x40, 0x06, 0xE8, 0xD5, 0x92, 0xB1, 0x40, 0x95, 0x66, 0x40, 0x77, 0x05, 0x52, 0x05, 0x3B, 0x02, 0xCF, 0xB2, 0x77, 0x03, 0x07, 0xE0, 0xC9
+ }
+ },
+ {
+ 394,
+ 79,
+ 0x39,
+ 0x01B5,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xB5, 0x00, 0x03, 0x52, 0x03, 0x3B, 0x04, 0xCE, 0x8E, 0x3D, 0xFC, 0x00, 0xB0, 0x0B, 0x62, 0xD0, 0x04, 0x51, 0xE3, 0x62, 0xD0, 0x04, 0x53, 0xE2, 0x38, 0xF9, 0x20, 0x7F, 0x10, 0x4F, 0x38, 0x02, 0x92, 0x68, 0x40, 0x48, 0xFC, 0x01, 0xA0, 0x09, 0x52, 0xFB, 0x05, 0x01, 0x52, 0xFA, 0x0D, 0x00, 0x66, 0xFB, 0x6C, 0xFA, 0x70, 0xFB, 0x6F, 0xFC, 0x3D, 0xFC, 0x00, 0xBF, 0xE7, 0x93, 0xB0, 0x40, 0x38, 0x30, 0x6A
+ }
+ },
+ {
+ 395,
+ 79,
+ 0x39,
+ 0x01B6,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xB6, 0xFE, 0x20, 0x7F, 0x51, 0xE9, 0x60, 0xD4, 0x3E, 0xE8, 0x7F, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x65, 0xE8, 0x6B, 0xE9, 0x65, 0xE8, 0x6B, 0xE9, 0x65, 0xE8, 0x6B, 0xE9, 0x7F, 0x65, 0xE8, 0x6B, 0xE9, 0x65, 0xE8, 0x6B, 0xE9, 0x7F, 0x52, 0x00, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x7F, 0x70, 0xFB, 0x6E, 0xE9, 0x6E, 0xE8, 0x70, 0xFB, 0x6E, 0xE9, 0x6E, 0xE8, 0x70, 0xFB, 0x6E, 0xE9, 0x6E, 0xE8, 0x70, 0x4E, 0xA7
+ }
+ },
+ {
+ 396,
+ 79,
+ 0x39,
+ 0x01B7,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xB7, 0xFB, 0x6E, 0xE9, 0x6E, 0xE8, 0x7F, 0x70, 0xFB, 0x6E, 0xE9, 0x6E, 0xE8, 0x70, 0xFB, 0x6E, 0xE9, 0x6E, 0xE8, 0x70, 0xFB, 0x6E, 0xE9, 0x6E, 0xE8, 0x7F, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x65, 0xE8, 0x6B, 0xE9, 0x7F, 0x60, 0xD4, 0x3E, 0xE8, 0x53, 0xE9, 0x7F, 0x51, 0xE7, 0x60, 0xD5, 0x51, 0xE9, 0x3F, 0xE6, 0x7F, 0x70, 0xFB, 0x6E, 0xE9, 0x6E, 0xE8, 0x7F, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x55, 0x4C, 0xA4
+ }
+ },
+ {
+ 397,
+ 79,
+ 0x39,
+ 0x01B8,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xB8, 0xE6, 0x03, 0x55, 0xE7, 0x00, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x00, 0x3C, 0xE7, 0x00, 0xB0, 0x06, 0x3C, 0xE6, 0x00, 0xA0, 0x1A, 0x70, 0xFB, 0x6E, 0xE7, 0x6E, 0xE6, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x04, 0xE1, 0x51, 0xE9, 0x0C, 0xE0, 0x65, 0xE8, 0x6B, 0xE9, 0x8F, 0xDE, 0x5F, 0xE8, 0xE1, 0x5F, 0xE9, 0xE0, 0x62, 0xD0, 0x00, 0x06, 0xE8, 0xCC, 0x0E, 0xE9, 0x02, 0x7F, 0x53, 0xE8, 0xA8, 0x5D
+ }
+ },
+ {
+ 398,
+ 79,
+ 0x39,
+ 0x01B9,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xB9, 0x55, 0xE9, 0x00, 0x55, 0xE6, 0x03, 0x55, 0xE7, 0x00, 0x55, 0xE1, 0x00, 0x55, 0xE0, 0x00, 0x3C, 0xE7, 0x00, 0xB0, 0x06, 0x3C, 0xE6, 0x00, 0xA0, 0x1A, 0x70, 0xFB, 0x6E, 0xE7, 0x6E, 0xE6, 0xD0, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x04, 0xE1, 0x51, 0xE9, 0x0C, 0xE0, 0x65, 0xE8, 0x6B, 0xE9, 0x8F, 0xDE, 0x5F, 0xE8, 0xE1, 0x5F, 0xE9, 0xE0, 0x62, 0xD0, 0x00, 0x06, 0xE8, 0xCD, 0x0E, 0xE9, 0x80, 0x0E
+ }
+ },
+ {
+ 399,
+ 79,
+ 0x39,
+ 0x01BA,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xBA, 0x02, 0x7F, 0x62, 0xD0, 0x01, 0x51, 0xE7, 0x08, 0x51, 0xE6, 0x62, 0xD0, 0x03, 0x53, 0xEC, 0x18, 0x53, 0xED, 0x62, 0xD0, 0x01, 0x51, 0xE5, 0x08, 0x51, 0xE4, 0x62, 0xD0, 0x03, 0x53, 0xEA, 0x18, 0x53, 0xEB, 0x7F, 0x53, 0xE8, 0x52, 0x01, 0x09, 0x00, 0x60, 0xD4, 0x3E, 0xE8, 0x7F, 0x52, 0x00, 0x53, 0xE6, 0x55, 0xE7, 0x00, 0x7F, 0x53, 0xE6, 0x55, 0xE7, 0x00, 0x65, 0xE6, 0x6B, 0xE7, 0x7F, 0x2B, 0x65
+ }
+ },
+ {
+ 400,
+ 79,
+ 0x39,
+ 0x01BB,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xBB, 0x62, 0xD0, 0x01, 0x51, 0xEF, 0x08, 0x51, 0xEE, 0x62, 0xD0, 0x03, 0x53, 0xE8, 0x18, 0x53, 0xE9, 0x62, 0xD0, 0x01, 0x51, 0xED, 0x08, 0x51, 0xEC, 0x62, 0xD0, 0x03, 0x53, 0xE6, 0x18, 0x53, 0xE7, 0x7F, 0x53, 0xE9, 0x3E, 0xE8, 0x53, 0xE8, 0x7F, 0x62, 0xD0, 0x00, 0x51, 0xAF, 0x29, 0x01, 0x53, 0xAF, 0x51, 0xAF, 0x60, 0x04, 0x51, 0xAF, 0x29, 0x08, 0x53, 0xAF, 0x51, 0xAF, 0x60, 0x04, 0x7F, 0x67, 0xDE
+ }
+ },
+ {
+ 401,
+ 79,
+ 0x39,
+ 0x01BC,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xBC, 0x02, 0xE8, 0x53, 0xE8, 0x50, 0x00, 0x0A, 0xE9, 0x53, 0xE9, 0x06, 0xE8, 0x62, 0x0E, 0xE9, 0x0F, 0x51, 0xE9, 0x10, 0x58, 0xE8, 0x28, 0x20, 0x7F, 0x52, 0x05, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x7F, 0x53, 0xAF, 0x51, 0xAF, 0x60, 0x04, 0x7F, 0x52, 0x02, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x7F, 0x62, 0xD0, 0x03, 0x51, 0x99, 0x21, 0x70, 0x54, 0x00, 0x3D, 0x00, 0x00, 0x7F, 0x62, 0xD0, 0x03, 0x51, 0x11, 0x33
+ }
+ },
+ {
+ 402,
+ 79,
+ 0x39,
+ 0x01BD,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xBD, 0x99, 0x21, 0x70, 0x7F, 0x52, 0x04, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x7F, 0x62, 0xD0, 0x00, 0x52, 0x02, 0x53, 0xE8, 0x7F, 0x0E, 0xE9, 0x03, 0x51, 0xE9, 0x60, 0xD5, 0x7F, 0x51, 0xE9, 0x10, 0x58, 0xE8, 0x28, 0x20, 0x7F, 0x62, 0xD0, 0x00, 0x26, 0xAF, 0xF7, 0x51, 0xAF, 0x60, 0x04, 0x26, 0xAF, 0xFE, 0x51, 0xAF, 0x60, 0x04, 0x7F, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x67, 0xE0
+ }
+ },
+ {
+ 403,
+ 79,
+ 0x39,
+ 0x01BE,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xBE, 0x04, 0x53, 0x9D, 0x18, 0x53, 0x9E, 0x7F, 0x62, 0xD0, 0x03, 0x51, 0xF7, 0x08, 0x51, 0xF6, 0x62, 0xD0, 0x03, 0x53, 0xBC, 0x18, 0x53, 0xBD, 0x62, 0xD0, 0x03, 0x51, 0xF5, 0x08, 0x51, 0xF4, 0x62, 0xD0, 0x03, 0x53, 0xBE, 0x18, 0x53, 0xBF, 0x7F, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x04, 0x53, 0x9F, 0x18, 0x53, 0xA0, 0x7F, 0x62, 0xD0, 0x00, 0x52, 0xFC, 0x53, 0xE8, 0x85, 0x1D
+ }
+ },
+ {
+ 404,
+ 79,
+ 0x39,
+ 0x01BF,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xBF, 0x7F, 0x62, 0xD0, 0x00, 0x52, 0x00, 0x3A, 0x0E, 0x7F, 0x56, 0x01, 0x00, 0x56, 0x00, 0x00, 0x7F, 0x51, 0xE9, 0x60, 0xD5, 0x51, 0xE7, 0x3F, 0xE8, 0x7F, 0x51, 0xE9, 0x60, 0xD5, 0x52, 0x00, 0x3F, 0xE8, 0x7F, 0x0E, 0xE9, 0x02, 0x51, 0xE9, 0x60, 0xD5, 0x7F, 0x62, 0xD0, 0x03, 0x52, 0x01, 0x53, 0xE5, 0x52, 0x00, 0x53, 0xE4, 0x7F, 0x52, 0x02, 0x53, 0xE8, 0x52, 0x01, 0x60, 0xD4, 0x3E, 0xE8, 0x95, 0x3E
+ }
+ },
+ {
+ 405,
+ 79,
+ 0x39,
+ 0x01C0,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xC0, 0x7F, 0x70, 0xFB, 0x6F, 0x01, 0x6F, 0x02, 0x70, 0xFB, 0x6F, 0x01, 0x6F, 0x02, 0x7F, 0x62, 0xD0, 0x00, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x7F, 0x65, 0xE8, 0x6B, 0xE9, 0x51, 0xE8, 0x7F, 0x65, 0xE6, 0x6B, 0xE7, 0x65, 0xE6, 0x6B, 0xE7, 0x7F, 0x53, 0xE9, 0x62, 0xD0, 0x04, 0x51, 0xD4, 0x62, 0xD0, 0x00, 0x3A, 0xE9, 0x7F, 0x53, 0xE9, 0x62, 0xD0, 0x04, 0x51, 0xD9, 0x62, 0xD0, 0x00, 0x3A, 0xE9, 0x2E, 0x71
+ }
+ },
+ {
+ 406,
+ 79,
+ 0x39,
+ 0x01C1,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xC1, 0x7F, 0x62, 0xD0, 0x03, 0x55, 0xEF, 0x00, 0x55, 0xEE, 0x00, 0x7F, 0x56, 0x01, 0x00, 0x80, 0x03, 0x77, 0x01, 0x3D, 0x01, 0x0A, 0xCF, 0xFA, 0x62, 0xD0, 0x00, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xCF, 0x01, 0x7F, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x08, 0x57, 0x89, 0x28, 0x53, 0xE9, 0x18, 0x75, 0x09, 0x00, 0x28, 0x53, 0xE8, 0x20, 0x7F, 0x62, 0xD0, 0x04, 0x51, 0xAA, 0x62, 0xD0, 0x00, 0x12, 0xA0, 0x56
+ }
+ },
+ {
+ 407,
+ 79,
+ 0x39,
+ 0x01C2,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xC2, 0xE8, 0x62, 0xD0, 0x04, 0x51, 0xA9, 0x62, 0xD0, 0x00, 0x1A, 0xE9, 0x7F, 0x62, 0xD0, 0x03, 0x51, 0xDF, 0x62, 0xD0, 0x04, 0x12, 0xB2, 0x62, 0xD0, 0x03, 0x51, 0xDE, 0x62, 0xD0, 0x04, 0x1A, 0xB1, 0x7F, 0x62, 0xD0, 0x00, 0x51, 0xE9, 0x62, 0xD0, 0x03, 0x7F, 0x70, 0xFE, 0x62, 0xD0, 0x03, 0x51, 0xD9, 0x08, 0x51, 0xD8, 0x62, 0xD0, 0x00, 0x53, 0x0A, 0x18, 0x53, 0x0B, 0x71, 0x01, 0x7F, 0x53, 0x76, 0x03
+ }
+ },
+ {
+ 408,
+ 79,
+ 0x39,
+ 0x01C3,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xC3, 0xE6, 0x55, 0xE7, 0x00, 0x51, 0xE8, 0x12, 0xE6, 0x51, 0xE9, 0x1A, 0xE7, 0x7F, 0x60, 0xD4, 0x3E, 0xE8, 0x54, 0x03, 0x7F, 0x70, 0xFB, 0x6F, 0x01, 0x6F, 0x02, 0x7F, 0x62, 0xD0, 0x00, 0x51, 0x0E, 0x13, 0xFC, 0x62, 0xD0, 0x00, 0x54, 0x02, 0x7F, 0x70, 0xFE, 0x62, 0xD0, 0x00, 0x51, 0x0D, 0x7F, 0x52, 0xFB, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x7F, 0x5D, 0xC8, 0x62, 0xD0, 0x00, 0x39, 0x00, 0x7F, 0x80, 0x18
+ }
+ },
+ {
+ 409,
+ 79,
+ 0x39,
+ 0x01C4,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xC4, 0x52, 0x03, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x7F, 0x0E, 0xE9, 0x01, 0x51, 0xE9, 0x60, 0xD5, 0x7F, 0x71, 0x10, 0x5D, 0xE0, 0x54, 0x01, 0x41, 0xE0, 0xE7, 0x43, 0xE0, 0x18, 0x70, 0xCF, 0x62, 0xE3, 0x38, 0x7F, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x04, 0x53, 0xAD, 0x18, 0x53, 0xAE, 0x7F, 0x62, 0xD0, 0x00, 0x52, 0x01, 0x53, 0xE8, 0x52, 0x00, 0x53, 0xE9, 0x7F, 0x62, 0xD0, 0x04, 0x51, 0xA8, 0x08, 0xD8, 0xC9
+ }
+ },
+ {
+ 410,
+ 79,
+ 0x39,
+ 0x01C5,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xC5, 0x51, 0xA7, 0x62, 0xD0, 0x03, 0x53, 0xEE, 0x18, 0x53, 0xEF, 0x7F, 0x52, 0x05, 0x54, 0x03, 0x52, 0x02, 0x54, 0x04, 0x7F, 0x62, 0xD0, 0x00, 0x51, 0x0D, 0x08, 0x51, 0x0C, 0x62, 0xD0, 0x03, 0x53, 0xD4, 0x18, 0x53, 0xD5, 0x7F, 0x5D, 0xD6, 0x53, 0xE9, 0x2E, 0xE9, 0xFE, 0x51, 0xE9, 0x54, 0x02, 0x43, 0xD6, 0x01, 0x52, 0xFC, 0x7F, 0x53, 0xE8, 0x52, 0xFB, 0x09, 0x00, 0x60, 0xD5, 0x7F, 0x62, 0xD2, 0xBE
+ }
+ },
+ {
+ 411,
+ 79,
+ 0x39,
+ 0x01C6,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xC6, 0xD0, 0x00, 0x51, 0xE9, 0x62, 0xD0, 0x04, 0x7F, 0x62, 0xD0, 0x04, 0x53, 0xCE, 0x62, 0xD0, 0x04, 0x51, 0xE0, 0x7F, 0x62, 0xD0, 0x04, 0x51, 0xE1, 0x62, 0xD0, 0x00, 0x3A, 0x0E, 0x7F, 0x62, 0xD0, 0x00, 0x52, 0x06, 0x53, 0xE8, 0x55, 0xE9, 0x00, 0x7F, 0x52, 0x06, 0x53, 0xE6, 0x55, 0xE7, 0x00, 0x7F, 0x62, 0xD0, 0x04, 0x52, 0x00, 0x3A, 0xE1, 0x7F, 0x52, 0x02, 0x03, 0x02, 0x54, 0x00, 0x07, 0x01, 0x1D
+ }
+ },
+ {
+ 412,
+ 79,
+ 0x39,
+ 0x01C7,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xC7, 0x00, 0x2E, 0x7F, 0x51, 0xE8, 0x08, 0x51, 0xE9, 0x62, 0xD0, 0x04, 0x53, 0xA1, 0x18, 0x53, 0xA2, 0x7F, 0x12, 0xE8, 0x50, 0x00, 0x1A, 0xE9, 0x7F, 0x62, 0xD0, 0x03, 0x51, 0x9D, 0x62, 0xD0, 0x00, 0x7F, 0x62, 0xD0, 0x04, 0x51, 0xE1, 0x13, 0x01, 0x62, 0xD0, 0x00, 0x54, 0x00, 0x7F, 0x55, 0xDC, 0x00, 0x62, 0xD0, 0x04, 0x7F, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x54, 0x0A, 0x51, 0xE9, 0x54, 0x09, 0x45, 0xA6
+ }
+ },
+ {
+ 413,
+ 79,
+ 0x39,
+ 0x01C8,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xC8, 0x7F, 0x08, 0x57, 0x98, 0x28, 0x53, 0xE9, 0x18, 0x75, 0x09, 0x00, 0x28, 0x7F, 0x08, 0x57, 0x91, 0x28, 0x53, 0xE9, 0x18, 0x75, 0x09, 0x00, 0x28, 0x7F, 0x62, 0xD0, 0x00, 0x55, 0x0B, 0x01, 0x55, 0x0A, 0x00, 0x71, 0x01, 0x7F, 0x62, 0xD0, 0x00, 0x51, 0xE8, 0x54, 0x01, 0x51, 0xE9, 0x54, 0x00, 0x7F, 0x52, 0x04, 0x53, 0xE6, 0x55, 0xE7, 0x00, 0x7F, 0x50, 0x0D, 0x10, 0x57, 0x88, 0x28, 0x20, 0x36, 0x89
+ }
+ },
+ {
+ 414,
+ 79,
+ 0x39,
+ 0x01C9,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xC9, 0x7F, 0x62, 0xD0, 0x04, 0x52, 0x00, 0x3A, 0xC0, 0x7F, 0x62, 0xD0, 0x00, 0x53, 0xE9, 0x51, 0xE8, 0x7F, 0x51, 0xAF, 0x60, 0x04, 0x62, 0xD0, 0x00, 0x7F, 0x52, 0xFC, 0x62, 0xD0, 0x04, 0x53, 0xD7, 0x56, 0xFC, 0x00, 0x7F, 0x62, 0xD0, 0x00, 0x50, 0x0D, 0x10, 0x57, 0x87, 0x28, 0x20, 0x7F, 0x62, 0xD0, 0x04, 0x51, 0xA8, 0x62, 0xD0, 0x03, 0x12, 0xEF, 0x7F, 0x62, 0xD0, 0x04, 0x51, 0xA7, 0x62, 0xF2, 0x02
+ }
+ },
+ {
+ 415,
+ 79,
+ 0x39,
+ 0x01CA,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xCA, 0xD0, 0x03, 0x1A, 0xEE, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xD1, 0x00, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xD6, 0x00, 0x7F, 0x62, 0xD0, 0x03, 0x47, 0x99, 0x70, 0x7F, 0x50, 0x00, 0x3F, 0xE8, 0x3F, 0xE8, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xB2, 0xFF, 0x55, 0xB1, 0xFF, 0x7F, 0x56, 0x01, 0x00, 0x56, 0x02, 0x00, 0x7F, 0x71, 0x10, 0x60, 0xE0, 0x70, 0xCF, 0x7F, 0x62, 0xD0, 0x03, 0x51, 0xF6, 0x62, 0xD0, 0x51, 0xC1
+ }
+ },
+ {
+ 416,
+ 79,
+ 0x39,
+ 0x01CB,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xCB, 0x03, 0x7F, 0x62, 0xD0, 0x03, 0x51, 0xF7, 0x62, 0xD0, 0x03, 0x7F, 0x71, 0x10, 0x43, 0xD7, 0x20, 0x43, 0xE0, 0x40, 0x7F, 0x52, 0xFA, 0x13, 0xF6, 0x52, 0xF9, 0x1B, 0xF5, 0x7F, 0x62, 0xD0, 0x00, 0x51, 0x0E, 0x62, 0xD0, 0x04, 0x7F, 0x3F, 0xE8, 0x62, 0xD0, 0x04, 0x51, 0xB6, 0x7F, 0x50, 0x0D, 0x10, 0x57, 0x86, 0x28, 0x20, 0x7F, 0x50, 0x0D, 0x10, 0x57, 0x9A, 0x28, 0x20, 0x7F, 0x62, 0xD0, 0x10, 0x40
+ }
+ },
+ {
+ 417,
+ 79,
+ 0x39,
+ 0x01CC,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xCC, 0x00, 0x52, 0x00, 0x13, 0x01, 0x7F, 0x62, 0xD0, 0x00, 0x52, 0x01, 0x13, 0x00, 0x7F, 0x50, 0x0D, 0x10, 0x57, 0x9B, 0x28, 0x20, 0x7F, 0x60, 0x0C, 0x62, 0xD0, 0x00, 0x51, 0xB2, 0x7F, 0x60, 0x08, 0x62, 0xD0, 0x00, 0x51, 0xB1, 0x7F, 0x62, 0xD0, 0x03, 0x51, 0x9B, 0x21, 0x0F, 0x7F, 0x62, 0xD0, 0x03, 0x47, 0x99, 0x04, 0x7F, 0x62, 0xD0, 0x04, 0x3C, 0xCD, 0x02, 0x7F, 0x06, 0xE8, 0x01, 0x0E, 0x82, 0x25
+ }
+ },
+ {
+ 418,
+ 79,
+ 0x39,
+ 0x01CD,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xCD, 0xE9, 0x00, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xCC, 0x00, 0x7F, 0x13, 0x03, 0x51, 0xE9, 0x1B, 0x02, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xD7, 0x00, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xD9, 0x00, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xD5, 0x00, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xDD, 0x01, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xCB, 0xF4, 0x7F, 0x62, 0xD0, 0x04, 0x55, 0xB4, 0x00, 0x7F, 0x41, 0xD7, 0xDF, 0x41, 0xE0, 0x54, 0xCA
+ }
+ },
+ {
+ 419,
+ 79,
+ 0x39,
+ 0x01CE,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xCE, 0xBF, 0x7F, 0x41, 0xE0, 0xEF, 0x62, 0xDA, 0xEF, 0x7F, 0x41, 0xE0, 0x7F, 0x62, 0xDA, 0x7F, 0x7F, 0x62, 0xD0, 0x00, 0x3C, 0xBA, 0x00, 0x7F, 0x00, 0xBF, 0x00, 0x20, 0x00, 0xEA, 0x00, 0x06, 0x01, 0x00, 0x00, 0xA0, 0x02, 0xB1, 0x00, 0x4F, 0x03, 0x99, 0x00, 0x47, 0x03, 0xE0, 0x01, 0x0D, 0x03, 0xE1, 0x00, 0x1F, 0x04, 0x99, 0x00, 0x49, 0x04, 0xE2, 0x02, 0x01, 0x00, 0xFF, 0x00, 0x30, 0x30, 0xF0, 0x03
+ }
+ },
+ {
+ 420,
+ 79,
+ 0x39,
+ 0x01CF,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xCF, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x24
+ }
+ },
+ {
+ 421,
+ 79,
+ 0x39,
+ 0x01D0,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xD0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x25
+ }
+ },
+ {
+ 422,
+ 79,
+ 0x39,
+ 0x01D1,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xD1, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x26
+ }
+ },
+ {
+ 423,
+ 79,
+ 0x39,
+ 0x01D2,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xD2, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x27
+ }
+ },
+ {
+ 424,
+ 79,
+ 0x39,
+ 0x01D3,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xD3, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x28
+ }
+ },
+ {
+ 425,
+ 79,
+ 0x39,
+ 0x01D4,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xD4, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x29
+ }
+ },
+ {
+ 426,
+ 79,
+ 0x39,
+ 0x01D5,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xD5, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x2A
+ }
+ },
+ {
+ 427,
+ 79,
+ 0x39,
+ 0x01D6,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xD6, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x2B
+ }
+ },
+ {
+ 428,
+ 79,
+ 0x39,
+ 0x01D7,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xD7, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x2C
+ }
+ },
+ {
+ 429,
+ 79,
+ 0x39,
+ 0x01D8,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xD8, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x2D
+ }
+ },
+ {
+ 430,
+ 79,
+ 0x39,
+ 0x01D9,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xD9, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x2E
+ }
+ },
+ {
+ 431,
+ 79,
+ 0x39,
+ 0x01DA,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xDA, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x2F
+ }
+ },
+ {
+ 432,
+ 79,
+ 0x39,
+ 0x01DB,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xDB, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30
+ }
+ },
+ {
+ 433,
+ 79,
+ 0x39,
+ 0x01DC,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xDC, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x31
+ }
+ },
+ {
+ 434,
+ 79,
+ 0x39,
+ 0x01DD,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xDD, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x32
+ }
+ },
+ {
+ 435,
+ 79,
+ 0x39,
+ 0x01DE,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xDE, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x33
+ }
+ },
+ {
+ 436,
+ 79,
+ 0x39,
+ 0x01DF,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xDF, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x34
+ }
+ },
+ {
+ 437,
+ 79,
+ 0x39,
+ 0x01E0,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xE0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x35
+ }
+ },
+ {
+ 438,
+ 79,
+ 0x39,
+ 0x01E1,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xE1, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x36
+ }
+ },
+ {
+ 439,
+ 79,
+ 0x39,
+ 0x01E2,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xE2, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x37
+ }
+ },
+ {
+ 440,
+ 79,
+ 0x39,
+ 0x01E3,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xE3, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x38
+ }
+ },
+ {
+ 441,
+ 79,
+ 0x39,
+ 0x01E4,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xE4, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x39
+ }
+ },
+ {
+ 442,
+ 79,
+ 0x39,
+ 0x01E5,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xE5, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x3A
+ }
+ },
+ {
+ 443,
+ 79,
+ 0x39,
+ 0x01E6,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xE6, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x3B
+ }
+ },
+ {
+ 444,
+ 79,
+ 0x39,
+ 0x01E7,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xE7, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x3C
+ }
+ },
+ {
+ 445,
+ 79,
+ 0x39,
+ 0x01E8,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xE8, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x3D
+ }
+ },
+ {
+ 446,
+ 79,
+ 0x39,
+ 0x01E9,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xE9, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x3E
+ }
+ },
+ {
+ 447,
+ 79,
+ 0x39,
+ 0x01EA,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xEA, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x3F
+ }
+ },
+ {
+ 448,
+ 79,
+ 0x39,
+ 0x01EB,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xEB, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x40
+ }
+ },
+ {
+ 449,
+ 79,
+ 0x39,
+ 0x01EC,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xEC, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x41
+ }
+ },
+ {
+ 450,
+ 79,
+ 0x39,
+ 0x01ED,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xED, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x42
+ }
+ },
+ {
+ 451,
+ 79,
+ 0x39,
+ 0x01EE,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xEE, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x43
+ }
+ },
+ {
+ 452,
+ 79,
+ 0x39,
+ 0x01EF,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xEF, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x44
+ }
+ },
+ {
+ 453,
+ 79,
+ 0x39,
+ 0x01F0,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xF0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x45
+ }
+ },
+ {
+ 454,
+ 79,
+ 0x39,
+ 0x01F1,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xF1, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x46
+ }
+ },
+ {
+ 455,
+ 79,
+ 0x39,
+ 0x01F2,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xF2, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x47
+ }
+ },
+ {
+ 456,
+ 79,
+ 0x39,
+ 0x01F3,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xF3, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x48
+ }
+ },
+ {
+ 457,
+ 79,
+ 0x39,
+ 0x01F4,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xF4, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x49
+ }
+ },
+ {
+ 458,
+ 79,
+ 0x39,
+ 0x01F5,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xF5, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x4A
+ }
+ },
+ {
+ 459,
+ 79,
+ 0x39,
+ 0x01F6,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xF6, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x4B
+ }
+ },
+ {
+ 460,
+ 79,
+ 0x39,
+ 0x01F7,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xF7, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x4C
+ }
+ },
+ {
+ 461,
+ 79,
+ 0x39,
+ 0x01F8,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xF8, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x4D
+ }
+ },
+ {
+ 462,
+ 79,
+ 0x39,
+ 0x01F9,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xF9, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x4E
+ }
+ },
+ {
+ 463,
+ 79,
+ 0x39,
+ 0x01FA,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xFA, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x4F
+ }
+ },
+ {
+ 464,
+ 79,
+ 0x39,
+ 0x01FB,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xFB, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x50
+ }
+ },
+ {
+ 465,
+ 79,
+ 0x39,
+ 0x01FC,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x51
+ }
+ },
+ {
+ 466,
+ 79,
+ 0x39,
+ 0x01FD,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xFD, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x52
+ }
+ },
+ {
+ 467,
+ 79,
+ 0x39,
+ 0x01FE,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x53
+ }
+ },
+ {
+ 468,
+ 79,
+ 0x39,
+ 0x01FF,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x01, 0xFF, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x54
+ }
+ },
+ {
+ 469,
+ 79,
+ 0x39,
+ 0x001E,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x1E, 0x19, 0xE5, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x01, 0x0B, 0x10, 0x12, 0xA0, 0x02, 0x04, 0x00, 0xC0, 0xC1, 0xC2, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xA5, 0xBC
+ }
+ },
+ {
+ 470,
+ 79,
+ 0x39,
+ 0x001F,
+ {
+ 0x00, 0xFF, 0x39, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x1F, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xA0, 0x07, 0x5F, 0xF8, 0x3E, 0xEF
+ }
+ },
+ {
+ 471,
+ 11,
+ 0x3B,
+ -1,
+ {
+ 0x00, 0xFF, 0x3B, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+ }
+ },
+};
+
+unsigned short cyttsp_fw_records = 472;
+
+unsigned char cyttsp_fw_tts_verh = 0x10;
+unsigned char cyttsp_fw_tts_verl = 0x12;
+unsigned char cyttsp_fw_app_idh = 0xA0;
+unsigned char cyttsp_fw_app_idl = 0x02;
+unsigned char cyttsp_fw_app_verh = 0x04;
+unsigned char cyttsp_fw_app_verl = 0x00;
+unsigned char cyttsp_fw_cid_0 = 0xC0;
+unsigned char cyttsp_fw_cid_1 = 0xC1;
+unsigned char cyttsp_fw_cid_2 = 0xC2;
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
new file mode 100644
index 0000000..c9905a4
--- /dev/null
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -0,0 +1,654 @@
+/*
+ *
+ * FocalTech ft5x06 TouchScreen driver.
+ *
+ * Copyright (c) 2010 Focal tech Ltd.
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/input.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/regulator/consumer.h>
+#include <linux/input/ft5x06_ts.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+/* Early-suspend level */
+#define FT5X06_SUSPEND_LEVEL 1
+#endif
+
+#define CFG_MAX_TOUCH_POINTS 5
+
+#define FT_STARTUP_DLY 150
+#define FT_RESET_DLY 20
+
+#define FT_PRESS 0x7F
+#define FT_MAX_ID 0x0F
+#define FT_TOUCH_STEP 6
+#define FT_TOUCH_X_H_POS 3
+#define FT_TOUCH_X_L_POS 4
+#define FT_TOUCH_Y_H_POS 5
+#define FT_TOUCH_Y_L_POS 6
+#define FT_TOUCH_EVENT_POS 3
+#define FT_TOUCH_ID_POS 5
+
+#define POINT_READ_BUF (3 + FT_TOUCH_STEP * CFG_MAX_TOUCH_POINTS)
+
+/*register address*/
+#define FT5X06_REG_PMODE 0xA5
+#define FT5X06_REG_FW_VER 0xA6
+#define FT5X06_REG_POINT_RATE 0x88
+#define FT5X06_REG_THGROUP 0x80
+
+/* power register bits*/
+#define FT5X06_PMODE_ACTIVE 0x00
+#define FT5X06_PMODE_MONITOR 0x01
+#define FT5X06_PMODE_STANDBY 0x02
+#define FT5X06_PMODE_HIBERNATE 0x03
+
+#define FT5X06_VTG_MIN_UV 2600000
+#define FT5X06_VTG_MAX_UV 3300000
+#define FT5X06_I2C_VTG_MIN_UV 1800000
+#define FT5X06_I2C_VTG_MAX_UV 1800000
+
+struct ts_event {
+ u16 x[CFG_MAX_TOUCH_POINTS]; /*x coordinate */
+ u16 y[CFG_MAX_TOUCH_POINTS]; /*y coordinate */
+ /* touch event: 0 -- down; 1-- contact; 2 -- contact */
+ u8 touch_event[CFG_MAX_TOUCH_POINTS];
+ u8 finger_id[CFG_MAX_TOUCH_POINTS]; /*touch ID */
+ u16 pressure;
+ u8 touch_point;
+};
+
+struct ft5x06_ts_data {
+ struct i2c_client *client;
+ struct input_dev *input_dev;
+ struct ts_event event;
+ const struct ft5x06_ts_platform_data *pdata;
+ struct regulator *vdd;
+ struct regulator *vcc_i2c;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+};
+
+static int ft5x06_i2c_read(struct i2c_client *client, char *writebuf,
+ int writelen, char *readbuf, int readlen)
+{
+ int ret;
+
+ if (writelen > 0) {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if (ret < 0)
+ dev_err(&client->dev, "%s: i2c read error.\n",
+ __func__);
+ } else {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = readlen,
+ .buf = readbuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 1);
+ if (ret < 0)
+ dev_err(&client->dev, "%s:i2c read error.\n", __func__);
+ }
+ return ret;
+}
+
+static int ft5x06_i2c_write(struct i2c_client *client, char *writebuf,
+ int writelen)
+{
+ int ret;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = writelen,
+ .buf = writebuf,
+ },
+ };
+ ret = i2c_transfer(client->adapter, msgs, 1);
+ if (ret < 0)
+ dev_err(&client->dev, "%s: i2c write error.\n", __func__);
+
+ return ret;
+}
+
+static void ft5x06_report_value(struct ft5x06_ts_data *data)
+{
+ struct ts_event *event = &data->event;
+ int i;
+ int fingerdown = 0;
+
+ for (i = 0; i < event->touch_point; i++) {
+ if (event->touch_event[i] == 0 || event->touch_event[i] == 2) {
+ event->pressure = FT_PRESS;
+ fingerdown++;
+ } else {
+ event->pressure = 0;
+ }
+
+ input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+ event->x[i]);
+ input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+ event->y[i]);
+ input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+ event->pressure);
+ input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
+ event->finger_id[i]);
+ input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+ event->pressure);
+ input_mt_sync(data->input_dev);
+ }
+
+ input_report_key(data->input_dev, BTN_TOUCH, !!fingerdown);
+ input_sync(data->input_dev);
+}
+
+static int ft5x06_handle_touchdata(struct ft5x06_ts_data *data)
+{
+ struct ts_event *event = &data->event;
+ int ret, i;
+ u8 buf[POINT_READ_BUF] = { 0 };
+ u8 pointid = FT_MAX_ID;
+
+ ret = ft5x06_i2c_read(data->client, buf, 1, buf, POINT_READ_BUF);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "%s read touchdata failed.\n",
+ __func__);
+ return ret;
+ }
+ memset(event, 0, sizeof(struct ts_event));
+
+ event->touch_point = 0;
+ for (i = 0; i < CFG_MAX_TOUCH_POINTS; i++) {
+ pointid = (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
+ if (pointid >= FT_MAX_ID)
+ break;
+ else
+ event->touch_point++;
+ event->x[i] =
+ (s16) (buf[FT_TOUCH_X_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
+ 8 | (s16) buf[FT_TOUCH_X_L_POS + FT_TOUCH_STEP * i];
+ event->y[i] =
+ (s16) (buf[FT_TOUCH_Y_H_POS + FT_TOUCH_STEP * i] & 0x0F) <<
+ 8 | (s16) buf[FT_TOUCH_Y_L_POS + FT_TOUCH_STEP * i];
+ event->touch_event[i] =
+ buf[FT_TOUCH_EVENT_POS + FT_TOUCH_STEP * i] >> 6;
+ event->finger_id[i] =
+ (buf[FT_TOUCH_ID_POS + FT_TOUCH_STEP * i]) >> 4;
+ }
+
+ ft5x06_report_value(data);
+
+ return 0;
+}
+
+static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
+{
+ struct ft5x06_ts_data *data = dev_id;
+ int rc;
+
+ rc = ft5x06_handle_touchdata(data);
+ if (rc)
+ pr_err("%s: handling touchdata failed\n", __func__);
+
+ return IRQ_HANDLED;
+}
+
+static int ft5x06_power_on(struct ft5x06_ts_data *data, bool on)
+{
+ int rc;
+
+ if (!on)
+ goto power_off;
+
+ rc = regulator_enable(data->vdd);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vdd enable failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_enable(data->vcc_i2c);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_i2c enable failed rc=%d\n", rc);
+ regulator_disable(data->vdd);
+ }
+
+ return rc;
+
+power_off:
+ rc = regulator_disable(data->vdd);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vdd disable failed rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = regulator_disable(data->vcc_i2c);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator vcc_i2c disable failed rc=%d\n", rc);
+ regulator_enable(data->vdd);
+ }
+
+ return rc;
+}
+
+static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
+{
+ int rc;
+
+ if (!on)
+ goto pwr_deinit;
+
+ data->vdd = regulator_get(&data->client->dev, "vdd");
+ if (IS_ERR(data->vdd)) {
+ rc = PTR_ERR(data->vdd);
+ dev_err(&data->client->dev,
+ "Regulator get failed vdd rc=%d\n", rc);
+ return rc;
+ }
+
+ if (regulator_count_voltages(data->vdd) > 0) {
+ rc = regulator_set_voltage(data->vdd, FT5X06_VTG_MIN_UV,
+ FT5X06_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator set_vtg failed vdd rc=%d\n", rc);
+ goto reg_vdd_put;
+ }
+ }
+
+ data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
+ if (IS_ERR(data->vcc_i2c)) {
+ rc = PTR_ERR(data->vcc_i2c);
+ dev_err(&data->client->dev,
+ "Regulator get failed vcc_i2c rc=%d\n", rc);
+ goto reg_vdd_set_vtg;
+ }
+
+ if (regulator_count_voltages(data->vcc_i2c) > 0) {
+ rc = regulator_set_voltage(data->vcc_i2c, FT5X06_I2C_VTG_MIN_UV,
+ FT5X06_I2C_VTG_MAX_UV);
+ if (rc) {
+ dev_err(&data->client->dev,
+ "Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
+ goto reg_vcc_i2c_put;
+ }
+ }
+
+ return 0;
+
+reg_vcc_i2c_put:
+ regulator_put(data->vcc_i2c);
+reg_vdd_set_vtg:
+ if (regulator_count_voltages(data->vdd) > 0)
+ regulator_set_voltage(data->vdd, 0, FT5X06_VTG_MAX_UV);
+reg_vdd_put:
+ regulator_put(data->vdd);
+ return rc;
+
+pwr_deinit:
+ if (regulator_count_voltages(data->vdd) > 0)
+ regulator_set_voltage(data->vdd, 0, FT5X06_VTG_MAX_UV);
+
+ regulator_put(data->vdd);
+
+ if (regulator_count_voltages(data->vcc_i2c) > 0)
+ regulator_set_voltage(data->vcc_i2c, 0, FT5X06_I2C_VTG_MAX_UV);
+
+ regulator_put(data->vcc_i2c);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int ft5x06_ts_suspend(struct device *dev)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+ char txbuf[2];
+
+ disable_irq(data->client->irq);
+
+ if (gpio_is_valid(data->pdata->reset_gpio)) {
+ txbuf[0] = FT5X06_REG_PMODE;
+ txbuf[1] = FT5X06_PMODE_HIBERNATE;
+ ft5x06_i2c_write(data->client, txbuf, sizeof(txbuf));
+ }
+
+ return 0;
+}
+
+static int ft5x06_ts_resume(struct device *dev)
+{
+ struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+ if (gpio_is_valid(data->pdata->reset_gpio)) {
+ gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
+ msleep(FT_RESET_DLY);
+ gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
+ }
+ enable_irq(data->client->irq);
+
+ return 0;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void ft5x06_ts_early_suspend(struct early_suspend *handler)
+{
+ struct ft5x06_ts_data *data = container_of(handler,
+ struct ft5x06_ts_data,
+ early_suspend);
+
+ ft5x06_ts_suspend(&data->client->dev);
+}
+
+static void ft5x06_ts_late_resume(struct early_suspend *handler)
+{
+ struct ft5x06_ts_data *data = container_of(handler,
+ struct ft5x06_ts_data,
+ early_suspend);
+
+ ft5x06_ts_resume(&data->client->dev);
+}
+#endif
+
+static const struct dev_pm_ops ft5x06_ts_pm_ops = {
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = ft5x06_ts_suspend,
+ .resume = ft5x06_ts_resume,
+#endif
+};
+#endif
+
+static int ft5x06_ts_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ const struct ft5x06_ts_platform_data *pdata = client->dev.platform_data;
+ struct ft5x06_ts_data *data;
+ struct input_dev *input_dev;
+ u8 reg_value;
+ u8 reg_addr;
+ int err;
+
+ if (!pdata) {
+ dev_err(&client->dev, "Invalid pdata\n");
+ return -EINVAL;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "I2C not supported\n");
+ return -ENODEV;
+ }
+
+ data = kzalloc(sizeof(struct ft5x06_ts_data), GFP_KERNEL);
+ if (!data) {
+ dev_err(&client->dev, "Not enough memory\n");
+ return -ENOMEM;
+ }
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ err = -ENOMEM;
+ dev_err(&client->dev, "failed to allocate input device\n");
+ goto free_mem;
+ }
+
+ data->input_dev = input_dev;
+ data->client = client;
+ data->pdata = pdata;
+
+ input_dev->name = "ft5x06_ts";
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->dev.parent = &client->dev;
+
+ input_set_drvdata(input_dev, data);
+ i2c_set_clientdata(client, data);
+
+ __set_bit(EV_KEY, input_dev->evbit);
+ __set_bit(EV_ABS, input_dev->evbit);
+ __set_bit(BTN_TOUCH, input_dev->keybit);
+
+ input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0,
+ pdata->x_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0,
+ pdata->y_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
+ CFG_MAX_TOUCH_POINTS, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, FT_PRESS, 0, 0);
+ input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, FT_PRESS, 0, 0);
+
+ err = input_register_device(input_dev);
+ if (err) {
+ dev_err(&client->dev, "Input device registration failed\n");
+ goto free_inputdev;
+ }
+
+ if (pdata->power_init) {
+ err = pdata->power_init(true);
+ if (err) {
+ dev_err(&client->dev, "power init failed");
+ goto unreg_inputdev;
+ }
+ } else {
+ err = ft5x06_power_init(data, true);
+ if (err) {
+ dev_err(&client->dev, "power init failed");
+ goto unreg_inputdev;
+ }
+ }
+
+ if (pdata->power_on) {
+ err = pdata->power_on(true);
+ if (err) {
+ dev_err(&client->dev, "power on failed");
+ goto pwr_deinit;
+ }
+ } else {
+ err = ft5x06_power_on(data, true);
+ if (err) {
+ dev_err(&client->dev, "power on failed");
+ goto pwr_deinit;
+ }
+ }
+
+ if (gpio_is_valid(pdata->irq_gpio)) {
+ err = gpio_request(pdata->irq_gpio, "ft5x06_irq_gpio");
+ if (err) {
+ dev_err(&client->dev, "irq gpio request failed");
+ goto pwr_off;
+ }
+ err = gpio_direction_input(pdata->irq_gpio);
+ if (err) {
+ dev_err(&client->dev,
+ "set_direction for irq gpio failed\n");
+ goto free_irq_gpio;
+ }
+ }
+
+ if (gpio_is_valid(pdata->reset_gpio)) {
+ err = gpio_request(pdata->reset_gpio, "ft5x06_reset_gpio");
+ if (err) {
+ dev_err(&client->dev, "reset gpio request failed");
+ goto free_irq_gpio;
+ }
+
+ err = gpio_direction_output(pdata->reset_gpio, 0);
+ if (err) {
+ dev_err(&client->dev,
+ "set_direction for reset gpio failed\n");
+ goto free_reset_gpio;
+ }
+ msleep(FT_RESET_DLY);
+ gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
+ }
+
+ /* make sure CTP already finish startup process */
+ msleep(FT_STARTUP_DLY);
+
+ /*get some register information */
+ reg_addr = FT5X06_REG_FW_VER;
+ err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
+ if (err)
+ dev_err(&client->dev, "version read failed");
+
+ dev_info(&client->dev, "[FTS] Firmware version = 0x%x\n", reg_value);
+
+ reg_addr = FT5X06_REG_POINT_RATE;
+ ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
+ if (err)
+ dev_err(&client->dev, "report rate read failed");
+ dev_info(&client->dev, "[FTS] report rate is %dHz.\n", reg_value * 10);
+
+ reg_addr = FT5X06_REG_THGROUP;
+ err = ft5x06_i2c_read(client, ®_addr, 1, ®_value, 1);
+ if (err)
+ dev_err(&client->dev, "threshold read failed");
+ dev_dbg(&client->dev, "[FTS] touch threshold is %d.\n", reg_value * 4);
+
+ err = request_threaded_irq(client->irq, NULL,
+ ft5x06_ts_interrupt, pdata->irqflags,
+ client->dev.driver->name, data);
+ if (err) {
+ dev_err(&client->dev, "request irq failed\n");
+ goto free_reset_gpio;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+ FT5X06_SUSPEND_LEVEL;
+ data->early_suspend.suspend = ft5x06_ts_early_suspend;
+ data->early_suspend.resume = ft5x06_ts_late_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+
+ return 0;
+
+free_reset_gpio:
+ if (gpio_is_valid(pdata->reset_gpio))
+ gpio_free(pdata->reset_gpio);
+free_irq_gpio:
+ if (gpio_is_valid(pdata->irq_gpio))
+ gpio_free(pdata->reset_gpio);
+pwr_off:
+ if (pdata->power_on)
+ pdata->power_on(false);
+ else
+ ft5x06_power_on(data, false);
+pwr_deinit:
+ if (pdata->power_init)
+ pdata->power_init(false);
+ else
+ ft5x06_power_init(data, false);
+unreg_inputdev:
+ input_unregister_device(input_dev);
+ input_dev = NULL;
+free_inputdev:
+ input_free_device(input_dev);
+free_mem:
+ kfree(data);
+ return err;
+}
+
+static int __devexit ft5x06_ts_remove(struct i2c_client *client)
+{
+ struct ft5x06_ts_data *data = i2c_get_clientdata(client);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&data->early_suspend);
+#endif
+ free_irq(client->irq, data);
+
+ if (gpio_is_valid(data->pdata->reset_gpio))
+ gpio_free(data->pdata->reset_gpio);
+
+ if (gpio_is_valid(data->pdata->irq_gpio))
+ gpio_free(data->pdata->reset_gpio);
+
+ if (data->pdata->power_on)
+ data->pdata->power_on(false);
+ else
+ ft5x06_power_on(data, false);
+
+ if (data->pdata->power_init)
+ data->pdata->power_init(false);
+ else
+ ft5x06_power_init(data, false);
+
+ input_unregister_device(data->input_dev);
+ kfree(data);
+
+ return 0;
+}
+
+static const struct i2c_device_id ft5x06_ts_id[] = {
+ {"ft5x06_ts", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id);
+
+static struct i2c_driver ft5x06_ts_driver = {
+ .probe = ft5x06_ts_probe,
+ .remove = __devexit_p(ft5x06_ts_remove),
+ .driver = {
+ .name = "ft5x06_ts",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &ft5x06_ts_pm_ops,
+#endif
+ },
+ .id_table = ft5x06_ts_id,
+};
+
+static int __init ft5x06_ts_init(void)
+{
+ return i2c_add_driver(&ft5x06_ts_driver);
+}
+module_init(ft5x06_ts_init);
+
+static void __exit ft5x06_ts_exit(void)
+{
+ i2c_del_driver(&ft5x06_ts_driver);
+}
+module_exit(ft5x06_ts_exit);
+
+MODULE_DESCRIPTION("FocalTech ft5x06 TouchScreen driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/msm_touch.c b/drivers/input/touchscreen/msm_touch.c
new file mode 100644
index 0000000..7ba896a
--- /dev/null
+++ b/drivers/input/touchscreen/msm_touch.c
@@ -0,0 +1,317 @@
+/* drivers/input/touchscreen/msm_touch.c
+ *
+ * Copyright (c) 2008-2009, 2011, Code Aurora Forum. 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.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+#include <linux/io.h>
+
+#include <mach/msm_touch.h>
+
+/* HW register map */
+#define TSSC_CTL_REG 0x100
+#define TSSC_SI_REG 0x108
+#define TSSC_OPN_REG 0x104
+#define TSSC_STATUS_REG 0x10C
+#define TSSC_AVG12_REG 0x110
+
+/* status bits */
+#define TSSC_STS_OPN_SHIFT 0x6
+#define TSSC_STS_OPN_BMSK 0x1C0
+#define TSSC_STS_NUMSAMP_SHFT 0x1
+#define TSSC_STS_NUMSAMP_BMSK 0x3E
+
+/* CTL bits */
+#define TSSC_CTL_EN (0x1 << 0)
+#define TSSC_CTL_SW_RESET (0x1 << 2)
+#define TSSC_CTL_MASTER_MODE (0x3 << 3)
+#define TSSC_CTL_AVG_EN (0x1 << 5)
+#define TSSC_CTL_DEB_EN (0x1 << 6)
+#define TSSC_CTL_DEB_12_MS (0x2 << 7) /* 1.2 ms */
+#define TSSC_CTL_DEB_16_MS (0x3 << 7) /* 1.6 ms */
+#define TSSC_CTL_DEB_2_MS (0x4 << 7) /* 2 ms */
+#define TSSC_CTL_DEB_3_MS (0x5 << 7) /* 3 ms */
+#define TSSC_CTL_DEB_4_MS (0x6 << 7) /* 4 ms */
+#define TSSC_CTL_DEB_6_MS (0x7 << 7) /* 6 ms */
+#define TSSC_CTL_INTR_FLAG1 (0x1 << 10)
+#define TSSC_CTL_DATA (0x1 << 11)
+#define TSSC_CTL_SSBI_CTRL_EN (0x1 << 13)
+
+/* control reg's default state */
+#define TSSC_CTL_STATE ( \
+ TSSC_CTL_DEB_12_MS | \
+ TSSC_CTL_DEB_EN | \
+ TSSC_CTL_AVG_EN | \
+ TSSC_CTL_MASTER_MODE | \
+ TSSC_CTL_EN)
+
+#define TSSC_NUMBER_OF_OPERATIONS 2
+#define TS_PENUP_TIMEOUT_MS 20
+
+#define TS_DRIVER_NAME "msm_touchscreen"
+
+#define X_MAX 1024
+#define Y_MAX 1024
+#define P_MAX 256
+
+struct ts {
+ struct input_dev *input;
+ struct timer_list timer;
+ int irq;
+ unsigned int x_max;
+ unsigned int y_max;
+};
+
+static void __iomem *virt;
+#define TSSC_REG(reg) (virt + TSSC_##reg##_REG)
+
+static void ts_update_pen_state(struct ts *ts, int x, int y, int pressure)
+{
+ if (pressure) {
+ input_report_abs(ts->input, ABS_X, x);
+ input_report_abs(ts->input, ABS_Y, y);
+ input_report_abs(ts->input, ABS_PRESSURE, pressure);
+ input_report_key(ts->input, BTN_TOUCH, !!pressure);
+ } else {
+ input_report_abs(ts->input, ABS_PRESSURE, 0);
+ input_report_key(ts->input, BTN_TOUCH, 0);
+ }
+
+ input_sync(ts->input);
+}
+
+static void ts_timer(unsigned long arg)
+{
+ struct ts *ts = (struct ts *)arg;
+
+ ts_update_pen_state(ts, 0, 0, 0);
+}
+
+static irqreturn_t ts_interrupt(int irq, void *dev_id)
+{
+ u32 avgs, x, y, lx, ly;
+ u32 num_op, num_samp;
+ u32 status;
+
+ struct ts *ts = dev_id;
+
+ status = readl_relaxed(TSSC_REG(STATUS));
+ avgs = readl_relaxed(TSSC_REG(AVG12));
+ x = avgs & 0xFFFF;
+ y = avgs >> 16;
+
+ /* For pen down make sure that the data just read is still valid.
+ * The DATA bit will still be set if the ARM9 hasn't clobbered
+ * the TSSC. If it's not set, then it doesn't need to be cleared
+ * here, so just return.
+ */
+ if (!(readl_relaxed(TSSC_REG(CTL)) & TSSC_CTL_DATA))
+ goto out;
+
+ /* Data has been read, OK to clear the data flag */
+ writel_relaxed(TSSC_CTL_STATE, TSSC_REG(CTL));
+ /* barrier: Write to complete before the next sample */
+ mb();
+ /* Valid samples are indicated by the sample number in the status
+ * register being the number of expected samples and the number of
+ * samples collected being zero (this check is due to ADC contention).
+ */
+ num_op = (status & TSSC_STS_OPN_BMSK) >> TSSC_STS_OPN_SHIFT;
+ num_samp = (status & TSSC_STS_NUMSAMP_BMSK) >> TSSC_STS_NUMSAMP_SHFT;
+
+ if ((num_op == TSSC_NUMBER_OF_OPERATIONS) && (num_samp == 0)) {
+ /* TSSC can do Z axis measurment, but driver doesn't support
+ * this yet.
+ */
+
+ /*
+ * REMOVE THIS:
+ * These x, y co-ordinates adjustments will be removed once
+ * Android framework adds calibration framework.
+ */
+#ifdef CONFIG_ANDROID_TOUCHSCREEN_MSM_HACKS
+ lx = ts->x_max - x;
+ ly = ts->y_max - y;
+#else
+ lx = x;
+ ly = y;
+#endif
+ ts_update_pen_state(ts, lx, ly, 255);
+ /* kick pen up timer - to make sure it expires again(!) */
+ mod_timer(&ts->timer,
+ jiffies + msecs_to_jiffies(TS_PENUP_TIMEOUT_MS));
+
+ } else
+ printk(KERN_INFO "Ignored interrupt: {%3d, %3d},"
+ " op = %3d samp = %3d\n",
+ x, y, num_op, num_samp);
+
+out:
+ return IRQ_HANDLED;
+}
+
+static int __devinit ts_probe(struct platform_device *pdev)
+{
+ int result;
+ struct input_dev *input_dev;
+ struct resource *res, *ioarea;
+ struct ts *ts;
+ unsigned int x_max, y_max, pressure_max;
+ struct msm_ts_platform_data *pdata = pdev->dev.platform_data;
+
+ /* The primary initialization of the TS Hardware
+ * is taken care of by the ADC code on the modem side
+ */
+
+ ts = kzalloc(sizeof(struct ts), GFP_KERNEL);
+ input_dev = input_allocate_device();
+ if (!input_dev || !ts) {
+ result = -ENOMEM;
+ goto fail_alloc_mem;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n");
+ result = -ENOENT;
+ goto fail_alloc_mem;
+ }
+
+ ts->irq = platform_get_irq(pdev, 0);
+ if (!ts->irq) {
+ dev_err(&pdev->dev, "Could not get IORESOURCE_IRQ\n");
+ result = -ENODEV;
+ goto fail_alloc_mem;
+ }
+
+ ioarea = request_mem_region(res->start, resource_size(res), pdev->name);
+ if (!ioarea) {
+ dev_err(&pdev->dev, "Could not allocate io region\n");
+ result = -EBUSY;
+ goto fail_alloc_mem;
+ }
+
+ virt = ioremap(res->start, resource_size(res));
+ if (!virt) {
+ dev_err(&pdev->dev, "Could not ioremap region\n");
+ result = -ENOMEM;
+ goto fail_ioremap;
+ }
+
+ input_dev->name = TS_DRIVER_NAME;
+ input_dev->phys = "msm_touch/input0";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0002;
+ input_dev->id.version = 0x0100;
+ input_dev->dev.parent = &pdev->dev;
+
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE);
+ input_dev->absbit[BIT_WORD(ABS_MISC)] = BIT_MASK(ABS_MISC);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+ if (pdata) {
+ x_max = pdata->x_max ? : X_MAX;
+ y_max = pdata->y_max ? : Y_MAX;
+ pressure_max = pdata->pressure_max ? : P_MAX;
+ } else {
+ x_max = X_MAX;
+ y_max = Y_MAX;
+ pressure_max = P_MAX;
+ }
+
+ ts->x_max = x_max;
+ ts->y_max = y_max;
+
+ input_set_abs_params(input_dev, ABS_X, 0, x_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_Y, 0, y_max, 0, 0);
+ input_set_abs_params(input_dev, ABS_PRESSURE, 0, pressure_max, 0, 0);
+
+ result = input_register_device(input_dev);
+ if (result)
+ goto fail_ip_reg;
+
+ ts->input = input_dev;
+
+ setup_timer(&ts->timer, ts_timer, (unsigned long)ts);
+ result = request_irq(ts->irq, ts_interrupt, IRQF_TRIGGER_RISING,
+ "touchscreen", ts);
+ if (result)
+ goto fail_req_irq;
+
+ platform_set_drvdata(pdev, ts);
+
+ return 0;
+
+fail_req_irq:
+ input_unregister_device(input_dev);
+ input_dev = NULL;
+fail_ip_reg:
+ iounmap(virt);
+fail_ioremap:
+ release_mem_region(res->start, resource_size(res));
+fail_alloc_mem:
+ input_free_device(input_dev);
+ kfree(ts);
+ return result;
+}
+
+static int __devexit ts_remove(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct ts *ts = platform_get_drvdata(pdev);
+
+ free_irq(ts->irq, ts);
+ del_timer_sync(&ts->timer);
+
+ input_unregister_device(ts->input);
+ iounmap(virt);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, resource_size(res));
+ platform_set_drvdata(pdev, NULL);
+ kfree(ts);
+
+ return 0;
+}
+
+static struct platform_driver ts_driver = {
+ .probe = ts_probe,
+ .remove = __devexit_p(ts_remove),
+ .driver = {
+ .name = TS_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ts_init(void)
+{
+ return platform_driver_register(&ts_driver);
+}
+module_init(ts_init);
+
+static void __exit ts_exit(void)
+{
+ platform_driver_unregister(&ts_driver);
+}
+module_exit(ts_exit);
+
+MODULE_DESCRIPTION("MSM Touch Screen driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:msm_touchscreen");
diff --git a/drivers/input/touchscreen/msm_ts.c b/drivers/input/touchscreen/msm_ts.c
new file mode 100644
index 0000000..eb2e73b
--- /dev/null
+++ b/drivers/input/touchscreen/msm_ts.c
@@ -0,0 +1,513 @@
+/* drivers/input/touchscreen/msm_ts.c
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (c) 2010-2012, Code Aurora Forum. 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.
+ *
+ * TODO:
+ * - Add a timer to simulate a pen_up in case there's a timeout.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/marimba-tsadc.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#endif
+
+#include <linux/input/msm_ts.h>
+
+#define TSSC_CTL 0x100
+#define TSSC_CTL_PENUP_IRQ (1 << 12)
+#define TSSC_CTL_DATA_FLAG (1 << 11)
+#define TSSC_CTL_DEBOUNCE_EN (1 << 6)
+#define TSSC_CTL_EN_AVERAGE (1 << 5)
+#define TSSC_CTL_MODE_MASTER (3 << 3)
+#define TSSC_CTL_SW_RESET (1 << 2)
+#define TSSC_CTL_ENABLE (1 << 0)
+#define TSSC_OPN 0x104
+#define TSSC_OPN_NOOP 0x00
+#define TSSC_OPN_4WIRE_X 0x01
+#define TSSC_OPN_4WIRE_Y 0x02
+#define TSSC_OPN_4WIRE_Z1 0x03
+#define TSSC_OPN_4WIRE_Z2 0x04
+#define TSSC_SAMPLING_INT 0x108
+#define TSSC_STATUS 0x10c
+#define TSSC_AVG_12 0x110
+#define TSSC_AVG_34 0x114
+#define TSSC_SAMPLE(op,samp) ((0x118 + ((op & 0x3) * 0x20)) + \
+ ((samp & 0x7) * 0x4))
+#define TSSC_TEST_1 0x198
+ #define TSSC_TEST_1_EN_GATE_DEBOUNCE (1 << 2)
+#define TSSC_TEST_2 0x19c
+
+struct msm_ts {
+ struct msm_ts_platform_data *pdata;
+ struct input_dev *input_dev;
+ void __iomem *tssc_base;
+ uint32_t ts_down:1;
+ struct ts_virt_key *vkey_down;
+ struct marimba_tsadc_client *ts_client;
+
+ unsigned int sample_irq;
+ unsigned int pen_up_irq;
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
+ struct device *dev;
+};
+
+static uint32_t msm_tsdebug;
+module_param_named(tsdebug, msm_tsdebug, uint, 0664);
+
+#define tssc_readl(t, a) (readl_relaxed(((t)->tssc_base) + (a)))
+#define tssc_writel(t, v, a) do {writel_relaxed(v, \
+ ((t)->tssc_base) + (a)); } \
+ while (0)
+
+static void setup_next_sample(struct msm_ts *ts)
+{
+ uint32_t tmp;
+
+ /* 1.2ms debounce time */
+ tmp = ((2 << 7) | TSSC_CTL_DEBOUNCE_EN | TSSC_CTL_EN_AVERAGE |
+ TSSC_CTL_MODE_MASTER | TSSC_CTL_ENABLE);
+ tssc_writel(ts, tmp, TSSC_CTL);
+ /* barrier: Make sure the write completes before the next sample */
+ mb();
+}
+
+static struct ts_virt_key *find_virt_key(struct msm_ts *ts,
+ struct msm_ts_virtual_keys *vkeys,
+ uint32_t val)
+{
+ int i;
+
+ if (!vkeys)
+ return NULL;
+
+ for (i = 0; i < vkeys->num_keys; ++i)
+ if ((val >= vkeys->keys[i].min) && (val <= vkeys->keys[i].max))
+ return &vkeys->keys[i];
+ return NULL;
+}
+
+
+static irqreturn_t msm_ts_irq(int irq, void *dev_id)
+{
+ struct msm_ts *ts = dev_id;
+ struct msm_ts_platform_data *pdata = ts->pdata;
+
+ uint32_t tssc_avg12, tssc_avg34, tssc_status, tssc_ctl;
+ int x, y, z1, z2;
+ int was_down;
+ int down;
+
+ tssc_ctl = tssc_readl(ts, TSSC_CTL);
+ tssc_status = tssc_readl(ts, TSSC_STATUS);
+ tssc_avg12 = tssc_readl(ts, TSSC_AVG_12);
+ tssc_avg34 = tssc_readl(ts, TSSC_AVG_34);
+
+ setup_next_sample(ts);
+
+ x = tssc_avg12 & 0xffff;
+ y = tssc_avg12 >> 16;
+ z1 = tssc_avg34 & 0xffff;
+ z2 = tssc_avg34 >> 16;
+
+ /* invert the inputs if necessary */
+ if (pdata->inv_x) x = pdata->inv_x - x;
+ if (pdata->inv_y) y = pdata->inv_y - y;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+
+ down = !(tssc_ctl & TSSC_CTL_PENUP_IRQ);
+ was_down = ts->ts_down;
+ ts->ts_down = down;
+
+ /* no valid data */
+ if (down && !(tssc_ctl & TSSC_CTL_DATA_FLAG))
+ return IRQ_HANDLED;
+
+ if (msm_tsdebug & 2)
+ printk("%s: down=%d, x=%d, y=%d, z1=%d, z2=%d, status %x\n",
+ __func__, down, x, y, z1, z2, tssc_status);
+
+ if (!was_down && down) {
+ struct ts_virt_key *vkey = NULL;
+
+ if (pdata->vkeys_y && (y > pdata->virt_y_start))
+ vkey = find_virt_key(ts, pdata->vkeys_y, x);
+ if (!vkey && ts->pdata->vkeys_x && (x > pdata->virt_x_start))
+ vkey = find_virt_key(ts, pdata->vkeys_x, y);
+
+ if (vkey) {
+ WARN_ON(ts->vkey_down != NULL);
+ if(msm_tsdebug)
+ printk("%s: virtual key down %d\n", __func__,
+ vkey->key);
+ ts->vkey_down = vkey;
+ input_report_key(ts->input_dev, vkey->key, 1);
+ input_sync(ts->input_dev);
+ return IRQ_HANDLED;
+ }
+ } else if (ts->vkey_down != NULL) {
+ if (!down) {
+ if(msm_tsdebug)
+ printk("%s: virtual key up %d\n", __func__,
+ ts->vkey_down->key);
+ input_report_key(ts->input_dev, ts->vkey_down->key, 0);
+ input_sync(ts->input_dev);
+ ts->vkey_down = NULL;
+ }
+ return IRQ_HANDLED;
+ }
+
+ if (down) {
+ input_report_abs(ts->input_dev, ABS_X, x);
+ input_report_abs(ts->input_dev, ABS_Y, y);
+ input_report_abs(ts->input_dev, ABS_PRESSURE, z1);
+ }
+ input_report_key(ts->input_dev, BTN_TOUCH, down);
+ input_sync(ts->input_dev);
+
+ return IRQ_HANDLED;
+}
+
+static void dump_tssc_regs(struct msm_ts *ts)
+{
+#define __dump_tssc_reg(r) \
+ do { printk(#r " %x\n", tssc_readl(ts, (r))); } while(0)
+
+ __dump_tssc_reg(TSSC_CTL);
+ __dump_tssc_reg(TSSC_OPN);
+ __dump_tssc_reg(TSSC_SAMPLING_INT);
+ __dump_tssc_reg(TSSC_STATUS);
+ __dump_tssc_reg(TSSC_AVG_12);
+ __dump_tssc_reg(TSSC_AVG_34);
+ __dump_tssc_reg(TSSC_TEST_1);
+#undef __dump_tssc_reg
+}
+
+static int msm_ts_hw_init(struct msm_ts *ts)
+{
+ uint32_t tmp;
+
+ /* Enable the register clock to tssc so we can configure it. */
+ tssc_writel(ts, TSSC_CTL_ENABLE, TSSC_CTL);
+ /* Enable software reset*/
+ tssc_writel(ts, TSSC_CTL_SW_RESET, TSSC_CTL);
+
+ /* op1 - measure X, 1 sample, 12bit resolution */
+ tmp = (TSSC_OPN_4WIRE_X << 16) | (2 << 8) | (2 << 0);
+ /* op2 - measure Y, 1 sample, 12bit resolution */
+ tmp |= (TSSC_OPN_4WIRE_Y << 20) | (2 << 10) | (2 << 2);
+ /* op3 - measure Z1, 1 sample, 8bit resolution */
+ tmp |= (TSSC_OPN_4WIRE_Z1 << 24) | (2 << 12) | (0 << 4);
+
+ /* XXX: we don't actually need to measure Z2 (thus 0 samples) when
+ * doing voltage-driven measurement */
+ /* op4 - measure Z2, 0 samples, 8bit resolution */
+ tmp |= (TSSC_OPN_4WIRE_Z2 << 28) | (0 << 14) | (0 << 6);
+ tssc_writel(ts, tmp, TSSC_OPN);
+
+ /* 16ms sampling interval */
+ tssc_writel(ts, 16, TSSC_SAMPLING_INT);
+ /* Enable gating logic to fix the timing delays caused because of
+ * enabling debounce logic */
+ tssc_writel(ts, TSSC_TEST_1_EN_GATE_DEBOUNCE, TSSC_TEST_1);
+
+ setup_next_sample(ts);
+
+ return 0;
+}
+
+static void msm_ts_enable(struct msm_ts *ts, bool enable)
+{
+ uint32_t val;
+
+ if (enable == true)
+ msm_ts_hw_init(ts);
+ else {
+ val = tssc_readl(ts, TSSC_CTL);
+ val &= ~TSSC_CTL_ENABLE;
+ tssc_writel(ts, val, TSSC_CTL);
+ }
+}
+
+#ifdef CONFIG_PM
+static int
+msm_ts_suspend(struct device *dev)
+{
+ struct msm_ts *ts = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev) &&
+ device_may_wakeup(dev->parent))
+ enable_irq_wake(ts->sample_irq);
+ else {
+ disable_irq(ts->sample_irq);
+ disable_irq(ts->pen_up_irq);
+ msm_ts_enable(ts, false);
+ }
+
+ return 0;
+}
+
+static int
+msm_ts_resume(struct device *dev)
+{
+ struct msm_ts *ts = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev) &&
+ device_may_wakeup(dev->parent))
+ disable_irq_wake(ts->sample_irq);
+ else {
+ msm_ts_enable(ts, true);
+ enable_irq(ts->sample_irq);
+ enable_irq(ts->pen_up_irq);
+ }
+
+ return 0;
+}
+
+static struct dev_pm_ops msm_touchscreen_pm_ops = {
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = msm_ts_suspend,
+ .resume = msm_ts_resume,
+#endif
+};
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void msm_ts_early_suspend(struct early_suspend *h)
+{
+ struct msm_ts *ts = container_of(h, struct msm_ts, early_suspend);
+
+ msm_ts_suspend(ts->dev);
+}
+
+static void msm_ts_late_resume(struct early_suspend *h)
+{
+ struct msm_ts *ts = container_of(h, struct msm_ts, early_suspend);
+
+ msm_ts_resume(ts->dev);
+}
+#endif
+
+
+static int __devinit msm_ts_probe(struct platform_device *pdev)
+{
+ struct msm_ts_platform_data *pdata = pdev->dev.platform_data;
+ struct msm_ts *ts;
+ struct resource *tssc_res;
+ struct resource *irq1_res;
+ struct resource *irq2_res;
+ int err = 0;
+ int i;
+ struct marimba_tsadc_client *ts_client;
+
+ printk("%s\n", __func__);
+
+ tssc_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tssc");
+ irq1_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tssc1");
+ irq2_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tssc2");
+
+ if (!tssc_res || !irq1_res || !irq2_res) {
+ pr_err("%s: required resources not defined\n", __func__);
+ return -ENODEV;
+ }
+
+ if (pdata == NULL) {
+ pr_err("%s: missing platform_data\n", __func__);
+ return -ENODEV;
+ }
+
+ ts = kzalloc(sizeof(struct msm_ts), GFP_KERNEL);
+ if (ts == NULL) {
+ pr_err("%s: No memory for struct msm_ts\n", __func__);
+ return -ENOMEM;
+ }
+ ts->pdata = pdata;
+ ts->dev = &pdev->dev;
+
+ ts->sample_irq = irq1_res->start;
+ ts->pen_up_irq = irq2_res->start;
+
+ ts->tssc_base = ioremap(tssc_res->start, resource_size(tssc_res));
+ if (ts->tssc_base == NULL) {
+ pr_err("%s: Can't ioremap region (0x%08x - 0x%08x)\n", __func__,
+ (uint32_t)tssc_res->start, (uint32_t)tssc_res->end);
+ err = -ENOMEM;
+ goto err_ioremap_tssc;
+ }
+
+ ts_client = marimba_tsadc_register(pdev, 1);
+ if (IS_ERR(ts_client)) {
+ pr_err("%s: Unable to register with TSADC\n", __func__);
+ err = -ENOMEM;
+ goto err_tsadc_register;
+ }
+ ts->ts_client = ts_client;
+
+ err = marimba_tsadc_start(ts_client);
+ if (err) {
+ pr_err("%s: Unable to start TSADC\n", __func__);
+ err = -EINVAL;
+ goto err_start_tsadc;
+ }
+
+ ts->input_dev = input_allocate_device();
+ if (ts->input_dev == NULL) {
+ pr_err("failed to allocate touchscreen input device\n");
+ err = -ENOMEM;
+ goto err_alloc_input_dev;
+ }
+ ts->input_dev->name = "msm-touchscreen";
+ ts->input_dev->dev.parent = &pdev->dev;
+
+ input_set_drvdata(ts->input_dev, ts);
+
+ input_set_capability(ts->input_dev, EV_KEY, BTN_TOUCH);
+ set_bit(EV_ABS, ts->input_dev->evbit);
+
+ input_set_abs_params(ts->input_dev, ABS_X, pdata->min_x, pdata->max_x,
+ 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_Y, pdata->min_y, pdata->max_y,
+ 0, 0);
+ input_set_abs_params(ts->input_dev, ABS_PRESSURE, pdata->min_press,
+ pdata->max_press, 0, 0);
+
+ for (i = 0; pdata->vkeys_x && (i < pdata->vkeys_x->num_keys); ++i)
+ input_set_capability(ts->input_dev, EV_KEY,
+ pdata->vkeys_x->keys[i].key);
+ for (i = 0; pdata->vkeys_y && (i < pdata->vkeys_y->num_keys); ++i)
+ input_set_capability(ts->input_dev, EV_KEY,
+ pdata->vkeys_y->keys[i].key);
+
+ err = input_register_device(ts->input_dev);
+ if (err != 0) {
+ pr_err("%s: failed to register input device\n", __func__);
+ goto err_input_dev_reg;
+ }
+
+ msm_ts_hw_init(ts);
+
+ err = request_irq(ts->sample_irq, msm_ts_irq,
+ (irq1_res->flags & ~IORESOURCE_IRQ) | IRQF_DISABLED,
+ "msm_touchscreen", ts);
+ if (err != 0) {
+ pr_err("%s: Cannot register irq1 (%d)\n", __func__, err);
+ goto err_request_irq1;
+ }
+
+ err = request_irq(ts->pen_up_irq, msm_ts_irq,
+ (irq2_res->flags & ~IORESOURCE_IRQ) | IRQF_DISABLED,
+ "msm_touchscreen", ts);
+ if (err != 0) {
+ pr_err("%s: Cannot register irq2 (%d)\n", __func__, err);
+ goto err_request_irq2;
+ }
+
+ platform_set_drvdata(pdev, ts);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+ TSSC_SUSPEND_LEVEL;
+ ts->early_suspend.suspend = msm_ts_early_suspend;
+ ts->early_suspend.resume = msm_ts_late_resume;
+ register_early_suspend(&ts->early_suspend);
+#endif
+
+ device_init_wakeup(&pdev->dev, pdata->can_wakeup);
+ pr_info("%s: tssc_base=%p irq1=%d irq2=%d\n", __func__,
+ ts->tssc_base, (int)ts->sample_irq, (int)ts->pen_up_irq);
+ dump_tssc_regs(ts);
+ return 0;
+
+err_request_irq2:
+ free_irq(ts->sample_irq, ts);
+
+err_request_irq1:
+ /* disable the tssc */
+ tssc_writel(ts, TSSC_CTL_ENABLE, TSSC_CTL);
+
+err_input_dev_reg:
+ input_set_drvdata(ts->input_dev, NULL);
+ input_free_device(ts->input_dev);
+
+err_alloc_input_dev:
+err_start_tsadc:
+ marimba_tsadc_unregister(ts->ts_client);
+
+err_tsadc_register:
+ iounmap(ts->tssc_base);
+
+err_ioremap_tssc:
+ kfree(ts);
+ return err;
+}
+
+static int __devexit msm_ts_remove(struct platform_device *pdev)
+{
+ struct msm_ts *ts = platform_get_drvdata(pdev);
+
+ device_init_wakeup(&pdev->dev, 0);
+ marimba_tsadc_unregister(ts->ts_client);
+ free_irq(ts->sample_irq, ts);
+ free_irq(ts->pen_up_irq, ts);
+ input_unregister_device(ts->input_dev);
+ iounmap(ts->tssc_base);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ts->early_suspend);
+#endif
+ platform_set_drvdata(pdev, NULL);
+ kfree(ts);
+
+ return 0;
+}
+
+static struct platform_driver msm_touchscreen_driver = {
+ .driver = {
+ .name = "msm_touchscreen",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &msm_touchscreen_pm_ops,
+#endif
+ },
+ .probe = msm_ts_probe,
+ .remove = __devexit_p(msm_ts_remove),
+};
+
+static int __init msm_ts_init(void)
+{
+ return platform_driver_register(&msm_touchscreen_driver);
+}
+
+static void __exit msm_ts_exit(void)
+{
+ platform_driver_unregister(&msm_touchscreen_driver);
+}
+
+module_init(msm_ts_init);
+module_exit(msm_ts_exit);
+MODULE_DESCRIPTION("Qualcomm MSM/QSD Touchscreen controller driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:msm_touchscreen");
diff --git a/drivers/input/touchscreen/synaptics/Makefile b/drivers/input/touchscreen/synaptics/Makefile
new file mode 100644
index 0000000..32cbd76
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/Makefile
@@ -0,0 +1,11 @@
+CFLAGS_rmi_bus.o := -DDEBUG
+CFLAGS_rmi_sensor.o := -DDEBUG
+CFLAGS_rmi_function.o := -DDEBUG
+CFLAGS_rmi_f01.o := -DDEBUG
+CFLAGS_rmi_f05.o := -DDEBUG
+CFLAGS_rmi_f11.o := -DDEBUG
+CFLAGS_rmi_f19.o := -DDEBUG
+CFLAGS_rmi_f34.o := -DDEBUG
+CFLAGS_rmi_i2c.o := -DDEBUG
+CFLAGS_rmi_spi.o := -DDEBUG
+obj-y += rmi_bus.o rmi_sensor.o rmi_function.o rmi_f01.o rmi_f05.o rmi_f11.o rmi_f19.o rmi_f34.o rmi_i2c.o
diff --git a/drivers/input/touchscreen/synaptics/rmi.h b/drivers/input/touchscreen/synaptics/rmi.h
new file mode 100644
index 0000000..7484258
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi.h
@@ -0,0 +1,164 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Header File.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#ifndef _RMI_H
+#define _RMI_H
+
+/* RMI4 Protocol Support
+ */
+
+/* For each function present on the RMI device, we need to get the RMI4 Function
+ * Descriptor info from the Page Descriptor Table. This will give us the
+ * addresses for Query, Command, Control, Data and the Source Count (number
+ * of sources for this function) and the function id.
+ */
+struct rmi_function_descriptor {
+ unsigned char queryBaseAddr;
+ unsigned char commandBaseAddr;
+ unsigned char controlBaseAddr;
+ unsigned char dataBaseAddr;
+ unsigned char interruptSrcCnt;
+ unsigned char functionNum;
+};
+
+/* This encapsulates the information found using the RMI4 Function $01
+ * query registers. There is only one Function $01 per device.
+ *
+ * Assuming appropriate endian-ness, you can populate most of this
+ * structure by reading query registers starting at the query base address
+ * that was obtained from RMI4 function 0x01 function descriptor info read
+ * from the Page Descriptor Table.
+ *
+ * Specific register information is provided in the comments for each field.
+ * For further reference, please see the "Synaptics RMI 4 Interfacing
+ * Guide" document : go to http://www.synaptics.com/developers/manuals - and
+ * select "Synaptics RMI 4 Interfacting Guide".
+ */
+struct rmi_F01_query {
+ /* The manufacturer identification byte.*/
+ unsigned char mfgid;
+
+ /* The Product Properties information.*/
+ unsigned char properties;
+
+ /* The product info bytes.*/
+ unsigned char prod_info[2];
+
+ /* Date Code - Year, Month, Day.*/
+ unsigned char date_code[3];
+
+ /* Tester ID (14 bits).*/
+ unsigned short tester_id;
+
+ /* Serial Number (14 bits).*/
+ unsigned short serial_num;
+
+ /* A null-terminated string that identifies this particular product.*/
+ char prod_id[11];
+};
+
+/* This encapsulates the F01 Device Control control registers.
+ * TODO: This isn't right. The number of interrupt enables needs to be determined
+ * dynamically as the sensor is initialized. Fix this.
+ */
+struct rmi_F01_control {
+ unsigned char deviceControl;
+ unsigned char interruptEnable[1];
+};
+
+/** This encapsulates the F01 Device Control data registers.
+ * TODO: This isn't right. The number of irqs needs to be determined
+ * dynamically as the sensor is initialized. Fix this.
+ */
+struct rmi_F01_data {
+ unsigned char deviceStatus;
+ unsigned char irqs[1];
+};
+
+
+/**********************************************************/
+
+/** This is the data read from the F11 query registers.
+ */
+struct rmi_F11_device_query {
+ bool hasQuery9;
+ unsigned char numberOfSensors;
+};
+
+struct rmi_F11_sensor_query {
+ bool configurable;
+ bool hasSensitivityAdjust;
+ bool hasGestures;
+ bool hasAbs;
+ bool hasRel;
+ unsigned char numberOfFingers;
+ unsigned char numberOfXElectrodes;
+ unsigned char numberOfYElectrodes;
+ unsigned char maximumElectrodes;
+ bool hasAnchoredFinger;
+ unsigned char absDataSize;
+};
+
+struct rmi_F11_control {
+ bool relativeBallistics;
+ bool relativePositionFilter;
+ bool absolutePositionFilter;
+ unsigned char reportingMode;
+ bool manuallyTrackedFinger;
+ bool manuallyTrackedFingerEnable;
+ unsigned char motionSensitivity;
+ unsigned char palmDetectThreshold;
+ unsigned char deltaXPosThreshold;
+ unsigned char deltaYPosThreshold;
+ unsigned char velocity;
+ unsigned char acceleration;
+ unsigned short sensorMaxXPos;
+ unsigned short sensorMaxYPos;
+};
+
+
+/**********************************************************/
+
+/** This is the data read from the F19 query registers.
+ */
+struct rmi_F19_query {
+ bool hasHysteresisThreshold;
+ bool hasSensitivityAdjust;
+ bool configurable;
+ unsigned char buttonCount;
+};
+
+struct rmi_F19_control {
+ unsigned char buttonUsage;
+ unsigned char filterMode;
+ unsigned char *intEnableRegisters;
+ unsigned char *singleButtonControl;
+ unsigned char *sensorMap;
+ unsigned char *singleButtonSensitivity;
+ unsigned char globalSensitivityAdjustment;
+ unsigned char globalHysteresisThreshold;
+};
+
+#endif
diff --git a/drivers/input/touchscreen/synaptics/rmi_bus.c b/drivers/input/touchscreen/synaptics/rmi_bus.c
new file mode 100644
index 0000000..b65eabb
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_bus.c
@@ -0,0 +1,402 @@
+/**
+ * Synaptics Register Mapped Interface (RMI4) - RMI Bus Module.
+ * Copyright (C) 2007 - 2011, Synaptics Incorporated
+ *
+ * Impliments "rmi" bus per Documentation/driver-model/bus.txt
+ *
+ * This protocol is layered as follows.
+ *
+ *
+ *
+ * +-------+ +-------+ +-------+ +--------+
+ * | Fn32 | | Fn11| | Fn19 | | Fn11 | Devices/Functions
+ * *---|---+ +--|----+ +----|--+ +----|---* (2D, cap. btns, etc.)
+ * | | | |
+ * +----------------+ +----------------+
+ * | Sensor0 | | Sensor1 | Sensors Dev/Drivers
+ * +----------------+ +----------------+ (a sensor has one or
+ * | | more functions)
+ * | |
+ * +----------------------------------------+
+ * | |
+ * | RMI4 Bus | RMI Bus Layer
+ * | (this file) |
+ * *--|-----|------|--------------|---------*
+ * | | | |
+ * | | | |
+ * +-----+-----+-------+--------------------+
+ * | I2C | SPI | SMBus | etc. | Physical Layer
+ * +-----+-----+-------+--------------------+
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+static const char busname[] = "rmi";
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/hrtimer.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/input/rmi_platformdata.h>
+#include <linux/module.h>
+
+#include "rmi_drvr.h"
+#include "rmi.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+
+/* list of physical drivers - i2c, spi, etc. */
+static LIST_HEAD(phys_drivers);
+static DEFINE_MUTEX(phys_drivers_mutex);
+
+/* list of sensors found on a physical bus (i2c, smi, etc.)*/
+static LIST_HEAD(sensor_drivers);
+static DEFINE_MUTEX(sensor_drivers_mutex);
+static LIST_HEAD(sensor_devices);
+static DEFINE_MUTEX(sensor_devices_mutex);
+
+#define PDT_START_SCAN_LOCATION 0x00E9
+#define PDT_END_SCAN_LOCATION 0x0005
+#define PDT_ENTRY_SIZE 0x0006
+
+/* definitions for rmi bus */
+struct device rmi_bus_device;
+
+struct bus_type rmi_bus_type;
+EXPORT_SYMBOL(rmi_bus_type);
+
+
+/*
+ * This method is called, perhaps multiple times, whenever a new device or driver
+ * is added for this bus. It should return a nonzero value if the given device can be
+ * handled by the given driver. This function must be handled at the bus level,
+ * because that is where the proper logic exists; the core kernel cannot know how
+ * to match devices and drivers for every possible bus type
+ * The match function does a comparison between the hardware ID provided by
+ * the device itself and the IDs supported by the driver.
+ *
+ */
+static int rmi_bus_match(struct device *dev, struct device_driver *driver)
+{
+ printk(KERN_DEBUG "%s: Matching %s for rmi bus.\n", __func__, dev->bus->name);
+ return !strncmp(dev->bus->name, driver->name, strlen(driver->name));
+}
+
+/** Stub for now.
+ */
+static int rmi_bus_suspend(struct device *dev, pm_message_t state)
+{
+ printk(KERN_INFO "%s: RMI bus suspending.", __func__);
+ return 0;
+}
+
+/** Stub for now.
+ */
+static int rmi_bus_resume(struct device *dev)
+{
+ printk(KERN_INFO "%s: RMI bus resuming.", __func__);
+ return 0;
+}
+
+/*
+ * This method is called, whenever a new device is added for this bus.
+ * It will scan the devices PDT to get the function $01 query, control,
+ * command and data regsiters so that it can create a function $01 (sensor)
+ * device for the new physical device. It also caches the PDT for later use by
+ * other functions that are created for the device. For example, if a function
+ * $11 is found it will need the query, control, command and data register
+ * addresses for that function. The new function could re-scan the PDT but
+ * since it is being done here we can cache it and keep it around.
+ *
+ * TODO: If the device is reset or some action takes place that would invalidate
+ * the PDT - such as a reflash of the firmware - then the device should be re-added
+ * to the bus and the PDT re-scanned and cached.
+ *
+ */
+int rmi_register_sensor(struct rmi_phys_driver *rpd, struct rmi_sensordata *sensordata)
+{
+ int i;
+ int pdt_entry_count = 0;
+ struct rmi_sensor_device *rmi_sensor_dev;
+ struct rmi_function_info *rfi;
+ struct rmi_function_descriptor rmi_fd;
+ int retval;
+ static int index;
+
+ /* Make sure we have a read, write, read_multiple, write_multiple
+ function pointers from whatever physical layer the sensor is on.
+ */
+ if (!rpd->name) {
+ printk(KERN_ERR "%s: Physical driver must specify a name",
+ __func__);
+ return -EINVAL;
+ }
+ if (!rpd->write) {
+ printk(KERN_ERR
+ "%s: Physical driver %s must specify a writer.",
+ __func__, rpd->name);
+ return -EINVAL;
+ }
+ if (!rpd->read) {
+ printk(KERN_ERR
+ "%s: Physical driver %s must specify a reader.",
+ __func__, rpd->name);
+ return -EINVAL;
+ }
+ if (!rpd->write_multiple) {
+ printk(KERN_ERR "%s: Physical driver %s must specify a "
+ "multiple writer.",
+ __func__, rpd->name);
+ return -EINVAL;
+ }
+ if (!rpd->read_multiple) {
+ printk(KERN_ERR "%s: Physical driver %s must specify a "
+ "multiple reader.",
+ __func__, rpd->name);
+ return -EINVAL;
+ }
+
+ /* Get some information from the device */
+ printk(KERN_DEBUG "%s: Identifying sensors by presence of F01...", __func__);
+
+ rmi_sensor_dev = NULL;
+
+ /* Scan the page descriptor table until we find F01. If we find that,
+ * we assume that we can reliably talk to this sensor.
+ */
+ for (i = PDT_START_SCAN_LOCATION; /* Register the rmi sensor driver */
+ i >= PDT_END_SCAN_LOCATION;
+ i -= PDT_ENTRY_SIZE) {
+ retval = rpd->read_multiple(rpd, i, (char *)&rmi_fd,
+ sizeof(rmi_fd));
+ if (!retval) {
+ rfi = NULL;
+
+ if (rmi_fd.functionNum != 0x00 && rmi_fd.functionNum != 0xff) {
+ pdt_entry_count++;
+ if ((rmi_fd.functionNum & 0xff) == 0x01) {
+ printk(KERN_DEBUG "%s: F01 Found - RMI Device Control", __func__);
+
+ /* This appears to be a valid device, so create a sensor
+ * device and sensor driver for it. */
+ rmi_sensor_dev = kzalloc(sizeof(*rmi_sensor_dev), GFP_KERNEL);
+ if (!rmi_sensor_dev) {
+ printk(KERN_ERR "%s: Error allocating memory for rmi_sensor_device\n", __func__);
+ retval = -ENOMEM;
+ goto exit_fail;
+ }
+ rmi_sensor_dev->dev.bus = &rmi_bus_type;
+
+ retval = rmi_sensor_register_device(rmi_sensor_dev, index++);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: Error %d registering sensor device.", __func__, retval);
+ goto exit_fail;
+ }
+
+ rmi_sensor_dev->driver = kzalloc(sizeof(struct rmi_sensor_driver), GFP_KERNEL);
+ if (!rmi_sensor_dev->driver) {
+ printk(KERN_ERR "%s: Error allocating memory for rmi_sensor_driver\n", __func__);
+ retval = -ENOMEM;
+ goto exit_fail;
+ }
+ rmi_sensor_dev->driver->sensor_device = rmi_sensor_dev;
+ rmi_sensor_dev->driver->polling_required = rpd->polling_required;
+ rmi_sensor_dev->driver->rpd = rpd;
+ if (sensordata)
+ rmi_sensor_dev->driver->perfunctiondata = sensordata->perfunctiondata;
+ INIT_LIST_HEAD(&rmi_sensor_dev->driver->functions);
+
+ retval = rmi_sensor_register_driver(rmi_sensor_dev->driver);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: Error %d registering sensor driver.", __func__, retval);
+ goto exit_fail;
+ }
+
+ /* link the attention fn in the rpd to the sensor attn fn */
+
+ rpd->sensor = rmi_sensor_dev->driver;
+ rpd->attention = rmi_sensor_dev->driver->attention;
+
+ /* Add it into the list of sensors on the rmi bus */
+ mutex_lock(&sensor_devices_mutex);
+ list_add_tail(&rmi_sensor_dev->sensors, &sensor_devices);
+ mutex_unlock(&sensor_devices_mutex);
+
+ /* All done with this sensor, fall out of PDT scan loop. */
+ break;
+ } else {
+ /* Just print out the function found for now */
+ printk(KERN_DEBUG "%s: Found Function %02x - Ignored.\n", __func__, rmi_fd.functionNum & 0xff);
+ }
+ } else {
+ /* A zero or 0xff in the function number
+ signals the end of the PDT */
+ pr_debug("%s: Found End of PDT.",
+ __func__);
+ break;
+ }
+ } else {
+ /* failed to read next PDT entry - end PDT
+ scan - this may result in an incomplete set
+ of recognized functions - should probably
+ return an error but the driver may still be
+ viable for diagnostics and debugging so let's
+ let it continue. */
+ printk(KERN_ERR "%s: Read Error %d when reading next PDT entry - "
+ "ending PDT scan.",
+ __func__, retval);
+ break;
+ }
+ }
+
+ /* If we actually found a sensor, keep it around. */
+ if (rmi_sensor_dev) {
+ /* Add physical driver struct to list */
+ mutex_lock(&phys_drivers_mutex);
+ list_add_tail(&rpd->drivers, &phys_drivers);
+ mutex_unlock(&phys_drivers_mutex);
+ printk(KERN_DEBUG "%s: Registered sensor drivers.", __func__);
+ retval = 0;
+ } else {
+ printk(KERN_ERR "%s: Failed to find sensor. PDT contained %d entries.", __func__, pdt_entry_count);
+ retval = -ENODEV;
+ }
+
+exit_fail:
+ return retval;
+}
+EXPORT_SYMBOL(rmi_register_sensor);
+
+int rmi_unregister_sensors(struct rmi_phys_driver *rpd)
+{
+ if (rpd->sensor) {
+ printk(KERN_WARNING "%s: WARNING: unregister of %s while %s still attached.",
+ __func__, rpd->name, rpd->sensor->drv.name);
+ }
+
+ pr_debug("%s: Unregistering sensor drivers %s\n", __func__, rpd->name);
+
+ /* TODO: We should call sensor_teardown() for each sensor before we get
+ * rid of this list.
+ */
+
+ mutex_lock(&sensor_drivers_mutex);
+ list_del(&rpd->sensor->sensor_drivers);
+ mutex_unlock(&sensor_drivers_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(rmi_unregister_sensors);
+
+
+static void rmi_bus_dev_release(struct device *dev)
+{
+ printk(KERN_DEBUG "rmi bus device release\n");
+}
+
+
+int rmi_register_bus_device(struct device *rmibusdev)
+{
+ printk(KERN_DEBUG "%s: Registering RMI4 bus device.\n", __func__);
+
+ /* Here, we simply fill in some of the embedded device structure fields
+ (which individual drivers should not need to know about), and register
+ the device with the driver core. */
+
+ rmibusdev->bus = &rmi_bus_type;
+ rmibusdev->parent = &rmi_bus_device;
+ rmibusdev->release = rmi_bus_dev_release;
+ dev_set_name(rmibusdev, "rmi");
+
+ /* If we wanted to add bus-specific attributes to the device, we could do so here.*/
+
+ return device_register(rmibusdev);
+}
+EXPORT_SYMBOL(rmi_register_bus_device);
+
+void rmi_unregister_bus_device(struct device *rmibusdev)
+{
+ printk(KERN_DEBUG "%s: Unregistering bus device.", __func__);
+
+ device_unregister(rmibusdev);
+}
+EXPORT_SYMBOL(rmi_unregister_bus_device);
+
+static int __init rmi_bus_init(void)
+{
+ int status;
+
+ status = 0;
+
+ printk(KERN_INFO "%s: RMI Bus Driver Init", __func__);
+
+ /* Register the rmi bus */
+ rmi_bus_type.name = busname;
+ rmi_bus_type.match = rmi_bus_match;
+ rmi_bus_type.suspend = rmi_bus_suspend;
+ rmi_bus_type.resume = rmi_bus_resume;
+ status = bus_register(&rmi_bus_type);
+ if (status < 0) {
+ printk(KERN_ERR "%s: Error %d registering the rmi bus.", __func__, status);
+ goto err_exit;
+ }
+ printk(KERN_DEBUG "%s: registered bus.", __func__);
+
+#if 0
+ /** This doesn't seem to be required any more. It worked OK in Froyo,
+ * but breaks in Gingerbread */
+ /* Register the rmi bus device - "rmi". There is only one rmi bus device. */
+ status = rmi_register_bus_device(&rmi_bus_device);
+ if (status < 0) {
+ printk(KERN_ERR "%s: Error %d registering rmi bus device.", __func__, status);
+ bus_unregister(&rmi_bus_type);
+ goto err_exit;
+ }
+ printk(KERN_DEBUG "%s: Registered bus device.", __func__);
+#endif
+
+ return 0;
+err_exit:
+ return status;
+}
+
+static void __exit rmi_bus_exit(void)
+{
+ printk(KERN_DEBUG "%s: RMI Bus Driver Exit.", __func__);
+
+ /* Unregister the rmi bus device - "rmi". There is only one rmi bus device. */
+ rmi_unregister_bus_device(&rmi_bus_device);
+
+ /* Unregister the rmi bus */
+ bus_unregister(&rmi_bus_type);
+}
+
+
+module_init(rmi_bus_init);
+module_exit(rmi_bus_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("RMI4 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/synaptics/rmi_bus.h b/drivers/input/touchscreen/synaptics/rmi_bus.h
new file mode 100644
index 0000000..1e9bd24
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_bus.h
@@ -0,0 +1,32 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) - RMI Bus Module Header.
+ * Copyright (C) 2007 - 2010, Synaptics Incorporated
+ *
+ */
+/*
+ *
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#ifndef _RMI_BUS_H
+#define _RMI_BUS_H
+
+
+extern struct bus_type rmi_bus_type;
+
+#endif
diff --git a/drivers/input/touchscreen/synaptics/rmi_drvr.h b/drivers/input/touchscreen/synaptics/rmi_drvr.h
new file mode 100644
index 0000000..d8c848d
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_drvr.h
@@ -0,0 +1,104 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) RMI Driver Header File.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include "rmi.h"
+
+#ifndef _RMI_DRVR_H
+#define _RMI_DRVR_H
+
+#include <linux/input/rmi_platformdata.h>
+
+/* RMI4 Protocol Support
+ */
+
+struct rmi_phys_driver {
+ char *name;
+ int (*write)(struct rmi_phys_driver *physdrvr, unsigned short address,
+ char data);
+ int (*read)(struct rmi_phys_driver *physdrvr, unsigned short address,
+ char *buffer);
+ int (*write_multiple)(struct rmi_phys_driver *physdrvr,
+ unsigned short address, char *buffer, int length);
+ int (*read_multiple)(struct rmi_phys_driver *physdrvr, unsigned short address,
+ char *buffer, int length);
+ void (*attention)(struct rmi_phys_driver *physdrvr, int instance);
+ bool polling_required;
+ int irq;
+
+ /* Standard kernel linked list implementation.
+ * Documentation on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head drivers;
+ struct rmi_sensor_driver *sensor;
+ struct module *module;
+};
+
+int rmi_read(struct rmi_sensor_driver *sensor, unsigned short address, char *dest);
+int rmi_write(struct rmi_sensor_driver *sensor, unsigned short address,
+ unsigned char data);
+int rmi_read_multiple(struct rmi_sensor_driver *sensor, unsigned short address,
+ char *dest, int length);
+int rmi_write_multiple(struct rmi_sensor_driver *sensor, unsigned short address,
+ unsigned char *data, int length);
+int rmi_register_sensor(struct rmi_phys_driver *physdrvr,
+ struct rmi_sensordata *sensordata);
+int rmi_unregister_sensors(struct rmi_phys_driver *physdrvr);
+
+/* Utility routine to set bits in a register. */
+int rmi_set_bits(struct rmi_sensor_driver *sensor, unsigned short address, unsigned char bits);
+/* Utility routine to clear bits in a register. */
+int rmi_clear_bits(struct rmi_sensor_driver *sensor, unsigned short address, unsigned char bits);
+/* Utility routine to set the value of a bit field in a register. */
+int rmi_set_bit_field(struct rmi_sensor_driver *sensor, unsigned short address,
+ unsigned char field_mask, unsigned char bits);
+
+/* Set this to 1 to turn on code used in detecting buffer leaks. */
+#define RMI_ALLOC_STATS 1
+
+#if RMI_ALLOC_STATS
+extern int appallocsrmi;
+extern int rfiallocsrmi;
+extern int fnallocsrmi;
+
+#define INC_ALLOC_STAT(X) (X##allocsrmi++)
+#define DEC_ALLOC_STAT(X) \
+ do { \
+ if (X##allocsrmi) X##allocsrmi--; \
+ else printk(KERN_DEBUG "Too many " #X " frees\n"); \
+ } while (0)
+#define CHECK_ALLOC_STAT(X) \
+ do { \
+ if (X##allocsrmi) \
+ printk(KERN_DEBUG "Left over " #X " buffers: %d\n", \
+ X##allocsrmi); \
+ } while (0)
+#else
+#define INC_ALLOC_STAT(X) do { } while (0)
+#define DEC_ALLOC_STAT(X) do { } while (0)
+#define CHECK_ALLOC_STAT(X) do { } while (0)
+#endif
+
+#endif
diff --git a/drivers/input/touchscreen/synaptics/rmi_f01.c b/drivers/input/touchscreen/synaptics/rmi_f01.c
new file mode 100644
index 0000000..25a337d
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_f01.c
@@ -0,0 +1,603 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $01 support for sensor
+ * control and configuration.
+ *
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/param.h>
+#include <linux/input/rmi_platformdata.h>
+#include <linux/module.h>
+
+#include "rmi.h"
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f01.h"
+
+/* Control register bits. */
+#define F01_CONFIGURED (1 << 7)
+#define NONSTANDARD_REPORT_RATE (1 << 6)
+
+/* Command register bits. */
+#define F01_RESET 1
+#define F01_SHUTDOWN (1 << 1)
+
+/* Data register 0 bits. */
+#define F01_UNCONFIGURED (1 << 7)
+#define F01_FLASH_PROGRAMMING_MODE (1 << 6)
+#define F01_STATUS_MASK 0x0F
+
+/** Context data for each F01 we find.
+ */
+struct f01_instance_data {
+ struct rmi_F01_control *controlRegisters;
+ struct rmi_F01_data *dataRegisters;
+ struct rmi_F01_query *query_registers;
+
+ bool nonstandard_report_rate;
+};
+
+static ssize_t rmi_fn_01_productinfo_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_01_productinfo_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(productinfo, 0444, rmi_fn_01_productinfo_show, rmi_fn_01_productinfo_store); /* RO attr */
+
+static ssize_t rmi_fn_01_productid_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_01_productid_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(productid, 0444, rmi_fn_01_productid_show, rmi_fn_01_productid_store); /* RO attr */
+
+static ssize_t rmi_fn_01_manufacturer_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_01_manufacturer_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(manufacturer, 0444, rmi_fn_01_manufacturer_show, rmi_fn_01_manufacturer_store); /* RO attr */
+
+static ssize_t rmi_fn_01_datecode_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_01_datecode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(datecode, 0444, rmi_fn_01_datecode_show, rmi_fn_01_datecode_store); /* RO attr */
+
+static ssize_t rmi_fn_01_reportrate_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_01_reportrate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(reportrate, 0644, rmi_fn_01_reportrate_show, rmi_fn_01_reportrate_store); /* RW attr */
+
+static ssize_t rmi_fn_01_reset_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_01_reset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(reset, 0200, rmi_fn_01_reset_show, rmi_fn_01_reset_store); /* WO attr */
+
+static ssize_t rmi_fn_01_testerid_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_01_testerid_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(testerid, 0444, rmi_fn_01_testerid_show, rmi_fn_01_testerid_store); /* RO attr */
+
+static ssize_t rmi_fn_01_serialnumber_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_01_serialnumber_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(serialnumber, 0444, rmi_fn_01_serialnumber_show, rmi_fn_01_serialnumber_store); /* RO attr */
+
+static int set_report_rate(struct rmi_function_info *function_info, bool nonstandard)
+{
+ if (nonstandard) {
+ return rmi_set_bits(function_info->sensor, function_info->funcDescriptor.controlBaseAddr, NONSTANDARD_REPORT_RATE);
+ } else {
+ return rmi_set_bits(function_info->sensor, function_info->funcDescriptor.controlBaseAddr, NONSTANDARD_REPORT_RATE);
+ }
+}
+
+/*.
+ * The interrupt handler for Fn $01 doesn't do anything (for now).
+ */
+void FN_01_inthandler(struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs)
+{
+ struct f01_instance_data *instanceData = (struct f01_instance_data *) rmifninfo->fndata;
+
+ printk(KERN_DEBUG "%s: Read device status.", __func__);
+
+ if (rmi_read_multiple(rmifninfo->sensor, rmifninfo->funcDescriptor.dataBaseAddr,
+ &instanceData->dataRegisters->deviceStatus, 1)) {
+ printk(KERN_ERR "%s : Could not read F01 device status.\n",
+ __func__);
+ }
+ printk(KERN_INFO "%s: read device status register. Value 0x%02X.", __func__, instanceData->dataRegisters->deviceStatus);
+
+ if (instanceData->dataRegisters->deviceStatus & F01_UNCONFIGURED) {
+ printk(KERN_INFO "%s: ++++ Device reset detected.", __func__);
+ /* TODO: Handle device reset appropriately.
+ */
+ }
+}
+EXPORT_SYMBOL(FN_01_inthandler);
+
+/*
+ * This reads in the function $01 source data.
+ *
+ */
+void FN_01_attention(struct rmi_function_info *rmifninfo)
+{
+ struct f01_instance_data *instanceData = (struct f01_instance_data *) rmifninfo->fndata;
+
+ /* TODO: Compute size to read and number of IRQ registers to processors
+ * dynamically. See comments in rmi.h. */
+ if (rmi_read_multiple(rmifninfo->sensor, rmifninfo->funcDescriptor.dataBaseAddr+1,
+ instanceData->dataRegisters->irqs, 1)) {
+ printk(KERN_ERR "%s : Could not read interrupt status registers at 0x%02x\n",
+ __func__, rmifninfo->funcDescriptor.dataBaseAddr);
+ return;
+ }
+
+ if (instanceData->dataRegisters->irqs[0] & instanceData->controlRegisters->interruptEnable[0]) {
+// printk(KERN_INFO "%s: ++++ IRQs == 0x%02X", __func__, instanceData->dataRegisters->irqs[0]);
+ /* call down to the sensors irq dispatcher to dispatch all enabled IRQs */
+ rmifninfo->sensor->dispatchIRQs(rmifninfo->sensor,
+ instanceData->dataRegisters->irqs[0]);
+ }
+
+}
+EXPORT_SYMBOL(FN_01_attention);
+
+int FN_01_config(struct rmi_function_info *rmifninfo)
+{
+ int retval = 0;
+ struct f01_instance_data *instance_data = rmifninfo->fndata;
+
+ printk(KERN_DEBUG "%s: RMI4 function $01 config\n", __func__);
+
+ /* First thing to do is set the configuration bit. We'll check this at
+ * the end to determine if the device has reset during the config process.
+ */
+ retval = rmi_set_bits(rmifninfo->sensor, rmifninfo->funcDescriptor.controlBaseAddr, F01_CONFIGURED);
+ if (retval)
+ printk(KERN_WARNING "%s: failed to set configured bit, errno = %d.",
+ __func__, retval);
+
+ /* At config time, the device is presumably in its default state, so we
+ * only need to write non-default configuration settings.
+ */
+ if (instance_data->nonstandard_report_rate) {
+ retval = set_report_rate(rmifninfo, true);
+ if (!retval)
+ printk(KERN_WARNING "%s: failed to configure report rate, errno = %d.",
+ __func__, retval);
+ }
+
+ /* TODO: Check for reset! */
+
+ return retval;
+}
+EXPORT_SYMBOL(FN_01_config);
+
+/* Initialize any function $01 specific params and settings - input
+ * settings, device settings, etc.
+ */
+int FN_01_init(struct rmi_function_device *function_device)
+{
+ int retval;
+ struct rmi_f01_functiondata *functiondata = rmi_sensor_get_functiondata(function_device->sensor, RMI_F01_INDEX);
+ struct f01_instance_data *instance_data = function_device->rfi->fndata;
+
+ pr_debug("%s: RMI4 function $01 init\n", __func__);
+
+ if (functiondata) {
+ instance_data->nonstandard_report_rate = functiondata->nonstandard_report_rate;
+ }
+
+ retval = device_create_file(&function_device->dev, &dev_attr_productinfo);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create productinfo.", __func__);
+ return retval;
+ }
+ retval = device_create_file(&function_device->dev, &dev_attr_productid);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create productid.", __func__);
+ return retval;
+ }
+ retval = device_create_file(&function_device->dev, &dev_attr_manufacturer);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create manufacturer.", __func__);
+ return retval;
+ }
+ retval = device_create_file(&function_device->dev, &dev_attr_datecode);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create datecode.", __func__);
+ return retval;
+ }
+ retval = device_create_file(&function_device->dev, &dev_attr_reportrate);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create reportrate.", __func__);
+ return retval;
+ }
+ retval = device_create_file(&function_device->dev, &dev_attr_reset);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create reset.", __func__);
+ return retval;
+ }
+ retval = device_create_file(&function_device->dev, &dev_attr_serialnumber);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create serialnumber.", __func__);
+ return retval;
+ }
+ retval = device_create_file(&function_device->dev, &dev_attr_testerid);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create testerid.", __func__);
+ return retval;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(FN_01_init);
+
+int FN_01_detect(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr, unsigned int interruptCount)
+{
+ int i;
+ int InterruptOffset;
+ int retval = 0;
+ struct f01_instance_data *instanceData = NULL;
+ struct rmi_F01_control *controlRegisters = NULL;
+ struct rmi_F01_data *dataRegisters = NULL;
+ struct rmi_F01_query *query_registers = NULL;
+ unsigned char query_buffer[21];
+
+ pr_debug("%s: RMI4 function $01 detect\n", __func__);
+
+ /* Store addresses - used elsewhere to read data,
+ * control, query, etc. */
+ rmifninfo->funcDescriptor.queryBaseAddr = fndescr->queryBaseAddr;
+ rmifninfo->funcDescriptor.commandBaseAddr = fndescr->commandBaseAddr;
+ rmifninfo->funcDescriptor.controlBaseAddr = fndescr->controlBaseAddr;
+ rmifninfo->funcDescriptor.dataBaseAddr = fndescr->dataBaseAddr;
+ rmifninfo->funcDescriptor.interruptSrcCnt = fndescr->interruptSrcCnt;
+ rmifninfo->funcDescriptor.functionNum = fndescr->functionNum;
+
+ rmifninfo->numSources = fndescr->interruptSrcCnt;
+
+ /* Set up context data. */
+ instanceData = kzalloc(sizeof(*instanceData), GFP_KERNEL);
+ if (!instanceData) {
+ printk(KERN_ERR "%s: Error allocating memory for F01 context data.\n", __func__);
+ retval = -ENOMEM;
+ goto error_exit;
+ }
+ query_registers = kzalloc(sizeof(*query_registers), GFP_KERNEL);
+ if (!query_registers) {
+ printk(KERN_ERR "%s: Error allocating memory for F01 query registers.\n", __func__);
+ retval = -ENOMEM;
+ goto error_exit;
+ }
+ instanceData->query_registers = query_registers;
+
+ /* Read the query info and unpack it. */
+ retval = rmi_read_multiple(rmifninfo->sensor, rmifninfo->funcDescriptor.queryBaseAddr,
+ query_buffer, 21);
+ if (retval) {
+ printk(KERN_ERR "%s : Could not read F01 query registers at 0x%02x. Error %d.\n",
+ __func__, rmifninfo->funcDescriptor.queryBaseAddr, retval);
+ /* Presumably if the read fails, the buffer should be all zeros, so we're OK to continue. */
+ }
+ query_registers->mfgid = query_buffer[0];
+ query_registers->properties = query_buffer[1];
+ query_registers->prod_info[0] = query_buffer[2] & 0x7F;
+ query_registers->prod_info[1] = query_buffer[3] & 0x7F;
+ query_registers->date_code[0] = query_buffer[4] & 0x1F;
+ query_registers->date_code[1] = query_buffer[5] & 0x0F;
+ query_registers->date_code[2] = query_buffer[6] & 0x1F;
+ query_registers->tester_id = (((unsigned short) query_buffer[7] & 0x7F) << 7) | (query_buffer[8] & 0x7F);
+ query_registers->serial_num = (((unsigned short) query_buffer[9] & 0x7F) << 7) | (query_buffer[10] & 0x7F);
+ memcpy(query_registers->prod_id, &query_buffer[11], 10);
+
+ printk(KERN_DEBUG "%s: RMI4 Protocol Function $01 Query information, rmifninfo->funcDescriptor.queryBaseAddr = %d\n", __func__, rmifninfo->funcDescriptor.queryBaseAddr);
+ printk(KERN_DEBUG "%s: Manufacturer ID: %d %s\n", __func__,
+ query_registers->mfgid, query_registers->mfgid == 1 ? "(Synaptics)" : "");
+ printk(KERN_DEBUG "%s: Product Properties: 0x%x\n",
+ __func__, query_registers->properties);
+ printk(KERN_DEBUG "%s: Product Info: 0x%x 0x%x\n",
+ __func__, query_registers->prod_info[0], query_registers->prod_info[1]);
+ printk(KERN_DEBUG "%s: Date Code: Year : %d Month: %d Day: %d\n",
+ __func__, query_registers->date_code[0], query_registers->date_code[1],
+ query_registers->date_code[2]);
+ printk(KERN_DEBUG "%s: Tester ID: %d\n", __func__, query_registers->tester_id);
+ printk(KERN_DEBUG "%s: Serial Number: 0x%x\n",
+ __func__, query_registers->serial_num);
+ printk(KERN_DEBUG "%s: Product ID: %s\n", __func__, query_registers->prod_id);
+
+ /* TODO: size of control registers needs to be computed dynamically. See comment
+ * in rmi.h. */
+ controlRegisters = kzalloc(sizeof(*controlRegisters), GFP_KERNEL);
+ if (!controlRegisters) {
+ printk(KERN_ERR "%s: Error allocating memory for F01 control registers.\n", __func__);
+ retval = -ENOMEM;
+ goto error_exit;
+ }
+ instanceData->controlRegisters = controlRegisters;
+ retval = rmi_read_multiple(rmifninfo->sensor, rmifninfo->funcDescriptor.controlBaseAddr,
+ (char *)instanceData->controlRegisters, sizeof(struct rmi_F01_control));
+ if (retval) {
+ printk(KERN_ERR "%s : Could not read F01 control registers at 0x%02x. Error %d.\n",
+ __func__, rmifninfo->funcDescriptor.controlBaseAddr, retval);
+ }
+
+ /* TODO: size of data registers needs to be computed dynamically. See comment
+ * in rmi.h. */
+ dataRegisters = kzalloc(sizeof(*dataRegisters), GFP_KERNEL);
+ if (!dataRegisters) {
+ printk(KERN_ERR "%s: Error allocating memory for F01 data registers.\n", __func__);
+ retval = -ENOMEM;
+ goto error_exit;
+ }
+ instanceData->dataRegisters = dataRegisters;
+ rmifninfo->fndata = instanceData;
+
+ /* Need to get interrupt info to be used later when handling
+ * interrupts. */
+ rmifninfo->interruptRegister = interruptCount/8;
+
+ /* loop through interrupts for each source and or in a bit
+ * to the interrupt mask for each. */
+ InterruptOffset = interruptCount % 8;
+
+ for (i = InterruptOffset;
+ i < ((fndescr->interruptSrcCnt & 0x7) + InterruptOffset);
+ i++) {
+ rmifninfo->interruptMask |= 1 << i;
+ }
+
+ return retval;
+
+error_exit:
+ kfree(instanceData);
+ kfree(query_registers);
+ kfree(controlRegisters);
+ kfree(dataRegisters);
+ return retval;
+}
+EXPORT_SYMBOL(FN_01_detect);
+
+static ssize_t rmi_fn_01_productinfo_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f01_instance_data *instance_data = (struct f01_instance_data *)fn->rfi->fndata;
+
+ if (instance_data && instance_data->query_registers && instance_data->query_registers->prod_info)
+ return sprintf(buf, "0x%02X 0x%02X\n", instance_data->query_registers->prod_info[0], instance_data->query_registers->prod_info[1]);
+
+ return sprintf(buf, "unknown");
+}
+
+static ssize_t rmi_fn_01_productinfo_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return -EPERM;
+}
+
+
+static ssize_t rmi_fn_01_productid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f01_instance_data *instance_data = (struct f01_instance_data *)fn->rfi->fndata;
+
+ if (instance_data && instance_data->query_registers && instance_data->query_registers->prod_id)
+ return sprintf(buf, "%s\n", instance_data->query_registers->prod_id);
+
+ return sprintf(buf, "unknown");
+}
+
+static ssize_t rmi_fn_01_productid_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return -EPERM;
+}
+
+static ssize_t rmi_fn_01_manufacturer_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f01_instance_data *instance_data = (struct f01_instance_data *)fn->rfi->fndata;
+
+ if (instance_data && instance_data->query_registers)
+ return sprintf(buf, "0x%02X\n", instance_data->query_registers->mfgid);
+
+ return sprintf(buf, "unknown");
+}
+
+static ssize_t rmi_fn_01_manufacturer_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return -EPERM;
+}
+
+static ssize_t rmi_fn_01_datecode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f01_instance_data *instance_data = (struct f01_instance_data *)fn->rfi->fndata;
+
+ if (instance_data && instance_data->query_registers && instance_data->query_registers->date_code)
+ return sprintf(buf, "20%02u-%02u-%02u\n", instance_data->query_registers->date_code[0], instance_data->query_registers->date_code[1], instance_data->query_registers->date_code[2]);
+
+ return sprintf(buf, "unknown");
+}
+
+static ssize_t rmi_fn_01_datecode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return -EPERM;
+}
+
+static ssize_t rmi_fn_01_reportrate_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f01_instance_data *instance_data = (struct f01_instance_data *)fn->rfi->fndata;
+
+ if (instance_data && instance_data->query_registers && instance_data->query_registers->date_code)
+ return sprintf(buf, "%d\n", instance_data->nonstandard_report_rate);
+
+ return sprintf(buf, "unknown");
+}
+
+static ssize_t rmi_fn_01_reportrate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f01_instance_data *instance_data = (struct f01_instance_data *)fn->rfi->fndata;
+ unsigned int new_rate;
+ int retval;
+
+ printk(KERN_DEBUG "%s: Report rate set to %s", __func__, buf);
+
+ if (sscanf(buf, "%u", &new_rate) != 1)
+ return -EINVAL;
+ if (new_rate < 0 || new_rate > 1)
+ return -EINVAL;
+ instance_data->nonstandard_report_rate = new_rate;
+
+ retval = set_report_rate(fn->rfi, new_rate);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: failed to set report rate bit, error = %d.", __func__, retval);
+ return retval;
+ }
+
+ return count;
+}
+
+static ssize_t rmi_fn_01_reset_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return -EPERM;
+}
+
+static ssize_t rmi_fn_01_reset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ unsigned int reset;
+ int retval;
+
+ printk(KERN_INFO "%s: Reset written with %s", __func__, buf);
+
+ if (sscanf(buf, "%u", &reset) != 1)
+ return -EINVAL;
+ if (reset < 0 || reset > 1)
+ return -EINVAL;
+
+ /* Per spec, 0 has no effect, so we skip it entirely. */
+ if (reset) {
+ retval = rmi_set_bits(fn->sensor, fn->rfi->funcDescriptor.commandBaseAddr, F01_RESET);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: failed to issue reset command, error = %d.", __func__, retval);
+ return retval;
+ }
+ }
+
+ return count;
+}
+
+static ssize_t rmi_fn_01_serialnumber_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f01_instance_data *instance_data = (struct f01_instance_data *)fn->rfi->fndata;
+
+ if (instance_data && instance_data->query_registers)
+ return sprintf(buf, "%u\n", instance_data->query_registers->serial_num);
+
+ return sprintf(buf, "unknown");
+}
+
+static ssize_t rmi_fn_01_serialnumber_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return -EPERM;
+}
+
+static ssize_t rmi_fn_01_testerid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f01_instance_data *instance_data = (struct f01_instance_data *)fn->rfi->fndata;
+
+ if (instance_data && instance_data->query_registers)
+ return sprintf(buf, "%u\n", instance_data->query_registers->tester_id);
+
+ return sprintf(buf, "unknown");
+}
+
+static ssize_t rmi_fn_01_testerid_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return -EPERM;
+}
diff --git a/drivers/input/touchscreen/synaptics/rmi_f01.h b/drivers/input/touchscreen/synaptics/rmi_f01.h
new file mode 100644
index 0000000..976e062
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_f01.h
@@ -0,0 +1,40 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $01 header.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ * There is only one function $01 for each RMI4 sensor. This will be
+ * the function that is used to set sensor control and configurations
+ * and check the interrupts to find the source function that is interrupting.
+ *
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+#ifndef _RMI_FUNCTION_01_H
+#define _RMI_FUNCTION_01_H
+
+void FN_01_inthandler(struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs);
+int FN_01_config(struct rmi_function_info *rmifninfo);
+int FN_01_init(struct rmi_function_device *function_device);
+int FN_01_detect(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr,
+ unsigned int interruptCount);
+void FN_01_attention(struct rmi_function_info *rmifninfo);
+#endif
diff --git a/drivers/input/touchscreen/synaptics/rmi_f05.c b/drivers/input/touchscreen/synaptics/rmi_f05.c
new file mode 100644
index 0000000..4f209e7
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_f05.c
@@ -0,0 +1,137 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $11 support for 2D.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/input/rmi_platformdata.h>
+#include <linux/module.h>
+
+#include "rmi.h"
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f05.h"
+
+struct f05_instance_data {
+ int dummy; /* TODO: Write this */
+};
+
+/*
+ * There is no attention function for F05 - it is left NULL
+ * in the function table so it is not called.
+ *
+ */
+
+
+/*
+ * This reads in a sample and reports the F05 source data to the
+ * input subsystem. It is used for both polling and interrupt driven
+ * operation. This is called a lot so don't put in any informational
+ * printks since they will slow things way down!
+ */
+void FN_05_inthandler(struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs)
+{
+// struct f05_instance_data *instance_data = rmifninfo->fndata;
+}
+EXPORT_SYMBOL(FN_05_inthandler);
+
+int FN_05_config(struct rmi_function_info *rmifninfo)
+{
+ int retval = 0;
+
+ pr_debug("%s: RMI4 F05 config\n", __func__);
+
+ /* TODO: Perform configuration. In particular, write any cached control
+ * register values to the device. */
+
+ return retval;
+}
+EXPORT_SYMBOL(FN_05_config);
+
+/* Initialize any F05 specific params and settings - input
+ * settings, device settings, etc.
+ */
+int FN_05_init(struct rmi_function_device *function_device)
+{
+ int retval = 0;
+// struct f05_instance_data *instance_data = function_device->rfi->fndata;
+// struct rmi_f05_functiondata *functiondata = rmi_sensor_get_functiondata(function_device->sensor, RMI_F05_INDEX);
+
+ printk(KERN_DEBUG "%s: RMI4 F05 init\n", __func__);
+
+ return retval;
+}
+EXPORT_SYMBOL(FN_05_init);
+
+
+int FN_05_detect(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr, unsigned int interruptCount)
+{
+ int retval = 0;
+ int i;
+ struct f05_instance_data *instanceData;
+ int fn05InterruptOffset;
+
+ printk(KERN_DEBUG "%s: RMI4 F05 detect\n", __func__);
+
+ instanceData = kzalloc(sizeof(struct f05_instance_data), GFP_KERNEL);
+ if (!instanceData) {
+ printk(KERN_ERR "%s: Error allocating F05 instance data.\n", __func__);
+ return -ENOMEM;
+ }
+ rmifninfo->fndata = instanceData;
+
+ /* Store addresses - used elsewhere to read data,
+ * control, query, etc. */
+ rmifninfo->funcDescriptor.queryBaseAddr = fndescr->queryBaseAddr;
+ rmifninfo->funcDescriptor.commandBaseAddr = fndescr->commandBaseAddr;
+ rmifninfo->funcDescriptor.controlBaseAddr = fndescr->controlBaseAddr;
+ rmifninfo->funcDescriptor.dataBaseAddr = fndescr->dataBaseAddr;
+ rmifninfo->funcDescriptor.interruptSrcCnt = fndescr->interruptSrcCnt;
+ rmifninfo->funcDescriptor.functionNum = fndescr->functionNum;
+
+ rmifninfo->numSources = fndescr->interruptSrcCnt;
+ /* Need to get interrupt info to be used later when handling
+ interrupts. */
+ rmifninfo->interruptRegister = interruptCount/8;
+
+ /* loop through interrupts for each source in fn $11 and or in a bit
+ to the interrupt mask for each. */
+ fn05InterruptOffset = interruptCount % 8;
+
+ for (i = fn05InterruptOffset;
+ i < ((fndescr->interruptSrcCnt & 0x7) + fn05InterruptOffset);
+ i++)
+ rmifninfo->interruptMask |= 1 << i;
+
+ return retval;
+}
+EXPORT_SYMBOL(FN_05_detect);
diff --git a/drivers/input/touchscreen/synaptics/rmi_f05.h b/drivers/input/touchscreen/synaptics/rmi_f05.h
new file mode 100644
index 0000000..b820e71
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_f05.h
@@ -0,0 +1,43 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $11 header.
+ * Copyright (c) 2007 - 2010, Synaptics Incorporated
+ *
+ * For every RMI4 function that has a data source - like 2D sensors,
+ * buttons, LEDs, GPIOs, etc. - the user will create a new rmi_function_xx.c
+ * file and add these functions to perform the config(), init(), report()
+ * and detect() functionality. The function pointers are then srored under
+ * the RMI function info and these functions will automatically be called by
+ * the global config(), init(), report() and detect() functions that will
+ * loop through all data sources and call the data sources functions using
+ * these functions pointed to by the function ptrs.
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+#ifndef _RMI_FUNCTION_05_H
+#define _RMI_FUNCTION_05_H
+
+void FN_05_inthandler(struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs);
+int FN_05_config(struct rmi_function_info *rmifninfo);
+int FN_05_init(struct rmi_function_device *function_device);
+int FN_05_detect(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr,
+ unsigned int interruptCount);
+/* No attention function for F05 */
+#endif
diff --git a/drivers/input/touchscreen/synaptics/rmi_f11.c b/drivers/input/touchscreen/synaptics/rmi_f11.c
new file mode 100644
index 0000000..b75b3e0
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_f11.c
@@ -0,0 +1,913 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $11 support for 2D.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/input/rmi_platformdata.h>
+#include <linux/module.h>
+
+#include "rmi.h"
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f11.h"
+
+static int sensorMaxX;
+static int sensorMaxY;
+
+struct f11_instance_data {
+ struct rmi_F11_device_query *deviceInfo;
+ struct rmi_F11_sensor_query *sensorInfo;
+ struct rmi_F11_control *controlRegisters;
+ int button_height;
+ unsigned char fingerDataBufferSize;
+ unsigned char absDataOffset;
+ unsigned char absDataSize;
+ unsigned char relDataOffset;
+ unsigned char gestureDataOffset;
+ unsigned char *fingerDataBuffer;
+ /* Last X & Y seen, needed at finger lift. Was down indicates at least one finger was here. */
+ /* TODO: Eventually we'll need to track this info on a per finger basis. */
+ bool wasdown;
+ unsigned int oldX;
+ unsigned int oldY;
+ /* Transformations to be applied to coordinates before reporting. */
+ bool flipX;
+ bool flipY;
+ int offsetX;
+ int offsetY;
+ int clipXLow;
+ int clipXHigh;
+ int clipYLow;
+ int clipYHigh;
+ bool swap_axes;
+ bool relReport;
+};
+
+enum f11_finger_state {
+ F11_NO_FINGER = 0,
+ F11_PRESENT = 1,
+ F11_INACCURATE = 2,
+ F11_RESERVED = 3
+};
+
+static ssize_t rmi_fn_11_flip_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_11_flip_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(flip, 0664, rmi_fn_11_flip_show, rmi_fn_11_flip_store); /* RW attr */
+
+static ssize_t rmi_fn_11_clip_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_11_clip_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(clip, 0664, rmi_fn_11_clip_show, rmi_fn_11_clip_store); /* RW attr */
+
+static ssize_t rmi_fn_11_offset_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_11_offset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(offset, 0664, rmi_fn_11_offset_show, rmi_fn_11_offset_store); /* RW attr */
+
+static ssize_t rmi_fn_11_swap_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_11_swap_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(swap, 0664, rmi_fn_11_swap_show, rmi_fn_11_swap_store); /* RW attr */
+
+static ssize_t rmi_fn_11_relreport_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_11_relreport_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(relreport, 0664, rmi_fn_11_relreport_show, rmi_fn_11_relreport_store); /* RW attr */
+
+static ssize_t rmi_fn_11_maxPos_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_11_maxPos_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(maxPos, 0664, rmi_fn_11_maxPos_show, rmi_fn_11_maxPos_store); /* RW attr */
+
+
+static void FN_11_relreport(struct rmi_function_info *rmifninfo);
+
+/*
+ * There is no attention function for Fn $11 - it is left NULL
+ * in the function table so it is not called.
+ *
+ */
+
+
+/*
+ * This reads in a sample and reports the function $11 source data to the
+ * input subsystem. It is used for both polling and interrupt driven
+ * operation. This is called a lot so don't put in any informational
+ * printks since they will slow things way down!
+ */
+void FN_11_inthandler(struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs)
+{
+ /* number of touch points - fingers down in this case */
+ int fingerDownCount;
+ int finger;
+ struct rmi_function_device *function_device;
+ struct f11_instance_data *instanceData;
+
+ instanceData = (struct f11_instance_data *) rmifninfo->fndata;
+
+ fingerDownCount = 0;
+ function_device = rmifninfo->function_device;
+
+ /* get 2D sensor finger data */
+
+ if (rmi_read_multiple(rmifninfo->sensor, rmifninfo->funcDescriptor.dataBaseAddr,
+ instanceData->fingerDataBuffer, instanceData->fingerDataBufferSize)) {
+ printk(KERN_ERR "%s: Failed to read finger data registers.\n", __func__);
+ return;
+ }
+
+ /* First we need to count the fingers and generate some events related to that. */
+ for (finger = 0; finger < instanceData->sensorInfo->numberOfFingers; finger++) {
+ int reg;
+ int fingerShift;
+ int fingerStatus;
+
+ /* determine which data byte the finger status is in */
+ reg = finger/4;
+ /* bit shift to get finger's status */
+ fingerShift = (finger % 4) * 2;
+ fingerStatus = (instanceData->fingerDataBuffer[reg] >> fingerShift) & 3;
+
+ if (fingerStatus == F11_PRESENT || fingerStatus == F11_INACCURATE) {
+ fingerDownCount++;
+ instanceData->wasdown = true;
+ }
+ }
+ input_report_key(function_device->input,
+ BTN_TOUCH, !!fingerDownCount);
+
+ for (finger = 0; finger < instanceData->sensorInfo->numberOfFingers; finger++) {
+ int reg;
+ int fingerShift;
+ int fingerStatus;
+ int X = 0, Y = 0, Z = 0, Wy = 0, Wx = 0;
+
+ /* determine which data byte the finger status is in */
+ reg = finger/4;
+ /* bit shift to get finger's status */
+ fingerShift = (finger % 4) * 2;
+ fingerStatus = (instanceData->fingerDataBuffer[reg] >> fingerShift) & 3;
+
+ /* if finger status indicates a finger is present then
+ read the finger data and report it */
+ if (fingerStatus == F11_PRESENT || fingerStatus == F11_INACCURATE) {
+
+ if (instanceData->sensorInfo->hasAbs) {
+ int maxX = instanceData->controlRegisters->sensorMaxXPos;
+ int maxY = instanceData->controlRegisters->sensorMaxYPos;
+ reg = instanceData->absDataOffset + (finger * instanceData->absDataSize);
+ X = (instanceData->fingerDataBuffer[reg] << 4) & 0x0ff0;
+ X |= (instanceData->fingerDataBuffer[reg+2] & 0x0f);
+ Y = (instanceData->fingerDataBuffer[reg+1] << 4) & 0x0ff0;
+ Y |= ((instanceData->fingerDataBuffer[reg+2] & 0xf0) >> 4) & 0x0f;
+ /* First thing to do is swap axes if needed.
+ */
+ if (instanceData->swap_axes) {
+ int temp = X;
+ X = Y;
+ Y = temp;
+ maxX = instanceData->controlRegisters->sensorMaxYPos;
+ maxY = instanceData->controlRegisters->sensorMaxXPos;
+ }
+ if (instanceData->flipX)
+ X = max(maxX-X, 0);
+ X = X - instanceData->offsetX;
+ X = min(max(X, instanceData->clipXLow), instanceData->clipXHigh);
+ if (instanceData->flipY)
+ Y = max(maxY-Y, 0);
+ Y = Y - instanceData->offsetY;
+ Y = min(max(Y, instanceData->clipYLow), instanceData->clipYHigh);
+
+ /* upper 4 bits of W are Wy,
+ lower 4 of W are Wx */
+ Wy = (instanceData->fingerDataBuffer[reg+3] >> 4) & 0x0f;
+ Wx = instanceData->fingerDataBuffer[reg+3] & 0x0f;
+ if (instanceData->swap_axes) {
+ int temp = Wx;
+ Wx = Wy;
+ Wy = temp;
+ }
+
+ Z = instanceData->fingerDataBuffer[reg+4];
+
+ /* if this is the first finger report normal
+ ABS_X, ABS_Y, PRESSURE, TOOL_WIDTH events for
+ non-MT apps. Apps that support Multi-touch
+ will ignore these events and use the MT events.
+ Apps that don't support Multi-touch will still
+ function.
+ */
+ if (fingerDownCount == 1) {
+ instanceData->oldX = X;
+ instanceData->oldY = Y;
+ input_report_abs(function_device->input, ABS_X, X);
+ input_report_abs(function_device->input, ABS_Y, Y);
+ input_report_abs(function_device->input, ABS_PRESSURE, Z);
+ input_report_abs(function_device->input, ABS_TOOL_WIDTH,
+ max(Wx, Wy));
+
+ } else {
+ /* TODO generate non MT events for multifinger situation. */
+ }
+#ifdef CONFIG_SYNA_MULTI_TOUCH
+ /* Report Multi-Touch events for each finger */
+ input_report_abs(function_device->input,
+ ABS_MT_PRESSURE, Z);
+ input_report_abs(function_device->input, ABS_MT_POSITION_X, X);
+ input_report_abs(function_device->input, ABS_MT_POSITION_Y, Y);
+
+ /* TODO: Tracking ID needs to be reported but not used yet. */
+ /* Could be formed by keeping an id per position and assiging */
+ /* a new id when fingerStatus changes for that position.*/
+ input_report_abs(function_device->input, ABS_MT_TRACKING_ID,
+ finger);
+ /* MT sync between fingers */
+ input_mt_sync(function_device->input);
+#endif
+ }
+ }
+ }
+
+ /* if we had a finger down before and now we don't have any send a button up. */
+ if ((fingerDownCount == 0) && instanceData->wasdown) {
+ instanceData->wasdown = false;
+
+#ifdef CONFIG_SYNA_MULTI_TOUCH
+ input_report_abs(function_device->input, ABS_MT_PRESSURE, 0);
+ input_report_key(function_device->input, BTN_TOUCH, 0);
+ input_mt_sync(function_device->input);
+#endif
+ }
+
+ FN_11_relreport(rmifninfo);
+ input_sync(function_device->input); /* sync after groups of events */
+
+}
+EXPORT_SYMBOL(FN_11_inthandler);
+
+/* This function reads in relative data for first finger and send to input system */
+static void FN_11_relreport(struct rmi_function_info *rmifninfo)
+{
+ struct f11_instance_data *instanceData;
+ struct rmi_function_device *function_device;
+ signed char X, Y;
+ unsigned short fn11DataBaseAddr;
+
+ instanceData = (struct f11_instance_data *) rmifninfo->fndata;
+
+ if (instanceData->sensorInfo->hasRel && instanceData->relReport) {
+ int reg = instanceData->relDataOffset;
+
+ function_device = rmifninfo->function_device;
+
+ fn11DataBaseAddr = rmifninfo->funcDescriptor.dataBaseAddr;
+ /* Read and report Rel data for primary finger one register for X and one for Y*/
+ X = instanceData->fingerDataBuffer[reg];
+ Y = instanceData->fingerDataBuffer[reg+1];
+ if (instanceData->swap_axes) {
+ signed char temp = X;
+ X = Y;
+ Y = temp;
+ }
+ if (instanceData->flipX) {
+ X = -X;
+ }
+ if (instanceData->flipY) {
+ Y = -Y;
+ }
+ X = (signed char) min(127, max(-128, (int) X));
+ Y = (signed char) min(127, max(-128, (int) Y));
+
+ input_report_rel(function_device->input, REL_X, X);
+ input_report_rel(function_device->input, REL_Y, Y);
+ }
+}
+
+int FN_11_config(struct rmi_function_info *rmifninfo)
+{
+ /* For the data source - print info and do any
+ source specific configuration. */
+ unsigned char data[14];
+ int retval = 0;
+
+ pr_debug("%s: RMI4 function $11 config\n", __func__);
+
+ /* Get and print some info about the data source... */
+
+ /* To Query 2D devices we need to read from the address obtained
+ * from the function descriptor stored in the RMI function info.
+ */
+ retval = rmi_read_multiple(rmifninfo->sensor, rmifninfo->funcDescriptor.queryBaseAddr,
+ data, 9);
+ if (retval) {
+ printk(KERN_ERR "%s: RMI4 function $11 config:"
+ "Could not read function query registers 0x%x\n",
+ __func__, rmifninfo->funcDescriptor.queryBaseAddr);
+ } else {
+ pr_debug("%s: Number of Fingers: %d\n",
+ __func__, data[1] & 7);
+ pr_debug("%s: Is Configurable: %d\n",
+ __func__, data[1] & (1 << 7) ? 1 : 0);
+ pr_debug("%s: Has Gestures: %d\n",
+ __func__, data[1] & (1 << 5) ? 1 : 0);
+ pr_debug("%s: Has Absolute: %d\n",
+ __func__, data[1] & (1 << 4) ? 1 : 0);
+ pr_debug("%s: Has Relative: %d\n",
+ __func__, data[1] & (1 << 3) ? 1 : 0);
+
+ pr_debug("%s: Number X Electrodes: %d\n",
+ __func__, data[2] & 0x1f);
+ pr_debug("%s: Number Y Electrodes: %d\n",
+ __func__, data[3] & 0x1f);
+ pr_debug("%s: Maximum Electrodes: %d\n",
+ __func__, data[4] & 0x1f);
+
+ pr_debug("%s: Absolute Data Size: %d\n",
+ __func__, data[5] & 3);
+
+ pr_debug("%s: Has XY Dist: %d\n",
+ __func__, data[7] & (1 << 7) ? 1 : 0);
+ pr_debug("%s: Has Pinch: %d\n",
+ __func__, data[7] & (1 << 6) ? 1 : 0);
+ pr_debug("%s: Has Press: %d\n",
+ __func__, data[7] & (1 << 5) ? 1 : 0);
+ pr_debug("%s: Has Flick: %d\n",
+ __func__, data[7] & (1 << 4) ? 1 : 0);
+ pr_debug("%s: Has Early Tap: %d\n",
+ __func__, data[7] & (1 << 3) ? 1 : 0);
+ pr_debug("%s: Has Double Tap: %d\n",
+ __func__, data[7] & (1 << 2) ? 1 : 0);
+ pr_debug("%s: Has Tap and Hold: %d\n",
+ __func__, data[7] & (1 << 1) ? 1 : 0);
+ pr_debug("%s: Has Tap: %d\n",
+ __func__, data[7] & 1 ? 1 : 0);
+ pr_debug("%s: Has Palm Detect: %d\n",
+ __func__, data[8] & 1 ? 1 : 0);
+ pr_debug("%s: Has Rotate: %d\n",
+ __func__, data[8] & (1 << 1) ? 1 : 0);
+
+ retval = rmi_read_multiple(rmifninfo->sensor,
+ rmifninfo->funcDescriptor.controlBaseAddr, data, 14);
+ if (retval) {
+ printk(KERN_ERR "%s: RMI4 function $11 config:"
+ "Could not read control registers 0x%x\n",
+ __func__, rmifninfo->funcDescriptor.controlBaseAddr);
+ return retval;
+ }
+
+ /* Store these for use later...*/
+ sensorMaxX = ((data[6] & 0x1f) << 8) | ((data[7] & 0xff) << 0);
+ sensorMaxY = ((data[8] & 0x1f) << 8) | ((data[9] & 0xff) << 0);
+
+ pr_debug("%s: Sensor Max X: %d\n", __func__, sensorMaxX);
+ pr_debug("%s: Sensor Max Y: %d\n", __func__, sensorMaxY);
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(FN_11_config);
+
+/* This operation is done in a number of places, so we have a handy routine
+ * for it.
+ */
+static void f11_set_abs_params(struct rmi_function_device *function_device)
+{
+ struct f11_instance_data *instance_data = function_device->rfi->fndata;
+ /* Use the max X and max Y read from the device, or the clip values,
+ * whichever is stricter.
+ */
+ int xMin = instance_data->clipXLow;
+ int xMax = min((int) instance_data->controlRegisters->sensorMaxXPos, instance_data->clipXHigh);
+ int yMin = instance_data->clipYLow;
+ int yMax = min((int) instance_data->controlRegisters->sensorMaxYPos, instance_data->clipYHigh) - instance_data->button_height;
+ if (instance_data->swap_axes) {
+ int temp = xMin;
+ xMin = yMin;
+ yMin = temp;
+ temp = xMax;
+ xMax = yMax;
+ yMax = temp;
+ }
+ printk(KERN_DEBUG "%s: Set ranges X=[%d..%d] Y=[%d..%d].", __func__, xMin, xMax, yMin, yMax);
+ input_set_abs_params(function_device->input, ABS_X, xMin, xMax,
+ 0, 0);
+ input_set_abs_params(function_device->input, ABS_Y, yMin, yMax,
+ 0, 0);
+ input_set_abs_params(function_device->input, ABS_PRESSURE, 0, 255, 0, 0);
+ input_set_abs_params(function_device->input, ABS_TOOL_WIDTH, 0, 15, 0, 0);
+
+#ifdef CONFIG_SYNA_MULTI_TOUCH
+ input_set_abs_params(function_device->input, ABS_MT_PRESSURE,
+ 0, 15, 0, 0);
+ input_set_abs_params(function_device->input, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+ input_set_abs_params(function_device->input, ABS_MT_TRACKING_ID,
+ 0, 10, 0, 0);
+ input_set_abs_params(function_device->input, ABS_MT_POSITION_X, xMin, xMax,
+ 0, 0);
+ input_set_abs_params(function_device->input, ABS_MT_POSITION_Y, yMin, yMax,
+ 0, 0);
+#endif
+}
+
+/* Initialize any function $11 specific params and settings - input
+ * settings, device settings, etc.
+ */
+int FN_11_init(struct rmi_function_device *function_device)
+{
+ struct f11_instance_data *instanceData = function_device->rfi->fndata;
+ int retval = 0;
+ struct rmi_f11_functiondata *functiondata = rmi_sensor_get_functiondata(function_device->sensor, RMI_F11_INDEX);
+ printk(KERN_DEBUG "%s: RMI4 F11 init", __func__);
+
+ /* TODO: Initialize these through some normal kernel mechanism.
+ */
+ instanceData->flipX = false;
+ instanceData->flipY = false;
+ instanceData->swap_axes = false;
+ instanceData->relReport = true;
+ instanceData->offsetX = instanceData->offsetY = 0;
+ instanceData->clipXLow = instanceData->clipYLow = 0;
+ /* TODO: 65536 should actually be the largest valid RMI4 position coordinate */
+ instanceData->clipXHigh = instanceData->clipYHigh = 65536;
+
+ /* Load any overrides that were specified via platform data.
+ */
+ if (functiondata) {
+ printk(KERN_DEBUG "%s: found F11 per function platformdata.", __func__);
+ instanceData->flipX = functiondata->flipX;
+ instanceData->flipY = functiondata->flipY;
+ instanceData->button_height = functiondata->button_height;
+ instanceData->swap_axes = functiondata->swap_axes;
+ if (functiondata->offset) {
+ instanceData->offsetX = functiondata->offset->x;
+ instanceData->offsetY = functiondata->offset->y;
+ }
+ if (functiondata->clipX) {
+ if (functiondata->clipX->min >= functiondata->clipX->max) {
+ printk(KERN_WARNING "%s: Clip X min (%d) >= X clip max (%d) - ignored.",
+ __func__, functiondata->clipX->min, functiondata->clipX->max);
+ } else {
+ instanceData->clipXLow = functiondata->clipX->min;
+ instanceData->clipXHigh = functiondata->clipX->max;
+ }
+ }
+ if (functiondata->clipY) {
+ if (functiondata->clipY->min >= functiondata->clipY->max) {
+ printk(KERN_WARNING "%s: Clip Y min (%d) >= Y clip max (%d) - ignored.",
+ __func__, functiondata->clipY->min, functiondata->clipY->max);
+ } else {
+ instanceData->clipYLow = functiondata->clipY->min;
+ instanceData->clipYHigh = functiondata->clipY->max;
+ }
+ }
+ }
+
+ /* need to init the input abs params for the 2D */
+ set_bit(EV_ABS, function_device->input->evbit);
+ set_bit(EV_SYN, function_device->input->evbit);
+ set_bit(EV_KEY, function_device->input->evbit);
+ set_bit(BTN_TOUCH, function_device->input->keybit);
+ set_bit(KEY_OK, function_device->input->keybit);
+
+ f11_set_abs_params(function_device);
+
+ printk(KERN_DEBUG "%s: Creating sysfs files.", __func__);
+ retval = device_create_file(&function_device->dev, &dev_attr_flip);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create flip.", __func__);
+ return retval;
+ }
+ retval = device_create_file(&function_device->dev, &dev_attr_clip);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create clip.", __func__);
+ return retval;
+ }
+ retval = device_create_file(&function_device->dev, &dev_attr_offset);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create offset.", __func__);
+ return retval;
+ }
+ retval = device_create_file(&function_device->dev, &dev_attr_swap);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create swap.", __func__);
+ return retval;
+ }
+ retval = device_create_file(&function_device->dev, &dev_attr_relreport);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create relreport.", __func__);
+ return retval;
+ }
+ retval = device_create_file(&function_device->dev, &dev_attr_maxPos);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create maxPos.", __func__);
+ return retval;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(FN_11_init);
+
+int FN_11_detect(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr, unsigned int interruptCount)
+{
+ unsigned char fn11Queries[12]; /* TODO: Compute size correctly. */
+ unsigned char fn11Control[12]; /* TODO: Compute size correctly. */
+ int i;
+ unsigned short fn11InterruptOffset;
+ unsigned char fn11AbsDataBlockSize;
+ int fn11HasPinch, fn11HasFlick, fn11HasTap;
+ int fn11HasTapAndHold, fn11HasDoubleTap;
+ int fn11HasEarlyTap, fn11HasPress;
+ int fn11HasPalmDetect, fn11HasRotate;
+ int fn11HasRel;
+ unsigned char f11_egr_0, f11_egr_1;
+ unsigned int fn11AllDataBlockSize;
+ int retval = 0;
+ struct f11_instance_data *instanceData;
+
+ printk(KERN_DEBUG "%s: RMI4 F11 detect\n", __func__);
+
+ instanceData = kzalloc(sizeof(struct f11_instance_data), GFP_KERNEL);
+ if (!instanceData) {
+ printk(KERN_ERR "%s: Error allocating F11 instance data.\n", __func__);
+ return -ENOMEM;
+ }
+ instanceData->deviceInfo = kzalloc(sizeof(struct rmi_F11_device_query), GFP_KERNEL);
+ if (!instanceData->deviceInfo) {
+ printk(KERN_ERR "%s: Error allocating F11 device query.\n", __func__);
+ return -ENOMEM;
+ }
+ instanceData->sensorInfo = kzalloc(sizeof(struct rmi_F11_sensor_query), GFP_KERNEL);
+ if (!instanceData->sensorInfo) {
+ printk(KERN_ERR "%s: Error allocating F11 sensor query.\n", __func__);
+ return -ENOMEM;
+ }
+ rmifninfo->fndata = instanceData;
+
+ /* Store addresses - used elsewhere to read data,
+ * control, query, etc. */
+ rmifninfo->funcDescriptor.queryBaseAddr = fndescr->queryBaseAddr;
+ rmifninfo->funcDescriptor.commandBaseAddr = fndescr->commandBaseAddr;
+ rmifninfo->funcDescriptor.controlBaseAddr = fndescr->controlBaseAddr;
+ rmifninfo->funcDescriptor.dataBaseAddr = fndescr->dataBaseAddr;
+ rmifninfo->funcDescriptor.interruptSrcCnt = fndescr->interruptSrcCnt;
+ rmifninfo->funcDescriptor.functionNum = fndescr->functionNum;
+
+ rmifninfo->numSources = fndescr->interruptSrcCnt;
+
+ /* need to get number of fingers supported, data size, etc. -
+ to be used when getting data since the number of registers to
+ read depends on the number of fingers supported and data size. */
+ retval = rmi_read_multiple(rmifninfo->sensor, fndescr->queryBaseAddr, fn11Queries,
+ sizeof(fn11Queries));
+ if (retval) {
+ printk(KERN_ERR "%s: RMI4 function $11 detect: "
+ "Could not read function query registers 0x%x\n",
+ __func__, rmifninfo->funcDescriptor.queryBaseAddr);
+ return retval;
+ }
+
+ /* Extract device data. */
+ instanceData->deviceInfo->hasQuery9 = (fn11Queries[0] & 0x04) != 0;
+ instanceData->deviceInfo->numberOfSensors = (fn11Queries[0] & 0x07) + 1;
+ printk(KERN_DEBUG "%s: F11 device - %d sensors. Query 9? %d.", __func__, instanceData->deviceInfo->numberOfSensors, instanceData->deviceInfo->hasQuery9);
+
+ /* Extract sensor data. */
+ /* 2D data sources have only 3 bits for the number of fingers
+ supported - so the encoding is a bit wierd. */
+ instanceData->sensorInfo->numberOfFingers = 2; /* default number of fingers supported */
+ if ((fn11Queries[1] & 0x7) <= 4)
+ /* add 1 since zero based */
+ instanceData->sensorInfo->numberOfFingers = (fn11Queries[1] & 0x7) + 1;
+ else {
+ /* a value of 5 is up to 10 fingers - 6 and 7 are reserved
+ (shouldn't get these i int retval;n a normal 2D source). */
+ if ((fn11Queries[1] & 0x7) == 5)
+ instanceData->sensorInfo->numberOfFingers = 10;
+ }
+ instanceData->sensorInfo->configurable = (fn11Queries[1] & 0x80) != 0;
+ instanceData->sensorInfo->hasSensitivityAdjust = (fn11Queries[1] & 0x40) != 0;
+ instanceData->sensorInfo->hasGestures = (fn11Queries[1] & 0x20) != 0;
+ instanceData->sensorInfo->hasAbs = (fn11Queries[1] & 0x10) != 0;
+ instanceData->sensorInfo->hasRel = (fn11Queries[1] & 0x08) != 0;
+ instanceData->sensorInfo->absDataSize = fn11Queries[5] & 0x03;
+ printk(KERN_DEBUG "%s: Number of fingers: %d.", __func__, instanceData->sensorInfo->numberOfFingers);
+
+ /* Need to get interrupt info to be used later when handling
+ interrupts. */
+ rmifninfo->interruptRegister = interruptCount/8;
+
+ /* loop through interrupts for each source in fn $11 and or in a bit
+ to the interrupt mask for each. */
+ fn11InterruptOffset = interruptCount % 8;
+
+ for (i = fn11InterruptOffset;
+ i < ((fndescr->interruptSrcCnt & 0x7) + fn11InterruptOffset);
+ i++)
+ rmifninfo->interruptMask |= 1 << i;
+
+ /* Figure out just how much data we'll need to read. */
+ instanceData->fingerDataBufferSize = (instanceData->sensorInfo->numberOfFingers + 3) / 4;
+ /* One each for X and Y, one for LSB for X & Y, one for W, one for Z */
+ fn11AbsDataBlockSize = 5;
+ if (instanceData->sensorInfo->absDataSize != 0)
+ printk(KERN_WARNING "%s: Unrecognized abs data size %d ignored.", __func__, instanceData->sensorInfo->absDataSize);
+ if (instanceData->sensorInfo->hasAbs) {
+ instanceData->absDataSize = fn11AbsDataBlockSize;
+ instanceData->absDataOffset = instanceData->fingerDataBufferSize;
+ instanceData->fingerDataBufferSize += instanceData->sensorInfo->numberOfFingers * fn11AbsDataBlockSize;
+ }
+ if (instanceData->sensorInfo->hasRel) {
+ instanceData->relDataOffset = ((instanceData->sensorInfo->numberOfFingers + 3) / 4) +
+ /* absolute data, per finger times number of fingers */
+ (fn11AbsDataBlockSize * instanceData->sensorInfo->numberOfFingers);
+ instanceData->fingerDataBufferSize += instanceData->sensorInfo->numberOfFingers * 2;
+ }
+ if (instanceData->sensorInfo->hasGestures) {
+ instanceData->gestureDataOffset = instanceData->fingerDataBufferSize;
+ printk(KERN_WARNING "%s: WARNING Need to correctly compute gesture data location.", __func__);
+ }
+
+ /* need to determine the size of data to read - this depends on
+ conditions such as whether Relative data is reported and if Gesture
+ data is reported. */
+ f11_egr_0 = fn11Queries[7];
+ f11_egr_1 = fn11Queries[8];
+
+ /* Get info about what EGR data is supported, whether it has
+ Relative data supported, etc. */
+ fn11HasPinch = f11_egr_0 & 0x40;
+ fn11HasFlick = f11_egr_0 & 0x10;
+ fn11HasTap = f11_egr_0 & 0x01;
+ fn11HasTapAndHold = f11_egr_0 & 0x02;
+ fn11HasDoubleTap = f11_egr_0 & 0x04;
+ fn11HasEarlyTap = f11_egr_0 & 0x08;
+ fn11HasPress = f11_egr_0 & 0x20;
+ fn11HasPalmDetect = f11_egr_1 & 0x01;
+ fn11HasRotate = f11_egr_1 & 0x02;
+ fn11HasRel = fn11Queries[1] & 0x08;
+
+ /* Size of all data including finger status, absolute data for each
+ finger, relative data and EGR data */
+ fn11AllDataBlockSize =
+ /* finger status, four fingers per register */
+ ((instanceData->sensorInfo->numberOfFingers + 3) / 4) +
+ /* absolute data, per finger times number of fingers */
+ (fn11AbsDataBlockSize * instanceData->sensorInfo->numberOfFingers) +
+ /* two relative registers (if relative is being reported) */
+ 2 * fn11HasRel +
+ /* F11_2D_Data8 is only present if the egr_0
+ register is non-zero. */
+ !!(f11_egr_0) +
+ /* F11_2D_Data9 is only present if either egr_0 or
+ egr_1 registers are non-zero. */
+ (f11_egr_0 || f11_egr_1) +
+ /* F11_2D_Data10 is only present if EGR_PINCH or EGR_FLICK of
+ egr_0 reports as 1. */
+ !!(fn11HasPinch | fn11HasFlick) +
+ /* F11_2D_Data11 and F11_2D_Data12 are only present if
+ EGR_FLICK of egr_0 reports as 1. */
+ 2 * !!(fn11HasFlick);
+ instanceData->fingerDataBuffer = kcalloc(instanceData->fingerDataBufferSize, sizeof(unsigned char), GFP_KERNEL);
+ if (!instanceData->fingerDataBuffer) {
+ printk(KERN_ERR "%s: Failed to allocate finger data buffer.", __func__);
+ return -ENOMEM;
+ }
+
+ /* Grab a copy of the control registers. */
+ instanceData->controlRegisters = kzalloc(sizeof(struct rmi_F11_control), GFP_KERNEL);
+ if (!instanceData->controlRegisters) {
+ printk(KERN_ERR "%s: Error allocating F11 control registers.\n", __func__);
+ return -ENOMEM;
+ }
+ retval = rmi_read_multiple(rmifninfo->sensor, fndescr->controlBaseAddr,
+ fn11Control, sizeof(fn11Control));
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to read F11 control registers.", __func__);
+ return retval;
+ }
+ instanceData->controlRegisters->sensorMaxXPos = (((int) fn11Control[7] & 0x0F) << 8) + fn11Control[6];
+ instanceData->controlRegisters->sensorMaxYPos = (((int) fn11Control[9] & 0x0F) << 8) + fn11Control[8];
+ printk(KERN_DEBUG "%s: Max X %d Max Y %d", __func__, instanceData->controlRegisters->sensorMaxXPos, instanceData->controlRegisters->sensorMaxYPos);
+ return 0;
+}
+EXPORT_SYMBOL(FN_11_detect);
+
+static ssize_t rmi_fn_11_maxPos_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u %u\n", instance_data->controlRegisters->sensorMaxXPos, instance_data->controlRegisters->sensorMaxYPos);
+}
+
+static ssize_t rmi_fn_11_maxPos_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ return -EPERM;
+}
+
+static ssize_t rmi_fn_11_flip_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u %u\n", instance_data->flipX, instance_data->flipY);
+}
+
+static ssize_t rmi_fn_11_flip_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
+ unsigned int newX, newY;
+
+ printk(KERN_DEBUG "%s: Flip set to %s", __func__, buf);
+
+ if (sscanf(buf, "%u %u", &newX, &newY) != 2)
+ return -EINVAL;
+ if (newX < 0 || newX > 1 || newY < 0 || newY > 1)
+ return -EINVAL;
+ instance_data->flipX = newX;
+ instance_data->flipY = newY;
+
+ return count;
+}
+
+static ssize_t rmi_fn_11_swap_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u\n", instance_data->swap_axes);
+}
+
+static ssize_t rmi_fn_11_swap_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
+ unsigned int newSwap;
+
+ printk(KERN_DEBUG "%s: Swap set to %s", __func__, buf);
+
+ if (sscanf(buf, "%u", &newSwap) != 1)
+ return -EINVAL;
+ if (newSwap < 0 || newSwap > 1)
+ return -EINVAL;
+ instance_data->swap_axes = newSwap;
+
+ f11_set_abs_params(fn);
+
+ return count;
+}
+
+static ssize_t rmi_fn_11_relreport_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u \n", instance_data->relReport);
+}
+
+static ssize_t rmi_fn_11_relreport_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
+ unsigned int relRep;
+
+ printk(KERN_DEBUG "%s: relReport set to %s", __func__, buf);
+ if (sscanf(buf, "%u", &relRep) != 1)
+ return -EINVAL;
+ if (relRep < 0 || relRep > 1)
+ return -EINVAL;
+ instance_data->relReport = relRep;
+
+ return count;
+}
+
+static ssize_t rmi_fn_11_offset_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%d %d\n", instance_data->offsetX, instance_data->offsetY);
+}
+
+static ssize_t rmi_fn_11_offset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
+ int newX, newY;
+
+ printk(KERN_DEBUG "%s: Offset set to %s", __func__, buf);
+
+ if (sscanf(buf, "%d %d", &newX, &newY) != 2)
+ return -EINVAL;
+ instance_data->offsetX = newX;
+ instance_data->offsetY = newY;
+
+ return count;
+}
+
+static ssize_t rmi_fn_11_clip_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u %u %u %u\n",
+ instance_data->clipXLow, instance_data->clipXHigh,
+ instance_data->clipYLow, instance_data->clipYHigh);
+}
+
+static ssize_t rmi_fn_11_clip_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f11_instance_data *instance_data = (struct f11_instance_data *)fn->rfi->fndata;
+ unsigned int newXLow, newXHigh, newYLow, newYHigh;
+
+ printk(KERN_DEBUG "%s: Clip set to %s", __func__, buf);
+
+ if (sscanf(buf, "%u %u %u %u", &newXLow, &newXHigh, &newYLow, &newYHigh) != 4)
+ return -EINVAL;
+ if (newXLow < 0 || newXLow >= newXHigh || newYLow < 0 || newYLow >= newYHigh)
+ return -EINVAL;
+ instance_data->clipXLow = newXLow;
+ instance_data->clipXHigh = newXHigh;
+ instance_data->clipYLow = newYLow;
+ instance_data->clipYHigh = newYHigh;
+
+ f11_set_abs_params(fn);
+
+ return count;
+}
diff --git a/drivers/input/touchscreen/synaptics/rmi_f11.h b/drivers/input/touchscreen/synaptics/rmi_f11.h
new file mode 100644
index 0000000..0bf386a
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_f11.h
@@ -0,0 +1,43 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $11 header.
+ * Copyright (c) 2007 - 2010, Synaptics Incorporated
+ *
+ * For every RMI4 function that has a data source - like 2D sensors,
+ * buttons, LEDs, GPIOs, etc. - the user will create a new rmi_function_xx.c
+ * file and add these functions to perform the config(), init(), report()
+ * and detect() functionality. The function pointers are then srored under
+ * the RMI function info and these functions will automatically be called by
+ * the global config(), init(), report() and detect() functions that will
+ * loop through all data sources and call the data sources functions using
+ * these functions pointed to by the function ptrs.
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+#ifndef _RMI_FUNCTION_11_H
+#define _RMI_FUNCTION_11_H
+
+void FN_11_inthandler(struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs);
+int FN_11_config(struct rmi_function_info *rmifninfo);
+int FN_11_init(struct rmi_function_device *function_device);
+int FN_11_detect(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr,
+ unsigned int interruptCount);
+/* No attention function for Fn $11 */
+#endif
diff --git a/drivers/input/touchscreen/synaptics/rmi_f19.c b/drivers/input/touchscreen/synaptics/rmi_f19.c
new file mode 100644
index 0000000..7bb8712
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_f19.c
@@ -0,0 +1,514 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $11 support for 2D.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/input/rmi_platformdata.h>
+#include <linux/module.h>
+
+#include "rmi.h"
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f19.h"
+
+struct f19_instance_data {
+ struct rmi_F19_query *deviceInfo;
+ struct rmi_F19_control *controlRegisters;
+ bool *buttonDown;
+ unsigned char buttonDataBufferSize;
+ unsigned char *buttonDataBuffer;
+ unsigned char *buttonMap;
+ int fn19ControlRegisterSize;
+ int fn19regCountForBitPerButton;
+ int fn19btnUsageandfilterModeOffset;
+ int fn19intEnableOffset;
+ int fn19intEnableLen;
+ int fn19singleBtnCtrlLen;
+ int fn19singleBtnCtrlOffset;
+ int fn19sensorMapCtrlOffset;
+ int fn19sensorMapCtrlLen;
+ int fn19singleBtnSensOffset;
+ int fn19singleBtnSensLen;
+ int fn19globalSensOffset;
+ int fn19globalHystThreshOffset;
+};
+
+static ssize_t rmi_f19_buttonCount_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f19_buttonCount_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(buttonCount, 0444, rmi_f19_buttonCount_show, rmi_f19_buttonCount_store); /* RO attr */
+
+static ssize_t rmi_f19_buttonMap_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f19_buttonMap_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+DEVICE_ATTR(buttonMap, 0664, rmi_f19_buttonMap_show, rmi_f19_buttonMap_store); /* RW attr */
+
+
+/*
+ * There is no attention function for F19 - it is left NULL
+ * in the function table so it is not called.
+ *
+ */
+
+
+/*
+ * This reads in a sample and reports the F19 source data to the
+ * input subsystem. It is used for both polling and interrupt driven
+ * operation. This is called a lot so don't put in any informational
+ * printks since they will slow things way down!
+ */
+void FN_19_inthandler(struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs)
+{
+ struct rmi_function_device *function_device;
+ struct f19_instance_data *instanceData;
+ int button;
+
+ instanceData = (struct f19_instance_data *) rmifninfo->fndata;
+
+ function_device = rmifninfo->function_device;
+
+ /* Read the button data. */
+
+ if (rmi_read_multiple(rmifninfo->sensor, rmifninfo->funcDescriptor.dataBaseAddr,
+ instanceData->buttonDataBuffer, instanceData->buttonDataBufferSize)) {
+ printk(KERN_ERR "%s: Failed to read button data registers.\n", __func__);
+ return;
+ }
+
+ /* Generate events for buttons that change state. */
+ for (button = 0; button < instanceData->deviceInfo->buttonCount; button++) {
+ int buttonReg;
+ int buttonShift;
+ bool buttonStatus;
+
+ /* determine which data byte the button status is in */
+ buttonReg = button/4;
+ /* bit shift to get button's status */
+ buttonShift = button % 8;
+ buttonStatus = ((instanceData->buttonDataBuffer[buttonReg] >> buttonShift) & 0x01) != 0;
+
+ /* if the button state changed from the last time report it and store the new state */
+ if (buttonStatus != instanceData->buttonDown[button]) {
+ printk(KERN_DEBUG "%s: Button %d (code %d) -> %d.", __func__, button, instanceData->buttonMap[button], buttonStatus);
+ /* Generate an event here. */
+ input_report_key(function_device->input,
+ instanceData->buttonMap[button], buttonStatus);
+ instanceData->buttonDown[button] = buttonStatus;
+ }
+ }
+
+ input_sync(function_device->input); /* sync after groups of events */
+}
+EXPORT_SYMBOL(FN_19_inthandler);
+
+int FN_19_config(struct rmi_function_info *rmifninfo)
+{
+ int retval = 0;
+
+ pr_debug("%s: RMI4 F19 config\n", __func__);
+
+ /* TODO: Perform configuration. In particular, write any cached control
+ * register values to the device. */
+
+ return retval;
+}
+EXPORT_SYMBOL(FN_19_config);
+
+/* Initialize any F19 specific params and settings - input
+ * settings, device settings, etc.
+ */
+int FN_19_init(struct rmi_function_device *function_device)
+{
+ int i, retval = 0;
+ struct f19_instance_data *instance_data = function_device->rfi->fndata;
+ struct rmi_f19_functiondata *functiondata = rmi_sensor_get_functiondata(function_device->sensor, RMI_F19_INDEX);
+
+ printk(KERN_DEBUG "%s: RMI4 F19 init\n", __func__);
+
+ if (functiondata) {
+ if (functiondata->button_map) {
+ if (functiondata->button_map->nbuttons != instance_data->deviceInfo->buttonCount) {
+ printk(KERN_WARNING "%s: Platformdata button map size (%d) != number of buttons on device (%d) - ignored.", __func__, functiondata->button_map->nbuttons, instance_data->deviceInfo->buttonCount);
+ } else if (!functiondata->button_map->map) {
+ printk(KERN_WARNING "%s: Platformdata button map is missing!", __func__);
+ } else {
+ for (i = 0; i < functiondata->button_map->nbuttons; i++)
+ instance_data->buttonMap[i] = functiondata->button_map->map[i];
+ }
+ }
+ }
+
+ /* Set up any input events. */
+ set_bit(EV_SYN, function_device->input->evbit);
+ set_bit(EV_KEY, function_device->input->evbit);
+ /* set bits for each button...*/
+ for (i = 0; i < instance_data->deviceInfo->buttonCount; i++) {
+ set_bit(instance_data->buttonMap[i], function_device->input->keybit);
+ }
+
+ printk(KERN_DEBUG "%s: Creating sysfs files.", __func__);
+ retval = device_create_file(&function_device->dev, &dev_attr_buttonCount);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create button count.", __func__);
+ return retval;
+ }
+
+ retval = device_create_file(&function_device->dev, &dev_attr_buttonMap);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to create button map.", __func__);
+ return retval;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(FN_19_init);
+
+static int getControlRegisters(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr)
+{
+ struct f19_instance_data *instanceData;
+ unsigned char *fn19Control = NULL;
+ int retval = 0;
+
+ /* Get the instance data - it should have been allocated and stored in detect.*/
+ instanceData = rmifninfo->fndata;
+
+ /* Check to make sure instanceData is really there before using.*/
+ if (!instanceData) {
+ printk(KERN_ERR "%s: Error - instance data not initialized yet when getting fn19 control registers.\n", __func__);
+ return -EINVAL;
+ }
+
+ /* Allocate memory for the control registers. */
+ instanceData->controlRegisters = kzalloc(sizeof(struct rmi_F19_control), GFP_KERNEL);
+ if (!instanceData->controlRegisters) {
+ printk(KERN_ERR "%s: Error allocating F19 control registers.\n", __func__);
+ return -ENOMEM;
+ }
+
+ instanceData->fn19regCountForBitPerButton = (instanceData->deviceInfo->buttonCount + 7)/8;
+
+ /* Need to compute the amount of data to read since it varies with the
+ * number of buttons */
+ instanceData->fn19ControlRegisterSize = 1 /* 1 for filter mode and button usage bits */
+ + 2*instanceData->fn19regCountForBitPerButton /* interrupt enable bits and single button participation bits */
+ + 2*instanceData->deviceInfo->buttonCount /* sensormap registers + single button sensitivity registers */
+ + 2; /* 1 for global sensitivity adjust + 1 for global hysteresis threshold */
+
+ /* Allocate a temp memory buffer to read the control registers into */
+ fn19Control = kzalloc(instanceData->fn19ControlRegisterSize, GFP_KERNEL);
+ if (!fn19Control) {
+ printk(KERN_ERR "%s: Error allocating temp storage to read fn19 control info.\n", __func__);
+ return -ENOMEM;
+ }
+
+ /* Grab a copy of the control registers. */
+ retval = rmi_read_multiple(rmifninfo->sensor, fndescr->controlBaseAddr,
+ fn19Control, instanceData->fn19ControlRegisterSize);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed to read F19 control registers.", __func__);
+ return retval;
+ }
+
+ /* Copy over control registers data to the instance data */
+ instanceData->fn19btnUsageandfilterModeOffset = 0;
+ instanceData->controlRegisters->buttonUsage = fn19Control[instanceData->fn19btnUsageandfilterModeOffset] & 0x3;
+ instanceData->controlRegisters->filterMode = fn19Control[instanceData->fn19btnUsageandfilterModeOffset] & 0xc;
+
+ /* Fill in interrupt enable registers */
+ instanceData->fn19intEnableOffset = 1;
+ instanceData->fn19intEnableLen = instanceData->fn19regCountForBitPerButton;
+ instanceData->controlRegisters->intEnableRegisters = kzalloc(instanceData->fn19intEnableLen, GFP_KERNEL);
+ if (!instanceData->controlRegisters->intEnableRegisters) {
+ printk(KERN_ERR "%s: Error allocating storage for interrupt enable control info.\n", __func__);
+ return -ENOMEM;
+ }
+ memcpy(instanceData->controlRegisters->intEnableRegisters, &fn19Control[instanceData->fn19intEnableOffset],
+ instanceData->fn19intEnableLen);
+
+ /* Fill in single button control registers */
+ instanceData->fn19singleBtnCtrlOffset = instanceData->fn19intEnableOffset + instanceData->fn19intEnableLen;
+ instanceData->fn19singleBtnCtrlLen = instanceData->fn19regCountForBitPerButton;
+ instanceData->controlRegisters->singleButtonControl = kzalloc(instanceData->fn19singleBtnCtrlLen, GFP_KERNEL);
+ if (!instanceData->controlRegisters->singleButtonControl) {
+ printk(KERN_ERR "%s: Error allocating storage for single button participation control info.\n", __func__);
+ return -ENOMEM;
+ }
+ memcpy(instanceData->controlRegisters->singleButtonControl, &fn19Control[instanceData->fn19singleBtnCtrlOffset],
+ instanceData->fn19singleBtnCtrlLen);
+
+ /* Fill in sensor map registers */
+ instanceData->fn19sensorMapCtrlOffset = instanceData->fn19singleBtnCtrlOffset + instanceData->fn19singleBtnCtrlLen;
+ instanceData->fn19sensorMapCtrlLen = instanceData->deviceInfo->buttonCount;
+ instanceData->controlRegisters->sensorMap = kzalloc(instanceData->fn19sensorMapCtrlLen, GFP_KERNEL);
+ if (!instanceData->controlRegisters->sensorMap) {
+ printk(KERN_ERR "%s: Error allocating storage for sensor map control info.\n", __func__);
+ return -ENOMEM;
+ }
+ memcpy(instanceData->controlRegisters->sensorMap, &fn19Control[instanceData->fn19sensorMapCtrlOffset],
+ instanceData->fn19sensorMapCtrlLen);
+
+ /* Fill in single button sensitivity registers */
+ instanceData->fn19singleBtnSensOffset = instanceData->fn19sensorMapCtrlOffset + instanceData->fn19sensorMapCtrlLen;
+ instanceData->fn19singleBtnSensLen = instanceData->deviceInfo->buttonCount;
+ instanceData->controlRegisters->singleButtonSensitivity = kzalloc(instanceData->fn19singleBtnSensLen, GFP_KERNEL);
+ if (!instanceData->controlRegisters->intEnableRegisters) {
+ printk(KERN_ERR "%s: Error allocating storage for single button sensitivity control info.\n", __func__);
+ return -ENOMEM;
+ }
+ memcpy(instanceData->controlRegisters->singleButtonSensitivity, &fn19Control[instanceData->fn19singleBtnSensOffset],
+ instanceData->fn19singleBtnSensLen);
+
+ /* Fill in global sensitivity adjustment and global hysteresis threshold values */
+ instanceData->fn19globalSensOffset = instanceData->fn19singleBtnSensOffset + instanceData->fn19singleBtnSensLen;
+ instanceData->fn19globalHystThreshOffset = instanceData->fn19globalSensOffset + 1;
+ instanceData->controlRegisters->globalSensitivityAdjustment = fn19Control[instanceData->fn19globalSensOffset] & 0x1f;
+ instanceData->controlRegisters->globalHysteresisThreshold = fn19Control[instanceData->fn19globalHystThreshOffset] & 0x0f;
+
+ /* Free up temp storage that held copy of control registers */
+ kfree(fn19Control);
+
+ return 0;
+}
+
+int FN_19_detect(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr, unsigned int interruptCount)
+{
+ unsigned char fn19queries[2];
+ int retval = 0;
+ int i;
+ struct f19_instance_data *instanceData;
+ int fn19InterruptOffset;
+
+ printk(KERN_DEBUG "%s: RMI4 F19 detect\n", __func__);
+
+ instanceData = kzalloc(sizeof(struct f19_instance_data), GFP_KERNEL);
+ if (!instanceData) {
+ printk(KERN_ERR "%s: Error allocating F19 instance data.\n", __func__);
+ return -ENOMEM;
+ }
+ instanceData->deviceInfo = kzalloc(sizeof(struct rmi_F19_query), GFP_KERNEL);
+ if (!instanceData->deviceInfo) {
+ printk(KERN_ERR "%s: Error allocating F19 device query.\n", __func__);
+ return -ENOMEM;
+ }
+ rmifninfo->fndata = instanceData;
+
+ /* Store addresses - used elsewhere to read data,
+ * control, query, etc. */
+ rmifninfo->funcDescriptor.queryBaseAddr = fndescr->queryBaseAddr;
+ rmifninfo->funcDescriptor.commandBaseAddr = fndescr->commandBaseAddr;
+ rmifninfo->funcDescriptor.controlBaseAddr = fndescr->controlBaseAddr;
+ rmifninfo->funcDescriptor.dataBaseAddr = fndescr->dataBaseAddr;
+ rmifninfo->funcDescriptor.interruptSrcCnt = fndescr->interruptSrcCnt;
+ rmifninfo->funcDescriptor.functionNum = fndescr->functionNum;
+
+ rmifninfo->numSources = fndescr->interruptSrcCnt;
+
+ /* need to get number of fingers supported, data size, etc. -
+ to be used when getting data since the number of registers to
+ read depends on the number of fingers supported and data size. */
+ retval = rmi_read_multiple(rmifninfo->sensor, fndescr->queryBaseAddr, fn19queries,
+ sizeof(fn19queries));
+ if (retval) {
+ printk(KERN_ERR "%s: RMI4 F19 detect: "
+ "Could not read function query registers 0x%x\n",
+ __func__, rmifninfo->funcDescriptor.queryBaseAddr);
+ return retval;
+ }
+
+ /* Extract device data. */
+ instanceData->deviceInfo->configurable = fn19queries[0] & 0x01;
+ instanceData->deviceInfo->hasSensitivityAdjust = fn19queries[0] & 0x02;
+ instanceData->deviceInfo->hasHysteresisThreshold = fn19queries[0] & 0x04;
+ instanceData->deviceInfo->buttonCount = fn19queries[1] & 0x01F;
+ printk(KERN_DEBUG "%s: F19 device - %d buttons...", __func__, instanceData->deviceInfo->buttonCount);
+
+ /* Need to get interrupt info to be used later when handling
+ interrupts. */
+ rmifninfo->interruptRegister = interruptCount/8;
+
+ /* loop through interrupts for each source in fn $11 and or in a bit
+ to the interrupt mask for each. */
+ fn19InterruptOffset = interruptCount % 8;
+
+ for (i = fn19InterruptOffset;
+ i < ((fndescr->interruptSrcCnt & 0x7) + fn19InterruptOffset);
+ i++)
+ rmifninfo->interruptMask |= 1 << i;
+
+ /* Figure out just how much data we'll need to read. */
+ instanceData->buttonDown = kcalloc(instanceData->deviceInfo->buttonCount, sizeof(bool), GFP_KERNEL);
+ if (!instanceData->buttonDown) {
+ printk(KERN_ERR "%s: Error allocating F19 button state buffer.\n", __func__);
+ return -ENOMEM;
+ }
+
+ instanceData->buttonDataBufferSize = (instanceData->deviceInfo->buttonCount + 7) / 8;
+ instanceData->buttonDataBuffer = kcalloc(instanceData->buttonDataBufferSize, sizeof(unsigned char), GFP_KERNEL);
+ if (!instanceData->buttonDataBuffer) {
+ printk(KERN_ERR "%s: Failed to allocate button data buffer.", __func__);
+ return -ENOMEM;
+ }
+
+ instanceData->buttonMap = kcalloc(instanceData->deviceInfo->buttonCount, sizeof(unsigned char), GFP_KERNEL);
+ if (!instanceData->buttonMap) {
+ printk(KERN_ERR "%s: Error allocating F19 button map.\n", __func__);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < instanceData->deviceInfo->buttonCount; i++)
+ instanceData->buttonMap[i] = BTN_0 + i; /* default values */
+
+ /* Grab the control register info. */
+ retval = getControlRegisters(rmifninfo, fndescr);
+ if (retval) {
+ printk(KERN_ERR "%s: Error %d getting fn19 control register info.\n", __func__, retval);
+ return retval;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(FN_19_detect);
+
+static ssize_t rmi_f19_buttonCount_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f19_instance_data *instance_data = (struct f19_instance_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u\n", instance_data->deviceInfo->buttonCount);
+}
+
+static ssize_t rmi_f19_buttonCount_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ /* Not allowed. */
+ return -EPERM;
+}
+
+static ssize_t rmi_f19_buttonMap_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f19_instance_data *instance_data = (struct f19_instance_data *)fn->rfi->fndata;
+ int i, len, totalLen = 0;
+
+ /* loop through each button map value and copy it's string representation into buf */
+ for (i = 0; i < instance_data->deviceInfo->buttonCount; i++) {
+ /* get next button mapping value and write it to buf */
+ len = sprintf(buf, "%u ", instance_data->buttonMap[i]);
+ /* bump up ptr to next location in buf if the sprintf was valid */
+ if (len > 0) {
+ buf += len;
+ totalLen += len;
+ }
+ }
+
+ return totalLen;
+}
+
+static ssize_t rmi_f19_buttonMap_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct f19_instance_data *instance_data = (struct f19_instance_data *)fn->rfi->fndata;
+ unsigned int button;
+ int i;
+ int retval = count;
+ int buttonCount = 0;
+ unsigned char *tmpButtonMap;
+
+ /* Do validation on the button map data passed in. */
+ /* Store button mappings into a temp buffer and then verify button count
+ and data prior to clearing out old button mappings and storing the new ones. */
+ tmpButtonMap = kzalloc(instance_data->deviceInfo->buttonCount, GFP_KERNEL);
+ if (!tmpButtonMap) {
+ printk(KERN_ERR "%s: Error allocating temp button map.\n", __func__);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < instance_data->deviceInfo->buttonCount && *buf != 0; i++) {
+ /* get next button mapping value and store and bump up to point to next item in buf */
+ sscanf(buf, "%u", &button);
+
+ /* Make sure the key is a valid key */
+ if (button > KEY_MAX) {
+ printk(KERN_ERR "%s: Error - button map for button %d is not a valid value 0x%x.\n",
+ __func__, i, button);
+ retval = -EINVAL;
+ goto err_ret;
+ }
+
+ tmpButtonMap[i] = button;
+ buttonCount++;
+
+ /* bump up buf to point to next item to read */
+ while (*buf != 0) {
+ buf++;
+ if (*(buf-1) == ' ')
+ break;
+ }
+ }
+
+ /* Make sure the button count matches */
+ if (buttonCount != instance_data->deviceInfo->buttonCount) {
+ printk(KERN_ERR "%s: Error - button map count of %d doesn't match device button count of %d.\n"
+ , __func__, buttonCount, instance_data->deviceInfo->buttonCount);
+ retval = -EINVAL;
+ goto err_ret;
+ }
+
+ /* Clear out old buttonMap data */
+ memset(instance_data->buttonMap, 0, buttonCount);
+
+ /* Loop through the temp buffer and copy the button event and set the key bit for the new mapping. */
+ for (i = 0; i < buttonCount; i++) {
+ instance_data->buttonMap[i] = tmpButtonMap[1];
+ set_bit(instance_data->buttonMap[i], fn->input->keybit);
+ }
+
+err_ret:
+ kfree(tmpButtonMap);
+
+ return retval;
+}
diff --git a/drivers/input/touchscreen/synaptics/rmi_f19.h b/drivers/input/touchscreen/synaptics/rmi_f19.h
new file mode 100644
index 0000000..41f3e4d
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_f19.h
@@ -0,0 +1,43 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $11 header.
+ * Copyright (c) 2007 - 2010, Synaptics Incorporated
+ *
+ * For every RMI4 function that has a data source - like 2D sensors,
+ * buttons, LEDs, GPIOs, etc. - the user will create a new rmi_function_xx.c
+ * file and add these functions to perform the config(), init(), report()
+ * and detect() functionality. The function pointers are then srored under
+ * the RMI function info and these functions will automatically be called by
+ * the global config(), init(), report() and detect() functions that will
+ * loop through all data sources and call the data sources functions using
+ * these functions pointed to by the function ptrs.
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+#ifndef _RMI_FUNCTION_19_H
+#define _RMI_FUNCTION_19_H
+
+void FN_19_inthandler(struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs);
+int FN_19_config(struct rmi_function_info *rmifninfo);
+int FN_19_init(struct rmi_function_device *function_device);
+int FN_19_detect(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr,
+ unsigned int interruptCount);
+/* No attention function for Fn $19 */
+#endif
diff --git a/drivers/input/touchscreen/synaptics/rmi_f34.c b/drivers/input/touchscreen/synaptics/rmi_f34.c
new file mode 100644
index 0000000..26b6389
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_f34.c
@@ -0,0 +1,557 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $34 support for sensor
+ * firmware reflashing.
+ *
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/sysfs.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_function.h"
+#include "rmi_f34.h"
+
+/* data specific to fn $34 that needs to be kept around */
+struct rmi_fn_34_data {
+ unsigned char status;
+ unsigned char cmd;
+ unsigned short bootloaderid;
+ unsigned short blocksize;
+};
+
+
+static ssize_t rmi_fn_34_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_34_status_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+
+static ssize_t rmi_fn_34_cmd_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_34_cmd_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+static ssize_t rmi_fn_34_data_read(struct file *,
+ struct kobject *kobj,
+ struct bin_attribute *attributes,
+ char *buf, loff_t pos, size_t count);
+
+static ssize_t rmi_fn_34_data_write(struct file *,
+ struct kobject *kobj,
+ struct bin_attribute *attributes,
+ char *buf, loff_t pos, size_t count);
+
+static ssize_t rmi_fn_34_bootloaderid_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_34_bootloaderid_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+static ssize_t rmi_fn_34_blocksize_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_fn_34_blocksize_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+/* define the device attributes using DEVICE_ATTR macros */
+DEVICE_ATTR(status, 0444, rmi_fn_34_status_show, rmi_fn_34_status_store); /* RO attr */
+DEVICE_ATTR(cmd, 0664, rmi_fn_34_cmd_show, rmi_fn_34_cmd_store); /* RW attr */
+DEVICE_ATTR(bootloaderid, 0644, rmi_fn_34_bootloaderid_show, rmi_fn_34_bootloaderid_store); /* RW attr */
+DEVICE_ATTR(blocksize, 0444, rmi_fn_34_blocksize_show, rmi_fn_34_blocksize_store); /* RO attr */
+
+
+struct bin_attribute dev_attr_data = {
+ .attr = {
+ .name = "data",
+ .mode = 0644
+ },
+ .size = 0,
+ .read = rmi_fn_34_data_read,
+ .write = rmi_fn_34_data_write,
+};
+
+/* Helper fn to convert from processor specific data to our firmware specific endianness.
+ * TODO: Should we use ntohs or something like that?
+ */
+void copyEndianAgnostic(unsigned char *dest, unsigned short src)
+{
+ dest[0] = src%0x100;
+ dest[1] = src/0x100;
+}
+
+/*.
+ * The interrupt handler for Fn $34.
+ */
+void FN_34_inthandler(struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs)
+{
+ unsigned int status;
+ struct rmi_fn_34_data *fn34data = (struct rmi_fn_34_data *)rmifninfo->fndata;
+
+ /* Read the Fn $34 status register to see whether the previous command executed OK */
+ /* inform user space - through a sysfs param. */
+ if (rmi_read_multiple(rmifninfo->sensor, rmifninfo->funcDescriptor.dataBaseAddr+3,
+ (unsigned char *)&status, 1)) {
+ printk(KERN_ERR "%s : Could not read status from 0x%x\n",
+ __func__, rmifninfo->funcDescriptor.dataBaseAddr+3);
+ status = 0xff; /* failure */
+ }
+
+ /* set a sysfs value that the user mode can read - only upper 4 bits are the status */
+ fn34data->status = status & 0xf0; /* successful is $80, anything else is failure */
+}
+EXPORT_SYMBOL(FN_34_inthandler);
+
+void FN_34_attention(struct rmi_function_info *rmifninfo)
+{
+
+}
+EXPORT_SYMBOL(FN_34_attention);
+
+int FN_34_config(struct rmi_function_info *rmifninfo)
+{
+ pr_debug("%s: RMI4 function $34 config\n", __func__);
+ return 0;
+}
+EXPORT_SYMBOL(FN_34_config);
+
+
+int FN_34_init(struct rmi_function_device *function_device)
+{
+ int retval = 0;
+ unsigned char uData[2];
+ struct rmi_function_info *rmifninfo = function_device->rfi;
+ struct rmi_fn_34_data *fn34data;
+
+ pr_debug("%s: RMI4 function $34 init\n", __func__);
+
+ /* Here we will need to set up sysfs files for Bootloader ID and Block size */
+ fn34data = kzalloc(sizeof(struct rmi_fn_34_data), GFP_KERNEL);
+ if (!fn34data) {
+ printk(KERN_ERR "%s: Error allocating memeory for rmi_fn_34_data.\n", __func__);
+ return -ENOMEM;
+ }
+ rmifninfo->fndata = (void *)fn34data;
+
+ /* set up sysfs file for Bootloader ID. */
+ if (sysfs_create_file(&function_device->dev.kobj, &dev_attr_bootloaderid.attr) < 0) {
+ printk(KERN_ERR "%s: Failed to create sysfs file for fn 34 bootloaderid.\n", __func__);
+ return -ENODEV;
+ }
+
+ /* set up sysfs file for Block Size. */
+ if (sysfs_create_file(&function_device->dev.kobj, &dev_attr_blocksize.attr) < 0) {
+ printk(KERN_ERR "%s: Failed to create sysfs file for fn 34 blocksize.\n", __func__);
+ return -ENODEV;
+ }
+
+ /* get the Bootloader ID and Block Size and store in the sysfs attributes. */
+ retval = rmi_read_multiple(rmifninfo->sensor, rmifninfo->funcDescriptor.queryBaseAddr,
+ uData, 2);
+ if (retval) {
+ printk(KERN_ERR "%s : Could not read bootloaderid from 0x%x\n",
+ __func__, function_device->function->functionQueryBaseAddr);
+ return retval;
+ }
+ /* need to convert from our firmware storage to processore specific data */
+ fn34data->bootloaderid = (unsigned int)uData[0] + (unsigned int)uData[1]*0x100;
+
+ retval = rmi_read_multiple(rmifninfo->sensor, rmifninfo->funcDescriptor.queryBaseAddr+3,
+ uData, 2);
+ if (retval) {
+ printk(KERN_ERR "%s : Could not read block size from 0x%x\n",
+ __func__, rmifninfo->funcDescriptor.queryBaseAddr+3);
+ return retval;
+ }
+ /* need to convert from our firmware storage to processor specific data */
+ fn34data->blocksize = (unsigned int)uData[0] + (unsigned int)uData[1]*0x100;
+
+ /* set up sysfs file for status. */
+ if (sysfs_create_file(&function_device->dev.kobj, &dev_attr_status.attr) < 0) {
+ printk(KERN_ERR "%s: Failed to create sysfs file for fn 34 status.\n", __func__);
+ return -ENODEV;
+ }
+
+ /* Also, sysfs will need to have a file set up to distinguish between commands - like
+ Config write/read, Image write/verify.*/
+ /* set up sysfs file for command code. */
+ if (sysfs_create_file(&function_device->dev.kobj, &dev_attr_cmd.attr) < 0) {
+ printk(KERN_ERR "%s: Failed to create sysfs file for fn 34 cmd.\n", __func__);
+ return -ENODEV;
+ }
+
+ /* We will also need a sysfs file for the image/config block to write or read.*/
+ /* set up sysfs bin file for binary data block. Since the image is already in our format
+ there is no need to convert the data for endianess. */
+ if (sysfs_create_bin_file(&function_device->dev.kobj, &dev_attr_data) < 0) {
+ printk(KERN_ERR "%s: Failed to create sysfs file for fn 34 data.\n", __func__);
+ return -ENODEV;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(FN_34_init);
+
+int FN_34_detect(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr, unsigned int interruptCount)
+{
+ int i;
+ int InterruptOffset;
+ int retval = 0;
+
+ pr_debug("%s: RMI4 function $34 detect\n", __func__);
+ if (rmifninfo->sensor == NULL) {
+ printk(KERN_ERR "%s: NULL sensor passed in!", __func__);
+ return -EINVAL;
+ }
+
+ /* Store addresses - used elsewhere to read data,
+ * control, query, etc. */
+ rmifninfo->funcDescriptor.queryBaseAddr = fndescr->queryBaseAddr;
+ rmifninfo->funcDescriptor.commandBaseAddr = fndescr->commandBaseAddr;
+ rmifninfo->funcDescriptor.controlBaseAddr = fndescr->controlBaseAddr;
+ rmifninfo->funcDescriptor.dataBaseAddr = fndescr->dataBaseAddr;
+ rmifninfo->funcDescriptor.interruptSrcCnt = fndescr->interruptSrcCnt;
+ rmifninfo->funcDescriptor.functionNum = fndescr->functionNum;
+
+ rmifninfo->numSources = fndescr->interruptSrcCnt;
+
+ /* Need to get interrupt info to be used later when handling
+ interrupts. */
+ rmifninfo->interruptRegister = interruptCount/8;
+
+ /* loop through interrupts for each source and or in a bit
+ to the interrupt mask for each. */
+ InterruptOffset = interruptCount % 8;
+
+ for (i = InterruptOffset;
+ i < ((fndescr->interruptSrcCnt & 0x7) + InterruptOffset);
+ i++) {
+ rmifninfo->interruptMask |= 1 << i;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(FN_34_detect);
+
+static ssize_t rmi_fn_34_bootloaderid_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct rmi_fn_34_data *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u\n", fn34data->bootloaderid);
+}
+
+static ssize_t rmi_fn_34_bootloaderid_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int error;
+ unsigned long val;
+ unsigned char uData[2];
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct rmi_fn_34_data *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+
+ /* need to convert the string data to an actual value */
+ error = strict_strtoul(buf, 10, &val);
+
+ if (error)
+ return error;
+
+ fn34data->bootloaderid = val;
+
+ /* Write the Bootloader ID key data back to the first two Block Data registers
+ (F34_Flash_Data2.0 and F34_Flash_Data2.1).*/
+ copyEndianAgnostic(uData, (unsigned short)val);
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr,
+ uData, 2);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write bootloader id to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr);
+ return error;
+ }
+
+ return count;
+}
+
+static ssize_t rmi_fn_34_blocksize_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct rmi_fn_34_data *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u\n", fn34data->blocksize);
+}
+
+static ssize_t rmi_fn_34_blocksize_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ /* Block Size is RO so we shouldn't do anything if the
+ user space writes to the sysfs file. */
+
+ return -EPERM;
+}
+
+static ssize_t rmi_fn_34_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct rmi_fn_34_data *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u\n", fn34data->status);
+}
+
+static ssize_t rmi_fn_34_status_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ /* Status is RO so we shouldn't do anything if the user
+ app writes to the sysfs file. */
+ return -EPERM;
+}
+
+static ssize_t rmi_fn_34_cmd_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct rmi_fn_34_data *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+
+ return sprintf(buf, "%u\n", fn34data->cmd);
+}
+
+static ssize_t rmi_fn_34_cmd_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct rmi_fn_34_data *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+ unsigned long val;
+ unsigned char cmd;
+ int error;
+
+ /* need to convert the string data to an actual value */
+ error = strict_strtoul(buf, 10, &val);
+
+ if (error)
+ return error;
+
+ fn34data->cmd = val;
+
+ /* determine the proper command to issue.
+ */
+ switch (val) {
+ case ENABLE_FLASH_PROG:
+ /* Issue a Flash Program Enable ($0F) command to the Flash Command
+ (F34_Flash_Data3, bits 3:0) field.*/
+ cmd = 0x0F;
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&cmd, 1);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write Flash Program Enable cmd to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ return error;
+ }
+ break;
+
+ case ERASE_ALL:
+ /* Issue a Erase All ($03) command to the Flash Command
+ (F34_Flash_Data3, bits 3:0) field.*/
+ cmd = 0x03;
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&cmd, 1);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write Erase All cmd to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ return error;
+ }
+ break;
+
+ case ERASE_CONFIG:
+ /* Issue a Erase Configuration ($07) command to the Flash Command
+ (F34_Flash_Data3, bits 3:0) field.*/
+ cmd = 0x07;
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&cmd, 1);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write Erase Configuration cmd to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ return error;
+ }
+ break;
+
+ case WRITE_FW_BLOCK:
+ /* Issue a Write Firmware Block ($02) command to the Flash Command
+ (F34_Flash_Data3, bits 3:0) field.*/
+ cmd = 0x02;
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&cmd, 1);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write Write Firmware Block cmd to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ return error;
+ }
+ break;
+
+ case WRITE_CONFIG_BLOCK:
+ /* Issue a Write Config Block ($06) command to the Flash Command
+ (F34_Flash_Data3, bits 3:0) field.*/
+ cmd = 0x06;
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&cmd, 1);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write Write Config Block cmd to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ return error;
+ }
+ break;
+
+ case READ_CONFIG_BLOCK:
+ /* Issue a Read Config Block ($05) command to the Flash Command
+ (F34_Flash_Data3, bits 3:0) field.*/
+ cmd = 0x05;
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+3,
+ (unsigned char *)&cmd, 1);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write Read Config Block cmd to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+3);
+ return error;
+ }
+ break;
+
+ case DISABLE_FLASH_PROG:
+ /* Issue a reset command ($01) - this will reboot the sensor and ATTN will now go to
+ the Fn $01 instead of the Fn $34 since the sensor will no longer be in Flash mode. */
+ cmd = 0x01;
+ /*if ((error = rmi_write_multiple(fn->sensor, fn->sensor->sensorCommandBaseAddr,
+ (unsigned char *)&cmd, 1))) {
+ printk(KERN_ERR "%s : Could not write Reset cmd to 0x%x\n",
+ __func__, fn->sensor->sensorCommandBaseAddr);
+ return error;
+ }*/
+ break;
+
+ default:
+ pr_debug("%s: RMI4 function $34 - unknown command.\n", __func__);
+ break;
+ }
+
+ return count;
+}
+
+static ssize_t rmi_fn_34_data_read(struct file * filp,
+ struct kobject *kobj,
+ struct bin_attribute *attributes,
+ char *buf, loff_t pos, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ int error;
+
+ /* TODO: add check for count to verify it's the correct blocksize */
+
+ /* read the data from flash into buf. */
+ /* the app layer will be blocked at reading from the sysfs file. */
+ /* when we return the count (or error if we fail) the app will resume. */
+ error = rmi_read_multiple(fn->sensor, fn->function->functionDataBaseAddr+pos,
+ (unsigned char *)buf, count);
+ if (error) {
+ printk(KERN_ERR "%s : Could not read data from 0x%llx\n",
+ __func__, fn->function->functionDataBaseAddr+pos);
+ return error;
+ }
+
+ return count;
+}
+
+static ssize_t rmi_fn_34_data_write(struct file *filp,
+ struct kobject *kobj,
+ struct bin_attribute *attributes,
+ char *buf, loff_t pos, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct rmi_function_device *fn = dev_get_drvdata(dev);
+ struct rmi_fn_34_data *fn34data = (struct rmi_fn_34_data *)fn->rfi->fndata;
+ unsigned int blocknum;
+ int error;
+
+ /* write the data from buf to flash. */
+ /* the app layer will be blocked at writing to the sysfs file. */
+ /* when we return the count (or error if we fail) the app will resume. */
+
+ /* TODO: Add check on count - if non-zero veriy it's the correct blocksize */
+
+ /* Verify that the byte offset is always aligned on a block boundary and if not
+ return an error. We can't just use the mod operator % and do a (pos % fn34data->blocksize) because of a gcc
+ bug that results in undefined symbols. So we have to compute it the hard
+ way. Grumble. */
+ unsigned int remainder;
+ div_u64_rem(pos, fn34data->blocksize, &remainder);
+ if (remainder) {
+ printk(KERN_ERR "%s : Invalid byte offset of %llx leads to invalid block number.\n",
+ __func__, pos);
+ return -EINVAL;
+ }
+
+ /* Compute the block number using the byte offset (pos) and the block size.
+ once again, we can't just do a divide due to a gcc bug. */
+ blocknum = div_u64(pos, fn34data->blocksize);
+
+ /* Write the block number first */
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr,
+ (unsigned char *)&blocknum, 2);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write block number to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr);
+ return error;
+ }
+
+ /* Write the data block - only if the count is non-zero */
+ if (count) {
+ error = rmi_write_multiple(fn->sensor, fn->function->functionDataBaseAddr+2,
+ (unsigned char *)buf, count);
+ if (error) {
+ printk(KERN_ERR "%s : Could not write block data to 0x%x\n",
+ __func__, fn->function->functionDataBaseAddr+2);
+ return error;
+ }
+ }
+
+ return count;
+}
diff --git a/drivers/input/touchscreen/synaptics/rmi_f34.h b/drivers/input/touchscreen/synaptics/rmi_f34.h
new file mode 100644
index 0000000..48293e3
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_f34.h
@@ -0,0 +1,50 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function $34 header.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ * There is only one function $34 for each RMI4 sensor. This will be
+ * the function that is used to reflash the firmware and get the
+ * boot loader address and the boot image block size.
+ *
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+#ifndef _RMI_FUNCTION_34_H
+#define _RMI_FUNCTION_34_H
+
+/* define fn $34 commands */
+#define WRITE_FW_BLOCK 2
+#define ERASE_ALL 3
+#define READ_CONFIG_BLOCK 5
+#define WRITE_CONFIG_BLOCK 6
+#define ERASE_CONFIG 7
+#define ENABLE_FLASH_PROG 15
+#define DISABLE_FLASH_PROG 16
+
+void FN_34_inthandler(struct rmi_function_info *rmifninfo,
+ unsigned int assertedIRQs);
+int FN_34_config(struct rmi_function_info *rmifninfo);
+int FN_34_init(struct rmi_function_device *function_device);
+int FN_34_detect(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr,
+ unsigned int interruptCount);
+void FN_34_attention(struct rmi_function_info *rmifninfo);
+
+#endif
diff --git a/drivers/input/touchscreen/synaptics/rmi_function.c b/drivers/input/touchscreen/synaptics/rmi_function.c
new file mode 100644
index 0000000..4a029f7
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_function.c
@@ -0,0 +1,326 @@
+/**
+ * Synaptics Register Mapped Interface (RMI4) - RMI Function Module.
+ * Copyright (C) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+static const char functionname[10] = "fn";
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/hrtimer.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+#include "rmi_drvr.h"
+#include "rmi_function.h"
+#include "rmi_bus.h"
+#include "rmi_sensor.h"
+#include "rmi_f01.h"
+#include "rmi_f05.h"
+#include "rmi_f11.h"
+#include "rmi_f19.h"
+#include "rmi_f34.h"
+
+/* Each time a new RMI4 function support is added the developer needs to
+bump the number of supported functions and add the info for
+that RMI4 function to the array along with pointers to the report,
+config, init and detect functions that they coded in rmi_fxx.c
+and rmi_fxx.h - where xx is the RMI4 function number in hex for the new
+RMI4 data source function. The information for the RMI4 functions is
+obtained from the RMI4 specification document.
+ */
+#define rmi4_num_supported_data_src_fns 5
+
+/* supported RMI4 functions list - controls what we
+ * will provide support for - if it's not in the list then
+ * the developer needs to add support functions for it.*/
+static LIST_HEAD(fns_list);
+static DEFINE_MUTEX(fns_mutex);
+
+/* NOTE: Developer - add in any new RMI4 fn data info - function number
+ * and ptrs to report, config, init and detect functions. This data is
+ * used to point to the functions that need to be called to config, init,
+ * detect and report data for the new RMI4 function. Refer to the RMI4
+ * specification for information on RMI4 functions.
+ */
+/* TODO: This will eventually go away, and each function will be an independent
+ * module. */
+static struct rmi_functions_data
+ rmi4_supported_data_src_functions[rmi4_num_supported_data_src_fns] = {
+ /* Fn $11 - 2D sensing */
+ {.functionNumber = 0x11, .inthandlerFn = FN_11_inthandler, .configFn = FN_11_config, .initFn = FN_11_init, .detectFn = FN_11_detect, .attnFn = NULL},
+ /* Fn $01 - device control */
+ {.functionNumber = 0x01, .inthandlerFn = FN_01_inthandler, .configFn = FN_01_config, .initFn = FN_01_init, .detectFn = FN_01_detect, .attnFn = FN_01_attention},
+ /* Fn $05 - analog report */
+ {.functionNumber = 0x05, .inthandlerFn = FN_05_inthandler, .configFn = FN_05_config, .initFn = FN_05_init, .detectFn = FN_05_detect, .attnFn = NULL},
+ /* Fn $19 - buttons */
+ {.functionNumber = 0x19, .inthandlerFn = FN_19_inthandler, .configFn = FN_19_config, .initFn = FN_19_init, .detectFn = FN_19_detect, .attnFn = NULL},
+ /* Fn $34 - firmware reflash */
+ {.functionNumber = 0x34, .inthandlerFn = FN_34_inthandler, .configFn = FN_34_config, .initFn = FN_34_init, .detectFn = FN_34_detect, .attnFn = FN_34_attention},
+};
+
+
+/* This function is here to provide a way for external modules to access the
+ * functions list. It will try to find a matching function base on the passed
+ * in RMI4 function number and return the pointer to the struct rmi_functions
+ * if a match is found or NULL if not found.
+ */
+struct rmi_functions *rmi_find_function(int functionNum)
+{
+ struct rmi_functions *fn;
+ bool found = false;
+
+ list_for_each_entry(fn, &fns_list, link) {
+ if (functionNum == fn->functionNum) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return NULL;
+ else
+ return fn;
+}
+EXPORT_SYMBOL(rmi_find_function);
+
+
+static void rmi_function_config(struct rmi_function_device *function)
+{
+ printk(KERN_DEBUG "%s: rmi_function_config", __func__);
+
+}
+
+#if 0 /* This may not be needed anymore. */
+/**
+ * This is the probe function passed to the RMI4 subsystem that gives us a
+ * chance to recognize an RMI4 function.
+ */
+static int rmi_function_probe(struct rmi_function_driver *function)
+{
+ struct rmi_phys_driver *rpd;
+
+ rpd = function->rpd;
+
+ if (!rpd) {
+ printk(KERN_ERR "%s: Invalid rmi physical driver - null ptr.", __func__);
+ return 0;
+ }
+
+ return 1;
+}
+#endif
+
+/** Just a stub for now.
+ */
+static int rmi_function_suspend(struct device *dev, pm_message_t state)
+{
+ printk(KERN_INFO "%s: function suspend called.", __func__);
+ return 0;
+}
+
+/** Just a stub for now.
+ */
+static int rmi_function_resume(struct device *dev)
+{
+ printk(KERN_INFO "%s: function resume called.", __func__);
+ return 0;
+}
+
+int rmi_function_register_driver(struct rmi_function_driver *drv, int fnNumber)
+{
+ int retval;
+ char *drvrname;
+
+ printk(KERN_INFO "%s: Registering function driver for F%02x.\n", __func__, fnNumber);
+
+ retval = 0;
+
+ /* Create a function device and function driver for this Fn */
+ drvrname = kzalloc(sizeof(functionname) + 4, GFP_KERNEL);
+ if (!drvrname) {
+ printk(KERN_ERR "%s: Error allocating memeory for rmi_function_driver name.\n", __func__);
+ return -ENOMEM;
+ }
+ sprintf(drvrname, "fn%02x", fnNumber);
+
+ drv->drv.name = drvrname;
+ drv->module = drv->drv.owner;
+
+ drv->drv.suspend = rmi_function_suspend;
+ drv->drv.resume = rmi_function_resume;
+
+ /* register the sensor driver */
+ retval = driver_register(&drv->drv);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed driver_register %d\n",
+ __func__, retval);
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(rmi_function_register_driver);
+
+void rmi_function_unregister_driver(struct rmi_function_driver *drv)
+{
+ printk(KERN_INFO "%s: Unregistering function driver.\n", __func__);
+
+ driver_unregister(&drv->drv);
+}
+EXPORT_SYMBOL(rmi_function_unregister_driver);
+
+int rmi_function_register_device(struct rmi_function_device *function_device, int fnNumber)
+{
+ struct input_dev *input;
+ int retval;
+
+ printk(KERN_INFO "%s: Registering function device for F%02x.\n", __func__, fnNumber);
+
+ retval = 0;
+
+ /* make name - fn11, fn19, etc. */
+ dev_set_name(&function_device->dev, "%sfn%02x", function_device->sensor->drv.name, fnNumber);
+ dev_set_drvdata(&function_device->dev, function_device);
+ retval = device_register(&function_device->dev);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed device_register for function device.\n",
+ __func__);
+ return retval;
+ }
+
+ input = input_allocate_device();
+ if (input == NULL) {
+ printk(KERN_ERR "%s: Failed to allocate memory for a "
+ "new input device.\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ input->name = dev_name(&function_device->dev);
+ input->phys = "rmi_function";
+ function_device->input = input;
+
+
+ /* init any input specific params for this function */
+ function_device->rmi_funcs->init(function_device);
+
+ retval = input_register_device(input);
+
+ if (retval) {
+ printk(KERN_ERR "%s: Failed input_register_device.\n",
+ __func__);
+ return retval;
+ }
+
+
+ rmi_function_config(function_device);
+
+ return retval;
+}
+EXPORT_SYMBOL(rmi_function_register_device);
+
+void rmi_function_unregister_device(struct rmi_function_device *dev)
+{
+ printk(KERN_INFO "%s: Unregistering function device.n", __func__);
+
+ input_unregister_device(dev->input);
+ device_unregister(&dev->dev);
+}
+EXPORT_SYMBOL(rmi_function_unregister_device);
+
+static int __init rmi_function_init(void)
+{
+ struct rmi_functions_data *rmi4_fn;
+ int i;
+
+ printk(KERN_DEBUG "%s: RMI Function Init\n", __func__);
+
+ /* Initialize global list of RMI4 Functions.
+ We need to add the supported RMI4 funcions so that we will have
+ pointers to the associated functions for init, config, report and
+ detect. See rmi.h for more details. The developer will add a new
+ RMI4 function number in the array in rmi_drvr.h, then add a new file to
+ the build (called rmi_fXX.c where XX is the hex number for
+ the added RMI4 function). The rest should be automatic.
+ */
+
+ /* for each function number defined in rmi.h creat a new rmi_function
+ struct and initialize the pointers to the servicing functions and then
+ add it into the global list for function support.
+ */
+ for (i = 0; i < rmi4_num_supported_data_src_fns; i++) {
+ /* Add new rmi4 function struct to list */
+ struct rmi_functions *fn = kzalloc(sizeof(*fn), GFP_KERNEL);
+ if (!fn) {
+ printk(KERN_ERR "%s: could not allocate memory "
+ "for rmi_function struct for function 0x%x\n",
+ __func__,
+ rmi4_supported_data_src_functions[i].functionNumber);
+ return -ENOMEM;
+ } else {
+
+ rmi4_fn = &rmi4_supported_data_src_functions[i];
+ fn->functionNum = rmi4_fn->functionNumber;
+ /* Fill in ptrs to functions. The functions are
+ linked in from a file called rmi_fxx.c
+ where xx is the hex number of the RMI4 function
+ from the RMI4 spec. Also, the function prototypes
+ need to be added to rmi_fxx.h - also where
+ xx is the hex number of the RMI4 function. So
+ that you don't get compile errors and that new
+ header needs to be included in the rmi_function.h
+ */
+ fn->inthandler = rmi4_fn->inthandlerFn;
+ fn->config = rmi4_fn->configFn;
+ fn->init = rmi4_fn->initFn;
+ fn->detect = rmi4_fn->detectFn;
+ fn->attention = rmi4_fn->attnFn;
+
+ /* Add the new fn to the global list */
+ mutex_lock(&fns_mutex);
+ list_add_tail(&fn->link, &fns_list);
+ mutex_unlock(&fns_mutex);
+ }
+ }
+
+ return 0;
+}
+
+static void __exit rmi_function_exit(void)
+{
+ printk(KERN_DEBUG "%s: RMI Function Exit\n", __func__);
+}
+
+
+module_init(rmi_function_init);
+module_exit(rmi_function_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("RMI4 Function Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/synaptics/rmi_function.h b/drivers/input/touchscreen/synaptics/rmi_function.h
new file mode 100644
index 0000000..801609b
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_function.h
@@ -0,0 +1,213 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) Function Device Header File.
+ * Copyright (c) 2007 - 2011, Synaptics Incorporated
+ *
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#ifndef _RMI_FUNCTION_H
+#define _RMI_FUNCTION_H
+
+#include <linux/input.h>
+#include <linux/device.h>
+
+
+/* For each function present on the RMI device, there will be a corresponding
+ * entry in the functions list of the rmi_sensor_driver structure. This entry
+ * gives information about the number of data sources and the number of data
+ * registers associated with the function.
+ */
+struct rmi_function_info {
+ /* The sensor this function belongs to.
+ */
+ struct rmi_sensor_driver *sensor;
+
+ /* A device associated with this function.
+ */
+ struct rmi_function_device *function_device;
+
+ unsigned char functionNum;
+
+ /* This is the number of data sources associated with the function.*/
+ unsigned char numSources;
+
+ /* This is the number of data registers to read.*/
+ unsigned char dataRegBlockSize;
+
+ /* This is the interrupt register and mask - needed for enabling the
+ * interrupts and for checking what source had caused the attention line
+ * interrupt.
+ */
+ unsigned char interruptRegister;
+ unsigned char interruptMask;
+
+ /* This is the RMI function descriptor associated with this function.
+ * It contains the Base addresses for the functions query, command,
+ * control, and data registers.
+ */
+ struct rmi_function_descriptor funcDescriptor;
+
+ /* pointer to data specific to a functions implementation. */
+ void *fndata;
+
+ /* A list of the function information.
+ * This list uses the standard kernel linked list implementation.
+ * Documentation on on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head link;
+};
+
+
+/* This struct is for creating a list of RMI4 functions that have data sources
+associated with them. This is to facilitate adding new support for other
+data sources besides 2D sensors.
+To add a new data source support, the developer will create a new file
+and add these 4 functions below with FN$## in front of the names - where
+## is the hex number for the function taken from the RMI4 specification.
+
+The function number will be associated with this and later will be used to
+match the RMI4 function to the 4 functions for that RMI4 function number.
+The user will also have to add code that adds the new rmi_functions item
+to the global list of RMI4 functions and stores the pointers to the 4
+functions in the function pointers.
+ */
+struct rmi_functions {
+ unsigned char functionNum;
+
+ /* Pointers to function specific functions for interruptHandler, config, init
+ , detect and attention. */
+ /* These ptrs. need to be filled in for every RMI4 function that has
+ data source(s) associated with it - like fn $11 (2D sensors),
+ fn $19 (buttons), etc. Each RMI4 function that has data sources
+ will be added into a list that is used to match the function
+ number against the number stored here.
+ */
+ /* The sensor implementation will call this whenever and IRQ is
+ * dispatched that this function is interested in.
+ */
+ void (*inthandler)(struct rmi_function_info *rfi, unsigned int assertedIRQs);
+
+ int (*config)(struct rmi_function_info *rmifninfo);
+ int (*init)(struct rmi_function_device *function_device);
+ int (*detect)(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr,
+ unsigned int interruptCount);
+ /** If this is non-null, the sensor implemenation will call this
+ * whenever the ATTN line is asserted.
+ */
+ void (*attention)(struct rmi_function_info *rmifninfo);
+
+
+ /* Standard kernel linked list implementation.
+ * Documentation on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head link;
+};
+
+
+typedef void(*inthandlerFuncPtr)(struct rmi_function_info *rfi, unsigned int assertedIRQs);
+typedef int(*configFuncPtr)(struct rmi_function_info *rmifninfo);
+typedef int(*initFuncPtr)(struct rmi_function_device *function_device);
+typedef int(*detectFuncPtr)(struct rmi_function_info *rmifninfo,
+ struct rmi_function_descriptor *fndescr,
+ unsigned int interruptCount);
+typedef void (*attnFuncPtr)(struct rmi_function_info *rmifninfo);
+
+struct rmi_functions_data {
+ int functionNumber;
+ inthandlerFuncPtr inthandlerFn;
+ configFuncPtr configFn;
+ initFuncPtr initFn;
+ detectFuncPtr detectFn;
+ attnFuncPtr attnFn;
+};
+
+
+struct rmi_functions *rmi_find_function(int functionNum);
+int rmi_functions_init(struct input_dev *inputdev);
+
+struct rmi_function_driver {
+ struct module *module;
+ struct device_driver drv;
+
+ /* Probe Function
+ * This function is called to give the function driver layer an
+ * opportunity to claim an RMI function.
+ */
+ int (*probe)(struct rmi_function_driver *function);
+ /* Config Function
+ * This function is called after a successful probe. It gives the
+ * function driver an opportunity to query and/or configure an RMI
+ * function before data starts flowing.
+ */
+ void (*config)(struct rmi_function_driver *function);
+
+ unsigned short functionQueryBaseAddr; /* RMI4 function control */
+ unsigned short functionControlBaseAddr;
+ unsigned short functionCommandBaseAddr;
+ unsigned short functionDataBaseAddr;
+ unsigned int interruptRegisterOffset; /* offset from start of interrupt registers */
+ unsigned int interruptMask;
+
+ /* pointer to the corresponding phys driver info for this sensor */
+ /* The phys driver has the pointers to read, write, etc. */
+ /* Probably don't need it here - used down in bus driver and sensor driver */
+ struct rmi_phys_driver *rpd;
+
+ /* Standard kernel linked list implementation.
+ * Documentation on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head function_drivers; /* link function drivers into list */
+};
+
+struct rmi_function_device {
+ struct rmi_function_driver *function;
+ struct device dev;
+ struct input_dev *input;
+ struct rmi_sensor_driver *sensor; /* need this to be bound to phys driver layer */
+
+ /* the function ptrs to the config, init, detect and
+ report fns for this rmi function device. */
+ struct rmi_functions *rmi_funcs;
+ struct rmi_function_info *rfi;
+
+ /** An RMI sensor might actually have several IRQ registers -
+ * this tells us which IRQ register this function is interested in.
+ */
+ unsigned int irqRegisterSet;
+
+ /** This is a mask of the IRQs the function is interested in.
+ */
+ unsigned int irqMask;
+
+ /* Standard kernel linked list implementation.
+ * Documentation on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head functions; /* link functions into list */
+};
+
+int rmi_function_register_device(struct rmi_function_device *dev, int fnNumber);
+
+#endif
diff --git a/drivers/input/touchscreen/synaptics/rmi_i2c.c b/drivers/input/touchscreen/synaptics/rmi_i2c.c
new file mode 100644
index 0000000..1932b9b
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_i2c.c
@@ -0,0 +1,633 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) I2C Physical Layer Driver.
+ * Copyright (c) 2007-2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/input/rmi_platformdata.h>
+#include <linux/input/rmi_i2c.h>
+
+#include "rmi_drvr.h"
+
+#define DRIVER_NAME "rmi4_ts"
+
+#define DEVICE_NAME "rmi4_ts"
+
+/* Used to lock access to the page address.*/
+/* TODO: for multiple device support will need a per-device mutex */
+static DEFINE_MUTEX(page_mutex);
+
+
+static const struct i2c_device_id rmi_i2c_id_table[] = {
+ { DEVICE_NAME, 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, rmi_i2c_id_table);
+
+
+/* Used to count the number of I2C modules we get.
+ */
+static int device_count;
+
+
+/*
+ * This is the data kept on a per instance (client) basis. This data is
+ * always accessible by using the container_of() macro of the various elements
+ * inside.
+ */
+struct instance_data {
+ int instance_no;
+ int irq;
+ struct rmi_phys_driver rmiphysdrvr;
+ struct i2c_client *i2cclient; /* pointer to i2c_client for later use in
+ read, write, read_multiple, etc. */
+ int page;
+};
+
+/*
+ * RMI devices have 16-bit addressing, but some of the physical
+ * implementations (like SMBus) only have 8-bit addressing. So RMI implements
+ * a page address at 0xff of every page so we can reliable page addresses
+ * every 256 registers. This function sets the page.
+ *
+ * The page_mutex lock must be held when this function is entered.
+ *
+ * param[in] id - The pointer to the instance_data struct
+ * param[in] page - The new page address.
+ * returns zero on success, non-zero on failure.
+ */
+/** Writing to page select is giving errors in some configurations. It's
+ * not needed for basic operation, so we've turned it off for the moment.
+ */
+#if defined(USE_PAGESELECT)
+int
+rmi_set_page(struct instance_data *instancedata, unsigned int page)
+{
+ char txbuf[2];
+ int retval;
+ txbuf[0] = 0xff;
+ txbuf[1] = page;
+ retval = i2c_master_send(instancedata->i2cclient, txbuf, 2);
+ if (retval != 2) {
+ dev_err(&instancedata->i2cclient->dev,
+ "%s: Set page failed: %d.", __func__, retval);
+ } else {
+ retval = 0;
+ instancedata->page = page;
+ }
+ return retval;
+}
+#else
+int
+rmi_set_page(struct instance_data *instancedata, unsigned int page)
+{
+ return 0;
+}
+#endif
+
+/*
+ * Read a single register through i2c.
+ *
+ * param[in] pd - The pointer to the rmi_phys_driver struct
+ * param[in] address - The address at which to start the data read.
+ * param[out] valp - Pointer to the buffer where the data will be stored.
+ * returns zero upon success (with the byte read in valp), non-zero upon error.
+ */
+static int
+rmi_i2c_read(struct rmi_phys_driver *physdrvr, unsigned short address, char *valp)
+{
+ struct instance_data *instancedata =
+ container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+ char txbuf[2];
+ int retval = 0;
+ int retry_count = 0;
+
+ /* Can't have anyone else changing the page behind our backs */
+ mutex_lock(&page_mutex);
+
+ if (((address >> 8) & 0xff) != instancedata->page) {
+ /* Switch pages */
+ retval = rmi_set_page(instancedata, ((address >> 8) & 0xff));
+ if (retval)
+ goto exit;
+ }
+
+retry:
+ txbuf[0] = address & 0xff;
+ retval = i2c_master_send(instancedata->i2cclient, txbuf, 1);
+
+ if (retval != 1) {
+ dev_err(&instancedata->i2cclient->dev, "%s: Write fail: %d\n",
+ __func__, retval);
+ goto exit;
+ }
+ retval = i2c_master_recv(instancedata->i2cclient, txbuf, 1);
+
+ if (retval != 1) {
+ if (++retry_count == 5) {
+ dev_err(&instancedata->i2cclient->dev,
+ "%s: Read of 0x%04x fail: %d\n",
+ __func__, address, retval);
+ } else {
+ mdelay(10);
+ rmi_set_page(instancedata, ((address >> 8) & 0xff));
+ goto retry;
+ }
+ } else {
+ retval = 0;
+ *valp = txbuf[0];
+ }
+exit:
+
+ mutex_unlock(&page_mutex);
+ return retval;
+}
+
+/*
+ * Same as rmi_i2c_read, except that multiple bytes are allowed to be read.
+ *
+ * param[in] pd - The pointer to the rmi_phys_driver struct
+ * param[in] address - The address at which to start the data read.
+ * param[out] valp - Pointer to the buffer where the data will be stored. This
+ * buffer must be at least size bytes long.
+ * param[in] size - The number of bytes to be read.
+ * returns zero upon success (with the byte read in valp), non-zero upon error.
+ *
+ */
+static int
+rmi_i2c_read_multiple(struct rmi_phys_driver *physdrvr, unsigned short address,
+ char *valp, int size)
+{
+ struct instance_data *instancedata =
+ container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+ char txbuf[2];
+ int retval = 0;
+ int retry_count = 0;
+
+ /* Can't have anyone else changing the page behind our backs */
+ mutex_lock(&page_mutex);
+
+ if (((address >> 8) & 0xff) != instancedata->page) {
+ /* Switch pages */
+ retval = rmi_set_page(instancedata, ((address >> 8) & 0xff));
+ if (retval)
+ goto exit;
+ }
+
+retry:
+ txbuf[0] = address & 0xff;
+ retval = i2c_master_send(instancedata->i2cclient, txbuf, 1);
+
+ if (retval != 1) {
+ dev_err(&instancedata->i2cclient->dev, "%s: Write fail: %d\n",
+ __func__, retval);
+ goto exit;
+ }
+ retval = i2c_master_recv(instancedata->i2cclient, valp, size);
+
+ if (retval != size) {
+ if (++retry_count == 5) {
+ dev_err(&instancedata->i2cclient->dev,
+ "%s: Read of 0x%04x size %d fail: %d\n",
+ __func__, address, size, retval);
+ } else {
+ mdelay(10);
+ rmi_set_page(instancedata, ((address >> 8) & 0xff));
+ goto retry;
+ }
+ } else {
+ retval = 0;
+ }
+exit:
+
+ mutex_unlock(&page_mutex);
+ return retval;
+}
+
+
+/*
+ * Write a single register through i2c.
+ * You can write multiple registers at once, but I made the functions for that
+ * seperate for performance reasons. Writing multiple requires allocation and
+ * freeing.
+ *
+ * param[in] pd - The pointer to the rmi_phys_driver struct
+ * param[in] address - The address at which to start the write.
+ * param[in] data - The data to be written.
+ * returns one upon success, something else upon error.
+ */
+static int
+rmi_i2c_write(struct rmi_phys_driver *physdrvr, unsigned short address, char data)
+{
+ struct instance_data *instancedata =
+ container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+ unsigned char txbuf[2];
+ int retval = 0;
+
+ /* Can't have anyone else changing the page behind our backs */
+ mutex_lock(&page_mutex);
+
+ if (((address >> 8) & 0xff) != instancedata->page) {
+ /* Switch pages */
+ retval = rmi_set_page(instancedata, ((address >> 8) & 0xff));
+ if (retval)
+ goto exit;
+ }
+
+ txbuf[0] = address & 0xff;
+ txbuf[1] = data;
+ retval = i2c_master_send(instancedata->i2cclient, txbuf, 2);
+
+ /* TODO: Add in retry on writes only in certian error return values */
+ if (retval != 2) {
+ dev_err(&instancedata->i2cclient->dev, "%s: Write fail: %d\n",
+ __func__, retval);
+ goto exit; /* Leave this in case we add code below */
+ } else {
+ retval = 1;
+ }
+exit:
+
+ mutex_unlock(&page_mutex);
+ return retval;
+}
+
+/*
+ * Write multiple registers.
+ *
+ * For fast writes of 16 bytes of less we will re-use a buffer on the stack.
+ * For larger writes (like for RMI reflashing) we will need to allocate a
+ * temp buffer.
+ *
+ * param[in] pd - The pointer to the rmi_phys_driver struct
+ * param[in] address - The address at which to start the write.
+ * param[in] valp - A pointer to a buffer containing the data to be written.
+ * param[in] size - The number of bytes to write.
+ * returns one upon success, something else upon error.
+ */
+static int
+rmi_i2c_write_multiple(struct rmi_phys_driver *physdrvr, unsigned short address,
+ char *valp, int size)
+{
+ struct instance_data *instancedata =
+ container_of(physdrvr, struct instance_data, rmiphysdrvr);
+
+ unsigned char *txbuf;
+ unsigned char txbuf_most[17]; /* Use this buffer for fast writes of 16
+ bytes or less. The first byte will
+ contain the address at which to start
+ the write. */
+ int retval = 0;
+ int i;
+
+ if (size < sizeof(txbuf_most)) {
+ /* Avoid an allocation if we can help it. */
+ txbuf = txbuf_most;
+ } else {
+ /* over 16 bytes write we'll need to allocate a temp buffer */
+ txbuf = kzalloc(size + 1, GFP_KERNEL);
+ if (!txbuf)
+ return -ENOMEM;
+ }
+
+ /* Yes, it stinks here that we have to copy the buffer */
+ /* We copy from valp to txbuf leaving
+ the first location open for the address */
+ for (i = 0; i < size; i++)
+ txbuf[i + 1] = valp[i];
+
+ /* Can't have anyone else changing the page behind our backs */
+ mutex_lock(&page_mutex);
+
+ if (((address >> 8) & 0xff) != instancedata->page) {
+ /* Switch pages */
+ retval = rmi_set_page(instancedata, ((address >> 8) & 0xff));
+ if (retval)
+ goto exit;
+ }
+
+ txbuf[0] = address & 0xff; /* put the address in the first byte */
+ retval = i2c_master_send(instancedata->i2cclient, txbuf, size + 1);
+
+ /* TODO: Add in retyr on writes only in certian error return values */
+ if (retval != 1) {
+ dev_err(&instancedata->i2cclient->dev, "%s: Write fail: %d\n",
+ __func__, retval);
+ goto exit;
+ }
+exit:
+
+ mutex_unlock(&page_mutex);
+ if (txbuf != txbuf_most)
+ kfree(txbuf);
+ return retval;
+}
+
+/*
+ * This is the Interrupt Service Routine. It just notifies the application
+ * layer that attention is required.
+ */
+static irqreturn_t
+i2c_attn_isr(int irq, void *info)
+{
+ struct instance_data *instancedata = info;
+
+ disable_irq_nosync(instancedata->irq);
+
+ if (instancedata->rmiphysdrvr.attention) {
+ instancedata->rmiphysdrvr.attention(&instancedata->rmiphysdrvr,
+ instancedata->instance_no);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/* The Driver probe function - will allocate and initialize the instance
+ * data and request the irq and set the instance data as the clients
+ * platform data then register the physical driver which will do a scan of
+ * the RMI4 Physical Device Table and enumerate any RMI4 functions that
+ * have data sources associated with them.
+ */
+static int
+rmi_i2c_probe(struct i2c_client *client, const struct i2c_device_id *dev_id)
+{
+
+ struct instance_data *instancedata;
+ int retval = 0;
+ int irqtype = 0;
+
+ struct rmi_i2c_platformdata *platformdata;
+ struct rmi_sensordata *sensordata;
+
+ if (client == NULL) {
+ printk(KERN_ERR "%s: Invalid NULL client received.", __func__);
+ return -EINVAL;
+ }
+
+ printk(KERN_DEBUG "%s: Probing i2c RMI device, addr: 0x%02x", __func__, client->addr);
+
+
+ /* Allocate and initialize the instance data for this client */
+ instancedata = kzalloc(sizeof(*instancedata), GFP_KERNEL);
+ if (!instancedata) {
+ dev_err(&client->dev,
+ "%s: Out of memory trying to allocate instance_data.\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ instancedata->rmiphysdrvr.name = DRIVER_NAME;
+ instancedata->rmiphysdrvr.write = rmi_i2c_write;
+ instancedata->rmiphysdrvr.read = rmi_i2c_read;
+ instancedata->rmiphysdrvr.write_multiple = rmi_i2c_write_multiple;
+ instancedata->rmiphysdrvr.read_multiple = rmi_i2c_read_multiple;
+ instancedata->rmiphysdrvr.module = THIS_MODULE;
+
+ /* Set default to polling in case no matching platform data is located
+ for this device. We'll still work but in polling mode since we didn't
+ find any irq info */
+ instancedata->rmiphysdrvr.polling_required = true;
+
+ instancedata->page = 0xffff; /* Force a set page the first time */
+
+ /* cast to our struct rmi_i2c_platformdata so we know
+ the fields (see rmi_ic2.h) */
+ platformdata = client->dev.platform_data;
+ if (platformdata == NULL) {
+ printk(KERN_ERR "%s: CONFIGURATION ERROR - platform data is NULL.", __func__);
+ return -EINVAL;
+ }
+ sensordata = platformdata->sensordata;
+
+ /* Egregiously horrible delay here that seems to prevent I2C disasters on
+ * certain broken dev systems. In most cases, you can safely leave this
+ * as zero.
+ */
+ if (platformdata->delay_ms > 0)
+ mdelay(platformdata->delay_ms);
+
+ /* Call the platform setup routine, to do any setup that is required before
+ * interacting with the device.
+ */
+ if (sensordata && sensordata->rmi_sensor_setup) {
+ retval = sensordata->rmi_sensor_setup();
+ if (retval) {
+ printk(KERN_ERR "%s: sensor setup failed with code %d.", __func__, retval);
+ return retval;
+ }
+ }
+
+ printk(KERN_DEBUG "%s: sensor addr: 0x%02x irq: 0x%x type: %d",
+ __func__, platformdata->i2c_address, platformdata->irq, platformdata->irq_type);
+ if (client->addr != platformdata->i2c_address) {
+ printk(KERN_ERR "%s: CONFIGURATION ERROR - client I2C address 0x%02x doesn't match platform data address 0x%02x.", __func__, client->addr, platformdata->i2c_address);
+ return -EINVAL;
+ }
+
+ instancedata->instance_no = device_count++;
+
+ /* set the device name using the instance_no appended
+ to DEVICE_NAME to make a unique name */
+ dev_set_name(&client->dev,
+ "rmi4-i2c%d", instancedata->instance_no);
+
+ /* Determine if we need to poll (inefficient) or use interrupts.
+ */
+ if (platformdata->irq) {
+ instancedata->irq = platformdata->irq;
+ switch (platformdata->irq_type) {
+ case IORESOURCE_IRQ_HIGHEDGE:
+ irqtype = IRQF_TRIGGER_RISING;
+ break;
+ case IORESOURCE_IRQ_LOWEDGE:
+ irqtype = IRQF_TRIGGER_FALLING;
+ break;
+ case IORESOURCE_IRQ_HIGHLEVEL:
+ irqtype = IRQF_TRIGGER_HIGH;
+ break;
+ case IORESOURCE_IRQ_LOWLEVEL:
+ irqtype = IRQF_TRIGGER_LOW;
+ break;
+ default:
+ dev_warn(&client->dev,
+ "%s: Invalid IRQ flags in platform data.\n",
+ __func__);
+ kfree(instancedata);
+ return -ENXIO;
+ }
+
+ instancedata->rmiphysdrvr.polling_required = false;
+ instancedata->rmiphysdrvr.irq = instancedata->irq;
+
+ } else {
+ instancedata->rmiphysdrvr.polling_required = true;
+ dev_info(&client->dev,
+ "%s: No IRQ info given. Polling required.\n",
+ __func__);
+ }
+
+ /* Store the instance data in the i2c_client - we need to do this prior
+ * to calling register_physical_driver since it may use the read, write
+ * functions. If nothing was found then the id fields will be set to 0
+ * for the irq and the default will be set to polling required so we
+ * will still work but in polling mode. */
+ i2c_set_clientdata(client, instancedata);
+
+ /* Copy i2c_client pointer into instance_data's i2c_client pointer for
+ later use in rmi4_read, rmi4_write, etc. */
+ instancedata->i2cclient = client;
+
+ /* Register sensor drivers - this will call the detect function that
+ * will then scan the device and determine the supported RMI4 sensors
+ * and functions.
+ */
+ retval = rmi_register_sensor(&instancedata->rmiphysdrvr, platformdata->sensordata);
+ if (retval) {
+ dev_err(&client->dev, "%s: Failed to Register %s sensor drivers\n",
+ __func__, instancedata->rmiphysdrvr.name);
+ i2c_set_clientdata(client, NULL);
+ kfree(instancedata);
+ return retval;
+ }
+
+ if (instancedata->rmiphysdrvr.polling_required == false) {
+ retval = request_irq(instancedata->irq, i2c_attn_isr,
+ irqtype, "rmi_i2c", instancedata);
+ if (retval) {
+ dev_err(&client->dev, "%s: failed to obtain IRQ %d. Result: %d.",
+ __func__, instancedata->irq, retval);
+ dev_info(&client->dev, "%s: Reverting to polling.\n", __func__);
+ instancedata->rmiphysdrvr.polling_required = true;
+ /* TODO: Need to revert back to polling - create and start timer. */
+ } else {
+ dev_dbg(&client->dev, "%s: got irq.\n", __func__);
+ }
+ }
+
+ dev_dbg(&client->dev, "%s: Successfully registered %s sensor driver.\n",
+ __func__, instancedata->rmiphysdrvr.name);
+
+ printk(KERN_INFO "%s: Successfully registered %s sensor driver.\n", __func__, instancedata->rmiphysdrvr.name);
+
+ return retval;
+}
+
+/* The Driver remove function. We tear down the instance data and unregister
+ * the phys driver in this call.
+ */
+static int
+rmi_i2c_remove(struct i2c_client *client)
+{
+ struct instance_data *instancedata =
+ i2c_get_clientdata(client);
+
+ dev_dbg(&client->dev, "%s: Unregistering phys driver %s\n", __func__,
+ instancedata->rmiphysdrvr.name);
+
+ rmi_unregister_sensors(&instancedata->rmiphysdrvr);
+
+ dev_dbg(&client->dev, "%s: Unregistered phys driver %s\n",
+ __func__, instancedata->rmiphysdrvr.name);
+
+ /* only free irq if we have an irq - otherwise the instance_data
+ will be 0 for that field */
+ if (instancedata->irq)
+ free_irq(instancedata->irq, instancedata);
+
+ kfree(instancedata);
+ dev_dbg(&client->dev, "%s: Remove successful\n", __func__);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int
+rmi_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ /* Touch sleep mode */
+ return 0;
+}
+
+static int
+rmi_i2c_resume(struct i2c_client *client)
+{
+ /* Re-initialize upon resume */
+ return 0;
+}
+#else
+#define rmi_i2c_suspend NULL
+#define rmi_i2c_resume NULL
+#endif
+
+/*
+ * This structure tells the i2c subsystem about us.
+ *
+ * TODO: we should add .suspend and .resume fns.
+ *
+ */
+static struct i2c_driver rmi_i2c_driver = {
+ .probe = rmi_i2c_probe,
+ .remove = rmi_i2c_remove,
+ .suspend = rmi_i2c_suspend,
+ .resume = rmi_i2c_resume,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .id_table = rmi_i2c_id_table,
+};
+
+/*
+ * Register ourselves with i2c Chip Driver.
+ *
+ */
+static int __init rmi_phys_i2c_init(void)
+{
+ return i2c_add_driver(&rmi_i2c_driver);
+}
+
+/*
+ * Un-register ourselves from the i2c Chip Driver.
+ *
+ */
+static void __exit rmi_phys_i2c_exit(void)
+{
+ i2c_del_driver(&rmi_i2c_driver);
+}
+
+
+module_init(rmi_phys_i2c_init);
+module_exit(rmi_phys_i2c_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("RMI4 Driver I2C Physical Layer");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/synaptics/rmi_sensor.c b/drivers/input/touchscreen/synaptics/rmi_sensor.c
new file mode 100644
index 0000000..2c64609
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_sensor.c
@@ -0,0 +1,662 @@
+/**
+ * Synaptics Register Mapped Interface (RMI4) - RMI Sensor Module.
+ * Copyright (C) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *############################################################################
+ */
+
+static const char sensorname[] = "sensor";
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/list.h>
+#include <linux/device.h>
+#include <linux/hrtimer.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/freezer.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+
+
+#include "rmi_drvr.h"
+#include "rmi_bus.h"
+#include "rmi_function.h"
+#include "rmi_sensor.h"
+
+long polltime = 25000000; /* Shared with rmi_function.c. */
+EXPORT_SYMBOL(polltime);
+module_param(polltime, long, 0644);
+MODULE_PARM_DESC(polltime, "How long to wait between polls (in nano seconds).");
+
+
+#define PDT_START_SCAN_LOCATION 0x00E9
+#define PDT_END_SCAN_LOCATION 0x0005
+#define PDT_ENTRY_SIZE 0x0006
+
+static DEFINE_MUTEX(rfi_mutex);
+
+struct rmi_functions *rmi_find_function(int functionNum);
+
+int rmi_read(struct rmi_sensor_driver *sensor, unsigned short address,
+ char *dest)
+{
+ struct rmi_phys_driver *rpd = sensor->rpd;
+ if (!rpd)
+ return -ENODEV;
+ return rpd->read(rpd, address, dest);
+}
+EXPORT_SYMBOL(rmi_read);
+
+int rmi_write(struct rmi_sensor_driver *sensor, unsigned short address,
+ unsigned char data)
+{
+ struct rmi_phys_driver *rpd = sensor->rpd;
+ if (!rpd)
+ return -ENODEV;
+ return rpd->write(rpd, address, data);
+}
+EXPORT_SYMBOL(rmi_write);
+
+int rmi_read_multiple(struct rmi_sensor_driver *sensor,
+ unsigned short address, char *dest, int length)
+{
+ struct rmi_phys_driver *rpd = sensor->rpd;
+ if (!rpd)
+ return -ENODEV;
+ return rpd->read_multiple(rpd, address, dest, length);
+}
+EXPORT_SYMBOL(rmi_read_multiple);
+
+int rmi_write_multiple(struct rmi_sensor_driver *sensor,
+ unsigned short address, unsigned char *data, int length)
+{
+ struct rmi_phys_driver *rpd = sensor->rpd;
+ if (!rpd)
+ return -ENODEV;
+ return rpd->write_multiple(rpd, address, data, length);
+}
+EXPORT_SYMBOL(rmi_write_multiple);
+
+/* Utility routine to set bits in a register. */
+int rmi_set_bits(struct rmi_sensor_driver *sensor, unsigned short address,
+ unsigned char bits)
+{
+ unsigned char reg_contents;
+ int retval;
+
+ retval = rmi_read(sensor, address, ®_contents);
+ if (retval)
+ return retval;
+ reg_contents = reg_contents | bits;
+ retval = rmi_write(sensor, address, reg_contents);
+ if (retval == 1)
+ return 0;
+ else if (retval == 0)
+ return -EINVAL; /* TODO: What should this be? */
+ else
+ return retval;
+}
+EXPORT_SYMBOL(rmi_set_bits);
+
+/* Utility routine to clear bits in a register. */
+int rmi_clear_bits(struct rmi_sensor_driver *sensor,
+ unsigned short address, unsigned char bits)
+{
+ unsigned char reg_contents;
+ int retval;
+
+ retval = rmi_read(sensor, address, ®_contents);
+ if (retval)
+ return retval;
+ reg_contents = reg_contents & ~bits;
+ retval = rmi_write(sensor, address, reg_contents);
+ if (retval == 1)
+ return 0;
+ else if (retval == 0)
+ return -EINVAL; /* TODO: What should this be? */
+ else
+ return retval;
+}
+EXPORT_SYMBOL(rmi_clear_bits);
+
+/* Utility routine to set the value of a bit field in a register. */
+int rmi_set_bit_field(struct rmi_sensor_driver *sensor,
+ unsigned short address, unsigned char field_mask, unsigned char bits)
+{
+ unsigned char reg_contents;
+ int retval;
+
+ retval = rmi_read(sensor, address, ®_contents);
+ if (retval)
+ return retval;
+ reg_contents = (reg_contents & ~field_mask) | bits;
+ retval = rmi_write(sensor, address, reg_contents);
+ if (retval == 1)
+ return 0;
+ else if (retval == 0)
+ return -EINVAL; /* TODO: What should this be? */
+ else
+ return retval;
+}
+EXPORT_SYMBOL(rmi_set_bit_field);
+
+bool rmi_polling_required(struct rmi_sensor_driver *sensor)
+{
+ return sensor->polling_required;
+}
+EXPORT_SYMBOL(rmi_polling_required);
+
+/** Functions can call this in order to dispatch IRQs. */
+void dispatchIRQs(struct rmi_sensor_driver *sensor, unsigned int irqStatus)
+{
+ struct rmi_function_info *functionInfo;
+
+ list_for_each_entry(functionInfo, &sensor->functions, link) {
+ if ((functionInfo->interruptMask & irqStatus)) {
+ if (functionInfo->function_device->
+ rmi_funcs->inthandler) {
+ /* Call the functions interrupt handler function. */
+ functionInfo->function_device->rmi_funcs->
+ inthandler(functionInfo,
+ (functionInfo->interruptMask & irqStatus));
+ }
+ }
+ }
+}
+
+/**
+ * This is the function we pass to the RMI4 subsystem so we can be notified
+ * when attention is required. It may be called in interrupt context.
+ */
+static void attention(struct rmi_phys_driver *physdrvr, int instance)
+{
+ /* All we have to do is schedule work. */
+
+ /* TODO: It's possible that workIsReady is not really needed anymore.
+ * Investigate this to see if the race condition between setting up
+ * the work and enabling the interrupt still exists.
+ */
+ if (physdrvr->sensor->workIsReady) {
+ schedule_work(&(physdrvr->sensor->work));
+ } else {
+ /* Got an interrupt but we're not ready so enable the irq
+ * so it doesn't get hung up
+ */
+ printk(KERN_DEBUG "%s: Work not initialized yet -"
+ "enabling irqs.\n", __func__);
+ enable_irq(physdrvr->irq);
+ }
+}
+
+/**
+ * This notifies any interested functions that there
+ * is an Attention interrupt. The interested functions should take
+ * appropriate
+ * actions (such as reading the interrupt status register and dispatching any
+ * appropriate RMI4 interrupts).
+ */
+void attn_notify(struct rmi_sensor_driver *sensor)
+{
+ struct rmi_function_info *functionInfo;
+
+ /* check each function that has data sources and if the interrupt for
+ * that triggered then call that RMI4 functions report() function to
+ * gather data and report it to the input subsystem
+ */
+ list_for_each_entry(functionInfo, &sensor->functions, link) {
+ if (functionInfo->function_device &&
+ functionInfo->function_device->rmi_funcs->attention)
+ functionInfo->function_device->
+ rmi_funcs->attention(functionInfo);
+ }
+}
+
+/* This is the worker function - for now it simply has to call attn_notify.
+ * This work should be scheduled whenever an ATTN interrupt is asserted by
+ * the touch sensor.
+ * We then call attn_notify to dispatch notification of the ATTN interrupt
+ * to all
+ * interested functions. After all the attention handling functions
+ * have returned, it is presumed safe to re-enable the Attention interrupt.
+ */
+static void sensor_work_func(struct work_struct *work)
+{
+ struct rmi_sensor_driver *sensor = container_of(work,
+ struct rmi_sensor_driver, work);
+
+ attn_notify(sensor);
+
+ /* we only need to enable the irq if doing interrupts */
+ if (!rmi_polling_required(sensor))
+ enable_irq(sensor->rpd->irq);
+}
+
+/* This is the timer function for polling - it simply has to schedule work
+ * and restart the timer. */
+static enum hrtimer_restart sensor_poll_timer_func(struct hrtimer *timer)
+{
+ struct rmi_sensor_driver *sensor = container_of(timer,
+ struct rmi_sensor_driver, timer);
+
+ schedule_work(&sensor->work);
+ hrtimer_start(&sensor->timer, ktime_set(0, polltime),
+ HRTIMER_MODE_REL);
+ return HRTIMER_NORESTART;
+}
+
+/* This is the probe function passed to the RMI4 subsystem that gives us a
+ * chance to recognize an RMI4 device. In this case, we're looking for
+ * Synaptics devices that have data sources - such as touch screens, buttons,
+ * etc.
+ *
+ * TODO: Well, it used to do this. I'm not sure it's required any more.
+ */
+static int probe(struct rmi_sensor_driver *sensor)
+{
+ struct rmi_phys_driver *rpd;
+
+ rpd = sensor->rpd;
+
+ if (!rpd) {
+ printk(KERN_ERR "%s: Invalid rmi physical driver - null ptr:"
+ "%p\n", __func__, rpd);
+ return 0;
+ }
+
+ return 1;
+}
+
+static void config(struct rmi_sensor_driver *sensor)
+{
+ /* For each data source we had detected print info and set up interrupts
+ or polling. */
+ struct rmi_function_info *functionInfo;
+ struct rmi_phys_driver *rpd;
+
+ rpd = sensor->rpd; /* get ptr to rmi_physical_driver from app */
+
+ list_for_each_entry(functionInfo, &sensor->functions, link) {
+ /* Get and print some info about the data sources... */
+ struct rmi_functions *fn;
+ bool found = false;
+ /* check if function number matches - if so call that
+ config function */
+ fn = rmi_find_function(functionInfo->functionNum);
+ if (fn) {
+ found = true;
+
+ if (fn->config) {
+ fn->config(functionInfo);
+ } else {
+ /* the developer did not add in the
+ pointer to the config function into
+ rmi4_supported_data_src_functions */
+ printk(KERN_ERR
+ "%s: no config function for "
+ "function 0x%x\n",
+ __func__, functionInfo->functionNum);
+ break;
+ }
+ }
+
+ if (!found) {
+ /* if no support found for this RMI4 function
+ it means the developer did not add the
+ appropriate function pointer list into the
+ rmi4_supported_data_src_functions array and/or
+ did not bump up the number of supported RMI4
+ functions in rmi.h as required */
+ printk(KERN_ERR "%s: could not find support "
+ "for function 0x%x\n",
+ __func__, functionInfo->functionNum);
+ }
+ }
+
+ /* This will handle interrupts on the ATTN line (interrupt driven)
+ * or will be called every poll interval (when we're not interrupt
+ * driven).
+ */
+ INIT_WORK(&sensor->work, sensor_work_func);
+ sensor->workIsReady = true;
+
+ if (rmi_polling_required(sensor)) {
+ /* We're polling driven, so set up the polling timer
+ and timer function. */
+ hrtimer_init(&sensor->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ sensor->timer.function = sensor_poll_timer_func;
+ hrtimer_start(&sensor->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+}
+
+/** Just a stub for now.
+ */
+static int rmi_sensor_suspend(struct device *dev, pm_message_t state)
+{
+ printk(KERN_INFO "%s: sensor suspend called.", __func__);
+ return 0;
+}
+
+/** Just a stub for now.
+ */
+static int rmi_sensor_resume(struct device *dev)
+{
+ printk(KERN_INFO "%s: sensor resume called.", __func__);
+ return 0;
+}
+
+/*
+ * This method is called, whenever a new sensor device is added for the rmi
+ * bus.
+ *
+ * It will scan the devices PDT to determine the supported functions
+ * and create a new function device for each of these. It will read
+ * the query, control, command and data regsiters for the function
+ * to be used for each newly created function device.
+ *
+ * The sensor device is then bound to every function it supports.
+ *
+ */
+int rmi_sensor_register_functions(struct rmi_sensor_driver *sensor)
+{
+ struct rmi_function_device *function;
+ unsigned int interruptRegisterCount;
+ struct rmi_phys_driver *rpd;
+ int i;
+ unsigned char interruptCount;
+ struct rmi_function_info *functionInfo;
+ struct rmi_function_descriptor rmi_fd;
+ struct rmi_functions *fn;
+ int retval;
+
+ pr_debug("%s: Registering sensor functions\n", __func__);
+
+ retval = 0;
+
+ /* Scan device for functions that may be supported */
+ {
+ pr_debug("%s: Scanning sensor for Functions:\n", __func__);
+
+ interruptCount = 0;
+ rpd = sensor->rpd;
+
+ /* Read the Page Descriptor Table to determine what functions
+ * are present */
+
+ printk(KERN_DEBUG "%s: Scanning page descriptors.", __func__);
+ for (i = PDT_START_SCAN_LOCATION;
+ i >= PDT_END_SCAN_LOCATION;
+ i -= PDT_ENTRY_SIZE) {
+ printk(KERN_DEBUG "%s: Reading page descriptor 0x%02x", __func__, i);
+ retval = rpd->read_multiple(rpd, i, (char *)&rmi_fd,
+ sizeof(rmi_fd));
+ if (!retval) {
+ functionInfo = NULL;
+
+ if (rmi_fd.functionNum != 0x00 && rmi_fd.functionNum != 0xff) {
+ printk(KERN_DEBUG "%s: F%02x - queries %02x commands %02x control %02x data %02x ints %02x", __func__, rmi_fd.functionNum, rmi_fd.queryBaseAddr, rmi_fd.commandBaseAddr, rmi_fd.controlBaseAddr, rmi_fd.dataBaseAddr, rmi_fd.interruptSrcCnt);
+
+ if ((rmi_fd.functionNum & 0xff) == 0x01)
+ printk(KERN_DEBUG "%s: Fn $01 Found - RMI Device Control", __func__);
+
+ /* determine if the function is supported and if so
+ * then bind this function device to the sensor */
+ if (rmi_fd.interruptSrcCnt) {
+ functionInfo = kzalloc(sizeof(*functionInfo), GFP_KERNEL);
+ if (!functionInfo) {
+ printk(KERN_ERR "%s: could not allocate memory for function 0x%x.",
+ __func__, rmi_fd.functionNum);
+ retval = -ENOMEM;
+ goto exit_fail;
+ }
+ functionInfo->sensor = sensor;
+ functionInfo->functionNum = (rmi_fd.functionNum & 0xff);
+ INIT_LIST_HEAD(&functionInfo->link);
+ /* Get the ptr to the detect function based on
+ * the function number */
+ printk(KERN_DEBUG "%s: Checking for RMI function F%02x.", __func__, rmi_fd.functionNum);
+ fn = rmi_find_function(rmi_fd.functionNum);
+ if (fn) {
+ retval = fn->detect(functionInfo, &rmi_fd,
+ interruptCount);
+ if (retval)
+ printk(KERN_ERR "%s: Function detect for F%02x failed with %d.",
+ __func__, rmi_fd.functionNum, retval);
+
+ /* Create a function device and function driver for this Fn */
+ function = kzalloc(sizeof(*function), GFP_KERNEL);
+ if (!function) {
+ printk(KERN_ERR "%s: Error allocating memory for rmi_function_device.", __func__);
+ return -ENOMEM;
+ }
+
+ function->dev.parent = &sensor->sensor_device->dev;
+ function->dev.bus = sensor->sensor_device->dev.bus;
+ function->rmi_funcs = fn;
+ function->sensor = sensor;
+ function->rfi = functionInfo;
+ functionInfo->function_device = function;
+
+ /* Check if we have an interrupt mask of 0 and a non-NULL interrupt
+ handler function and print a debug message since we should never
+ have this.
+ */
+ if (functionInfo->interruptMask == 0 && fn->inthandler != NULL) {
+ printk(KERN_DEBUG "%s: Can't have a zero interrupt mask for function F%02x (which requires an interrupt handler).\n",
+ __func__, rmi_fd.functionNum);
+ }
+
+
+ /* Check if we have a non-zero interrupt mask and a NULL interrupt
+ handler function and print a debug message since we should never
+ have this.
+ */
+ if (functionInfo->interruptMask != 0 && fn->inthandler == NULL) {
+ printk(KERN_DEBUG "%s: Can't have a non-zero interrupt mask %d for function F%02x with a NULL inthandler fn.\n",
+ __func__, functionInfo->interruptMask, rmi_fd.functionNum);
+ }
+
+ /* Register the rmi function device */
+ retval = rmi_function_register_device(function, rmi_fd.functionNum);
+ if (retval) {
+ printk(KERN_ERR "%s: Failed rmi_function_register_device.\n",
+ __func__);
+ return retval;
+ }
+ } else {
+ printk(KERN_ERR "%s: could not find support for function 0x%02X.\n",
+ __func__, rmi_fd.functionNum);
+ }
+ } else {
+ printk(KERN_DEBUG "%s: Found function F%02x - Ignored.\n", __func__, rmi_fd.functionNum & 0xff);
+ }
+
+ /* bump interrupt count for next iteration */
+ /* NOTE: The value 7 is reserved - for now, only bump up one for an interrupt count of 7 */
+ if ((rmi_fd.interruptSrcCnt & 0x7) == 0x7) {
+ interruptCount += 1;
+ } else {
+ interruptCount +=
+ (rmi_fd.interruptSrcCnt & 0x7);
+ }
+
+ /* link this function info to the RMI module infos list
+ of functions */
+ if (functionInfo == NULL) {
+ printk(KERN_DEBUG "%s: WTF? functionInfo is null here.", __func__);
+ } else {
+ printk(KERN_DEBUG "%s: Adding function F%02x with %d sources.\n",
+ __func__, functionInfo->functionNum, functionInfo->numSources);
+
+ mutex_lock(&rfi_mutex);
+ list_add_tail(&functionInfo->link,
+ &sensor->functions);
+ mutex_unlock(&rfi_mutex);
+ }
+
+ } else {
+ /* A zero or 0xff in the function number
+ signals the end of the PDT */
+ printk(KERN_DEBUG "%s: Found End of PDT\n",
+ __func__);
+ break;
+ }
+ } else {
+ /* failed to read next PDT entry - end PDT
+ scan - this may result in an incomplete set
+ of recognized functions - should probably
+ return an error but the driver may still be
+ viable for diagnostics and debugging so let's
+ let it continue. */
+ printk(KERN_ERR "%s: Read Error %d when reading next PDT entry - "
+ "ending PDT scan.\n",
+ __func__, retval);
+ break;
+ }
+ }
+ printk(KERN_DEBUG "%s: Done scanning.", __func__);
+
+ /* calculate the interrupt register count - used in the
+ ISR to read the correct number of interrupt registers */
+ interruptRegisterCount = (interruptCount + 7) / 8;
+ sensor->interruptRegisterCount = interruptRegisterCount; /* TODO: Is this needed by the sensor anymore? */
+ }
+
+ return 0;
+
+exit_fail:
+ return retval;
+}
+EXPORT_SYMBOL(rmi_sensor_register_functions);
+
+int rmi_sensor_register_device(struct rmi_sensor_device *dev, int index)
+{
+ int status;
+
+ printk(KERN_INFO "%s: Registering sensor device.\n", __func__);
+
+ /* make name - sensor00, sensor01, etc. */
+ dev_set_name(&dev->dev, "sensor%02d", index);
+ status = device_register(&dev->dev);
+
+ return status;
+}
+EXPORT_SYMBOL(rmi_sensor_register_device);
+
+static void rmi_sensor_unregister_device(struct rmi_sensor_device *rmisensordev)
+{
+ printk(KERN_INFO "%s: Unregistering sensor device.\n", __func__);
+
+ device_unregister(&rmisensordev->dev);
+}
+EXPORT_SYMBOL(rmi_sensor_unregister_device);
+
+int rmi_sensor_register_driver(struct rmi_sensor_driver *driver)
+{
+ static int index;
+ int ret;
+ char *drvrname;
+
+ driver->workIsReady = false;
+
+ printk(KERN_INFO "%s: Registering sensor driver.\n", __func__);
+ driver->dispatchIRQs = dispatchIRQs;
+ driver->attention = attention;
+ driver->config = config;
+ driver->probe = probe;
+
+ /* assign the bus type for this driver to be rmi bus */
+ driver->drv.bus = &rmi_bus_type;
+ driver->drv.suspend = rmi_sensor_suspend;
+ driver->drv.resume = rmi_sensor_resume;
+ /* Create a function device and function driver for this Fn */
+ drvrname = kzalloc(sizeof(sensorname) + 4, GFP_KERNEL);
+ if (!drvrname) {
+ printk(KERN_ERR "%s: Error allocating memeory for rmi_sensor_driver name.\n", __func__);
+ return -ENOMEM;
+ }
+ sprintf(drvrname, "sensor%02d", index++);
+
+ driver->drv.name = drvrname;
+ driver->module = driver->drv.owner;
+
+ /* register the sensor driver */
+ ret = driver_register(&driver->drv);
+ if (ret) {
+ printk(KERN_ERR "%s: Failed driver_register %d\n",
+ __func__, ret);
+ goto exit_fail;
+ }
+
+ /* register the functions on the sensor */
+ ret = rmi_sensor_register_functions(driver);
+ if (ret) {
+ printk(KERN_ERR "%s: Failed rmi_sensor_register_functions %d\n",
+ __func__, ret);
+ }
+
+ /* configure the sensor - enable interrupts for each function, init work, set polling timer or adjust report rate, etc. */
+ config(driver);
+
+ printk(KERN_DEBUG "%s: sensor driver registration completed.", __func__);
+
+exit_fail:
+ return ret;
+}
+EXPORT_SYMBOL(rmi_sensor_register_driver);
+
+static void rmi_sensor_unregister_driver(struct rmi_sensor_driver *driver)
+{
+ printk(KERN_DEBUG "%s: Unregistering sensor driver.\n", __func__);
+
+ /* Stop the polling timer if doing polling */
+ if (rmi_polling_required(driver))
+ hrtimer_cancel(&driver->timer);
+
+ flush_scheduled_work(); /* Make sure all scheduled work is stopped */
+
+ driver_unregister(&driver->drv);
+}
+EXPORT_SYMBOL(rmi_sensor_unregister_driver);
+
+
+static int __init rmi_sensor_init(void)
+{
+ printk(KERN_DEBUG "%s: RMI Sensor Init\n", __func__);
+ return 0;
+}
+
+static void __exit rmi_sensor_exit(void)
+{
+ printk(KERN_DEBUG "%s: RMI Sensor Driver Exit\n", __func__);
+ flush_scheduled_work(); /* Make sure all scheduled work is stopped */
+}
+
+
+module_init(rmi_sensor_init);
+module_exit(rmi_sensor_exit);
+
+MODULE_AUTHOR("Synaptics, Inc.");
+MODULE_DESCRIPTION("RMI4 Sensor Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/synaptics/rmi_sensor.h b/drivers/input/touchscreen/synaptics/rmi_sensor.h
new file mode 100644
index 0000000..63d2555
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_sensor.h
@@ -0,0 +1,143 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) - RMI Sensor Module Header.
+ * Copyright (C) 2007 - 2011, Synaptics Incorporated
+ *
+ */
+/*
+ *
+ * This file is licensed under the GPL2 license.
+ *
+ *############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *############################################################################
+ */
+
+#include <linux/device.h>
+
+#ifndef _RMI_SENSOR_H
+#define _RMI_SENSOR_H
+
+#include <linux/input/rmi_platformdata.h>
+
+struct rmi_sensor_driver {
+ struct module *module;
+ struct device_driver drv;
+ struct rmi_sensor_device *sensor_device;
+
+ /* Attention Function
+ * This function is called by the low level isr in the physical
+ * driver. It merely schedules work to be done.
+ */
+ void (*attention)(struct rmi_phys_driver *physdrvr, int instance);
+ /* Probe Function
+ * This function is called to give the sensor driver layer an
+ * opportunity to claim an RMI device. The sensor layer cannot
+ * read RMI registers at this point since the rmi physical driver
+ * has not been bound to it yet. Defer that to the config
+ * function call which occurs immediately after a successful probe.
+ */
+ int (*probe)(struct rmi_sensor_driver *sensor);
+ /* Config Function
+ * This function is called after a successful probe. It gives the
+ * sensor driver an opportunity to query and/or configure an RMI
+ * device before data starts flowing.
+ */
+ void (*config)(struct rmi_sensor_driver *sensor);
+
+ /* Functions can call this in order to dispatch IRQs. */
+ void (*dispatchIRQs)(struct rmi_sensor_driver *sensor,
+ unsigned int irqStatus);
+
+ /* Register Functions
+ * This function is called in the rmi bus
+ * driver to have the sensor driver scan for any supported
+ * functions on the sensor and add devices for each one.
+ */
+ void (*rmi_sensor_register_functions)(struct rmi_sensor_driver
+ *sensor);
+
+ unsigned int interruptRegisterCount;
+
+ bool polling_required;
+
+ /* pointer to the corresponding phys driver info for this sensor */
+ /* The phys driver has the pointers to read, write, etc. */
+ struct rmi_phys_driver *rpd;
+
+ struct hrtimer timer;
+ struct work_struct work;
+ bool workIsReady;
+
+ /* This list is for keeping around the list of sensors.
+ * Every time that a physical device is detected by the
+ * physical layer - be it i2c, spi, or some other - then
+ * we need to bind the physical layer to the device. When
+ * the Page Descriptor Table is scanned and when Function $01
+ * is found then a new sensor device is created. The corresponding
+ * rmi_phys_driver struct pointer needs to be bound to the new
+ * sensor since Function $01 will be used to control and get
+ * interrupt information about the particular data source that is
+ * doing the interrupt. The rmi_phys_driver contains the pointers
+ * to the particular read, write, read_multiple, write_multiple
+ * functions for this device. This rmi_phys_driver struct will
+ * have to be up-bound to any drivers upstream that need it.
+ */
+
+ /* Standard kernel linked list implementation.
+ * Documentation on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head sensor_drivers; /* link sensor drivers into list */
+
+ struct list_head functions; /* List of rmi_function_infos */
+ /* Per function initialization data. */
+ struct rmi_functiondata_list *perfunctiondata;
+};
+
+/* macro to get the pointer to the device_driver struct from the sensor */
+#define to_rmi_sensor_driver(drv) container_of(drv, \
+ struct rmi_sensor_driver, drv);
+
+struct rmi_sensor_device {
+ struct rmi_sensor_driver *driver;
+ struct device dev;
+
+ /* Standard kernel linked list implementation.
+ * Documentation on how to use it can be found at
+ * http://isis.poly.edu/kulesh/stuff/src/klist/.
+ */
+ struct list_head sensors; /* link sensors into list */
+};
+
+int rmi_sensor_register_device(struct rmi_sensor_device *dev, int index);
+int rmi_sensor_register_driver(struct rmi_sensor_driver *driver);
+int rmi_sensor_register_functions(struct rmi_sensor_driver *sensor);
+bool rmi_polling_required(struct rmi_sensor_driver *sensor);
+
+static inline void *rmi_sensor_get_functiondata(struct rmi_sensor_driver
+ *driver, unsigned char function_index)
+{
+ int i;
+ if (driver->perfunctiondata) {
+ for (i = 0; i < driver->perfunctiondata->count; i++) {
+ if (driver->perfunctiondata->functiondata[i].
+ function_index == function_index)
+ return driver->perfunctiondata->
+ functiondata[i].data;
+ }
+ }
+ return NULL;
+}
+
+#endif
diff --git a/drivers/input/touchscreen/synaptics/rmi_spi.c b/drivers/input/touchscreen/synaptics/rmi_spi.c
new file mode 100644
index 0000000..d6b247d
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_spi.c
@@ -0,0 +1,616 @@
+/**
+ *
+ * Synaptics Register Mapped Interface (RMI4) SPI Physical Layer Driver.
+ * Copyright (C) 2008-2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *############################################################################
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+#include <linux/platform_device.h>
+#include <linux/semaphore.h>
+#include <linux/spi/spi.h>
+#include <linux/input/rmi_platformdata.h>
+#include "rmi_spi.h"
+#include "rmi_drvr.h"
+
+#define COMM_DEBUG 1 /* Set to 1 to dump transfers. */
+
+/* 65 microseconds inter-byte delay between bytes for RMI chip*/
+#define RMI_DEFAULT_BYTE_DELAY_US 0 /* 65 */
+#define SPI_BUFFER_SIZE 32
+
+static u8 *buf;
+
+/* This is the data kept on a per instance (client) basis. This data is
+ * always accessible by using the container_of() macro of the various elements
+ * inside.
+ */
+struct spi_device_instance_data {
+ int instance_no;
+ int irq;
+ unsigned int byte_delay_us;
+ struct rmi_phys_driver rpd;
+ struct spi_device *spidev;
+ struct rmi_spi_platformdata *platformdata;
+};
+
+static int spi_xfer(struct spi_device_instance_data *instance_data,
+ const u8 *txbuf, unsigned n_tx, u8 *rxbuf, unsigned n_rx)
+{
+ struct spi_device *spi = instance_data->spidev;
+#if COMM_DEBUG
+ int i;
+#endif
+ int status;
+ struct spi_message message;
+ struct spi_transfer *xfer_list;
+ u8 *local_buf;
+ int nXfers = 0;
+ int xfer_index = 0;
+
+ if ((n_tx + n_rx) > SPI_BUFFER_SIZE)
+ return -EINVAL;
+
+ if (n_tx)
+ nXfers += 1;
+ if (n_rx) {
+ if (instance_data->byte_delay_us)
+ nXfers += n_rx;
+ else
+ nXfers += 1;
+ }
+
+ xfer_list = kcalloc(nXfers, sizeof(struct spi_transfer), GFP_KERNEL);
+ if (!xfer_list)
+ return -ENOMEM;
+
+ /* ... unless someone else is using the pre-allocated buffer */
+ local_buf = kzalloc(SPI_BUFFER_SIZE, GFP_KERNEL);
+ if (!local_buf) {
+ kfree(xfer_list);
+ return -ENOMEM;
+ }
+
+ spi_message_init(&message);
+
+ if (n_tx) {
+ memset(&xfer_list[0], 0, sizeof(struct spi_transfer));
+ xfer_list[0].len = n_tx;
+ xfer_list[0].delay_usecs = instance_data->byte_delay_us;
+ spi_message_add_tail(&xfer_list[0], &message);
+ memcpy(local_buf, txbuf, n_tx);
+ xfer_list[0].tx_buf = local_buf;
+ xfer_index++;
+ }
+ if (n_rx) {
+ if (instance_data->byte_delay_us) {
+ int buffer_offset = n_tx;
+ for (; xfer_index < nXfers; xfer_index++) {
+ memset(&xfer_list[xfer_index], 0,
+ sizeof(struct spi_transfer));
+ xfer_list[xfer_index].len = 1;
+ xfer_list[xfer_index].delay_usecs =
+ instance_data->byte_delay_us;
+ xfer_list[xfer_index].rx_buf =
+ local_buf + buffer_offset;
+ buffer_offset++;
+ spi_message_add_tail(&xfer_list[xfer_index],
+ &message);
+#ifdef CONFIG_ARCH_OMAP
+ printk(KERN_INFO "%s: Did you compensate for
+ ARCH_OMAP?", __func__);
+/* x[1].len = n_rx-1; */ /* since OMAP has one dummy byte. */
+#else
+/* x[1].len = n_rx; */
+#endif
+ }
+ } else {
+ memset(&xfer_list[xfer_index], 0, sizeof(struct
+ spi_transfer));
+#ifdef CONFIG_ARCH_OMAP
+ /* since OMAP has one dummy byte. */
+ xfer_list[xfer_index].len = n_rx-1;
+#else
+ xfer_list[xfer_index].len = n_rx;
+#endif
+ xfer_list[xfer_index].rx_buf = local_buf + n_tx;
+ spi_message_add_tail(&xfer_list[xfer_index],
+ &message);
+ xfer_index++;
+ }
+ }
+ printk(KERN_INFO "%s: Ready to go, xfer_index = %d, nXfers = %d.",
+ __func__, xfer_index, nXfers);
+#if COMM_DEBUG
+ printk(KERN_INFO "%s: SPI transmits %d bytes...", __func__, n_tx);
+ for (i = 0; i < n_tx; i++)
+ printk(KERN_INFO " 0x%02X", local_buf[i]);
+#endif
+
+ /* do the i/o */
+ status = spi_sync(spi, &message);
+ if (status == 0) {
+ memcpy(rxbuf, local_buf + n_tx, n_rx);
+ status = message.status;
+#if COMM_DEBUG
+ if (n_rx) {
+ printk(KERN_INFO "%s: SPI received %d bytes...",
+ __func__, n_rx);
+ for (i = 0; i < n_rx; i++)
+ printk(KERN_INFO " 0x%02X", rxbuf[i]);
+ }
+#endif
+ } else {
+ printk(KERN_ERR "%s: spi_sync failed with error code %d.",
+ __func__, status);
+ }
+
+ kfree(local_buf);
+ kfree(xfer_list);
+
+ return status;
+}
+
+/**
+ * Read a single register through spi.
+ * \param[in] pd
+ * \param[in] address The address at which to start the data read.
+ * \param[out] valp Pointer to the buffer where the data will be stored.
+ * \return zero upon success (with the byte read in valp),non-zero upon error.
+ */
+static int
+rmi_spi_read(struct rmi_phys_driver *pd, unsigned short address, char *valp)
+{
+ struct spi_device_instance_data *id =
+ container_of(pd, struct spi_device_instance_data, rpd);
+
+ char rxbuf[2];
+ int retval;
+ unsigned short addr = address;
+
+ addr = ((addr & 0xff00) >> 8);
+ address = ((address & 0x00ff) << 8);
+ addr |= address;
+ addr |= 0x80; /* High bit set indicates read. */
+
+ retval = spi_xfer(id, (u8 *)&addr, 2, rxbuf, 1);
+
+ *valp = rxbuf[0];
+
+ return retval;
+}
+
+/**
+ * Same as rmi_spi_read, except that multiple bytes are allowed to be read.
+ * \param[in] pd
+ * \param[in] address The address at which to start the data read.
+ * \param[out] valp Pointer to the buffer where the data will be stored. This
+ * buffer must be at least size bytes long.
+ * \param[in] size The number of bytes to be read.
+ * \return zero upon success(with the byte read in valp), non-zero upon error.
+ */
+static int
+rmi_spi_read_multiple(struct rmi_phys_driver *pd, unsigned short address,
+ char *valp, int size)
+{
+ struct spi_device_instance_data *id =
+ container_of(pd, struct spi_device_instance_data, rpd);
+ int retval;
+
+ unsigned short addr = address;
+
+ addr = ((addr & 0xff00) >> 8);
+ address = ((address & 0x00ff) << 8);
+ addr |= address;
+ addr |= 0x80; /* High bit set indicates read. */
+
+ retval = spi_xfer(id, (u8 *)&addr, 2, valp, size);
+
+ return retval;
+}
+
+/**
+ * Write a single register through spi.
+ * You can write multiple registers at once, but I made the functions for that
+ * seperate for performance reasons. Writing multiple requires allocation and
+ * freeing.
+ * \param[in] pd
+ * \param[in] address The address at which to start the write.
+ * \param[in] data The data to be written.
+ * \return one upon success, something else upon error.
+ */
+static int
+rmi_spi_write(struct rmi_phys_driver *pd, unsigned short address, char data)
+{
+ struct spi_device_instance_data *id =
+ container_of(pd, struct spi_device_instance_data, rpd);
+ unsigned char txbuf[4];
+ int retval;
+
+ txbuf[2] = data;
+ txbuf[1] = address;
+ txbuf[0] = address>>8;
+
+ retval = spi_xfer(id, txbuf, 3, NULL, 0);
+ return retval ? 0 : 1;
+}
+
+/**
+ * Write multiple registers.
+ * \param[in] pd
+ * \param[in] address The address at which to start the write.
+ * \param[in] valp A pointer to a buffer containing the data to be written.
+ * \param[in] size The number of bytes to write.
+ * \return one upon success, something else upon error.
+ */
+static int
+rmi_spi_write_multiple(struct rmi_phys_driver *pd, unsigned short address,
+ char *valp, int size)
+{
+ struct spi_device_instance_data *id =
+ container_of(pd, struct spi_device_instance_data, rpd);
+ unsigned char txbuf[32];
+ int retval;
+ int i;
+
+ txbuf[1] = address;
+ txbuf[0] = address>>8;
+
+ for (i = 0; i < size; i++)
+ txbuf[i + 2] = valp[i];
+
+ retval = spi_xfer(id, txbuf, size+2, NULL, 0);
+
+ return retval ? 0 : 1;
+}
+
+/**
+ * This is the Interrupt Service Routine.
+ * It just notifies the physical device
+ * that attention is required.
+ */
+static irqreturn_t spi_attn_isr(int irq, void *info)
+{
+ struct spi_device_instance_data *instance_data = info;
+ disable_irq_nosync(instance_data->irq);
+ if (instance_data->rpd.attention)
+ instance_data->rpd.attention(&instance_data->rpd,
+ instance_data->instance_no);
+ return IRQ_HANDLED;
+}
+
+/* TODO: Move this to rmi_bus, and call a function to get the next sensorID
+ */
+static int sensor_count;
+
+static int __devinit rmi_spi_probe(struct spi_device *spi)
+{
+ struct spi_device_instance_data *instance_data;
+ int retval;
+ struct rmi_spi_platformdata *platformdata;
+ struct rmi_sensordata *sensordata;
+ int irqtype = 0;
+
+ printk(KERN_INFO "Probing RMI4 SPI device\n");
+
+ /* This should have already been set up in the board file,
+ shouldn't it? */
+ spi->bits_per_word = 8;
+
+ spi->mode = SPI_MODE_3;
+
+ retval = spi_setup(spi);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: spi_setup failed with %d.", __func__,
+ retval);
+ return retval;
+ }
+
+ buf = kzalloc(SPI_BUFFER_SIZE, GFP_KERNEL);
+ if (!buf) {
+ printk(KERN_ERR "%s: Failed to allocate memory for spi
+ buffer.", __func__);
+ return -ENOMEM;
+ }
+
+ instance_data = kzalloc(sizeof(*instance_data), GFP_KERNEL);
+ if (!instance_data) {
+ printk(KERN_ERR "%s: Failer to allocate memory for instance
+ data.", __func__);
+ return -ENOMEM;
+ }
+
+ instance_data->byte_delay_us = RMI_DEFAULT_BYTE_DELAY_US;
+ instance_data->spidev = spi;
+ instance_data->rpd.name = RMI4_SPI_DRIVER_NAME;
+ instance_data->rpd.write = rmi_spi_write;
+ instance_data->rpd.read = rmi_spi_read;
+ instance_data->rpd.write_multiple = rmi_spi_write_multiple;
+ instance_data->rpd.read_multiple = rmi_spi_read_multiple;
+ instance_data->rpd.module = THIS_MODULE;
+ /* default to polling if irq not used */
+ instance_data->rpd.polling_required = true;
+
+ platformdata = spi->dev.platform_data;
+ if (platformdata == NULL) {
+ printk(KERN_ERR "%s: CONFIGURATION ERROR - platform data
+ is NULL.", __func__);
+ return -EINVAL;
+ }
+
+ instance_data->platformdata = platformdata;
+ sensordata = platformdata->sensordata;
+
+ /* Call the platform setup routine, to do any setup that is required
+ * before
+ * interacting with the device.
+ */
+ if (sensordata && sensordata->rmi_sensor_setup) {
+ retval = sensordata->rmi_sensor_setup();
+ if (retval) {
+ printk(KERN_ERR "%s: sensor setup failed with
+ code %d.", __func__, retval);
+ kfree(instance_data);
+ return retval;
+ }
+ }
+
+ /* TODO: I think this if is no longer required. */
+ if (platformdata->chip == RMI_SUPPORT) {
+ instance_data->instance_no = sensor_count;
+ sensor_count++;
+
+ /* set the device name using the instance_no
+ * appended to DEVICE_NAME to make a unique name
+ */
+ dev_set_name(&spi->dev, "%s%d", RMI4_SPI_DEVICE_NAME,
+ instance_data->instance_no);
+ /*
+ * Determine if we need to poll (inefficient) or
+ * use interrupts.
+ */
+ if (platformdata->irq) {
+ switch (platformdata->irq_type) {
+ case IORESOURCE_IRQ_HIGHEDGE:
+ irqtype = IRQF_TRIGGER_RISING;
+ break;
+ case IORESOURCE_IRQ_LOWEDGE:
+ irqtype = IRQF_TRIGGER_FALLING;
+ break;
+ case IORESOURCE_IRQ_HIGHLEVEL:
+ irqtype = IRQF_TRIGGER_HIGH;
+ break;
+ case IORESOURCE_IRQ_LOWLEVEL:
+ irqtype = IRQF_TRIGGER_LOW;
+ break;
+ default:
+ dev_warn(&spi->dev, "%s: Invalid IRQ flags
+ in platform data.", __func__);
+ retval = -ENXIO;
+ goto error_exit;
+ }
+/*
+ retval = request_irq(instance_data->irq, spi_attn_isr,
+ irqtype, "rmi_spi", instance_data);
+ if (retval) {
+ dev_info(&spi->dev, "%s: Unable to get attn
+ irq %d. Reverting to polling. ", __func__,
+ instance_data->irq);
+ instance_data->rpd.polling_required = true;
+ } else {
+ dev_dbg(&spi->dev, "%s: got irq", __func__);
+ instance_data->rpd.polling_required = false;
+ instance_data->rpd.irq = instance_data->irq;
+ }
+*/
+ instance_data->rpd.polling_required = false;
+ } else {
+ instance_data->rpd.polling_required = true;
+ dev_info(&spi->dev, "%s: No IRQ info given.
+ Polling required.", __func__);
+ }
+ }
+
+ /* Store instance data for later access. */
+ if (instance_data)
+ spi_set_drvdata(spi, instance_data);
+
+ /* Register the sensor driver -
+ * which will trigger a scan of the PDT.
+ */
+ retval = rmi_register_sensor(&instance_data->rpd,
+ platformdata->sensordata);
+ if (retval) {
+ printk(KERN_ERR "%s: sensor registration failed with code
+ %d.", __func__, retval);
+ goto error_exit;
+ }
+
+ if (instance_data->rpd.polling_required == false) {
+ instance_data->irq = platformdata->irq;
+ retval = request_irq(platformdata->irq, spi_attn_isr,
+ irqtype, dev_name(&spi->dev), instance_data);
+ if (retval) {
+ dev_err(&spi->dev, "%s: failed to obtain IRQ %d.
+ Result: %d.", __func__,
+ platformdata->irq, retval);
+ dev_info(&spi->dev, "%s: Reverting to polling.\n",
+ __func__);
+ instance_data->rpd.polling_required = true;
+ instance_data->irq = 0;
+ /* TODO: Need to revert back to polling
+ * - create and start timer.
+ */
+ } else {
+ dev_dbg(&spi->dev, "%s: got irq.\n", __func__);
+ instance_data->rpd.irq = instance_data->irq;
+ }
+ }
+
+ printk(KERN_INFO "%s: Successfully Registered %s.",
+ __func__, instance_data->rpd.name);
+
+ return 0;
+
+error_exit:
+ if (sensordata && sensordata->rmi_sensor_teardown)
+ sensordata->rmi_sensor_teardown();
+ if (instance_data->irq)
+ free_irq(instance_data->irq, instance_data);
+ kfree(instance_data);
+ return retval;
+}
+
+static int rmi_spi_suspend(struct spi_device *spi, pm_message_t message)
+{
+ printk(KERN_INFO "%s: Suspending...", __func__);
+ return 0;
+}
+
+static int rmi_spi_resume(struct spi_device *spi)
+{
+ printk(KERN_INFO "%s: Resuming...", __func__);
+ return 0;
+}
+
+static int __devexit rmi_spi_remove(struct spi_device *spi)
+{
+ struct spi_device_instance_data *id = spi_get_drvdata(spi);
+
+ printk(KERN_INFO "%s: RMI SPI device removed.", __func__);
+
+ rmi_spi_suspend(spi, PMSG_SUSPEND);
+
+ rmi_unregister_sensors(&id->rpd);
+
+ if (id) {
+ if (id->irq)
+ free_irq(id->irq, id);
+ kfree(id);
+ }
+
+ return 0;
+}
+
+static struct spi_driver rmi_spi_driver = {
+ .driver = {
+ .name = RMI4_SPI_DRIVER_NAME,
+ .bus = &spi_bus_type,
+ .owner = THIS_MODULE,
+ },
+ .probe = rmi_spi_probe,
+ .remove = __devexit_p(rmi_spi_remove),
+ .suspend = rmi_spi_suspend,
+ .resume = rmi_spi_resume,
+};
+
+/**
+ * The Platform Driver probe function. We just tell the spi subsystem about
+ * ourselves in this call.
+ */
+static int
+rmi_spi_plat_probe(struct platform_device *dev)
+{
+ struct rmi_spi_platformdata *platform_data = dev->dev.platform_data;
+
+ printk(KERN_INFO "%s: Platform driver probe.", __func__);
+
+ if (!platform_data) {
+ printk(KERN_ERR "A platform device must contain
+ rmi_spi_platformdata\n");
+ return -ENXIO;
+ }
+
+ return spi_register_driver(&rmi_spi_driver);
+}
+
+/**
+ * Tell the spi subsystem that we're done.
+ * \param[in] dev
+ * \return Always returns 0.
+ */
+static int
+rmi_spi_plat_remove(struct platform_device *dev)
+{
+ printk(KERN_INFO "%s: Platform driver removed.", __func__);
+ spi_unregister_driver(&rmi_spi_driver);
+ return 0;
+}
+
+/**
+ * Structure used to tell the Platform Driver subsystem about us.
+ */
+static struct platform_driver rmi_spi_platform_driver = {
+ .driver = {
+ .name = RMI4_SPI_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = rmi_spi_plat_probe,
+ .remove = __devexit_p(rmi_spi_plat_remove),
+};
+
+static int __init rmi_spi_init(void)
+{
+ int retval;
+
+ printk(KERN_INFO "%s: RMI SPI physical layer initialization.",
+ __func__);
+ retval = spi_register_driver(&rmi_spi_driver);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: Failed to register spi driver, code
+ = %d.", __func__, retval);
+ return retval;
+ }
+/*
+#else
+ retval = platform_driver_register(&rmi_spi_platform_driver);
+ if (retval < 0) {
+ printk(KERN_ERR "%s: Failed to register platform driver,
+ code = %d.", __func__, retval);
+ return retval;
+ }
+#endif
+*/
+ printk(KERN_INFO "%s: result = %d", __func__, retval);
+ return retval;
+}
+module_init(rmi_spi_init);
+
+static void __exit rmi_spi_exit(void)
+{
+ printk(KERN_INFO "%s: RMI SPI physical layer exits.", __func__);
+ kfree(buf);
+ buf = NULL;
+ platform_driver_unregister(&rmi_spi_platform_driver);
+}
+module_exit(rmi_spi_exit);
+
+/** Standard driver module information - the author of the module.
+ */
+MODULE_AUTHOR("Synaptics, Inc.");
+/** Standard driver module information - a summary description of this module.
+ */
+MODULE_DESCRIPTION("RMI4 Driver SPI Physical Layer");
+/** Standard driver module information - the license under which this module
+ * is included in the kernel.
+ */
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/synaptics/rmi_spi.h b/drivers/input/touchscreen/synaptics/rmi_spi.h
new file mode 100644
index 0000000..daeebed
--- /dev/null
+++ b/drivers/input/touchscreen/synaptics/rmi_spi.h
@@ -0,0 +1,57 @@
+/**
+ *
+ * Register Mapped Interface SPI Physical Layer Driver Header File.
+ * Copyright (C) 2008-2011, Synaptics Incorporated
+ *
+ */
+/*
+ * This file is licensed under the GPL2 license.
+ *
+ *#############################################################################
+ * GPL
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ *#############################################################################
+ */
+
+#if !defined(_RMI_SPI_H)
+#define _RMI_SPI_H
+
+#include <linux/input/rmi_platformdata.h>
+
+#define RMI_CHIP_VER_3 0
+#define RMI_CHIP_VER_4 1
+
+#define RMI_SUPPORT (RMI_CHIP_VER_3|RMI_CHIP_VER_4)
+
+#define RMI4_SPI_DRIVER_NAME "rmi4_ts"
+#define RMI4_SPI_DEVICE_NAME "rmi4_ts"
+
+/** Platform-specific configuration data.
+ * This structure is used by the platform-specific driver to designate
+ * specific information about the hardware. A platform client may supply
+ * an array of these to the rmi_phys_spi driver.
+ */
+struct rmi_spi_platformdata {
+ int chip;
+
+ /* The number of the irq. Set to zero if polling is required. */
+ int irq;
+
+ /* The type of the irq (e.g., IRQF_TRIGGER_FALLING). Only valid if
+ * irq != 0 */
+ int irq_type;
+
+ /* Use this to specify platformdata that is not I2C specific. */
+ struct rmi_sensordata *sensordata;
+};
+
+#endif
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c
index 1473d23..e59ca17 100644
--- a/drivers/input/touchscreen/tsc2007.c
+++ b/drivers/input/touchscreen/tsc2007.c
@@ -26,6 +26,12 @@
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/i2c/tsc2007.h>
+#include <linux/pm.h>
+
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#define TSC2007_SUSPEND_LEVEL 1
+#endif
#define TSC2007_MEASURE_TEMP0 (0x0 << 4)
#define TSC2007_MEASURE_AUX (0x2 << 4)
@@ -66,6 +72,7 @@
struct tsc2007 {
struct input_dev *input;
char phys[32];
+ struct delayed_work work;
struct i2c_client *client;
@@ -74,14 +81,25 @@
u16 max_rt;
unsigned long poll_delay;
unsigned long poll_period;
+ u16 min_x;
+ u16 max_x;
+ u16 min_y;
+ u16 max_y;
+ bool pendown;
int irq;
- wait_queue_head_t wait;
- bool stopped;
+ bool invert_x;
+ bool invert_y;
+ bool invert_z1;
+ bool invert_z2;
int (*get_pendown_state)(void);
void (*clear_penirq)(void);
+ int (*power_shutdown)(bool);
+#if defined(CONFIG_HAS_EARLYSUSPEND)
+ struct early_suspend early_suspend;
+#endif
};
static inline int tsc2007_xfer(struct tsc2007 *tsc, u8 cmd)
@@ -118,6 +136,18 @@
tc->z1 = tsc2007_xfer(tsc, READ_Z1);
tc->z2 = tsc2007_xfer(tsc, READ_Z2);
+ if (tsc->invert_x == true)
+ tc->x = MAX_12BIT - tc->x;
+
+ if (tsc->invert_y == true)
+ tc->y = MAX_12BIT - tc->y;
+
+ if (tsc->invert_z1 == true)
+ tc->z1 = MAX_12BIT - tc->z1;
+
+ if (tsc->invert_z2 == true)
+ tc->z2 = MAX_12BIT - tc->z2;
+
/* Prepare for next touch reading - power down ADC, enable PENIRQ */
tsc2007_xfer(tsc, PWRDOWN);
}
@@ -142,8 +172,25 @@
return rt;
}
-static bool tsc2007_is_pen_down(struct tsc2007 *ts)
+static void tsc2007_send_up_event(struct tsc2007 *tsc)
{
+ struct input_dev *input = tsc->input;
+
+ dev_dbg(&tsc->client->dev, "UP\n");
+
+ input_report_key(input, BTN_TOUCH, 0);
+ input_report_abs(input, ABS_PRESSURE, 0);
+ input_sync(input);
+}
+
+static void tsc2007_work(struct work_struct *work)
+{
+ struct tsc2007 *ts =
+ container_of(to_delayed_work(work), struct tsc2007, work);
+ bool debounced = false;
+ struct ts_event tc;
+ u32 rt;
+
/*
* NOTE: We can't rely on the pressure to determine the pen down
* state, even though this controller has a pressure sensor.
@@ -154,82 +201,79 @@
* The only safe way to check for the pen up condition is in the
* work function by reading the pen signal state (it's a GPIO
* and IRQ). Unfortunately such callback is not always available,
- * in that case we assume that the pen is down and expect caller
- * to fall back on the pressure reading.
+ * in that case we have rely on the pressure anyway.
*/
-
- if (!ts->get_pendown_state)
- return true;
-
- return ts->get_pendown_state();
-}
-
-static irqreturn_t tsc2007_soft_irq(int irq, void *handle)
-{
- struct tsc2007 *ts = handle;
- struct input_dev *input = ts->input;
- struct ts_event tc;
- u32 rt;
-
- while (!ts->stopped && tsc2007_is_pen_down(ts)) {
-
- /* pen is down, continue with the measurement */
- tsc2007_read_values(ts, &tc);
-
- rt = tsc2007_calculate_pressure(ts, &tc);
-
- if (rt == 0 && !ts->get_pendown_state) {
- /*
- * If pressure reported is 0 and we don't have
- * callback to check pendown state, we have to
- * assume that pen was lifted up.
- */
- break;
+ if (ts->get_pendown_state) {
+ if (unlikely(!ts->get_pendown_state())) {
+ tsc2007_send_up_event(ts);
+ ts->pendown = false;
+ goto out;
}
- if (rt <= ts->max_rt) {
- dev_dbg(&ts->client->dev,
- "DOWN point(%4d,%4d), pressure (%4u)\n",
- tc.x, tc.y, rt);
-
- input_report_key(input, BTN_TOUCH, 1);
- input_report_abs(input, ABS_X, tc.x);
- input_report_abs(input, ABS_Y, tc.y);
- input_report_abs(input, ABS_PRESSURE, rt);
-
- input_sync(input);
-
- } else {
- /*
- * Sample found inconsistent by debouncing or pressure is
- * beyond the maximum. Don't report it to user space,
- * repeat at least once more the measurement.
- */
- dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
- }
-
- wait_event_timeout(ts->wait, ts->stopped,
- msecs_to_jiffies(ts->poll_period));
+ dev_dbg(&ts->client->dev, "pen is still down\n");
}
- dev_dbg(&ts->client->dev, "UP\n");
+ tsc2007_read_values(ts, &tc);
- input_report_key(input, BTN_TOUCH, 0);
- input_report_abs(input, ABS_PRESSURE, 0);
- input_sync(input);
+ rt = tsc2007_calculate_pressure(ts, &tc);
+ if (rt > ts->max_rt) {
+ /*
+ * Sample found inconsistent by debouncing or pressure is
+ * beyond the maximum. Don't report it to user space,
+ * repeat at least once more the measurement.
+ */
+ dev_dbg(&ts->client->dev, "ignored pressure %d\n", rt);
+ debounced = true;
+ goto out;
- if (ts->clear_penirq)
- ts->clear_penirq();
+ }
- return IRQ_HANDLED;
+ if (rt) {
+ struct input_dev *input = ts->input;
+
+ if (!ts->pendown) {
+ dev_dbg(&ts->client->dev, "DOWN\n");
+
+ input_report_key(input, BTN_TOUCH, 1);
+ ts->pendown = true;
+ }
+
+ input_report_abs(input, ABS_X, tc.x);
+ input_report_abs(input, ABS_Y, tc.y);
+ input_report_abs(input, ABS_PRESSURE, rt);
+
+ input_sync(input);
+
+ dev_dbg(&ts->client->dev, "point(%4d,%4d), pressure (%4u)\n",
+ tc.x, tc.y, rt);
+
+ } else if (!ts->get_pendown_state && ts->pendown) {
+ /*
+ * We don't have callback to check pendown state, so we
+ * have to assume that since pressure reported is 0 the
+ * pen was lifted up.
+ */
+ tsc2007_send_up_event(ts);
+ ts->pendown = false;
+ }
+
+ out:
+ if (ts->pendown || debounced)
+ schedule_delayed_work(&ts->work,
+ msecs_to_jiffies(ts->poll_period));
+ else
+ enable_irq(ts->irq);
}
-static irqreturn_t tsc2007_hard_irq(int irq, void *handle)
+static irqreturn_t tsc2007_irq(int irq, void *handle)
{
struct tsc2007 *ts = handle;
- if (!ts->get_pendown_state || likely(ts->get_pendown_state()))
- return IRQ_WAKE_THREAD;
+ if (!ts->get_pendown_state || likely(ts->get_pendown_state())) {
+ disable_irq_nosync(ts->irq);
+ schedule_delayed_work(&ts->work,
+ msecs_to_jiffies(ts->poll_delay));
+ }
if (ts->clear_penirq)
ts->clear_penirq();
@@ -237,42 +281,85 @@
return IRQ_HANDLED;
}
-static void tsc2007_stop(struct tsc2007 *ts)
+static void tsc2007_free_irq(struct tsc2007 *ts)
{
- ts->stopped = true;
- mb();
- wake_up(&ts->wait);
-
- disable_irq(ts->irq);
+ free_irq(ts->irq, ts);
+ if (cancel_delayed_work_sync(&ts->work)) {
+ /*
+ * Work was pending, therefore we need to enable
+ * IRQ here to balance the disable_irq() done in the
+ * interrupt handler.
+ */
+ enable_irq(ts->irq);
+ }
}
-static int tsc2007_open(struct input_dev *input_dev)
+#ifdef CONFIG_PM
+static int tsc2007_suspend(struct device *dev)
{
- struct tsc2007 *ts = input_get_drvdata(input_dev);
- int err;
+ int rc;
+ struct tsc2007 *ts = dev_get_drvdata(dev);
- ts->stopped = false;
- mb();
+ disable_irq(ts->irq);
- enable_irq(ts->irq);
+ if (cancel_delayed_work_sync(&ts->work))
+ enable_irq(ts->irq);
- /* Prepare for touch readings - power down ADC and enable PENIRQ */
- err = tsc2007_xfer(ts, PWRDOWN);
- if (err < 0) {
- tsc2007_stop(ts);
- return err;
+ if (ts->power_shutdown) {
+ rc = ts->power_shutdown(true);
+ if (rc) {
+ pr_err("%s: Power off failed, suspend failed (%d)\n",
+ __func__, rc);
+ return rc;
+ }
}
return 0;
}
-static void tsc2007_close(struct input_dev *input_dev)
+static int tsc2007_resume(struct device *dev)
{
- struct tsc2007 *ts = input_get_drvdata(input_dev);
+ int rc;
+ struct tsc2007 *ts = dev_get_drvdata(dev);
- tsc2007_stop(ts);
+ if (ts->power_shutdown) {
+ rc = ts->power_shutdown(false);
+ if (rc) {
+ pr_err("%s: Power on failed, resume failed (%d)\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+
+ enable_irq(ts->irq);
+
+ return 0;
}
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void tsc2007_early_suspend(struct early_suspend *h)
+{
+ struct tsc2007 *ts = container_of(h, struct tsc2007, early_suspend);
+
+ tsc2007_suspend(&ts->client->dev);
+}
+
+static void tsc2007_late_resume(struct early_suspend *h)
+{
+ struct tsc2007 *ts = container_of(h, struct tsc2007, early_suspend);
+
+ tsc2007_resume(&ts->client->dev);
+}
+#endif
+
+static const struct dev_pm_ops tsc2007_pm_ops = {
+#ifndef CONFIG_HAS_EARLYSUSPEND
+ .suspend = tsc2007_suspend,
+ .resume = tsc2007_resume,
+#endif
+};
+#endif
+
static int __devinit tsc2007_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -300,7 +387,7 @@
ts->client = client;
ts->irq = client->irq;
ts->input = input_dev;
- init_waitqueue_head(&ts->wait);
+ INIT_DELAYED_WORK(&ts->work, tsc2007_work);
ts->model = pdata->model;
ts->x_plate_ohms = pdata->x_plate_ohms;
@@ -309,12 +396,15 @@
ts->poll_period = pdata->poll_period ? : 1;
ts->get_pendown_state = pdata->get_pendown_state;
ts->clear_penirq = pdata->clear_penirq;
-
- if (pdata->x_plate_ohms == 0) {
- dev_err(&client->dev, "x_plate_ohms is not set up in platform data");
- err = -EINVAL;
- goto err_free_mem;
- }
+ ts->invert_x = pdata->invert_x;
+ ts->invert_y = pdata->invert_y;
+ ts->invert_z1 = pdata->invert_z1;
+ ts->invert_z2 = pdata->invert_z2;
+ ts->min_x = pdata->min_x ? pdata->min_x : 0;
+ ts->max_x = pdata->max_x ? pdata->max_x : MAX_12BIT;
+ ts->min_y = pdata->min_y ? pdata->min_y : 0;
+ ts->max_y = pdata->max_y ? pdata->max_y : MAX_12BIT;
+ ts->power_shutdown = pdata->power_shutdown;
snprintf(ts->phys, sizeof(ts->phys),
"%s/input0", dev_name(&client->dev));
@@ -323,41 +413,49 @@
input_dev->phys = ts->phys;
input_dev->id.bustype = BUS_I2C;
- input_dev->open = tsc2007_open;
- input_dev->close = tsc2007_close;
-
- input_set_drvdata(input_dev, ts);
-
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
- input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, pdata->fuzzx, 0);
- input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, pdata->fuzzy, 0);
+ input_set_abs_params(input_dev, ABS_X, ts->min_x,
+ ts->max_x, pdata->fuzzx, 0);
+ input_set_abs_params(input_dev, ABS_Y, ts->min_y,
+ ts->max_y, pdata->fuzzy, 0);
input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT,
pdata->fuzzz, 0);
if (pdata->init_platform_hw)
pdata->init_platform_hw();
- err = request_threaded_irq(ts->irq, tsc2007_hard_irq, tsc2007_soft_irq,
- IRQF_ONESHOT, client->dev.driver->name, ts);
+ err = request_irq(ts->irq, tsc2007_irq, pdata->irq_flags,
+ client->dev.driver->name, ts);
if (err < 0) {
dev_err(&client->dev, "irq %d busy?\n", ts->irq);
goto err_free_mem;
}
- tsc2007_stop(ts);
+ /* Prepare for touch readings - power down ADC and enable PENIRQ */
+ err = tsc2007_xfer(ts, PWRDOWN);
+ if (err < 0)
+ goto err_free_irq;
err = input_register_device(input_dev);
if (err)
goto err_free_irq;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+ TSC2007_SUSPEND_LEVEL;
+ ts->early_suspend.suspend = tsc2007_early_suspend;
+ ts->early_suspend.resume = tsc2007_late_resume;
+ register_early_suspend(&ts->early_suspend);
+#endif
+
i2c_set_clientdata(client, ts);
return 0;
err_free_irq:
- free_irq(ts->irq, ts);
+ tsc2007_free_irq(ts);
if (pdata->exit_platform_hw)
pdata->exit_platform_hw();
err_free_mem:
@@ -371,11 +469,14 @@
struct tsc2007 *ts = i2c_get_clientdata(client);
struct tsc2007_platform_data *pdata = client->dev.platform_data;
- free_irq(ts->irq, ts);
+ tsc2007_free_irq(ts);
if (pdata->exit_platform_hw)
pdata->exit_platform_hw();
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&ts->early_suspend);
+#endif
input_unregister_device(ts->input);
kfree(ts);
@@ -392,7 +493,10 @@
static struct i2c_driver tsc2007_driver = {
.driver = {
.owner = THIS_MODULE,
- .name = "tsc2007"
+ .name = "tsc2007",
+#ifdef CONFIG_PM
+ .pm = &tsc2007_pm_ops,
+#endif
},
.id_table = tsc2007_idtable,
.probe = tsc2007_probe,