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 = &reg;
+
+	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, &reg_addr, 1, &reg_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, &reg_addr, 1, &reg_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, &reg_addr, 1, &reg_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, &reg_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, &reg_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, &reg_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,