rk30 phone loauqt: add touch screen synaptics s3202 standar drivers
authorhhb <hhb@rock-chips.com>
Sun, 27 May 2012 07:52:01 +0000 (15:52 +0800)
committerhhb <hhb@rock-chips.com>
Sun, 27 May 2012 07:52:01 +0000 (15:52 +0800)
20 files changed:
drivers/input/touchscreen/rmi4/Kconfig [new file with mode: 0755]
drivers/input/touchscreen/rmi4/Makefile [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_bus.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_dev.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_driver.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_driver.h [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_f01.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_f09.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_f11.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_f17.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_f19.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_f1a.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_f21.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_f34.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_f54.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_i2c.c [new file with mode: 0755]
drivers/input/touchscreen/rmi4/rmi_reflash.c [new file with mode: 0644]
drivers/input/touchscreen/rmi4/rmi_reflash.h [new file with mode: 0644]
drivers/input/touchscreen/rmi4/rmi_spi.c [new file with mode: 0755]
include/linux/rmi.h [new file with mode: 0755]

diff --git a/drivers/input/touchscreen/rmi4/Kconfig b/drivers/input/touchscreen/rmi4/Kconfig
new file mode 100755 (executable)
index 0000000..3adf21d
--- /dev/null
@@ -0,0 +1,198 @@
+#
+# RMI4 configuration
+#
+config RMI4_BUS
+       bool "Synaptics RMI4 bus support"
+       depends on TOUCHSCREEN_SYNAPTICS_RMI4_I2C_RK
+       help
+         Say Y here if you want to support the Synaptics RMI4 bus.
+
+         If unsure, say Y.
+
+         This feature is not currently available as
+         a loadable module.
+
+config RMI4_DEBUG
+       bool "Synaptics RMI4 debugging"
+       depends on RMI4_BUS
+       help
+         Say Y here to enable debug feature in the RMI4 driver.
+
+         Note that the RMI4 driver debug features can generate a lot of
+         output (potentially clogging up your dmesg output) and generally
+         slow down driver operation.  It's recommended to enable them only
+         if you are actively developing/debugging RMI4 features.
+
+         If unsure, say N.
+
+config RMI4_I2C
+       bool "RMI4 I2C Support"
+       depends on RMI4_BUS && I2C
+       help
+         Say Y here if you want to support RMI4 devices connected to an I2C
+         bus.
+
+         If unsure, say Y.
+
+         This feature is not currently available as a loadable module.
+
+config RMI4_I2C_SCL_RATE
+       int "RMI4 I2C SCL RATE Support"
+       depends on RMI4_I2C
+
+config RMI4_SPI
+       bool "RMI4 SPI Support"
+       depends on RMI4_BUS && SPI
+       help
+         Say Y here if you want to support RMI4 devices connected to an SPI
+         bus.
+
+         If unsure, say Y.
+
+         This feature is not currently available as a loadable module.
+
+config RMI4_GENERIC
+       bool "RMI4 Generic driver"
+       depends on RMI4_BUS
+       help
+         Say Y here if you want to support generic RMI4 devices.
+
+         This is pretty much required if you want to do anything useful with
+         your RMI device.
+
+         This feature is not currently available as a loadable module.
+
+
+config RMI4_F1A
+       tristate "RMI4 Function 1A (capacitive button sensor)"
+       depends on RMI4_BUS && RMI4_GENERIC
+       help
+         Say Y here if you want to add support for RMI4 function 1A.
+
+         Function 1A provides self testing for touchscreens and touchpads.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rmi-f1a.
+
+config RMI4_F09
+       tristate "RMI4 Function 09 (self testing)"
+       depends on RMI4_BUS && RMI4_GENERIC
+       help
+         Say Y here if you want to add support for RMI4 function 09.
+
+         Function 09 provides self testing for touchscreens and touchpads.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rmi-f09.
+
+config RMI4_F11
+       tristate "RMI4 Function 11 (2D pointing)"
+       depends on RMI4_BUS && RMI4_GENERIC
+       help
+         Say Y here if you want to add support for RMI4 function 11.
+
+         Function 11 provides 2D multifinger pointing for touchscreens and
+         touchpads.  For sensors that support relative pointing, F11 also
+         provides mouse input.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rmi-f11.
+
+config RMI4_F11_PEN
+       bool "RMI4 F11 Pen Support"
+       depends on RMI4_F11
+       help
+         Say Y here to add support for pen input to RMI4 function 11.
+
+         If this feature is enabled, when pen inputs are detected they
+         will be reported to the input stream as MT_TOOL_PEN.  Otherwise,
+         pens will be treated the same as fingers.
+
+         Not all UI implementations deal gracefully with pen discrimination.
+         If your system is not recognizing pen touches and you know your
+         sensor supports pen input, you probably want to turn this feature
+         off.
+
+config RMI4_VIRTUAL_BUTTON
+       tristate "RMI4 Vitual Button"
+       depends on RMI4_F11
+       help
+         Say Y here if you want to add support for RMI4 virtual button to F11.
+
+         The virtual button feature implement the virtual button device in
+         certain RMI4 touch sensors.
+
+         This works only if your sensor supports F11 gestures.
+
+config RMI4_F17
+       tristate "RMI4 Function 17 (pointing sticks)"
+       depends on RMI4_BUS && RMI4_GENERIC
+       help
+         Say Y here if you want to add support for RMI4 function 17.
+
+         Function 19 provides support for capacitive and resistive
+         pointing sticks.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rmi-f17.
+
+config RMI4_F19
+       tristate "RMI4 Function 19 (0D pointing)"
+       depends on RMI4_BUS && RMI4_GENERIC
+       help
+         Say Y here if you want to add support for RMI4 function 19.
+
+         Function 19 provides support for capacitive buttons for sensors
+         that implement capacitive buttons.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rmi-f19.
+         
+config RMI4_F21
+       tristate "RMI4 Function 21 (2D Force)"
+       depends on RMI4_BUS && RMI4_GENERIC
+       help
+         Say Y here if you want to add support for RMI4 function 21.
+
+         Function 21 provides 2D Force Sensing for ForcePad products.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rmi-f21.
+
+config RMI4_F34
+       tristate "RMI4 Function 34 (device reflash)"
+       depends on RMI4_BUS && RMI4_GENERIC
+       help
+         Say Y here if you want to add support for RMI4 function 34.
+
+         Function 34 provides firmware upgrade capability for your sensor.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rmi-f34.
+config RMI4_REFLASH_WHEN_BOOT
+       tristate "RMI4 Function 34 (device reflash when system boot)"
+       depends on RMI4_BUS && RMI4_GENERIC
+
+config RMI4_F54
+       tristate "RMI4 Function 54 (analog diagnostics)"
+       depends on RMI4_BUS && RMI4_GENERIC
+       help
+         Say Y here if you want to add support for RMI4 function 54.
+
+         Function 54 provides access to various diagnostic features in
+         certain RMI4 touch sensors.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rmi-f54.
+
+config RMI4_DEV
+       tristate "Synaptics direct RMI device support (rmidev)"
+       depends on GPIO_SYSFS && (RMI4_I2C || RMI4_SPI)
+       help
+         Say Y here to add support for rmidev.
+
+         The rmidev feature implements a character device providing access
+         to RMI4 sensor register maps.
+
+         To compile this driver as a module, choose M here: the
+         module will be called rmi-dev.
diff --git a/drivers/input/touchscreen/rmi4/Makefile b/drivers/input/touchscreen/rmi4/Makefile
new file mode 100755 (executable)
index 0000000..81db85b
--- /dev/null
@@ -0,0 +1,34 @@
+obj-$(CONFIG_RMI4_BUS) += rmi_bus.o
+obj-$(CONFIG_RMI4_I2C) += rmi_i2c.o
+obj-$(CONFIG_RMI4_SPI) += rmi_spi.o
+obj-$(CONFIG_RMI4_GENERIC) += rmi_driver.o rmi_f01.o
+obj-$(CONFIG_RMI4_F09) += rmi_f09.o
+obj-$(CONFIG_RMI4_F1A) += rmi_f1a.o
+obj-$(CONFIG_RMI4_F11) += rmi_f11.o
+obj-$(CONFIG_RMI4_F17) += rmi_f17.o
+obj-$(CONFIG_RMI4_F19) += rmi_f19.o
+obj-$(CONFIG_RMI4_F21) += rmi_f21.o
+obj-$(CONFIG_RMI4_F34) += rmi_f34.o
+obj-$(CONFIG_RMI4_F54) += rmi_f54.o
+obj-$(CONFIG_RMI4_DEV) += rmi_dev.o
+obj-y += rmi_reflash.o
+
+ifeq ($(KERNELRELEASE),)
+
+# KERNELDIR ?= /home/<AndroidKernelDirectory>
+PWD := $(shell pwd)
+
+.PHONY: build clean
+
+build:
+       $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+clean:
+       rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c
+else
+
+$(info Building with KERNELRELEASE = ${KERNELRELEASE})
+obj-m +=    rmi_dev.o
+
+endif
+
diff --git a/drivers/input/touchscreen/rmi4/rmi_bus.c b/drivers/input/touchscreen/rmi4/rmi_bus.c
new file mode 100755 (executable)
index 0000000..b055a4a
--- /dev/null
@@ -0,0 +1,482 @@
+/*
+ * Copyright (c) 2011 Synaptics Incorporated
+ * Copyright (c) 2011 Unixphere
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/rmi.h>
+#include <linux/types.h>
+#ifdef CONFIG_RMI4_DEBUG
+#include <linux/debugfs.h>
+#endif
+#include "rmi_driver.h"
+DEFINE_MUTEX(rmi_bus_mutex);
+
+static struct rmi_function_list {
+       struct list_head list;
+       struct rmi_function_handler *fh;
+} rmi_supported_functions;
+
+static struct rmi_character_driver_list {
+       struct list_head list;
+       struct rmi_char_driver *cd;
+} rmi_character_drivers;
+
+static atomic_t physical_device_count;
+
+#ifdef CONFIG_RMI4_DEBUG
+static struct dentry *rmi_debugfs_root;
+#endif
+
+static int rmi_bus_match(struct device *dev, struct device_driver *driver)
+{
+       struct rmi_driver *rmi_driver;
+       struct rmi_device *rmi_dev;
+       struct rmi_device_platform_data *pdata;
+
+       rmi_driver = to_rmi_driver(driver);
+       rmi_dev = to_rmi_device(dev);
+       pdata = to_rmi_platform_data(rmi_dev);
+       dev_dbg(dev, "%s: Matching %s.\n", __func__, pdata->sensor_name);
+
+       if (!strcmp(pdata->driver_name, rmi_driver->driver.name)) {
+               rmi_dev->driver = rmi_driver;
+               dev_dbg(dev, "%s: Match %s to %s succeeded.\n", __func__,
+                       pdata->driver_name, rmi_driver->driver.name);
+               return 1;
+       }
+
+       dev_vdbg(dev, "%s: Match %s to %s failed.\n", __func__,
+               pdata->driver_name, rmi_driver->driver.name);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int rmi_bus_suspend(struct device *dev)
+{
+#ifdef GENERIC_SUBSYS_PM_OPS
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+       if (pm && pm->suspend)
+               return pm->suspend(dev);
+#endif
+
+       return 0;
+}
+
+static int rmi_bus_resume(struct device *dev)
+{
+#ifdef GENERIC_SUBSYS_PM_OPS
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+       if (pm && pm->resume)
+               return pm->resume(dev);
+       else if (dev->driver && dev->driver->resume)
+               return dev->driver->resume(dev);
+#else
+       if (dev->driver && dev->driver->resume)
+               return dev->driver->resume(dev);
+#endif
+
+       return 0;
+}
+#endif
+
+static int rmi_bus_probe(struct device *dev)
+{
+       struct rmi_driver *driver;
+       struct rmi_device *rmi_dev = to_rmi_device(dev);
+
+       driver = rmi_dev->driver;
+       if (driver && driver->probe)
+               return driver->probe(rmi_dev);
+
+       return 0;
+}
+
+static int rmi_bus_remove(struct device *dev)
+{
+       struct rmi_driver *driver;
+       struct rmi_device *rmi_dev = to_rmi_device(dev);
+
+       driver = rmi_dev->driver;
+       if (driver && driver->remove)
+               return driver->remove(rmi_dev);
+
+       return 0;
+}
+
+static void rmi_bus_shutdown(struct device *dev)
+{
+       struct rmi_driver *driver;
+       struct rmi_device *rmi_dev = to_rmi_device(dev);
+
+       driver = rmi_dev->driver;
+       if (driver && driver->shutdown)
+               driver->shutdown(rmi_dev);
+}
+
+static SIMPLE_DEV_PM_OPS(rmi_bus_pm_ops,
+                        rmi_bus_suspend, rmi_bus_resume);
+
+struct bus_type rmi_bus_type = {
+       .name           = "rmi",
+       .match          = rmi_bus_match,
+       .probe          = rmi_bus_probe,
+       .remove         = rmi_bus_remove,
+       .shutdown       = rmi_bus_shutdown,
+       .pm             = &rmi_bus_pm_ops
+};
+
+static void release_rmidev_device(struct device *dev) {
+       device_unregister(dev);
+}
+
+int rmi_register_phys_device(struct rmi_phys_device *phys)
+{
+       struct rmi_device_platform_data *pdata = phys->dev->platform_data;
+       struct rmi_device *rmi_dev;
+
+       if (!pdata) {
+               dev_err(phys->dev, "no platform data!\n");
+               return -EINVAL;
+       }
+
+       rmi_dev = kzalloc(sizeof(struct rmi_device), GFP_KERNEL);
+       if (!rmi_dev)
+               return -ENOMEM;
+
+       rmi_dev->phys = phys;
+       rmi_dev->dev.bus = &rmi_bus_type;
+
+       rmi_dev->number = atomic_inc_return(&physical_device_count) - 1;
+       rmi_dev->dev.release = release_rmidev_device;
+
+       dev_set_name(&rmi_dev->dev, "sensor%02d", rmi_dev->number);
+       dev_dbg(phys->dev, "%s: Registered %s as %s.\n", __func__,
+               pdata->sensor_name, dev_name(&rmi_dev->dev));
+
+#ifdef CONFIG_RMI4_DEBUG
+       if (rmi_debugfs_root) {
+               rmi_dev->debugfs_root = debugfs_create_dir(
+                       dev_name(&rmi_dev->dev), rmi_debugfs_root);
+               if (!rmi_dev->debugfs_root)
+                       dev_err(&rmi_dev->dev, "Failed to create debugfs root.\n");
+       }
+#endif
+       phys->rmi_dev = rmi_dev;
+       return device_register(&rmi_dev->dev);
+}
+EXPORT_SYMBOL(rmi_register_phys_device);
+
+void rmi_unregister_phys_device(struct rmi_phys_device *phys)
+{
+       struct rmi_device *rmi_dev = phys->rmi_dev;
+
+#ifdef CONFIG_RMI4_DEBUG
+       if (rmi_dev->debugfs_root)
+               debugfs_remove(rmi_dev->debugfs_root);
+#endif
+
+       kfree(rmi_dev);
+}
+EXPORT_SYMBOL(rmi_unregister_phys_device);
+
+int rmi_register_driver(struct rmi_driver *driver)
+{
+       driver->driver.bus = &rmi_bus_type;
+       return driver_register(&driver->driver);
+}
+EXPORT_SYMBOL(rmi_register_driver);
+
+static int __rmi_driver_remove(struct device *dev, void *data)
+{
+       struct rmi_driver *driver = data;
+       struct rmi_device *rmi_dev = to_rmi_device(dev);
+
+       if (rmi_dev->driver == driver)
+               rmi_dev->driver = NULL;
+
+       return 0;
+}
+
+void rmi_unregister_driver(struct rmi_driver *driver)
+{
+       bus_for_each_dev(&rmi_bus_type, NULL, driver, __rmi_driver_remove);
+       driver_unregister(&driver->driver);
+}
+EXPORT_SYMBOL(rmi_unregister_driver);
+
+static int __rmi_bus_fh_add(struct device *dev, void *data)
+{
+       struct rmi_driver *driver;
+       struct rmi_device *rmi_dev = to_rmi_device(dev);
+
+       driver = rmi_dev->driver;
+       if (driver && driver->fh_add)
+               driver->fh_add(rmi_dev, data);
+
+       return 0;
+}
+
+int rmi_register_function_driver(struct rmi_function_handler *fh)
+{
+       struct rmi_function_list *entry;
+       struct rmi_function_handler *fh_dup;
+
+       fh_dup = rmi_get_function_handler(fh->func);
+       if (fh_dup) {
+               pr_err("%s: function f%.2x already registered!\n", __func__,
+                       fh->func);
+               return -EINVAL;
+       }
+
+       entry = kzalloc(sizeof(struct rmi_function_list), GFP_KERNEL);
+       if (!entry)
+               return -ENOMEM;
+
+       entry->fh = fh;
+       INIT_LIST_HEAD(&entry->list);
+       list_add_tail(&entry->list, &rmi_supported_functions.list);
+
+       /* notify devices of the new function handler */
+       bus_for_each_dev(&rmi_bus_type, NULL, fh, __rmi_bus_fh_add);
+
+       return 0;
+}
+EXPORT_SYMBOL(rmi_register_function_driver);
+
+static int __rmi_bus_fh_remove(struct device *dev, void *data)
+{
+       struct rmi_driver *driver;
+       struct rmi_device *rmi_dev = to_rmi_device(dev);
+
+       driver = rmi_dev->driver;
+       if (driver && driver->fh_remove)
+               driver->fh_remove(rmi_dev, data);
+
+       return 0;
+}
+
+void rmi_unregister_function_driver(struct rmi_function_handler *fh)
+{
+       struct rmi_function_list *entry, *n;
+
+       /* notify devices of the removal of the function handler */
+       bus_for_each_dev(&rmi_bus_type, NULL, fh, __rmi_bus_fh_remove);
+
+       if (list_empty(&rmi_supported_functions.list))
+               return;
+
+       list_for_each_entry_safe(entry, n, &rmi_supported_functions.list,
+                                                                       list) {
+               if (entry->fh->func == fh->func) {
+                       list_del(&entry->list);
+                       kfree(entry);
+               }
+       }
+
+}
+EXPORT_SYMBOL(rmi_unregister_function_driver);
+
+struct rmi_function_handler *rmi_get_function_handler(int id)
+{
+       struct rmi_function_list *entry;
+
+       if (list_empty(&rmi_supported_functions.list))
+               return NULL;
+
+       list_for_each_entry(entry, &rmi_supported_functions.list, list)
+               if (entry->fh->func == id)
+                       return entry->fh;
+
+       return NULL;
+}
+EXPORT_SYMBOL(rmi_get_function_handler);
+
+static void rmi_release_character_device(struct device *dev)
+{
+       dev_dbg(dev, "%s: Called.\n", __func__);
+       return;
+}
+
+static int rmi_register_character_device(struct device *dev, void *data)
+{
+       struct rmi_device *rmi_dev;
+       struct rmi_char_driver *char_driver = data;
+       struct rmi_char_device *char_dev;
+       int retval;
+
+       dev_dbg(dev, "Attaching character device.\n");
+       rmi_dev = to_rmi_device(dev);
+       if (char_driver->match && !char_driver->match(rmi_dev))
+               return 0;
+
+       if (!char_driver->init) {
+               dev_err(dev, "ERROR: No init() function in %s.\n", __func__);
+               return -EINVAL;
+       }
+
+       char_dev = kzalloc(sizeof(struct rmi_char_device), GFP_KERNEL);
+       if (!char_dev)
+               return -ENOMEM;
+
+       char_dev->rmi_dev = rmi_dev;
+       char_dev->driver = char_driver;
+
+       char_dev->dev.parent = dev;
+       char_dev->dev.release = rmi_release_character_device;
+       char_dev->dev.driver = &char_driver->driver;
+       retval = device_register(&char_dev->dev);
+       if (!retval) {
+               dev_err(dev, "Failed to register character device.\n");
+               goto error_exit;
+       }
+
+       retval = char_driver->init(char_dev);
+       if (retval) {
+               dev_err(dev, "Failed to initialize character device.\n");
+               goto error_exit;
+       }
+
+       mutex_lock(&rmi_bus_mutex);
+       list_add_tail(&char_dev->list, &char_driver->devices);
+       mutex_unlock(&rmi_bus_mutex);
+       dev_info(&char_dev->dev, "Registered a device.\n");
+       return retval;
+
+error_exit:
+       kfree(char_dev);
+       return retval;
+}
+
+int rmi_register_character_driver(struct rmi_char_driver *char_driver)
+{
+       struct rmi_character_driver_list *entry;
+       int retval;
+
+       pr_debug("%s: Registering character driver %s.\n", __func__,
+               char_driver->driver.name);
+
+       char_driver->driver.bus = &rmi_bus_type;
+       INIT_LIST_HEAD(&char_driver->devices);
+       retval = driver_register(&char_driver->driver);
+       if (retval) {
+               pr_err("%s: Failed to register %s, code: %d.\n", __func__,
+                      char_driver->driver.name, retval);
+               return retval;
+       }
+
+       entry = kzalloc(sizeof(struct rmi_character_driver_list), GFP_KERNEL);
+       if (!entry)
+               return -ENOMEM;
+       entry->cd = char_driver;
+
+       mutex_lock(&rmi_bus_mutex);
+       list_add_tail(&entry->list, &rmi_character_drivers.list);
+       mutex_unlock(&rmi_bus_mutex);
+
+       /* notify devices of the removal of the function handler */
+       bus_for_each_dev(&rmi_bus_type, NULL, char_driver,
+                        rmi_register_character_device);
+
+       return 0;
+}
+EXPORT_SYMBOL(rmi_register_character_driver);
+
+
+int rmi_unregister_character_driver(struct rmi_char_driver *char_driver)
+{
+       struct rmi_character_driver_list *entry, *n;
+       struct rmi_char_device *char_dev, *m;
+       pr_debug("%s: Unregistering character driver %s.\n", __func__,
+               char_driver->driver.name);
+
+       mutex_lock(&rmi_bus_mutex);
+       list_for_each_entry_safe(char_dev, m, &char_driver->devices,
+                                list) {
+               list_del(&char_dev->list);
+               char_dev->driver->remove(char_dev);
+       }
+       list_for_each_entry_safe(entry, n, &rmi_character_drivers.list,
+                                list) {
+               if (entry->cd == char_driver) {
+                       list_del(&entry->list);
+                       kfree(entry);
+               }
+       }
+       mutex_unlock(&rmi_bus_mutex);
+
+       driver_unregister(&char_driver->driver);
+
+       return 0;
+}
+EXPORT_SYMBOL(rmi_unregister_character_driver);
+
+static int __init rmi_bus_init(void)
+{
+       int error;
+
+       mutex_init(&rmi_bus_mutex);
+       INIT_LIST_HEAD(&rmi_supported_functions.list);
+       INIT_LIST_HEAD(&rmi_character_drivers.list);
+
+#ifdef CONFIG_RMI4_DEBUG
+       rmi_debugfs_root = debugfs_create_dir(rmi_bus_type.name, NULL);
+       if (!rmi_debugfs_root)
+               pr_err("%s: Failed to create debugfs root.\n", __func__);
+       else if (IS_ERR(rmi_debugfs_root)) {
+               pr_err("%s: Kernel may not contain debugfs support, code=%ld\n",
+                      __func__, PTR_ERR(rmi_debugfs_root));
+               rmi_debugfs_root = NULL;
+       }
+#endif
+
+       error = bus_register(&rmi_bus_type);
+       if (error < 0) {
+               pr_err("%s: error registering the RMI bus: %d\n", __func__,
+                      error);
+               return error;
+       }
+       pr_debug("%s: successfully registered RMI bus.\n", __func__);
+
+       return 0;
+}
+
+static void __exit rmi_bus_exit(void)
+{
+       /* We should only ever get here if all drivers are unloaded, so
+        * all we have to do at this point is unregister ourselves.
+        */
+#ifdef CONFIG_RMI4_DEBUG
+       if (rmi_debugfs_root)
+               debugfs_remove(rmi_debugfs_root);
+#endif
+       bus_unregister(&rmi_bus_type);
+}
+
+module_init(rmi_bus_init);
+module_exit(rmi_bus_exit);
+
+MODULE_AUTHOR("Christopher Heiny <cheiny@synaptics.com");
+MODULE_DESCRIPTION("RMI bus");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
diff --git a/drivers/input/touchscreen/rmi4/rmi_dev.c b/drivers/input/touchscreen/rmi4/rmi_dev.c
new file mode 100755 (executable)
index 0000000..080db55
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2011 Synaptics Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/syscalls.h>
+
+#include <linux/rmi.h>
+#include "rmi_driver.h"
+
+#define CHAR_DEVICE_NAME "rmi"
+#define DEVICE_CLASS_NAME "rmidev"
+
+#define RMI_CHAR_DEV_TMPBUF_SZ 128
+#define RMI_REG_ADDR_PAGE_SELECT 0xFF
+#define REG_ADDR_LIMIT 0xFFFF
+
+struct rmidev_data {
+       /* mutex for file operation*/
+       struct mutex file_mutex;
+       /* main char dev structure */
+       struct cdev main_dev;
+
+       /* pointer to the corresponding RMI4 device.  We use this to do */
+       /* read, write, etc. */
+       struct rmi_device *rmi_dev;
+       /* reference count */
+       int ref_count;
+
+       struct class *device_class;
+};
+
+/*store dynamically allocated major number of char device*/
+static int rmidev_major_num;
+
+
+static struct class *rmidev_device_class;
+
+
+/* file operations for RMI char device */
+
+/*
+ * rmidev_llseek: - use to setup register address
+ *
+ * @filp: file structure for seek
+ * @off: offset
+ *       if whence == SEEK_SET,
+ *       high 16 bits: page address
+ *       low 16 bits: register address
+ *
+ *       if whence == SEEK_CUR,
+ *       offset from current position
+ *
+ *       if whence == SEEK_END,
+ *       offset from END(0xFFFF)
+ *
+ * @whence: SEEK_SET , SEEK_CUR or SEEK_END
+ */
+static loff_t rmidev_llseek(struct file *filp, loff_t off, int whence)
+{
+       loff_t newpos;
+       struct rmidev_data *data = filp->private_data;
+
+       if (IS_ERR(data)) {
+               pr_err("%s: pointer of char device is invalid", __func__);
+               return -EBADF;
+       }
+
+       mutex_lock(&(data->file_mutex));
+
+       switch (whence) {
+       case SEEK_SET:
+               newpos = off;
+               break;
+
+       case SEEK_CUR:
+               newpos = filp->f_pos + off;
+               break;
+
+       case SEEK_END:
+               newpos = REG_ADDR_LIMIT + off;
+               break;
+
+       default:                /* can't happen */
+               newpos = -EINVAL;
+               goto clean_up;
+       }
+
+       if (newpos < 0 || newpos > REG_ADDR_LIMIT) {
+               dev_err(&data->rmi_dev->dev, "newpos 0x%04x is invalid.\n",
+                       (unsigned int)newpos);
+               newpos = -EINVAL;
+               goto clean_up;
+       }
+
+       filp->f_pos = newpos;
+
+clean_up:
+       mutex_unlock(&(data->file_mutex));
+       return newpos;
+}
+
+/*
+ *  rmidev_read: - use to read data from RMI stream
+ *
+ *  @filp: file structure for read
+ *  @buf: user-level buffer pointer
+ *
+ *  @count: number of byte read
+ *  @f_pos: offset (starting register address)
+ *
+ *     @return number of bytes read into user buffer (buf) if succeeds
+ *          negative number if error occurs.
+ */
+static ssize_t rmidev_read(struct file *filp, char __user *buf,
+               size_t count, loff_t *f_pos)
+{
+       struct rmidev_data *data = filp->private_data;
+       ssize_t retval  = 0;
+       unsigned char tmpbuf[count+1];
+
+       /* limit offset to REG_ADDR_LIMIT-1 */
+       if (count > (REG_ADDR_LIMIT - *f_pos))
+               count = REG_ADDR_LIMIT - *f_pos;
+
+       if (count == 0)
+               return 0;
+
+       if (IS_ERR(data)) {
+               pr_err("%s: pointer of char device is invalid", __func__);
+               return -EBADF;
+       }
+
+       mutex_lock(&(data->file_mutex));
+
+       retval = rmi_read_block(data->rmi_dev, *f_pos, tmpbuf, count);
+
+       if (retval < 0)
+               goto clean_up;
+
+       if (copy_to_user(buf, tmpbuf, count))
+               retval = -EFAULT;
+       else
+               *f_pos += retval;
+
+clean_up:
+
+       mutex_unlock(&(data->file_mutex));
+
+       return retval;
+}
+
+/*
+ * rmidev_write: - use to write data into RMI stream
+ *
+ * @filep : file structure for write
+ * @buf: user-level buffer pointer contains data to be written
+ * @count: number of byte be be written
+ * @f_pos: offset (starting register address)
+ *
+ * @return number of bytes written from user buffer (buf) if succeeds
+ *         negative number if error occurs.
+ */
+static ssize_t rmidev_write(struct file *filp, const char __user *buf,
+               size_t count, loff_t *f_pos)
+{
+       struct rmidev_data *data = filp->private_data;
+       ssize_t retval  = 0;
+       unsigned char tmpbuf[count+1];
+
+       /* limit offset to REG_ADDR_LIMIT-1 */
+       if (count > (REG_ADDR_LIMIT - *f_pos))
+               count = REG_ADDR_LIMIT - *f_pos;
+
+       if (count == 0)
+               return 0;
+
+       if (IS_ERR(data)) {
+               pr_err("%s: pointer of char device is invalid", __func__);
+               return -EBADF;
+       }
+
+       if (copy_from_user(tmpbuf, buf, count))
+               return -EFAULT;
+
+       mutex_lock(&(data->file_mutex));
+
+       retval = rmi_write_block(data->rmi_dev, *f_pos, tmpbuf, count);
+
+       if (retval >= 0)
+               *f_pos += count;
+
+       mutex_unlock(&(data->file_mutex));
+
+       return retval;
+}
+
+/*
+ * rmidev_open: - get a new handle for from RMI stream
+ * @inp : inode struture
+ * @filp: file structure for read/write
+ *
+ * @return 0 if succeeds
+ */
+static int rmidev_open(struct inode *inp, struct file *filp)
+{
+       struct rmidev_data *data = container_of(inp->i_cdev,
+                       struct rmidev_data, main_dev);
+       int retval = 0;
+
+       filp->private_data = data;
+
+       if (!data->rmi_dev)
+               return -EACCES;
+
+       mutex_lock(&(data->file_mutex));
+       if (data->ref_count < 1)
+               data->ref_count++;
+       else
+               retval = -EACCES;
+
+       mutex_unlock(&(data->file_mutex));
+
+       return retval;
+}
+
+/*
+ *  rmidev_release: - release an existing handle
+ *  @inp: inode structure
+ *  @filp: file structure for read/write
+ *
+ *  @return 0 if succeeds
+ */
+static int rmidev_release(struct inode *inp, struct file *filp)
+{
+       struct rmidev_data *data = container_of(inp->i_cdev,
+                       struct rmidev_data, main_dev);
+
+       if (!data->rmi_dev)
+               return -EACCES;
+
+       mutex_lock(&(data->file_mutex));
+
+       data->ref_count--;
+       if (data->ref_count < 0)
+               data->ref_count = 0;
+
+       mutex_unlock(&(data->file_mutex));
+
+       return 0;
+}
+
+static const struct file_operations rmidev_fops = {
+       .owner =    THIS_MODULE,
+       .llseek =   rmidev_llseek,
+       .read =     rmidev_read,
+       .write =    rmidev_write,
+       .open =     rmidev_open,
+       .release =  rmidev_release,
+};
+
+/*
+ * rmidev_device_cleanup - release memory or unregister driver
+ * @rmidev_data: instance data for a particular device.
+ *
+ */
+static void rmidev_device_cleanup(struct rmidev_data *data)
+{
+       dev_t devno;
+
+       /* Get rid of our char dev entries */
+       if (data) {
+               devno = data->main_dev.dev;
+
+               if (data->device_class)
+                       device_destroy(data->device_class, devno);
+
+               cdev_del(&data->main_dev);
+               kfree(data);
+
+               /* cleanup_module is never called if registering failed */
+               unregister_chrdev_region(devno, 1);
+               pr_debug("%s: rmidev device is removed\n", __func__);
+       }
+}
+
+/*
+ * rmi_char_devnode - return device permission
+ *
+ * @dev: char device structure
+ * @mode: file permission
+ *
+ */
+static char *rmi_char_devnode(struct device *dev, mode_t *mode)
+{
+       if (!mode)
+               return NULL;
+       /**mode = 0666*/
+       *mode = (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+
+       return kasprintf(GFP_KERNEL, "rmi/%s", dev_name(dev));
+}
+
+static int rmidev_init_device(struct rmi_char_device *cd)
+{
+       struct rmi_device *rmi_dev = cd->rmi_dev;
+       struct rmidev_data *data;
+       dev_t dev_no;
+       int retval;
+       struct device *device_ptr;
+
+       if (rmidev_major_num) {
+               dev_no = MKDEV(rmidev_major_num, cd->rmi_dev->number);
+               retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME);
+       } else {
+               retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME);
+               /* let kernel allocate a major for us */
+               rmidev_major_num = MAJOR(dev_no);
+               dev_info(&rmi_dev->dev, "Major number of rmidev: %d\n",
+                                rmidev_major_num);
+       }
+       if (retval < 0) {
+               dev_err(&rmi_dev->dev,
+                       "Failed to get minor dev number %d, code %d.\n",
+                       cd->rmi_dev->number, retval);
+               return retval;
+       } else
+               dev_info(&rmi_dev->dev, "Allocated rmidev %d %d.\n",
+                        MAJOR(dev_no), MINOR(dev_no));
+
+       data = kzalloc(sizeof(struct rmidev_data), GFP_KERNEL);
+       if (!data) {
+               dev_err(&rmi_dev->dev, "Failed to allocate rmidev_data.\n");
+               /* unregister the char device region */
+               __unregister_chrdev(rmidev_major_num, MINOR(dev_no), 1,
+                               CHAR_DEVICE_NAME);
+               return -ENOMEM;
+       }
+
+       mutex_init(&data->file_mutex);
+
+       data->rmi_dev = cd->rmi_dev;
+       cd->data = data;
+
+       cdev_init(&data->main_dev, &rmidev_fops);
+
+       retval = cdev_add(&data->main_dev, dev_no, 1);
+       if (retval) {
+               dev_err(&cd->rmi_dev->dev, "Error %d adding rmi_char_dev.\n",
+                       retval);
+               rmidev_device_cleanup(data);
+               return retval;
+       }
+
+       dev_set_name(&cd->dev, "rmidev%d", MINOR(dev_no));
+       data->device_class = rmidev_device_class;
+       device_ptr = device_create(
+                       data->device_class,
+                       NULL, dev_no, NULL,
+                       CHAR_DEVICE_NAME"%d",
+                       MINOR(dev_no));
+
+       if (IS_ERR(device_ptr)) {
+               dev_err(&cd->rmi_dev->dev, "Failed to create rmi device.\n");
+               rmidev_device_cleanup(data);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static void rmidev_remove_device(struct rmi_char_device *cd)
+{
+       struct rmidev_data *data;
+
+       dev_dbg(&cd->dev, "%s: removing an rmidev device.\n", __func__);
+       if (!cd)
+               return;
+
+       data = cd->data;
+       if (data)
+               rmidev_device_cleanup(data);
+}
+
+static struct rmi_char_driver rmidev_driver = {
+       .driver = {
+               .name = "rmidev",
+               .owner = THIS_MODULE,
+       },
+
+       .init = rmidev_init_device,
+       .remove = rmidev_remove_device,
+};
+
+static int __init rmidev_init(void)
+{
+       int error = 0;
+       pr_debug("%s: rmi_dev initialization.\n", __func__);
+
+       /* create device node */
+       rmidev_device_class = class_create(THIS_MODULE, DEVICE_CLASS_NAME);
+
+       if (IS_ERR(rmidev_device_class)) {
+               pr_err("%s: ERROR - Failed to create /dev/%s.\n", __func__,
+                       CHAR_DEVICE_NAME);
+               return -ENODEV;
+       }
+       /* setup permission */
+       rmidev_device_class->devnode = rmi_char_devnode;
+
+       error = rmi_register_character_driver(&rmidev_driver);
+       if (error)
+               class_destroy(rmidev_device_class);
+       return error;
+}
+
+static void __exit rmidev_exit(void)
+{
+       pr_debug("%s: exiting.\n", __func__);
+       rmi_unregister_character_driver(&rmidev_driver);
+       class_destroy(rmidev_device_class);
+}
+
+module_init(rmidev_init);
+module_exit(rmidev_exit);
+
+MODULE_AUTHOR("Christopher Heiny <cheiny@synaptics.com>");
+MODULE_DESCRIPTION("RMI4 Char Device");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/rmi4/rmi_driver.c b/drivers/input/touchscreen/rmi4/rmi_driver.c
new file mode 100755 (executable)
index 0000000..67f84a8
--- /dev/null
@@ -0,0 +1,1616 @@
+/*
+ * Copyright (c) 2011 Synaptics Incorporated
+ * Copyright (c) 2011 Unixphere
+ *
+ * This driver adds support for generic RMI4 devices from Synpatics. It
+ * implements the mandatory f01 RMI register and depends on the presence of
+ * other required RMI functions.
+ *
+ * The RMI4 specification can be found here (URL split after files/ for
+ * style reasons):
+ * http://www.synaptics.com/sites/default/files/
+ *           511-000136-01-Rev-E-RMI4%20Intrfacing%20Guide.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/pm.h>
+#include <linux/rmi.h>
+#include "rmi_driver.h"
+#ifdef CONFIG_RMI4_DEBUG
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#endif
+
+#define REGISTER_DEBUG 0
+
+#define PDT_END_SCAN_LOCATION  0x0005
+#define PDT_PROPERTIES_LOCATION 0x00EF
+#define BSR_LOCATION 0x00FE
+#define HAS_BSR_MASK 0x20
+#define HAS_NONSTANDARD_PDT_MASK 0x40
+#define RMI4_END_OF_PDT(id) ((id) == 0x00 || (id) == 0xff)
+#define RMI4_MAX_PAGE 0xff
+#define RMI4_PAGE_SIZE 0x100
+
+#define RMI_DEVICE_RESET_CMD   0x01
+#define DEFAULT_RESET_DELAY_MS 20
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void rmi_driver_early_suspend(struct early_suspend *h);
+static void rmi_driver_late_resume(struct early_suspend *h);
+#endif
+
+/* sysfs files for attributes for driver values. */
+static ssize_t rmi_driver_bsr_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_driver_bsr_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count);
+
+static ssize_t rmi_driver_enabled_show(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf);
+
+static ssize_t rmi_driver_enabled_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count);
+
+#if REGISTER_DEBUG
+static ssize_t rmi_driver_reg_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count);
+#endif
+
+#ifdef CONFIG_RMI4_DEBUG
+
+struct driver_debugfs_data {
+       bool done;
+       struct rmi_device *rmi_dev;
+};
+
+static int debug_open(struct inode *inodep, struct file *filp) {
+       struct driver_debugfs_data *data;
+
+       data = kzalloc(sizeof(struct driver_debugfs_data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->rmi_dev = inodep->i_private;
+       filp->private_data = data;
+       return 0;
+}
+
+static int debug_release(struct inode *inodep, struct file *filp) {
+       kfree(filp->private_data);
+       return 0;
+}
+
+#ifdef CONFIG_RMI4_SPI
+#define DELAY_NAME "delay"
+
+static ssize_t delay_read(struct file *filp, char __user *buffer, size_t size,
+                   loff_t *offset) {
+       struct driver_debugfs_data *data = filp->private_data;
+       struct rmi_device_platform_data *pdata =
+                       data->rmi_dev->phys->dev->platform_data;
+       int retval;
+       char local_buf[size];
+
+       if (data->done)
+               return 0;
+
+       data->done = 1;
+
+       retval = snprintf(local_buf, size, "%d %d %d %d %d\n",
+               pdata->spi_data.read_delay_us, pdata->spi_data.write_delay_us,
+               pdata->spi_data.block_delay_us,
+               pdata->spi_data.pre_delay_us, pdata->spi_data.post_delay_us);
+
+       if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
+               return -EFAULT;
+
+       return retval;
+}
+
+static ssize_t delay_write(struct file *filp, const char __user *buffer,
+                          size_t size, loff_t *offset) {
+       struct driver_debugfs_data *data = filp->private_data;
+       struct rmi_device_platform_data *pdata =
+                       data->rmi_dev->phys->dev->platform_data;
+       int retval;
+       char local_buf[size];
+       unsigned int new_read_delay;
+       unsigned int new_write_delay;
+       unsigned int new_block_delay;
+       unsigned int new_pre_delay;
+       unsigned int new_post_delay;
+
+       retval = copy_from_user(local_buf, buffer, size);
+       if (retval)
+               return -EFAULT;
+
+       retval = sscanf(local_buf, "%u %u %u %u %u", &new_read_delay,
+                       &new_write_delay, &new_block_delay,
+                       &new_pre_delay, &new_post_delay);
+       if (retval != 5) {
+               dev_err(&data->rmi_dev->dev,
+                       "Incorrect number of values provided for delay.");
+               return -EINVAL;
+       }
+       if (new_read_delay < 0) {
+               dev_err(&data->rmi_dev->dev,
+                       "Byte delay must be positive microseconds.\n");
+               return -EINVAL;
+       }
+       if (new_write_delay < 0) {
+               dev_err(&data->rmi_dev->dev,
+                       "Write delay must be positive microseconds.\n");
+               return -EINVAL;
+       }
+       if (new_block_delay < 0) {
+               dev_err(&data->rmi_dev->dev,
+                       "Block delay must be positive microseconds.\n");
+               return -EINVAL;
+       }
+       if (new_pre_delay < 0) {
+               dev_err(&data->rmi_dev->dev,
+                       "Pre-transfer delay must be positive microseconds.\n");
+               return -EINVAL;
+       }
+       if (new_post_delay < 0) {
+               dev_err(&data->rmi_dev->dev,
+                       "Post-transfer delay must be positive microseconds.\n");
+               return -EINVAL;
+       }
+
+       dev_dbg(&data->rmi_dev->dev,
+                "Setting delays to %u %u %u %u %u.\n", new_read_delay,
+                new_write_delay, new_block_delay, new_pre_delay,
+                new_post_delay);
+       pdata->spi_data.read_delay_us = new_read_delay;
+       pdata->spi_data.write_delay_us = new_write_delay;
+       pdata->spi_data.block_delay_us = new_block_delay;
+       pdata->spi_data.pre_delay_us = new_pre_delay;
+       pdata->spi_data.post_delay_us = new_post_delay;
+
+       return size;
+}
+
+static struct file_operations delay_fops = {
+       .owner = THIS_MODULE,
+       .open = debug_open,
+       .release = debug_release,
+       .read = delay_read,
+       .write = delay_write,
+};
+#endif /* CONFIG_RMI4_SPI */
+
+#define PHYS_NAME "phys"
+
+static ssize_t phys_read(struct file *filp, char __user *buffer, size_t size,
+                   loff_t *offset) {
+       struct driver_debugfs_data *data = filp->private_data;
+       struct rmi_phys_info *info = &data->rmi_dev->phys->info;
+       int retval;
+       char local_buf[size];
+
+       if (data->done)
+               return 0;
+
+       data->done = 1;
+
+       retval = snprintf(local_buf, PAGE_SIZE,
+               "%-5s %ld %ld %ld %ld %ld %ld %ld\n",
+                info->proto ? info->proto : "unk",
+                info->tx_count, info->tx_bytes, info->tx_errs,
+                info->rx_count, info->rx_bytes, info->rx_errs,
+                info->attn_count);
+       if (retval <= 0 || copy_to_user(buffer, local_buf, retval))
+               return -EFAULT;
+
+       return retval;
+}
+
+static struct file_operations phys_fops = {
+       .owner = THIS_MODULE,
+       .open = debug_open,
+       .release = debug_release,
+       .read = phys_read,
+};
+
+static int setup_debugfs(struct rmi_device *rmi_dev) {
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+#ifdef CONFIG_RMI4_SPI
+       struct rmi_phys_info *info = &rmi_dev->phys->info;
+#endif
+       int retval = 0;
+
+       if (!rmi_dev->debugfs_root)
+               return -ENODEV;
+
+#ifdef CONFIG_RMI4_SPI
+       if (!strncmp("spi", info->proto, 3)) {
+               data->debugfs_delay = debugfs_create_file(DELAY_NAME, RMI_RW_ATTR,
+                                       rmi_dev->debugfs_root, rmi_dev, &delay_fops);
+               if (!data->debugfs_delay || IS_ERR(data->debugfs_delay)) {
+                       dev_warn(&rmi_dev->dev, "Failed to create debugfs delay.\n");
+                       data->debugfs_delay = NULL;
+               }
+       }
+#endif
+
+       data->debugfs_phys = debugfs_create_file(PHYS_NAME, RMI_RO_ATTR,
+                               rmi_dev->debugfs_root, rmi_dev, &phys_fops);
+       if (!data->debugfs_phys || IS_ERR(data->debugfs_phys)) {
+               dev_warn(&rmi_dev->dev, "Failed to create debugfs phys.\n");
+               data->debugfs_phys = NULL;
+       }
+
+       return retval;
+}
+
+static void teardown_debugfs(struct rmi_device *rmi_dev) {
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+
+#ifdef CONFIG_RMI4_SPI
+       if (!data->debugfs_delay)
+               debugfs_remove(data->debugfs_delay);
+#endif
+       if (!data->debugfs_phys)
+               debugfs_remove(data->debugfs_phys);
+}
+#endif
+
+static int rmi_driver_process_reset_requests(struct rmi_device *rmi_dev);
+
+static int rmi_driver_process_config_requests(struct rmi_device *rmi_dev);
+
+static int rmi_driver_irq_restore(struct rmi_device *rmi_dev);
+
+static struct device_attribute attrs[] = {
+       __ATTR(enabled, RMI_RW_ATTR,
+              rmi_driver_enabled_show, rmi_driver_enabled_store),
+#if REGISTER_DEBUG
+       __ATTR(reg, RMI_WO_ATTR,
+              rmi_show_error, rmi_driver_reg_store),
+#endif
+};
+
+static struct device_attribute bsr_attribute = __ATTR(bsr, RMI_RW_ATTR,
+              rmi_driver_bsr_show, rmi_driver_bsr_store);
+
+/* Useful helper functions for u8* */
+
+void u8_set_bit(u8 *target, int pos)
+{
+       target[pos/8] |= 1<<pos%8;
+}
+
+void u8_clear_bit(u8 *target, int pos)
+{
+       target[pos/8] &= ~(1<<pos%8);
+}
+
+bool u8_is_set(u8 *target, int pos)
+{
+       return target[pos/8] & 1<<pos%8;
+}
+
+bool u8_is_any_set(u8 *target, int size)
+{
+       int i;
+       for (i = 0; i < size; i++) {
+               if (target[i])
+                       return true;
+       }
+       return false;
+}
+
+void u8_or(u8 *dest, u8 *target1, u8 *target2, int size)
+{
+       int i;
+       for (i = 0; i < size; i++)
+               dest[i] = target1[i] | target2[i];
+}
+
+void u8_and(u8 *dest, u8 *target1, u8 *target2, int size)
+{
+       int i;
+       for (i = 0; i < size; i++)
+               dest[i] = target1[i] & target2[i];
+}
+
+static bool has_bsr(struct rmi_driver_data *data)
+{
+       return (data->pdt_props & HAS_BSR_MASK) != 0;
+}
+
+/* Utility routine to set bits in a register. */
+int rmi_set_bits(struct rmi_device *rmi_dev, unsigned short address,
+                unsigned char bits)
+{
+       unsigned char reg_contents;
+       int retval;
+
+       retval = rmi_read_block(rmi_dev, address, &reg_contents, 1);
+       if (retval)
+               return retval;
+       reg_contents = reg_contents | bits;
+       retval = rmi_write_block(rmi_dev, address, &reg_contents, 1);
+       if (retval == 1)
+               return 0;
+       else if (retval == 0)
+               return -EIO;
+       return retval;
+}
+EXPORT_SYMBOL(rmi_set_bits);
+
+/* Utility routine to clear bits in a register. */
+int rmi_clear_bits(struct rmi_device *rmi_dev, unsigned short address,
+                  unsigned char bits)
+{
+       unsigned char reg_contents;
+       int retval;
+
+       retval = rmi_read_block(rmi_dev, address, &reg_contents, 1);
+       if (retval)
+               return retval;
+       reg_contents = reg_contents & ~bits;
+       retval = rmi_write_block(rmi_dev, address, &reg_contents, 1);
+       if (retval == 1)
+               return 0;
+       else if (retval == 0)
+               return -EIO;
+       return retval;
+}
+EXPORT_SYMBOL(rmi_clear_bits);
+
+static void rmi_free_function_list(struct rmi_device *rmi_dev)
+{
+       struct rmi_function_container *entry, *n;
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+
+       if (!data) {
+               dev_err(&rmi_dev->dev, "WTF: No driver data in %s\n", __func__);
+               return;
+       }
+
+       if (data->f01_container) {
+               if (data->f01_container->fh && data->f01_container->fh->remove) {
+                       data->f01_container->fh->remove(data->f01_container);
+               }
+               device_unregister(&data->f01_container->dev);
+               kfree(data->f01_container->irq_mask);
+               kfree(data->f01_container);
+               data->f01_container = NULL;
+       }
+
+       if (list_empty(&data->rmi_functions.list))
+               return;
+
+       list_for_each_entry_safe(entry, n, &data->rmi_functions.list, list) {
+               if (entry->fh) {
+                       if (entry->fh->remove)
+                               entry->fh->remove(entry);
+                       device_unregister(&entry->dev);
+               }
+               kfree(entry->irq_mask);
+               list_del(&entry->list);
+               kfree(entry);
+       }
+}
+
+static void no_op(struct device *dev)
+{
+       dev_dbg(dev, "REMOVING KOBJ!");
+       kobject_put(&dev->kobj);
+}
+
+static int init_one_function(struct rmi_device *rmi_dev,
+                            struct rmi_function_container *fc)
+{
+       int retval;
+
+       if (!fc->fh) {
+               struct rmi_function_handler *fh =
+                       rmi_get_function_handler(fc->fd.function_number);
+               if (!fh) {
+                       dev_dbg(&rmi_dev->dev, "No handler for F%02X.\n",
+                               fc->fd.function_number);
+                       return 0;
+               }
+               fc->fh = fh;
+       }
+
+       if (!fc->fh->init)
+               return 0;
+       /* This memset might not be what we want to do... */
+       memset(&(fc->dev), 0, sizeof(struct device));
+       dev_set_name(&(fc->dev), "fn%02x", fc->fd.function_number);
+       fc->dev.release = no_op;
+
+       fc->dev.parent = &rmi_dev->dev;
+       dev_dbg(&rmi_dev->dev, "%s: Register F%02X.\n", __func__,
+                       fc->fd.function_number);
+       retval = device_register(&fc->dev);
+       if (retval) {
+               dev_err(&rmi_dev->dev, "Failed device_register for F%02X.\n",
+                       fc->fd.function_number);
+               return retval;
+       }
+
+       retval = fc->fh->init(fc);
+       if (retval < 0) {
+               dev_err(&rmi_dev->dev, "Failed to initialize function F%02x\n",
+                       fc->fd.function_number);
+               goto error_exit;
+       }
+
+       return 0;
+
+error_exit:
+       device_unregister(&fc->dev);
+       return retval;
+}
+
+static void rmi_driver_fh_add(struct rmi_device *rmi_dev,
+                             struct rmi_function_handler *fh)
+{
+       struct rmi_function_container *entry;
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+
+       if (!data)
+               return;
+       if (fh->func == 0x01) {
+               if (data->f01_container)
+                       data->f01_container->fh = fh;
+       } else if (!list_empty(&data->rmi_functions.list)) {
+               mutex_lock(&data->pdt_mutex);
+               list_for_each_entry(entry, &data->rmi_functions.list, list)
+                       if (entry->fd.function_number == fh->func) {
+                               entry->fh = fh;
+                               if (init_one_function(rmi_dev, entry) < 0)
+                                       entry->fh = NULL;
+                       }
+               mutex_unlock(&data->pdt_mutex);
+       }
+
+}
+
+static void rmi_driver_fh_remove(struct rmi_device *rmi_dev,
+                                struct rmi_function_handler *fh)
+{
+       struct rmi_function_container *entry, *temp;
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+
+       if (fh->func == 0x01) {
+               /* don't call remove here since
+                * rmi_f01_initialize just get call one time */
+               if (data->f01_container)
+                       data->f01_container->fh = NULL;
+               return;
+       }
+
+       list_for_each_entry_safe(entry, temp, &data->rmi_functions.list,
+                                                                       list) {
+               if (entry->fh && entry->fd.function_number == fh->func) {
+                       if (fh->remove)
+                               fh->remove(entry);
+
+                       entry->fh = NULL;
+                       device_unregister(&entry->dev);
+               }
+       }
+}
+
+static int rmi_driver_process_reset_requests(struct rmi_device *rmi_dev)
+{
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+       struct device *dev = &rmi_dev->dev;
+       struct rmi_function_container *entry;
+       int retval;
+
+       /* Device control (F01) is handled before anything else. */
+
+       if (data->f01_container && data->f01_container->fh &&
+                       data->f01_container->fh->reset) {
+               retval = data->f01_container->fh->reset(data->f01_container);
+               if (retval < 0) {
+                       dev_err(dev, "F%02x reset handler failed: %d.\n",
+                               data->f01_container->fh->func, retval);
+                       return retval;
+               }
+       }
+
+       if (list_empty(&data->rmi_functions.list))
+               return 0;
+
+       list_for_each_entry(entry, &data->rmi_functions.list, list) {
+               if (entry->fh && entry->fh->reset) {
+                       retval = entry->fh->reset(entry);
+                       if (retval < 0) {
+                               dev_err(dev, "F%02x reset handler failed: %d\n",
+                                       entry->fh->func, retval);
+                               return retval;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int rmi_driver_process_config_requests(struct rmi_device *rmi_dev)
+{
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+       struct device *dev = &rmi_dev->dev;
+       struct rmi_function_container *entry;
+       int retval;
+
+       /* Device control (F01) is handled before anything else. */
+
+       if (data->f01_container && data->f01_container->fh &&
+                       data->f01_container->fh->config) {
+               retval = data->f01_container->fh->config(data->f01_container);
+               if (retval < 0) {
+                       dev_err(dev, "F%02x config handler failed: %d.\n",
+                                       data->f01_container->fh->func, retval);
+                       return retval;
+               }
+       }
+
+       if (list_empty(&data->rmi_functions.list))
+               return 0;
+
+       list_for_each_entry(entry, &data->rmi_functions.list, list) {
+               if (entry->fh && entry->fh->config) {
+                       retval = entry->fh->config(entry);
+                       if (retval < 0) {
+                               dev_err(dev, "F%02x config handler failed: %d.\n",
+                                       entry->fh->func, retval);
+                               return retval;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static void construct_mask(u8 *mask, int num, int pos)
+{
+       int i;
+
+       for (i = 0; i < num; i++)
+               u8_set_bit(mask, pos+i);
+}
+
+static int process_interrupt_requests(struct rmi_device *rmi_dev)
+{
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+       struct device *dev = &rmi_dev->dev;
+       struct rmi_function_container *entry;
+       u8 irq_status[data->num_of_irq_regs];
+       u8 irq_bits[data->num_of_irq_regs];
+       int error;
+
+       error = rmi_read_block(rmi_dev,
+                               data->f01_container->fd.data_base_addr + 1,
+                               irq_status, data->num_of_irq_regs);
+       if (error < 0) {
+               dev_err(dev, "%s: failed to read irqs.", __func__);
+               return error;
+       }
+       /* Device control (F01) is handled before anything else. */
+       if (data->f01_container->irq_mask && data->f01_container->fh->attention) {
+               u8_and(irq_bits, irq_status, data->f01_container->irq_mask,
+                               data->num_of_irq_regs);
+               if (u8_is_any_set(irq_bits, data->num_of_irq_regs))
+                       data->f01_container->fh->attention(
+                                       data->f01_container, irq_bits);
+       }
+
+       u8_and(irq_status, irq_status, data->current_irq_mask,
+              data->num_of_irq_regs);
+       /* At this point, irq_status has all bits that are set in the
+        * interrupt status register and are enabled.
+        */
+
+       list_for_each_entry(entry, &data->rmi_functions.list, list)
+               if (entry->irq_mask && entry->fh && entry->fh->attention) {
+                       u8_and(irq_bits, irq_status, entry->irq_mask,
+                              data->num_of_irq_regs);
+                       if (u8_is_any_set(irq_bits, data->num_of_irq_regs)) {
+                               error = entry->fh->attention(entry, irq_bits);
+                               if (error < 0)
+                                       dev_err(dev, "%s: f%.2x"
+                                               " attention handler failed:"
+                                               " %d\n", __func__,
+                                               entry->fh->func, error);
+                       }
+               }
+
+       return 0;
+}
+
+static int rmi_driver_irq_handler(struct rmi_device *rmi_dev, int irq)
+{
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+
+       /* Can get called before the driver is fully ready to deal with
+        * interrupts.
+        */
+       if (!data || !data->f01_container || !data->f01_container->fh) {
+               dev_warn(&rmi_dev->dev,
+                        "Not ready to handle interrupts yet!\n");
+               return 0;
+       }
+       return process_interrupt_requests(rmi_dev);
+}
+
+static int rmi_driver_reset_handler(struct rmi_device *rmi_dev)
+{
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+       int error;
+
+       /* Can get called before the driver is fully ready to deal with
+        * interrupts.
+        */
+       if (!data || !data->f01_container || !data->f01_container->fh) {
+               dev_warn(&rmi_dev->dev,
+                        "Not ready to handle reset yet!\n");
+               return 0;
+       }
+
+       error = rmi_driver_process_reset_requests(rmi_dev);
+       if (error < 0)
+               return error;
+
+
+       error = rmi_driver_process_config_requests(rmi_dev);
+       if (error < 0)
+               return error;
+
+       if (data->irq_stored) {
+               error = rmi_driver_irq_restore(rmi_dev);
+               if (error < 0)
+                       return error;
+       }
+
+       return 0;
+}
+
+
+
+/*
+ * Construct a function's IRQ mask. This should
+ * be called once and stored.
+ */
+static u8 *rmi_driver_irq_get_mask(struct rmi_device *rmi_dev,
+                                  struct rmi_function_container *fc) {
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+
+       u8 *irq_mask = kzalloc(sizeof(u8) * data->num_of_irq_regs, GFP_KERNEL);
+       if (irq_mask)
+               construct_mask(irq_mask, fc->num_of_irqs, fc->irq_pos);
+
+       return irq_mask;
+}
+
+/*
+ * This pair of functions allows functions like function 54 to request to have
+ * other interupts disabled until the restore function is called. Only one store
+ * happens at a time.
+ */
+static int rmi_driver_irq_save(struct rmi_device *rmi_dev, u8 * new_ints)
+{
+       int retval = 0;
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+       struct device *dev = &rmi_dev->dev;
+
+       mutex_lock(&data->irq_mutex);
+       if (!data->irq_stored) {
+               /* Save current enabled interupts */
+               retval = rmi_read_block(rmi_dev,
+                               data->f01_container->fd.control_base_addr+1,
+                               data->irq_mask_store, data->num_of_irq_regs);
+               if (retval < 0) {
+                       dev_err(dev, "%s: Failed to read enabled interrupts!",
+                                                               __func__);
+                       goto error_unlock;
+               }
+               /*
+                * Disable every interupt except for function 54
+                * TODO:Will also want to not disable function 1-like functions.
+                * No need to take care of this now, since there's no good way
+                * to identify them.
+                */
+               retval = rmi_write_block(rmi_dev,
+                               data->f01_container->fd.control_base_addr+1,
+                               new_ints, data->num_of_irq_regs);
+               if (retval < 0) {
+                       dev_err(dev, "%s: Failed to change enabled interrupts!",
+                                                               __func__);
+                       goto error_unlock;
+               }
+               memcpy(data->current_irq_mask, new_ints,
+                                       data->num_of_irq_regs * sizeof(u8));
+               data->irq_stored = true;
+       } else {
+               retval = -ENOSPC; /* No space to store IRQs.*/
+               dev_err(dev, "%s: Attempted to save values when"
+                                               " already stored!", __func__);
+       }
+
+error_unlock:
+       mutex_unlock(&data->irq_mutex);
+       return retval;
+}
+
+static int rmi_driver_irq_restore(struct rmi_device *rmi_dev)
+{
+       int retval = 0;
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+       struct device *dev = &rmi_dev->dev;
+       mutex_lock(&data->irq_mutex);
+
+       if (data->irq_stored) {
+               retval = rmi_write_block(rmi_dev,
+                               data->f01_container->fd.control_base_addr+1,
+                               data->irq_mask_store, data->num_of_irq_regs);
+               if (retval < 0) {
+                       dev_err(dev, "%s: Failed to write enabled interupts!",
+                                                               __func__);
+                       goto error_unlock;
+               }
+               memcpy(data->current_irq_mask, data->irq_mask_store,
+                                       data->num_of_irq_regs * sizeof(u8));
+               data->irq_stored = false;
+       } else {
+               retval = -EINVAL;
+               dev_err(dev, "%s: Attempted to restore values when not stored!",
+                       __func__);
+       }
+
+error_unlock:
+       mutex_unlock(&data->irq_mutex);
+       return retval;
+}
+
+static int rmi_driver_fn_generic(struct rmi_device *rmi_dev,
+                                    struct pdt_entry *pdt_ptr,
+                                    int *current_irq_count,
+                                    u16 page_start)
+{
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+       struct rmi_function_container *fc = NULL;
+       int retval = 0;
+       struct device *dev = &rmi_dev->dev;
+       struct rmi_device_platform_data *pdata;
+
+       pdata = to_rmi_platform_data(rmi_dev);
+
+       dev_dbg(dev, "Initializing F%02X for %s.\n", pdt_ptr->function_number,
+               pdata->sensor_name);
+
+       fc = kzalloc(sizeof(struct rmi_function_container),
+                       GFP_KERNEL);
+       if (!fc) {
+               dev_err(dev, "Failed to allocate container for F%02X.\n",
+                       pdt_ptr->function_number);
+               retval = -ENOMEM;
+               goto error_free_data;
+       }
+
+       copy_pdt_entry_to_fd(pdt_ptr, &fc->fd, page_start);
+
+       fc->rmi_dev = rmi_dev;
+       fc->num_of_irqs = pdt_ptr->interrupt_source_count;
+       fc->irq_pos = *current_irq_count;
+       *current_irq_count += fc->num_of_irqs;
+
+       retval = init_one_function(rmi_dev, fc);
+       if (retval < 0) {
+               dev_err(dev, "Failed to initialize F%.2x\n",
+                       pdt_ptr->function_number);
+               goto error_free_data;
+       }
+
+       INIT_LIST_HEAD(&fc->list);
+       list_add_tail(&fc->list, &data->rmi_functions.list);
+       return 0;
+
+error_free_data:
+       kfree(fc);
+       return retval;
+}
+
+/*
+ * F01 was once handled very differently from all other functions.  It is
+ * now only slightly special, and as the driver is refined we expect this
+ * function to go away.
+ */
+static int rmi_driver_fn_01_specific(struct rmi_device *rmi_dev,
+                                    struct pdt_entry *pdt_ptr,
+                                    int *current_irq_count,
+                                    u16 page_start)
+{
+       struct rmi_driver_data *data = NULL;
+       struct rmi_function_container *fc = NULL;
+       union f01_device_status device_status;
+       int retval = 0;
+       struct device *dev = &rmi_dev->dev;
+       struct rmi_function_handler *fh =
+               rmi_get_function_handler(0x01);
+       struct rmi_device_platform_data *pdata;
+
+       pdata = to_rmi_platform_data(rmi_dev);
+       data = rmi_get_driverdata(rmi_dev);
+
+       retval = rmi_read(rmi_dev, pdt_ptr->data_base_addr, &device_status.reg);
+       if (retval) {
+               dev_err(dev, "Failed to read device status.\n");
+               return retval;
+       }
+
+       dev_dbg(dev, "Initializing F01 for %s.\n", pdata->sensor_name);
+
+       if (!fh)
+               dev_dbg(dev, "%s: No function handler for F01?!", __func__);
+
+       fc = kzalloc(sizeof(struct rmi_function_container), GFP_KERNEL);
+       if (!fc) {
+               retval = -ENOMEM;
+               return retval;
+       }
+
+       copy_pdt_entry_to_fd(pdt_ptr, &fc->fd, page_start);
+       fc->num_of_irqs = pdt_ptr->interrupt_source_count;
+       fc->irq_pos = *current_irq_count;
+       *current_irq_count += fc->num_of_irqs;
+
+       fc->rmi_dev        = rmi_dev;
+       fc->dev.parent     = &fc->rmi_dev->dev;
+       fc->fh = fh;
+
+       dev_set_name(&(fc->dev), "fn%02x", fc->fd.function_number);
+       fc->dev.release = no_op;
+
+       dev_dbg(dev, "%s: Register F01.\n", __func__);
+       retval = device_register(&fc->dev);
+       if (retval) {
+               dev_err(dev, "%s: Failed device_register for F01.\n", __func__);
+               goto error_free_data;
+       }
+
+       data->f01_container = fc;
+       data->f01_bootloader_mode = device_status.flash_prog;
+       if (device_status.flash_prog)
+               dev_warn(dev, "WARNING: RMI4 device is in bootloader mode!\n");
+
+       INIT_LIST_HEAD(&fc->list);
+
+       return retval;
+
+error_free_data:
+       kfree(fc);
+       return retval;
+}
+
+/*
+ * Scan the PDT for F01 so we can force a reset before anything else
+ * is done.  This forces the sensor into a known state, and also
+ * forces application of any pending updates from reflashing the
+ * firmware or configuration.  We have to do this before actually
+ * building the PDT because the reflash might cause various registers
+ * to move around.
+ */
+static int do_initial_reset(struct rmi_device *rmi_dev)
+{
+       struct pdt_entry pdt_entry;
+       int page;
+       struct device *dev = &rmi_dev->dev;
+       bool done = false;
+       int i;
+       int retval;
+       struct rmi_device_platform_data *pdata;
+
+       dev_dbg(dev, "Initial reset.\n");
+       pdata = to_rmi_platform_data(rmi_dev);
+       for (page = 0; (page <= RMI4_MAX_PAGE) && !done; page++) {
+               u16 page_start = RMI4_PAGE_SIZE * page;
+               u16 pdt_start = page_start + PDT_START_SCAN_LOCATION;
+               u16 pdt_end = page_start + PDT_END_SCAN_LOCATION;
+
+               done = true;
+               for (i = pdt_start; i >= pdt_end; i -= sizeof(pdt_entry)) {
+                       retval = rmi_read_block(rmi_dev, i, (u8 *)&pdt_entry,
+                                              sizeof(pdt_entry));
+                       if (retval != sizeof(pdt_entry)) {
+                               dev_err(dev, "Read PDT entry at 0x%04x"
+                                       "failed, code = %d.\n", i, retval);
+                               return retval;
+                       }
+
+                       if (RMI4_END_OF_PDT(pdt_entry.function_number))
+                               break;
+                       done = false;
+
+                       if (pdt_entry.function_number == 0x01) {
+                               u16 cmd_addr = page_start +
+                                       pdt_entry.command_base_addr;
+                               u8 cmd_buf = RMI_DEVICE_RESET_CMD;
+                               retval = rmi_write_block(rmi_dev, cmd_addr,
+                                               &cmd_buf, 1);
+                               if (retval < 0) {
+                                       dev_err(dev, "Initial reset failed. "
+                                               "Code = %d.\n", retval);
+                                       return retval;
+                               }
+                               mdelay(pdata->reset_delay_ms);
+                               return 0;
+                       }
+               }
+       }
+
+       dev_warn(dev, "WARNING: Failed to find F01 for initial reset.\n");
+       return -ENODEV;
+}
+
+static int rmi_scan_pdt(struct rmi_device *rmi_dev)
+{
+       struct rmi_driver_data *data;
+       struct pdt_entry pdt_entry;
+       int page;
+       struct device *dev = &rmi_dev->dev;
+       int irq_count = 0;
+       bool done = false;
+       int i;
+       int retval;
+#ifdef CONFIG_RMI4_DEBUG
+       dev_info(dev, "Scanning PDT...\n");
+#endif
+       data = rmi_get_driverdata(rmi_dev);
+       mutex_lock(&data->pdt_mutex);
+
+       for (page = 0; (page <= RMI4_MAX_PAGE) && !done; page++) {
+               u16 page_start = RMI4_PAGE_SIZE * page;
+               u16 pdt_start = page_start + PDT_START_SCAN_LOCATION;
+               u16 pdt_end = page_start + PDT_END_SCAN_LOCATION;
+
+               done = true;
+               for (i = pdt_start; i >= pdt_end; i -= sizeof(pdt_entry)) {
+                       retval = rmi_read_block(rmi_dev, i, (u8 *)&pdt_entry,
+                                              sizeof(pdt_entry));
+                       if (retval != sizeof(pdt_entry)) {
+                               dev_err(dev, "Read PDT entry at 0x%04x "
+                                       "failed.\n", i);
+                               goto error_exit;
+                       }
+
+                       if (RMI4_END_OF_PDT(pdt_entry.function_number))
+                               break;
+#ifdef CONFIG_RMI4_DEBUG
+                       dev_info(dev, "%s: Found F%.2X on page 0x%02X\n",
+                               __func__, pdt_entry.function_number, page);
+#endif
+                       done = false;
+
+                       if (pdt_entry.function_number == 0x01)
+                               retval = rmi_driver_fn_01_specific(rmi_dev,
+                                               &pdt_entry, &irq_count,
+                                               page_start);
+                       else
+                               retval = rmi_driver_fn_generic(rmi_dev,
+                                               &pdt_entry, &irq_count,
+                                               page_start);
+
+                       if (retval)
+                               goto error_exit;
+#ifdef CONFIG_RMI4_DEBUG
+                       printk("command_base_addr:%x, control_base_addr:%x, data_base_addr:%x\n", pdt_entry.command_base_addr,
+                                       pdt_entry.control_base_addr, pdt_entry.data_base_addr);
+#else
+                       msleep(1);         //in this for(), enough delay is needed, or may cause system die
+#endif
+               }
+               done = done || data->f01_bootloader_mode;
+       }
+       data->irq_count = irq_count;
+       data->num_of_irq_regs = (irq_count + 7) / 8;
+       dev_dbg(dev, "%s: Done with PDT scan.\n", __func__);
+       retval = 0;
+
+error_exit:
+       mutex_unlock(&data->pdt_mutex);
+       return retval;
+}
+
+static int rmi_driver_probe(struct rmi_device *rmi_dev)
+{
+       struct rmi_driver_data *data = NULL;
+       struct rmi_function_container *fc;
+       struct rmi_device_platform_data *pdata;
+       int retval = 0;
+       struct device *dev = &rmi_dev->dev;
+       int attr_count = 0;
+
+       dev_dbg(dev, "%s: Starting probe.\n", __func__);
+
+       pdata = to_rmi_platform_data(rmi_dev);
+
+       data = kzalloc(sizeof(struct rmi_driver_data), GFP_KERNEL);
+       if (!data) {
+               dev_err(dev, "%s: Failed to allocate driver data.\n", __func__);
+               return -ENOMEM;
+       }
+       INIT_LIST_HEAD(&data->rmi_functions.list);
+       rmi_set_driverdata(rmi_dev, data);
+       mutex_init(&data->pdt_mutex);
+
+       if (!pdata->reset_delay_ms)
+               pdata->reset_delay_ms = DEFAULT_RESET_DELAY_MS;
+       retval = do_initial_reset(rmi_dev);
+       if (retval)
+               dev_warn(dev, "RMI initial reset failed! Soldiering on.\n");
+
+
+       retval = rmi_scan_pdt(rmi_dev);
+       if (retval) {
+               dev_err(dev, "PDT scan for %s failed with code %d.\n",
+                       pdata->sensor_name, retval);
+               goto err_free_data;
+       }
+
+       if (!data->f01_container) {
+               dev_err(dev, "missing F01 container!\n");
+               retval = -EINVAL;
+               goto err_free_data;
+       }
+
+       data->f01_container->irq_mask = kzalloc(
+                       sizeof(u8) * data->num_of_irq_regs, GFP_KERNEL);
+       if (!data->f01_container->irq_mask) {
+               dev_err(dev, "Failed to allocate F01 IRQ mask.\n");
+               retval = -ENOMEM;
+               goto err_free_data;
+       }
+       construct_mask(data->f01_container->irq_mask,
+                      data->f01_container->num_of_irqs,
+                      data->f01_container->irq_pos);
+       list_for_each_entry(fc, &data->rmi_functions.list, list)
+               fc->irq_mask = rmi_driver_irq_get_mask(rmi_dev, fc);
+
+       retval = rmi_driver_f01_init(rmi_dev);
+       if (retval < 0) {
+               dev_err(dev, "Failed to initialize F01.\n");
+               goto err_free_data;
+       }
+
+       retval = rmi_read(rmi_dev, PDT_PROPERTIES_LOCATION,
+                        (char *) &data->pdt_props);
+       if (retval < 0) {
+               /* we'll print out a warning and continue since
+                * failure to get the PDT properties is not a cause to fail
+                */
+               dev_warn(dev, "Could not read PDT properties from 0x%04x. "
+                        "Assuming 0x00.\n", PDT_PROPERTIES_LOCATION);
+       }
+
+       dev_dbg(dev, "%s: Creating sysfs files.", __func__);
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               retval = device_create_file(dev, &attrs[attr_count]);
+               if (retval < 0) {
+                       dev_err(dev, "%s: Failed to create sysfs file %s.\n",
+                               __func__, attrs[attr_count].attr.name);
+                       goto err_free_data;
+               }
+       }
+       if (has_bsr(data)) {
+               retval = device_create_file(dev, &bsr_attribute);
+               if (retval < 0) {
+                       dev_err(dev, "%s: Failed to create sysfs file bsr.\n",
+                               __func__);
+                       goto err_free_data;
+               }
+       }
+
+       mutex_init(&data->irq_mutex);
+       data->current_irq_mask = kzalloc(sizeof(u8) * data->num_of_irq_regs,
+                                        GFP_KERNEL);
+       if (!data->current_irq_mask) {
+               dev_err(dev, "Failed to allocate current_irq_mask.\n");
+               retval = -ENOMEM;
+               goto err_free_data;
+       }
+       retval = rmi_read_block(rmi_dev,
+                               data->f01_container->fd.control_base_addr+1,
+                               data->current_irq_mask, data->num_of_irq_regs);
+       if (retval < 0) {
+               dev_err(dev, "%s: Failed to read current IRQ mask.\n",
+                       __func__);
+               goto err_free_data;
+       }
+       data->irq_mask_store = kzalloc(sizeof(u8) * data->num_of_irq_regs,
+                                      GFP_KERNEL);
+       if (!data->irq_mask_store) {
+               dev_err(dev, "Failed to allocate mask store.\n");
+               retval = -ENOMEM;
+               goto err_free_data;
+       }
+
+#ifdef CONFIG_PM
+       data->pm_data = pdata->pm_data;
+       data->pre_suspend = pdata->pre_suspend;
+       data->post_resume = pdata->post_resume;
+
+       mutex_init(&data->suspend_mutex);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       rmi_dev->early_suspend_handler.level =
+               EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+       rmi_dev->early_suspend_handler.suspend = rmi_driver_early_suspend;
+       rmi_dev->early_suspend_handler.resume = rmi_driver_late_resume;
+       register_early_suspend(&rmi_dev->early_suspend_handler);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+#endif /* CONFIG_PM */
+       data->enabled = true;
+
+#ifdef CONFIG_RMI4_DEBUG
+       retval = setup_debugfs(rmi_dev);
+       if (retval < 0)
+               dev_warn(&fc->dev, "Failed to setup debugfs. Code: %d.\n",
+                        retval);
+#endif
+
+       return 0;
+
+ err_free_data:
+       rmi_free_function_list(rmi_dev);
+       for (attr_count--; attr_count >= 0; attr_count--)
+               device_remove_file(dev, &attrs[attr_count]);
+       if (has_bsr(data))
+               device_remove_file(dev, &bsr_attribute);
+       if (data->f01_container)
+               kfree(data->f01_container->irq_mask);
+       kfree(data->irq_mask_store);
+       kfree(data->current_irq_mask);
+       kfree(data);
+       rmi_set_driverdata(rmi_dev, NULL);
+       return retval;
+}
+
+#ifdef CONFIG_PM
+static int rmi_driver_suspend(struct device *dev)
+{
+       struct rmi_device *rmi_dev;
+       struct rmi_driver_data *data;
+       struct rmi_function_container *entry;
+       int retval = 0;
+
+       rmi_dev = to_rmi_device(dev);
+       data = rmi_get_driverdata(rmi_dev);
+
+       mutex_lock(&data->suspend_mutex);
+       if (data->suspended)
+               goto exit;
+
+#ifndef        CONFIG_HAS_EARLYSUSPEND
+       if (data->pre_suspend) {
+               retval = data->pre_suspend(data->pm_data);
+               if (retval)
+                       goto exit;
+       }
+#endif  /* !CONFIG_HAS_EARLYSUSPEND */
+
+       list_for_each_entry(entry, &data->rmi_functions.list, list)
+               if (entry->fh && entry->fh->suspend) {
+                       retval = entry->fh->suspend(entry);
+                       if (retval < 0)
+                               goto exit;
+               }
+
+       if (data->f01_container && data->f01_container->fh
+                               && data->f01_container->fh->suspend) {
+               retval = data->f01_container->fh->suspend(data->f01_container);
+               if (retval < 0)
+                       goto exit;
+       }
+       data->suspended = true;
+
+exit:
+       mutex_unlock(&data->suspend_mutex);
+       return retval;
+}
+
+static int rmi_driver_resume(struct device *dev)
+{
+       struct rmi_device *rmi_dev;
+       struct rmi_driver_data *data;
+       struct rmi_function_container *entry;
+       int retval = 0;
+
+       rmi_dev = to_rmi_device(dev);
+       data = rmi_get_driverdata(rmi_dev);
+
+       mutex_lock(&data->suspend_mutex);
+       if (!data->suspended)
+               goto exit;
+
+       if (data->f01_container && data->f01_container->fh
+                               && data->f01_container->fh->resume) {
+               retval = data->f01_container->fh->resume(data->f01_container);
+               if (retval < 0)
+                       goto exit;
+       }
+
+       list_for_each_entry(entry, &data->rmi_functions.list, list)
+               if (entry->fh && entry->fh->resume) {
+                       retval = entry->fh->resume(entry);
+                       if (retval < 0)
+                               goto exit;
+               }
+
+#ifndef        CONFIG_HAS_EARLYSUSPEND
+       if (data->post_resume) {
+               retval = data->post_resume(data->pm_data);
+               if (retval)
+                       goto exit;
+       }
+#endif  /* !CONFIG_HAS_EARLYSUSPEND */
+
+       data->suspended = false;
+
+exit:
+       mutex_unlock(&data->suspend_mutex);
+       return retval;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void rmi_driver_early_suspend(struct early_suspend *h)
+{
+       struct rmi_device *rmi_dev =
+           container_of(h, struct rmi_device, early_suspend_handler);
+       struct rmi_driver_data *data;
+       struct rmi_function_container *entry;
+       int retval = 0;
+
+       data = rmi_get_driverdata(rmi_dev);
+       dev_dbg(&rmi_dev->dev, "Early suspend.\n");
+
+       mutex_lock(&data->suspend_mutex);
+       if (data->suspended)
+               goto exit;
+
+       if (data->pre_suspend) {
+               retval = data->pre_suspend(data->pm_data);
+               if (retval)
+                       goto exit;
+       }
+
+       list_for_each_entry(entry, &data->rmi_functions.list, list)
+               if (entry->fh && entry->fh->early_suspend) {
+                       retval = entry->fh->early_suspend(entry);
+                       if (retval < 0)
+                               goto exit;
+               }
+
+       if (data->f01_container && data->f01_container->fh
+                               && data->f01_container->fh->early_suspend) {
+               retval = data->f01_container->fh->early_suspend(
+                               data->f01_container);
+               if (retval < 0)
+                       goto exit;
+       }
+       data->suspended = true;
+
+exit:
+       mutex_unlock(&data->suspend_mutex);
+}
+
+static void rmi_driver_late_resume(struct early_suspend *h)
+{
+       struct rmi_device *rmi_dev =
+           container_of(h, struct rmi_device, early_suspend_handler);
+       struct rmi_driver_data *data;
+       struct rmi_function_container *entry;
+       int retval = 0;
+
+       data = rmi_get_driverdata(rmi_dev);
+       dev_dbg(&rmi_dev->dev, "Late resume.\n");
+
+       mutex_lock(&data->suspend_mutex);
+       if (!data->suspended)
+               goto exit;
+
+       if (data->f01_container && data->f01_container->fh
+                               && data->f01_container->fh->late_resume) {
+               retval = data->f01_container->fh->late_resume(
+                               data->f01_container);
+               if (retval < 0)
+                       goto exit;
+       }
+
+       list_for_each_entry(entry, &data->rmi_functions.list, list)
+               if (entry->fh && entry->fh->late_resume) {
+                       retval = entry->fh->late_resume(entry);
+                       if (retval < 0)
+                               goto exit;
+               }
+
+       if (data->post_resume) {
+               retval = data->post_resume(data->pm_data);
+               if (retval)
+                       goto exit;
+       }
+
+       data->suspended = false;
+
+exit:
+       mutex_unlock(&data->suspend_mutex);
+}
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+#endif /* CONFIG_PM */
+
+static int __devexit rmi_driver_remove(struct rmi_device *rmi_dev)
+{
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+       struct rmi_function_container *entry;
+       int i;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       unregister_early_suspend(&rmi_dev->early_suspend_handler);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+#ifdef CONFIG_RMI4_DEBUG
+       teardown_debugfs(rmi_dev);
+#endif
+
+       list_for_each_entry(entry, &data->rmi_functions.list, list)
+               if (entry->fh && entry->fh->remove)
+                       entry->fh->remove(entry);
+
+       rmi_free_function_list(rmi_dev);
+       for (i = 0; i < ARRAY_SIZE(attrs); i++)
+               device_remove_file(&rmi_dev->dev, &attrs[i]);
+       if (has_bsr(data))
+               device_remove_file(&rmi_dev->dev, &bsr_attribute);
+       kfree(data->f01_container->irq_mask);
+       kfree(data->irq_mask_store);
+       kfree(data->current_irq_mask);
+       kfree(data);
+
+       return 0;
+}
+
+#ifdef UNIVERSAL_DEV_PM_OPS
+static UNIVERSAL_DEV_PM_OPS(rmi_driver_pm, rmi_driver_suspend,
+                           rmi_driver_resume, NULL);
+#endif
+
+static struct rmi_driver sensor_driver = {
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = "rmi_generic",
+#ifdef UNIVERSAL_DEV_PM_OPS
+               .pm = &rmi_driver_pm,
+#endif
+       },
+       .probe = rmi_driver_probe,
+       .irq_handler = rmi_driver_irq_handler,
+       .reset_handler = rmi_driver_reset_handler,
+       .fh_add = rmi_driver_fh_add,
+       .fh_remove = rmi_driver_fh_remove,
+       .get_func_irq_mask = rmi_driver_irq_get_mask,
+       .store_irq_mask = rmi_driver_irq_save,
+       .restore_irq_mask = rmi_driver_irq_restore,
+       .remove = __devexit_p(rmi_driver_remove)
+};
+
+/* sysfs show and store fns for driver attributes */
+
+static ssize_t rmi_driver_bsr_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct rmi_device *rmi_dev;
+       struct rmi_driver_data *data;
+       rmi_dev = to_rmi_device(dev);
+       data = rmi_get_driverdata(rmi_dev);
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", data->bsr);
+}
+
+static ssize_t rmi_driver_bsr_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+       int retval;
+       unsigned long val;
+       struct rmi_device *rmi_dev;
+       struct rmi_driver_data *data;
+
+       rmi_dev = to_rmi_device(dev);
+       data = rmi_get_driverdata(rmi_dev);
+
+       /* need to convert the string data to an actual value */
+       retval = strict_strtoul(buf, 10, &val);
+       if (retval < 0) {
+               dev_err(dev, "Invalid value '%s' written to BSR.\n", buf);
+               return -EINVAL;
+       }
+
+       retval = rmi_write(rmi_dev, BSR_LOCATION, (unsigned char)val);
+       if (retval) {
+               dev_err(dev, "%s : failed to write bsr %u to 0x%x\n",
+                       __func__, (unsigned int)val, BSR_LOCATION);
+               return retval;
+       }
+
+       data->bsr = val;
+
+       return count;
+}
+
+static void disable_sensor(struct rmi_device *rmi_dev)
+{
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+
+       rmi_dev->phys->disable_device(rmi_dev->phys);
+
+       data->enabled = false;
+}
+
+static int enable_sensor(struct rmi_device *rmi_dev)
+{
+       struct rmi_driver_data *data = rmi_get_driverdata(rmi_dev);
+       int retval = 0;
+
+       retval = rmi_dev->phys->enable_device(rmi_dev->phys);
+       /* non-zero means error occurred */
+       if (retval)
+               return retval;
+
+       data->enabled = true;
+
+       return 0;
+}
+
+static ssize_t rmi_driver_enabled_show(struct device *dev,
+                                      struct device_attribute *attr, char *buf)
+{
+       struct rmi_device *rmi_dev;
+       struct rmi_driver_data *data;
+
+       rmi_dev = to_rmi_device(dev);
+       data = rmi_get_driverdata(rmi_dev);
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", data->enabled);
+}
+
+static ssize_t rmi_driver_enabled_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       int retval;
+       int new_value;
+       struct rmi_device *rmi_dev;
+       struct rmi_driver_data *data;
+
+       rmi_dev = to_rmi_device(dev);
+       data = rmi_get_driverdata(rmi_dev);
+
+       if (sysfs_streq(buf, "0"))
+               new_value = false;
+       else if (sysfs_streq(buf, "1"))
+               new_value = true;
+       else
+               return -EINVAL;
+
+       if (new_value) {
+               retval = enable_sensor(rmi_dev);
+               if (retval) {
+                       dev_err(dev, "Failed to enable sensor, code=%d.\n",
+                               retval);
+                       return -EIO;
+               }
+       } else {
+               disable_sensor(rmi_dev);
+       }
+
+       return count;
+}
+
+#if REGISTER_DEBUG
+static ssize_t rmi_driver_reg_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       int retval;
+       unsigned int address;
+       unsigned int bytes;
+       struct rmi_device *rmi_dev;
+       struct rmi_driver_data *data;
+       u8 readbuf[128];
+       unsigned char outbuf[512];
+       unsigned char *bufptr = outbuf;
+       int i;
+
+       rmi_dev = to_rmi_device(dev);
+       data = rmi_get_driverdata(rmi_dev);
+
+       retval = sscanf(buf, "%x %u", &address, &bytes);
+       if (retval != 2) {
+               dev_err(dev, "Invalid input (code %d) for reg store: %s",
+                       retval, buf);
+               return -EINVAL;
+       }
+       if (address < 0 || address > 0xFFFF) {
+               dev_err(dev, "Invalid address for reg store '%#06x'.\n",
+                       address);
+               return -EINVAL;
+       }
+       if (bytes < 0 || bytes >= sizeof(readbuf) || address+bytes > 65535) {
+               dev_err(dev, "Invalid byte count for reg store '%d'.\n",
+                       bytes);
+               return -EINVAL;
+       }
+
+       retval = rmi_read_block(rmi_dev, address, readbuf, bytes);
+       if (retval != bytes) {
+               dev_err(dev, "Failed to read %d registers at %#06x, code %d.\n",
+                       bytes, address, retval);
+               return retval;
+       }
+
+       dev_info(dev, "Reading %d bytes from %#06x.\n", bytes, address);
+       for (i = 0; i < bytes; i++) {
+               retval = snprintf(bufptr, 4, "%02X ", readbuf[i]);
+               if (retval < 0) {
+                       dev_err(dev, "Failed to format string. Code: %d",
+                               retval);
+                       return retval;
+               }
+               bufptr += retval;
+       }
+       dev_info(dev, "%s\n", outbuf);
+
+       return count;
+}
+#endif
+
+static int __init rmi_driver_init(void)
+{
+       return rmi_register_driver(&sensor_driver);
+}
+
+static void __exit rmi_driver_exit(void)
+{
+       rmi_unregister_driver(&sensor_driver);
+}
+
+module_init(rmi_driver_init);
+module_exit(rmi_driver_exit);
+
+MODULE_AUTHOR("Christopher Heiny <cheiny@synaptics.com");
+MODULE_DESCRIPTION("RMI generic driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
diff --git a/drivers/input/touchscreen/rmi4/rmi_driver.h b/drivers/input/touchscreen/rmi4/rmi_driver.h
new file mode 100755 (executable)
index 0000000..44504a1
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2011 Synaptics Incorporated
+ * Copyright (c) 2011 Unixphere
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _RMI_DRIVER_H
+#define _RMI_DRIVER_H
+
+#define RMI_DRIVER_VERSION "1.3"
+
+#define RMI_PRODUCT_ID_LENGTH    10
+#define RMI_PRODUCT_INFO_LENGTH   2
+#define RMI_DATE_CODE_LENGTH      3
+
+#include <linux/ctype.h>
+/* Sysfs related macros */
+
+/* You must define FUNCTION_DATA and FNUM to use these functions. */
+#define RMI4_SYSFS_DEBUG defined(CONFIG_RMI4_DEBUG) || defined(CONFIG_ANDROID))
+
+#if defined(FNUM) && defined(FUNCTION_DATA)
+
+#define tricat(x,y,z) tricat_(x,y,z)
+
+#define tricat_(x,y,z) x##y##z
+
+#define show_union_struct_prototype(propname)\
+static ssize_t tricat(rmi_fn_,FNUM,_##propname##_show)(\
+                                       struct device *dev,\
+                                       struct device_attribute *attr,\
+                                       char *buf);\
+\
+DEVICE_ATTR(propname, RMI_RO_ATTR,\
+               tricat(rmi_fn_,FNUM,_##propname##_show),\
+               rmi_store_error);
+
+#define store_union_struct_prototype(propname)\
+static ssize_t tricat(rmi_fn_,FNUM,_##propname##_store)(\
+                                       struct device *dev,\
+                                       struct device_attribute *attr,\
+                                       const char *buf, size_t count);\
+\
+DEVICE_ATTR(propname, RMI_WO_ATTR,\
+               rmi_show_error,\
+               tricat(rmi_fn_, FNUM, _##propname##_store));
+
+
+#define show_store_union_struct_prototype(propname)\
+static ssize_t tricat(rmi_fn_, FNUM, _##propname##_show)(\
+                                       struct device *dev,\
+                                       struct device_attribute *attr,\
+                                       char *buf);\
+\
+static ssize_t tricat(rmi_fn_, FNUM, _##propname##_store)(\
+                                       struct device *dev,\
+                                       struct device_attribute *attr,\
+                                       const char *buf, size_t count);\
+\
+DEVICE_ATTR(propname, RMI_RW_ATTR,\
+               tricat(rmi_fn_, FNUM, _##propname##_show),\
+               tricat(rmi_fn_, FNUM, _##propname##_store));
+
+#define simple_show_union_struct(regtype, propname, fmt)\
+static ssize_t tricat(rmi_fn_, FNUM, _##propname##_show)(struct device *dev,\
+                               struct device_attribute *attr, char *buf) {\
+       struct rmi_function_container *fc;\
+       struct FUNCTION_DATA *data;\
+\
+       fc = to_rmi_function_container(dev);\
+       data = fc->data;\
+\
+       return snprintf(buf, PAGE_SIZE, fmt,\
+                       data->regtype.propname);\
+}
+
+#define show_union_struct(regtype, reg_group, propname, fmt)\
+static ssize_t tricat(rmi_fn_, FNUM, _##propname##_show)(\
+                                       struct device *dev,\
+                                       struct device_attribute *attr,\
+                                       char *buf) {\
+       struct rmi_function_container *fc;\
+       struct FUNCTION_DATA *data;\
+       int result;\
+\
+       fc = to_rmi_function_container(dev);\
+       data = fc->data;\
+\
+       mutex_lock(&data->regtype##_mutex);\
+       /* Read current regtype values */\
+       result = rmi_read_block(fc->rmi_dev, data->regtype.reg_group->address,\
+                               (u8 *)data->regtype.reg_group,\
+                               sizeof(data->regtype.reg_group->regs));\
+       mutex_unlock(&data->regtype##_mutex);\
+       if (result < 0) {\
+               dev_dbg(dev, "%s : Could not read regtype at 0x%x\\n",\
+                                       __func__, data->regtype.reg_group->address);\
+               return result;\
+       }\
+       return snprintf(buf, PAGE_SIZE, fmt,\
+                       data->regtype.reg_group->propname);\
+}\
+
+#define show_store_union_struct(regtype, reg_group, propname, fmt)\
+show_union_struct(regtype, reg_group, propname, fmt)\
+\
+static ssize_t tricat(rmi_fn_, FNUM, _##propname##_store)(\
+                                       struct device *dev,\
+                                       struct device_attribute *attr,\
+                                       const char *buf, size_t count) {\
+       int result;\
+       unsigned long val;\
+       unsigned long old_val;\
+       struct rmi_function_container *fc;\
+       struct FUNCTION_DATA *data;\
+\
+       fc = to_rmi_function_container(dev);\
+       data = fc->data;\
+\
+       /* need to convert the string data to an actual value */\
+       result = strict_strtoul(buf, 10, &val);\
+\
+       /* if an error occured, return it */\
+       if (result)\
+               return result;\
+       /* Check value maybe */\
+\
+       /* Read current regtype values */\
+       mutex_lock(&data->regtype##_mutex);\
+       result =\
+           rmi_read_block(fc->rmi_dev, data->regtype.reg_group->address,\
+                               (u8 *)data->regtype.reg_group,\
+                               sizeof(data->regtype.reg_group->regs));\
+\
+       if (result < 0) {\
+               mutex_unlock(&data->regtype##_mutex);\
+               dev_dbg(dev, "%s : Could not read regtype at 0x%x\\n",\
+                                        __func__,\
+                                       data->regtype.reg_group->address);\
+               return result;\
+       }\
+       /* if the current regtype registers are already set as we want them,\
+        * do nothing to them */\
+       if (data->regtype.reg_group->propname == val) {\
+               mutex_unlock(&data->regtype##_mutex);\
+               return count;\
+       }\
+       /* Write the regtype back to the regtype register */\
+       old_val = data->regtype.reg_group->propname;\
+       data->regtype.reg_group->propname = val;\
+       result =\
+           rmi_write_block(fc->rmi_dev, data->regtype.reg_group->address,\
+                               (u8 *)data->regtype.reg_group,\
+                               sizeof(data->regtype.reg_group->regs));\
+       if (result < 0) {\
+               dev_dbg(dev, "%s : Could not write regtype to 0x%x\\n",\
+                                       __func__,\
+                                       data->regtype.reg_group->address);\
+               /* revert change to local value if value not written */\
+               data->regtype.reg_group->propname = old_val;\
+               mutex_unlock(&data->regtype##_mutex);\
+               return result;\
+       }\
+       mutex_unlock(&data->regtype##_mutex);\
+       return count;\
+}
+
+
+#define show_repeated_union_struct(regtype, reg_group, propname, fmt)\
+static ssize_t tricat(rmi_fn_, FNUM, _##propname##_show)(struct device *dev,\
+                                       struct device_attribute *attr,\
+                                       char *buf) {\
+       struct rmi_function_container *fc;\
+       struct FUNCTION_DATA *data;\
+       int reg_length;\
+       int result, size = 0;\
+       char *temp;\
+       int i;\
+\
+       fc = to_rmi_function_container(dev);\
+       data = fc->data;\
+       mutex_lock(&data->regtype##_mutex);\
+\
+       /* Read current regtype values */\
+       reg_length = data->regtype.reg_group->length;\
+       result = rmi_read_block(fc->rmi_dev, data->regtype.reg_group->address,\
+                       (u8*) data->regtype.reg_group->regs,\
+                       reg_length * sizeof(u8));\
+       mutex_unlock(&data->regtype##_mutex);\
+       if (result < 0) {\
+               dev_dbg(dev, "%s : Could not read regtype at 0x%x\n"\
+                                       "Data may be outdated.", __func__,\
+                                       data->regtype.reg_group->address);\
+       }\
+       temp = buf;\
+       for (i = 0; i < reg_length; i++) {\
+               result = snprintf(temp, PAGE_SIZE - size, fmt " ",\
+                                       data->regtype.reg_group->regs[i].propname);\
+               if (result < 0) {\
+                       dev_err(dev, "%s : Could not write output.", __func__);\
+                       return result;\
+               }\
+               size += result;\
+               temp += result;\
+       }\
+       result = snprintf(temp, PAGE_SIZE - size, "\n");\
+       if (result < 0) {\
+                       dev_err(dev, "%s : Could not write output.", __func__);\
+                       return result;\
+       }\
+       return size + result;\
+}
+
+#define show_store_repeated_union_struct(regtype, reg_group, propname, fmt)\
+show_repeated_union_struct(regtype, reg_group, propname, fmt)\
+\
+static ssize_t tricat(rmi_fn_, FNUM, _##propname##_store)(struct device *dev,\
+                                  struct device_attribute *attr,\
+                                  const char *buf, size_t count) {\
+       struct rmi_function_container *fc;\
+       struct FUNCTION_DATA *data;\
+       int reg_length;\
+       int result;\
+       const char *temp;\
+       int i;\
+       unsigned int newval;\
+\
+       fc = to_rmi_function_container(dev);\
+       data = fc->data;\
+       mutex_lock(&data->regtype##_mutex);\
+\
+       /* Read current regtype values */\
+\
+       reg_length = data->regtype.reg_group->length;\
+       result = rmi_read_block(fc->rmi_dev, data->regtype.reg_group->address,\
+                       (u8*) data->regtype.reg_group->regs,\
+                       reg_length * sizeof(u8));\
+\
+       if (result < 0) {\
+               dev_dbg(dev, "%s : Could not read regtype at 0x%x\n"\
+                                       "Data may be outdated.", __func__,\
+                                       data->regtype.reg_group->address);\
+       }\
+       /* parse input */\
+       \
+       temp = buf;\
+       for (i = 0; i < reg_length; i++) {\
+               if(sscanf(temp, fmt, &newval) == 1) {\
+                       data->regtype.reg_group->regs[i].propname = newval;\
+               } else {\
+                       /* If we don't read a value for each position, abort, restore
+                        * previous values locally by rereading */\
+                       result = rmi_read_block(fc->rmi_dev, data->regtype.reg_group->address,\
+                                                                                       (u8*) data->regtype.reg_group->regs,\
+                                                                                       reg_length * sizeof(u8));\
+\
+                       if (result < 0) {\
+                               dev_dbg(dev, "%s : Could not read regtype at 0x%x\n"\
+                                                       "Local data may be innacurrate.", __func__,\
+                                                       data->regtype.reg_group->address);\
+                       }\
+                       return -EINVAL;\
+               }\
+               /* move to next number */\
+               while (*temp != 0) {\
+                       temp++;\
+                       if (isspace(*(temp - 1)) && !isspace(*temp))\
+                               break;\
+               }\
+       }\
+       result = rmi_write_block(fc->rmi_dev, data->regtype.reg_group->address,\
+                       (u8*) data->regtype.reg_group->regs,\
+                       reg_length * sizeof(u8));\
+       mutex_unlock(&data->regtype##_mutex);\
+       if (result < 0) {\
+               dev_dbg(dev, "%s : Could not write new values"\
+                       " to 0x%x\n", __func__, data->regtype.reg_group->address);\
+               return result;\
+       }\
+       return count;\
+}
+
+/* Create templates for given types */
+#define simple_show_union_struct_unsigned(regtype, propname)\
+simple_show_union_struct(regtype, propname, "%u\n")
+
+#define show_union_struct_unsigned(regtype, reg_group, propname)\
+show_union_struct(regtype, reg_group, propname, "%u\n")
+
+#define show_store_union_struct_unsigned(regtype, reg_group, propname)\
+show_store_union_struct(regtype, reg_group, propname, "%u\n")
+
+#define show_repeated_union_struct_unsigned(regtype, reg_group, propname)\
+show_repeated_union_struct(regtype, reg_group, propname, "%u")
+
+#define show_store_repeated_union_struct_unsigned(regtype, reg_group, propname)\
+show_store_repeated_union_struct(regtype, reg_group, propname, "%u")
+
+/* Remove access to raw format string versions */
+/*#undef simple_show_union_struct
+#undef show_union_struct_unsigned
+#undef show_store_union_struct
+#undef show_repeated_union_struct
+#undef show_store_repeated_union_struct*/
+
+#endif
+
+#define GROUP(_attrs) { \
+       .attrs = _attrs,  \
+}
+
+#define attrify(nm) &dev_attr_##nm.attr
+
+union f01_device_status {
+       struct {
+               u8 status_code:4;
+               u8 reserved:2;
+               u8 flash_prog:1;
+               u8 unconfigured:1;
+       };
+       u8 reg;
+};
+
+struct rmi_driver_data {
+       struct rmi_function_container rmi_functions;
+
+       struct rmi_function_container *f01_container;
+       bool f01_bootloader_mode;
+
+       int num_of_irq_regs;
+       int irq_count;
+       u8 *current_irq_mask;
+       u8 *irq_mask_store;
+       bool irq_stored;
+       struct mutex irq_mutex;
+       struct mutex pdt_mutex;
+
+       unsigned char pdt_props;
+       unsigned char bsr;
+       bool enabled;
+
+#ifdef CONFIG_PM
+       bool suspended;
+       struct mutex suspend_mutex;
+
+       void *pm_data;
+       int (*pre_suspend) (const void *pm_data);
+       int (*post_resume) (const void *pm_data);
+#endif
+
+#ifdef CONFIG_RMI4_DEBUG
+#ifdef CONFIG_RMI4_SPI
+       struct dentry *debugfs_delay;
+#endif
+       struct dentry *debugfs_phys;
+       struct dentry *debugfs_reg_ctl;
+       struct dentry *debugfs_reg;
+       u16 reg_debug_addr;
+       u8 reg_debug_size;
+#endif
+
+       void *data;
+};
+
+struct pdt_entry {
+       u8 query_base_addr:8;
+       u8 command_base_addr:8;
+       u8 control_base_addr:8;
+       u8 data_base_addr:8;
+       u8 interrupt_source_count:3;
+       u8 bits3and4:2;
+       u8 function_version:2;
+       u8 bit7:1;
+       u8 function_number:8;
+};
+
+int rmi_driver_f01_init(struct rmi_device *rmi_dev);
+
+static inline void copy_pdt_entry_to_fd(struct pdt_entry *pdt,
+                                struct rmi_function_descriptor *fd,
+                                u16 page_start)
+{
+       fd->query_base_addr = pdt->query_base_addr + page_start;
+       fd->command_base_addr = pdt->command_base_addr + page_start;
+       fd->control_base_addr = pdt->control_base_addr + page_start;
+       fd->data_base_addr = pdt->data_base_addr + page_start;
+       fd->function_number = pdt->function_number;
+       fd->interrupt_source_count = pdt->interrupt_source_count;
+       fd->function_version = pdt->function_version;
+}
+
+#endif
+
diff --git a/drivers/input/touchscreen/rmi4/rmi_f01.c b/drivers/input/touchscreen/rmi4/rmi_f01.c
new file mode 100755 (executable)
index 0000000..1516ab7
--- /dev/null
@@ -0,0 +1,1389 @@
+/*
+ * Copyright (c) 2011-2012 Synaptics Incorporated
+ * Copyright (c) 2011 Unixphere
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/rmi.h>
+#include <linux/slab.h>
+#include "rmi_driver.h"
+
+/* control register bits */
+#define RMI_SLEEP_MODE_NORMAL (0x00)
+#define RMI_SLEEP_MODE_SENSOR_SLEEP (0x01)
+#define RMI_SLEEP_MODE_RESERVED0 (0x02)
+#define RMI_SLEEP_MODE_RESERVED1 (0x03)
+
+#define RMI_IS_VALID_SLEEPMODE(mode) \
+       (mode >= RMI_SLEEP_MODE_NORMAL && mode <= RMI_SLEEP_MODE_RESERVED1)
+
+union f01_device_commands {
+       struct {
+               u8 reset:1;
+               u8 reserved:1;
+       };
+       u8 reg;
+};
+
+struct f01_device_control_0 {
+       union {
+               struct {
+                       u8 sleep_mode:2;
+                       u8 nosleep:1;
+                       u8 reserved:2;
+                       u8 charger_input:1;
+                       u8 report_rate:1;
+                       u8 configured:1;
+               };
+               u8 reg;
+       };
+};
+
+struct f01_device_control {
+       struct f01_device_control_0 ctrl0;
+       u8 *interrupt_enable;
+       u8 doze_interval;
+       u8 wakeup_threshold;
+       u8 doze_holdoff;
+};
+
+union f01_basic_queries {
+       struct {
+               u8 manufacturer_id:8;
+
+               u8 custom_map:1;
+               u8 non_compliant:1;
+               u8 has_lts:1;
+               u8 has_sensor_id:1;
+               u8 has_charger_input:1;
+               u8 has_adjustable_doze:1;
+               u8 has_adjustable_doze_holdoff:1;
+               u8 has_product_properties_2:1;
+
+               u8 productinfo_1:7;
+               u8 q2_bit_7:1;
+               u8 productinfo_2:7;
+               u8 q3_bit_7:1;
+
+               u8 year:5;
+               u8 month:4;
+               u8 day:5;
+               u8 cp1:1;
+               u8 cp2:1;
+               u8 wafer_id1_lsb:8;
+               u8 wafer_id1_msb:8;
+               u8 wafer_id2_lsb:8;
+               u8 wafer_id2_msb:8;
+               u8 wafer_id3_lsb:8;
+       };
+       u8 regs[11];
+};
+
+union f01_query_42 {
+       struct {
+               u8 has_ds4_queries:1;
+               u8 has_multi_phy:1;
+               u8 has_guest:1;
+               u8 reserved:5;
+       };
+       u8 regs[1];
+};
+
+union f01_ds4_queries {
+       struct {
+               u8 length:4;
+               u8 reserved_1:4;
+
+               u8 has_package_id_query:1;
+               u8 has_packrat_query:1;
+               u8 has_reset_query:1;
+               u8 has_maskrev_query:1;
+               u8 reserved_2:4;
+
+               u8 has_i2c_control:1;
+               u8 has_spi_control:1;
+               u8 has_attn_control:1;
+               u8 reserved_3:5;
+
+               u8 reset_enabled:1;
+               u8 reset_polarity:1;
+               u8 pullup_enabled:1;
+               u8 reserved_4:1;
+               u8 reset_pin_number:4;
+       };
+       u8 regs[4];
+};
+
+struct f01_data {
+       struct f01_device_control device_control;
+       union f01_basic_queries basic_queries;
+       union f01_device_status device_status;
+       u8 product_id[RMI_PRODUCT_ID_LENGTH+1];
+
+       u8 interrupt_enable_addr;
+       u8 doze_interval_addr;
+       u8 wakeup_threshold_addr;
+       u8 doze_holdoff_addr;
+
+       int irq_count;
+       int num_of_irq_regs;
+
+#ifdef CONFIG_PM
+       bool suspended;
+       bool old_nosleep;
+#endif
+};
+
+
+static ssize_t rmi_fn_01_productinfo_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf);
+
+static ssize_t rmi_fn_01_productid_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf);
+
+static ssize_t rmi_fn_01_manufacturer_show(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf);
+
+static ssize_t rmi_fn_01_datecode_show(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf);
+
+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);
+
+static ssize_t rmi_fn_01_interrupt_enable_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf);
+
+static ssize_t rmi_fn_01_interrupt_enable_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t count);
+
+static ssize_t rmi_fn_01_doze_interval_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf);
+
+static ssize_t rmi_fn_01_doze_interval_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t count);
+
+static ssize_t rmi_fn_01_wakeup_threshold_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf);
+
+static ssize_t rmi_fn_01_wakeup_threshold_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t count);
+
+static ssize_t rmi_fn_01_doze_holdoff_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf);
+
+static ssize_t rmi_fn_01_doze_holdoff_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t count);
+
+static ssize_t rmi_fn_01_reset_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count);
+
+static ssize_t rmi_fn_01_sleepmode_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf);
+
+static ssize_t rmi_fn_01_sleepmode_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count);
+
+static ssize_t rmi_fn_01_nosleep_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf);
+
+static ssize_t rmi_fn_01_nosleep_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count);
+
+static ssize_t rmi_fn_01_chargerinput_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf);
+
+static ssize_t rmi_fn_01_chargerinput_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf, size_t count);
+
+static ssize_t rmi_fn_01_configured_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf);
+
+static ssize_t rmi_fn_01_unconfigured_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf);
+
+static ssize_t rmi_fn_01_flashprog_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf);
+
+static ssize_t rmi_fn_01_statuscode_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf);
+
+static int rmi_f01_alloc_memory(struct rmi_function_container *fc,
+                                       int num_of_irq_regs);
+
+static void rmi_f01_free_memory(struct rmi_function_container *fc);
+
+static int rmi_f01_initialize(struct rmi_function_container *fc);
+
+static int rmi_f01_create_sysfs(struct rmi_function_container *fc);
+
+static int rmi_f01_config(struct rmi_function_container *fc);
+
+static int rmi_f01_reset(struct rmi_function_container *fc);
+
+
+static struct device_attribute fn_01_attrs[] = {
+       __ATTR(productinfo, RMI_RO_ATTR,
+              rmi_fn_01_productinfo_show, rmi_store_error),
+       __ATTR(productid, RMI_RO_ATTR,
+              rmi_fn_01_productid_show, rmi_store_error),
+       __ATTR(manufacturer, RMI_RO_ATTR,
+              rmi_fn_01_manufacturer_show, rmi_store_error),
+       __ATTR(datecode, RMI_RO_ATTR,
+              rmi_fn_01_datecode_show, rmi_store_error),
+
+       /* control register access */
+       __ATTR(sleepmode, RMI_RW_ATTR,
+              rmi_fn_01_sleepmode_show, rmi_fn_01_sleepmode_store),
+       __ATTR(nosleep, RMI_RW_ATTR,
+              rmi_fn_01_nosleep_show, rmi_fn_01_nosleep_store),
+       __ATTR(chargerinput, RMI_RW_ATTR,
+              rmi_fn_01_chargerinput_show, rmi_fn_01_chargerinput_store),
+       __ATTR(reportrate, RMI_RW_ATTR,
+              rmi_fn_01_reportrate_show, rmi_fn_01_reportrate_store),
+       __ATTR(interrupt_enable, RMI_RW_ATTR,
+              rmi_fn_01_interrupt_enable_show,
+               rmi_fn_01_interrupt_enable_store),
+       __ATTR(doze_interval, RMI_RW_ATTR,
+              rmi_fn_01_doze_interval_show,
+               rmi_fn_01_doze_interval_store),
+       __ATTR(wakeup_threshold, RMI_RW_ATTR,
+              rmi_fn_01_wakeup_threshold_show,
+               rmi_fn_01_wakeup_threshold_store),
+       __ATTR(doze_holdoff, RMI_RW_ATTR,
+              rmi_fn_01_doze_holdoff_show,
+               rmi_fn_01_doze_holdoff_store),
+
+       /* We make report rate RO, since the driver uses that to look for
+        * resets.  We don't want someone faking us out by changing that
+        * bit.
+        */
+       __ATTR(configured, RMI_RO_ATTR,
+              rmi_fn_01_configured_show, rmi_store_error),
+
+       /* Command register access. */
+       __ATTR(reset, RMI_WO_ATTR,
+              rmi_show_error, rmi_fn_01_reset_store),
+
+       /* STatus register access. */
+       __ATTR(unconfigured, RMI_RO_ATTR,
+              rmi_fn_01_unconfigured_show, rmi_store_error),
+       __ATTR(flashprog, RMI_RO_ATTR,
+              rmi_fn_01_flashprog_show, rmi_store_error),
+       __ATTR(statuscode, RMI_RO_ATTR,
+              rmi_fn_01_statuscode_show, rmi_store_error),
+};
+
+/* Utility routine to set the value of a bit field in a register. */
+int rmi_set_bit_field(struct rmi_device *rmi_dev,
+                     unsigned short address,
+                     unsigned char field_mask,
+                     unsigned char bits)
+{
+       unsigned char reg_contents;
+       int retval;
+
+       retval = rmi_read(rmi_dev, address, &reg_contents);
+       if (retval)
+               return retval;
+       reg_contents = (reg_contents & ~field_mask) | bits;
+       retval = rmi_write(rmi_dev, address, reg_contents);
+       if (retval == 1)
+               return 0;
+       else if (retval == 0)
+               return -EIO;
+       return retval;
+}
+
+static ssize_t rmi_fn_01_productinfo_show(struct device *dev,
+                                         struct device_attribute *attr,
+                                         char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "0x%02x 0x%02x\n",
+                       data->basic_queries.productinfo_1,
+                       data->basic_queries.productinfo_2);
+}
+
+static ssize_t rmi_fn_01_productid_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%s\n", data->product_id);
+}
+
+static ssize_t rmi_fn_01_manufacturer_show(struct device *dev,
+                                          struct device_attribute *attr,
+                                          char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "0x%02x\n",
+                       data->basic_queries.manufacturer_id);
+}
+
+static ssize_t rmi_fn_01_datecode_show(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "20%02u-%02u-%02u\n",
+                       data->basic_queries.year,
+                       data->basic_queries.month,
+                       data->basic_queries.day);
+}
+
+static ssize_t rmi_fn_01_reset_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct rmi_function_container *fc = NULL;
+       unsigned int reset;
+       int retval = 0;
+       /* Command register always reads as 0, so we can just use a local. */
+       union f01_device_commands commands = {};
+
+       fc = to_rmi_function_container(dev);
+
+       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) {
+               commands.reset = 1;
+               retval = rmi_write_block(fc->rmi_dev, fc->fd.command_base_addr,
+                               &commands.reg, sizeof(commands.reg));
+               if (retval < 0) {
+                       dev_err(dev, "%s: failed to issue reset command, "
+                               "error = %d.", __func__, retval);
+                       return retval;
+               }
+       }
+
+       return count;
+}
+
+static ssize_t rmi_fn_01_sleepmode_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE,
+                       "%d\n", data->device_control.ctrl0.sleep_mode);
+}
+
+static ssize_t rmi_fn_01_sleepmode_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf,
+                                        size_t count)
+{
+       struct f01_data *data = NULL;
+       unsigned long new_value;
+       int retval;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       retval = strict_strtoul(buf, 10, &new_value);
+       if (retval < 0 || !RMI_IS_VALID_SLEEPMODE(new_value)) {
+               dev_err(dev, "%s: Invalid sleep mode %s.", __func__, buf);
+               return -EINVAL;
+       }
+
+       dev_dbg(dev, "Setting sleep mode to %ld.", new_value);
+       data->device_control.ctrl0.sleep_mode = new_value;
+       retval = rmi_write_block(fc->rmi_dev, fc->fd.control_base_addr,
+                       &data->device_control.ctrl0.reg,
+                       sizeof(data->device_control.ctrl0.reg));
+       if (retval >= 0)
+               retval = count;
+       else
+               dev_err(dev, "Failed to write sleep mode, code %d.\n", retval);
+       return retval;
+}
+
+static ssize_t rmi_fn_01_nosleep_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+               data->device_control.ctrl0.nosleep);
+}
+
+static ssize_t rmi_fn_01_nosleep_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf,
+                                      size_t count)
+{
+       struct f01_data *data = NULL;
+       unsigned long new_value;
+       int retval;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       retval = strict_strtoul(buf, 10, &new_value);
+       if (retval < 0 || new_value < 0 || new_value > 1) {
+               dev_err(dev, "%s: Invalid nosleep bit %s.", __func__, buf);
+               return -EINVAL;
+       }
+
+       data->device_control.ctrl0.nosleep = new_value;
+       retval = rmi_write_block(fc->rmi_dev, fc->fd.control_base_addr,
+                       &data->device_control.ctrl0.reg,
+                       sizeof(data->device_control.ctrl0.reg));
+       if (retval >= 0)
+               retval = count;
+       else
+               dev_err(dev, "Failed to write nosleep bit.\n");
+       return retval;
+}
+
+static ssize_t rmi_fn_01_chargerinput_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       data->device_control.ctrl0.charger_input);
+}
+
+static ssize_t rmi_fn_01_chargerinput_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf,
+                                      size_t count)
+{
+       struct f01_data *data = NULL;
+       unsigned long new_value;
+       int retval;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       retval = strict_strtoul(buf, 10, &new_value);
+       if (retval < 0 || new_value < 0 || new_value > 1) {
+               dev_err(dev, "%s: Invalid chargerinput bit %s.", __func__, buf);
+               return -EINVAL;
+       }
+
+       data->device_control.ctrl0.charger_input = new_value;
+       retval = rmi_write_block(fc->rmi_dev, fc->fd.control_base_addr,
+                       &data->device_control.ctrl0.reg,
+                       sizeof(data->device_control.ctrl0.reg));
+       if (retval >= 0)
+               retval = count;
+       else
+               dev_err(dev, "Failed to write chargerinput bit.\n");
+       return retval;
+}
+
+static ssize_t rmi_fn_01_reportrate_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       data->device_control.ctrl0.report_rate);
+}
+
+static ssize_t rmi_fn_01_reportrate_store(struct device *dev,
+                                      struct device_attribute *attr,
+                                      const char *buf,
+                                      size_t count)
+{
+       struct f01_data *data = NULL;
+       unsigned long new_value;
+       int retval;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       retval = strict_strtoul(buf, 10, &new_value);
+       if (retval < 0 || new_value < 0 || new_value > 1) {
+               dev_err(dev, "%s: Invalid reportrate bit %s.", __func__, buf);
+               return -EINVAL;
+       }
+
+       data->device_control.ctrl0.report_rate = new_value;
+       retval = rmi_write_block(fc->rmi_dev, fc->fd.control_base_addr,
+                       &data->device_control.ctrl0.reg,
+                       sizeof(data->device_control.ctrl0.reg));
+       if (retval >= 0)
+               retval = count;
+       else
+               dev_err(dev, "Failed to write reportrate bit.\n");
+       return retval;
+}
+
+static ssize_t rmi_fn_01_interrupt_enable_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f01_data *data;
+       int i, len, total_len = 0;
+       char *current_buf = buf;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       /* loop through each irq value and copy its
+        * string representation into buf */
+       for (i = 0; i < data->irq_count; i++) {
+               int irq_reg;
+               int irq_shift;
+               int interrupt_enable;
+
+               irq_reg = i / 8;
+               irq_shift = i % 8;
+               interrupt_enable =
+                   ((data->device_control.interrupt_enable[irq_reg]
+                       >> irq_shift) & 0x01);
+
+               /* get next irq value and write it to buf */
+               len = snprintf(current_buf, PAGE_SIZE - total_len,
+                       "%u ", interrupt_enable);
+               /* bump up ptr to next location in buf if the
+                * snprintf was valid.  Otherwise issue an error
+                * and return. */
+               if (len > 0) {
+                       current_buf += len;
+                       total_len += len;
+               } else {
+                       dev_err(dev, "%s: Failed to build interrupt_enable"
+                               " buffer, code = %d.\n", __func__, len);
+                       return snprintf(buf, PAGE_SIZE, "unknown\n");
+               }
+       }
+       len = snprintf(current_buf, PAGE_SIZE - total_len, "\n");
+       if (len > 0)
+               total_len += len;
+       else
+               dev_warn(dev, "%s: Failed to append carriage return.\n",
+                        __func__);
+       return total_len;
+
+}
+
+static ssize_t rmi_fn_01_interrupt_enable_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f01_data *data;
+       int i;
+       int irq_count = 0;
+       int retval = count;
+       int irq_reg = 0;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       for (i = 0; i < data->irq_count && *buf != 0;
+            i++, buf += 2) {
+               int irq_shift;
+               int interrupt_enable;
+               int result;
+
+               irq_reg = i / 8;
+               irq_shift = i % 8;
+
+               /* get next interrupt mapping value and store and bump up to
+                * point to next item in buf */
+               result = sscanf(buf, "%u", &interrupt_enable);
+               if ((result != 1) ||
+                       (interrupt_enable != 0 && interrupt_enable != 1)) {
+                       dev_err(dev,
+                               "%s: Error - interrupt enable[%d]"
+                               " is not a valid value 0x%x.\n",
+                               __func__, i, interrupt_enable);
+                       return -EINVAL;
+               }
+               if (interrupt_enable == 0) {
+                       data->device_control.interrupt_enable[irq_reg] &=
+                               (1 << irq_shift) ^ 0xFF;
+               } else
+                       data->device_control.interrupt_enable[irq_reg] |=
+                               (1 << irq_shift);
+               irq_count++;
+       }
+
+       /* Make sure the irq count matches */
+       if (irq_count != data->irq_count) {
+               dev_err(dev,
+                       "%s: Error - interrupt enable count of %d"
+                       " doesn't match device count of %d.\n",
+                        __func__, irq_count, data->irq_count);
+               return -EINVAL;
+       }
+
+       /* write back to the control register */
+       retval = rmi_write_block(fc->rmi_dev, data->interrupt_enable_addr,
+                       data->device_control.interrupt_enable,
+                       sizeof(u8)*(data->num_of_irq_regs));
+       if (retval < 0) {
+               dev_err(dev, "%s : Could not write interrupt_enable_store"
+                       " to 0x%x\n", __func__, data->interrupt_enable_addr);
+               return retval;
+       }
+
+       return count;
+
+}
+
+static ssize_t rmi_fn_01_doze_interval_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       data->device_control.doze_interval);
+
+}
+
+static ssize_t rmi_fn_01_doze_interval_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t count)
+{
+       struct f01_data *data = NULL;
+       unsigned long new_value;
+       int retval;
+       int ctrl_base_addr;
+
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       retval = strict_strtoul(buf, 10, &new_value);
+       if (retval < 0 || new_value < 0 || new_value > 255) {
+               dev_err(dev, "%s: Invalid doze interval %s.", __func__, buf);
+               return -EINVAL;
+       }
+
+       data->device_control.doze_interval = new_value;
+       ctrl_base_addr = fc->fd.control_base_addr + sizeof(u8) +
+                       (sizeof(u8)*(data->num_of_irq_regs));
+       dev_info(dev, "doze_interval store address %x, value %d",
+               ctrl_base_addr, data->device_control.doze_interval);
+
+       retval = rmi_write_block(fc->rmi_dev, data->doze_interval_addr,
+                       &data->device_control.doze_interval,
+                       sizeof(u8));
+       if (retval >= 0)
+               retval = count;
+       else
+               dev_err(dev, "Failed to write doze interval.\n");
+       return retval;
+
+}
+
+static ssize_t rmi_fn_01_wakeup_threshold_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       data->device_control.wakeup_threshold);
+}
+
+static ssize_t rmi_fn_01_wakeup_threshold_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t count)
+{
+       struct f01_data *data = NULL;
+       unsigned long new_value;
+       int retval;
+
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       retval = strict_strtoul(buf, 10, &new_value);
+       if (retval < 0 || new_value < 0 || new_value > 255) {
+               dev_err(dev, "%s: Invalid wakeup threshold %s.", __func__, buf);
+               return -EINVAL;
+       }
+
+       data->device_control.doze_interval = new_value;
+       retval = rmi_write_block(fc->rmi_dev, data->wakeup_threshold_addr,
+                       &data->device_control.wakeup_threshold,
+                       sizeof(u8));
+       if (retval >= 0)
+               retval = count;
+       else
+               dev_err(dev, "Failed to write wakeup threshold.\n");
+       return retval;
+
+}
+
+static ssize_t rmi_fn_01_doze_holdoff_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       data->device_control.doze_holdoff);
+
+}
+
+
+static ssize_t rmi_fn_01_doze_holdoff_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t count)
+{
+       struct f01_data *data = NULL;
+       unsigned long new_value;
+       int retval;
+
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       retval = strict_strtoul(buf, 10, &new_value);
+       if (retval < 0 || new_value < 0 || new_value > 255) {
+               dev_err(dev, "%s: Invalid doze holdoff %s.", __func__, buf);
+               return -EINVAL;
+       }
+
+       data->device_control.doze_interval = new_value;
+       retval = rmi_write_block(fc->rmi_dev, data->doze_holdoff_addr,
+                       &data->device_control.doze_holdoff,
+                       sizeof(u8));
+       if (retval >= 0)
+               retval = count;
+       else
+               dev_err(dev, "Failed to write doze holdoff.\n");
+       return retval;
+
+}
+
+static ssize_t rmi_fn_01_configured_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       data->device_control.ctrl0.configured);
+}
+
+static ssize_t rmi_fn_01_unconfigured_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       data->device_status.unconfigured);
+}
+
+static ssize_t rmi_fn_01_flashprog_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n",
+                       data->device_status.flash_prog);
+}
+
+static ssize_t rmi_fn_01_statuscode_show(struct device *dev,
+                                     struct device_attribute *attr,
+                                     char *buf)
+{
+       struct f01_data *data = NULL;
+       struct rmi_function_container *fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "0x%02x\n",
+                       data->device_status.status_code);
+}
+
+/* why is this not done in init? */
+int rmi_driver_f01_init(struct rmi_device *rmi_dev)
+{
+       struct rmi_driver_data *driver_data = rmi_get_driverdata(rmi_dev);
+       struct rmi_function_container *fc = driver_data->f01_container;
+       int error;
+
+       error = rmi_f01_alloc_memory(fc, driver_data->num_of_irq_regs);
+       if (error < 0)
+               goto error_exit;
+
+       error = rmi_f01_initialize(fc);
+       if (error < 0)
+               goto error_exit;
+
+       error = rmi_f01_create_sysfs(fc);
+       if (error < 0)
+               goto error_exit;
+
+       return 0;
+
+ error_exit:
+       rmi_f01_free_memory(fc);
+
+       return error;
+}
+
+static int rmi_f01_alloc_memory(struct rmi_function_container *fc,
+       int num_of_irq_regs)
+{
+       struct f01_data *f01;
+
+       f01 = kzalloc(sizeof(struct f01_data), GFP_KERNEL);
+       if (!f01) {
+               dev_err(&fc->dev, "Failed to allocate fn_01_data.\n");
+               return -ENOMEM;
+       }
+
+       f01->device_control.interrupt_enable =
+               kzalloc(sizeof(u8)*(num_of_irq_regs), GFP_KERNEL);
+       if (!f01->device_control.interrupt_enable) {
+               kfree(f01);
+               return -ENOMEM;
+       }
+       fc->data = f01;
+
+       return 0;
+}
+
+static void rmi_f01_free_memory(struct rmi_function_container *fc)
+{
+       struct f01_data *f01 = fc->data;
+       kfree(f01->device_control.interrupt_enable);
+       kfree(fc->data);
+       fc->data = NULL;
+}
+
+static int rmi_f01_initialize(struct rmi_function_container *fc)
+{
+       u8 temp;
+       int retval;
+       int ctrl_base_addr;
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct rmi_driver_data *driver_data = rmi_get_driverdata(rmi_dev);
+       struct f01_data *data = fc->data;
+       struct rmi_device_platform_data *pdata = to_rmi_platform_data(rmi_dev);
+
+       /* Set the configured bit and (optionally) other important stuff
+        * in the device control register. */
+       ctrl_base_addr = fc->fd.control_base_addr;
+       retval = rmi_read_block(rmi_dev, fc->fd.control_base_addr,
+                       &data->device_control.ctrl0.reg,
+                       sizeof(data->device_control.ctrl0.reg));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to read F01 control.\n");
+               return retval;
+       }
+       switch (pdata->power_management.nosleep) {
+       case RMI_F01_NOSLEEP_DEFAULT:
+               break;
+       case RMI_F01_NOSLEEP_OFF:
+               data->device_control.ctrl0.nosleep = 0;
+               break;
+       case RMI_F01_NOSLEEP_ON:
+               data->device_control.ctrl0.nosleep = 1;
+               break;
+       }
+       /* Sleep mode might be set as a hangover from a system crash or
+        * reboot without power cycle.  If so, clear it so the sensor
+        * is certain to function.
+        */
+       if (data->device_control.ctrl0.sleep_mode != RMI_SLEEP_MODE_NORMAL) {
+               dev_warn(&fc->dev,
+                        "WARNING: Non-zero sleep mode found. Clearing...\n");
+               data->device_control.ctrl0.sleep_mode = RMI_SLEEP_MODE_NORMAL;
+       }
+
+       data->device_control.ctrl0.configured = 1;
+       retval = rmi_write_block(rmi_dev, fc->fd.control_base_addr,
+                       &data->device_control.ctrl0.reg,
+                       sizeof(data->device_control.ctrl0.reg));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to write F01 control.\n");
+               return retval;
+       }
+
+       data->irq_count = driver_data->irq_count;
+       data->num_of_irq_regs = driver_data->num_of_irq_regs;
+       ctrl_base_addr += sizeof(struct f01_device_control_0);
+
+       data->interrupt_enable_addr = ctrl_base_addr;
+       retval = rmi_read_block(rmi_dev, ctrl_base_addr,
+                       data->device_control.interrupt_enable,
+                       sizeof(u8) * (driver_data->num_of_irq_regs));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to read F01 control interrupt enable register.\n");
+               goto error_exit;
+       }
+       ctrl_base_addr += (sizeof(u8) * (driver_data->num_of_irq_regs));
+
+       /* dummy read in order to clear irqs */
+       retval = rmi_read(rmi_dev, fc->fd.data_base_addr + 1, &temp);
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to read Interrupt Status.\n");
+               return retval;
+       }
+
+       retval = rmi_read_block(rmi_dev, fc->fd.query_base_addr,
+                               data->basic_queries.regs,
+                               sizeof(data->basic_queries.regs));
+
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to read device query registers.\n");
+               return retval;
+       }
+
+       retval = rmi_read_block(rmi_dev,
+               fc->fd.query_base_addr + sizeof(data->basic_queries.regs),
+               data->product_id, RMI_PRODUCT_ID_LENGTH);
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to read product ID.\n");
+               return retval;
+       }
+       data->product_id[RMI_PRODUCT_ID_LENGTH] = '\0';
+       dev_info(&fc->dev, "found RMI device, manufacturer: %s, product: %s\n",
+                data->basic_queries.manufacturer_id == 1 ?
+                                                       "synaptics" : "unknown",
+                data->product_id);
+
+       /* read control register */
+       if (data->basic_queries.has_adjustable_doze) {
+               data->doze_interval_addr = ctrl_base_addr;
+               ctrl_base_addr++;
+
+               if (pdata->power_management.doze_interval) {
+                       data->device_control.doze_interval =
+                               pdata->power_management.doze_interval;
+                       retval = rmi_write(rmi_dev, data->doze_interval_addr,
+                                       data->device_control.doze_interval);
+                       if (retval < 0) {
+                               dev_err(&fc->dev, "Failed to configure F01 doze interval register.\n");
+                               goto error_exit;
+                       }
+               } else {
+                       retval = rmi_read(rmi_dev, data->doze_interval_addr,
+                                       &data->device_control.doze_interval);
+                       if (retval < 0) {
+                               dev_err(&fc->dev, "Failed to read F01 doze interval register.\n");
+                               goto error_exit;
+                       }
+               }
+
+               data->wakeup_threshold_addr = ctrl_base_addr;
+               ctrl_base_addr++;
+
+               if (pdata->power_management.wakeup_threshold) {
+                       data->device_control.wakeup_threshold =
+                               pdata->power_management.wakeup_threshold;
+                       retval = rmi_write(rmi_dev, data->wakeup_threshold_addr,
+                                       data->device_control.wakeup_threshold);
+                       if (retval < 0) {
+                               dev_err(&fc->dev, "Failed to configure F01 wakeup threshold register.\n");
+                               goto error_exit;
+                       }
+               } else {
+                       retval = rmi_read(rmi_dev, data->wakeup_threshold_addr,
+                                       &data->device_control.wakeup_threshold);
+                       if (retval < 0) {
+                               dev_err(&fc->dev, "Failed to read F01 wakeup threshold register.\n");
+                               goto error_exit;
+                       }
+               }
+       }
+
+       if (data->basic_queries.has_adjustable_doze_holdoff) {
+               data->doze_holdoff_addr = ctrl_base_addr;
+               ctrl_base_addr++;
+
+               if (pdata->power_management.doze_holdoff) {
+                       data->device_control.doze_holdoff =
+                               pdata->power_management.doze_holdoff;
+                       retval = rmi_write(rmi_dev, data->doze_holdoff_addr,
+                                       data->device_control.doze_holdoff);
+                       if (retval < 0) {
+                               dev_err(&fc->dev, "Failed to configure F01 "
+                                       "doze holdoff register.\n");
+                               goto error_exit;
+                       }
+               } else {
+                       retval = rmi_read(rmi_dev, data->doze_holdoff_addr,
+                                       &data->device_control.doze_holdoff);
+                       if (retval < 0) {
+                               dev_err(&fc->dev, "Failed to read F01 doze"
+                                       " holdoff register.\n");
+                               goto error_exit;
+                       }
+               }
+       }
+
+       retval = rmi_read_block(rmi_dev, fc->fd.data_base_addr,
+                       &data->device_status.reg,
+                       sizeof(data->device_status.reg));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to read device status.\n");
+               goto error_exit;
+       }
+
+       if (data->device_status.unconfigured) {
+               dev_err(&fc->dev,
+                       "Device reset during configuration process, status: "
+                       "%#02x!\n", data->device_status.status_code);
+               retval = -EINVAL;
+               goto error_exit;
+       }
+
+       return retval;
+
+ error_exit:
+       kfree(data);
+       return retval;
+}
+
+static int rmi_f01_create_sysfs(struct rmi_function_container *fc)
+{
+       int attr_count = 0;
+       int retval = 0;
+       struct f01_data *data = fc->data;
+
+       dev_dbg(&fc->dev, "Creating sysfs files.");
+       for (attr_count = 0; attr_count < ARRAY_SIZE(fn_01_attrs);
+                       attr_count++) {
+               if (!strcmp("doze_interval", fn_01_attrs[attr_count].attr.name)
+                       && !data->basic_queries.has_lts) {
+                       continue;
+               }
+               if (!strcmp("wakeup_threshold",
+                       fn_01_attrs[attr_count].attr.name)
+                       && !data->basic_queries.has_adjustable_doze) {
+                       continue;
+               }
+               if (!strcmp("doze_holdoff", fn_01_attrs[attr_count].attr.name)
+                       && !data->basic_queries.has_adjustable_doze_holdoff) {
+                       continue;
+               }
+               retval = sysfs_create_file(&fc->dev.kobj,
+                                     &fn_01_attrs[attr_count].attr);
+               if (retval < 0) {
+                       dev_err(&fc->dev, "Failed to create sysfs file for %s.",
+                              fn_01_attrs[attr_count].attr.name);
+                       goto err_remove_sysfs;
+               }
+       }
+
+       return 0;
+
+err_remove_sysfs:
+       for (attr_count--; attr_count >= 0; attr_count--)
+               sysfs_remove_file(&fc->dev.kobj,
+                                 &fn_01_attrs[attr_count].attr);
+
+       return retval;
+}
+
+static int rmi_f01_config(struct rmi_function_container *fc)
+{
+       struct f01_data *data = fc->data;
+       int retval;
+
+       retval = rmi_write_block(fc->rmi_dev, fc->fd.control_base_addr,
+                       (u8 *)&data->device_control.ctrl0,
+                       sizeof(struct f01_device_control_0));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to write device_control.reg.\n");
+               return retval;
+       }
+
+       retval = rmi_write_block(fc->rmi_dev, data->interrupt_enable_addr,
+                       data->device_control.interrupt_enable,
+                       sizeof(u8)*(data->num_of_irq_regs));
+
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to write interrupt enable.\n");
+               return retval;
+       }
+       if (data->basic_queries.has_lts) {
+               retval = rmi_write_block(fc->rmi_dev, data->doze_interval_addr,
+                               &data->device_control.doze_interval,
+                               sizeof(u8));
+               if (retval < 0) {
+                       dev_err(&fc->dev, "Failed to write doze interval.\n");
+                       return retval;
+               }
+       }
+
+       if (data->basic_queries.has_adjustable_doze) {
+               retval = rmi_write_block(
+                               fc->rmi_dev, data->wakeup_threshold_addr,
+                               &data->device_control.wakeup_threshold,
+                               sizeof(u8));
+               if (retval < 0) {
+                       dev_err(&fc->dev, "Failed to write wakeup threshold.\n");
+                       return retval;
+               }
+       }
+
+       if (data->basic_queries.has_adjustable_doze_holdoff) {
+               retval = rmi_write_block(fc->rmi_dev, data->doze_holdoff_addr,
+                               &data->device_control.doze_holdoff,
+                               sizeof(u8));
+               if (retval < 0) {
+                       dev_err(&fc->dev, "Failed to write doze holdoff.\n");
+                       return retval;
+               }
+       }
+       return 0;
+}
+
+static int rmi_f01_reset(struct rmi_function_container *fc)
+{
+       /*do nothing here */
+       return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int rmi_f01_suspend(struct rmi_function_container *fc)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct rmi_driver_data *driver_data = rmi_get_driverdata(rmi_dev);
+       struct f01_data *data = driver_data->f01_container->data;
+       int retval = 0;
+
+       dev_info(&fc->dev, "Suspending...\n");
+       if (data->suspended)
+               return 0;
+
+       data->old_nosleep = data->device_control.ctrl0.nosleep;
+       data->device_control.ctrl0.nosleep = 0;
+       data->device_control.ctrl0.sleep_mode = RMI_SLEEP_MODE_SENSOR_SLEEP;
+       printk("++sleep_mode:%x\n", data->device_control.ctrl0.reg);
+       retval = rmi_write_block(rmi_dev,
+                       driver_data->f01_container->fd.control_base_addr,
+                       (u8 *)&data->device_control.ctrl0,
+                       sizeof(struct f01_device_control_0));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to write sleep mode. Code: %d.\n",
+                       retval);
+               data->device_control.ctrl0.nosleep = data->old_nosleep;
+               data->device_control.ctrl0.sleep_mode = RMI_SLEEP_MODE_NORMAL;
+       } else {
+               data->suspended = true;
+               retval = 0;
+       }
+
+       return retval;
+}
+
+static int rmi_f01_resume(struct rmi_function_container *fc)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct rmi_driver_data *driver_data = rmi_get_driverdata(rmi_dev);
+       struct f01_data *data = driver_data->f01_container->data;
+       int retval = 0;
+
+       dev_info(&fc->dev, "Resuming...\n");
+       if (!data->suspended)
+               return 0;
+
+       data->device_control.ctrl0.nosleep = data->old_nosleep;
+       data->device_control.ctrl0.sleep_mode = RMI_SLEEP_MODE_NORMAL;
+       printk("++sleep_mode:%x\n", data->device_control.ctrl0.reg);
+       retval = rmi_write_block(rmi_dev,
+                       driver_data->f01_container->fd.control_base_addr,
+                       (u8 *)&data->device_control.ctrl0,
+                       sizeof(struct f01_device_control_0));
+       if (retval < 0)
+               dev_err(&fc->dev,
+                       "Failed to restore normal operation. Code: %d.\n",
+                       retval);
+       else {
+               data->suspended = false;
+               retval = 0;
+       }
+
+       return retval;
+}
+#endif /* CONFIG_PM */
+
+static int rmi_f01_init(struct rmi_function_container *fc)
+{
+       return 0;
+}
+
+static void rmi_f01_remove(struct rmi_function_container *fc)
+{
+       int attr_count;
+
+       for (attr_count = 0; attr_count < ARRAY_SIZE(fn_01_attrs);
+                       attr_count++) {
+               sysfs_remove_file(&fc->dev.kobj, &fn_01_attrs[attr_count].attr);
+       }
+
+       rmi_f01_free_memory(fc);
+}
+
+static int rmi_f01_attention(struct rmi_function_container *fc, u8 *irq_bits)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct f01_data *data = fc->data;
+       int retval;
+
+       retval = rmi_read_block(rmi_dev, fc->fd.data_base_addr,
+               &data->device_status.reg,
+       sizeof(data->device_status.reg));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to read device status, code: %d.\n",
+                       retval);
+               return retval;
+       }
+       if (data->device_status.unconfigured) {
+               dev_warn(&fc->dev, "Device reset detected.\n");
+               retval = rmi_dev->driver->reset_handler(rmi_dev);
+               if (retval < 0)
+                       return retval;
+       }
+       return 0;
+}
+
+static struct rmi_function_handler function_handler = {
+       .func = 0x01,
+       .init = rmi_f01_init,
+       .config = rmi_f01_config,
+       .reset = rmi_f01_reset,
+       .attention = rmi_f01_attention,
+#ifdef CONFIG_PM
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       .early_suspend = rmi_f01_suspend,
+       .late_resume = rmi_f01_resume,
+#else
+       .suspend = rmi_f01_suspend,
+       .resume = rmi_f01_resume,
+#endif  /* CONFIG_HAS_EARLYSUSPEND */
+#endif  /* CONFIG_PM */
+       .remove = rmi_f01_remove,
+};
+
+static int __init rmi_f01_module_init(void)
+{
+       int error;
+
+       error = rmi_register_function_driver(&function_handler);
+       if (error < 0) {
+               pr_err("%s: register failed!\n", __func__);
+               return error;
+       }
+
+       return 0;
+}
+
+static void __exit rmi_f01_module_exit(void)
+{
+       rmi_unregister_function_driver(&function_handler);
+}
+
+module_init(rmi_f01_module_init);
+module_exit(rmi_f01_module_exit);
+
+MODULE_AUTHOR("Christopher Heiny <cheiny@synaptics.com>");
+MODULE_DESCRIPTION("RMI F01 module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
diff --git a/drivers/input/touchscreen/rmi4/rmi_f09.c b/drivers/input/touchscreen/rmi4/rmi_f09.c
new file mode 100755 (executable)
index 0000000..e71f472
--- /dev/null
@@ -0,0 +1,771 @@
+/*
+ * Copyright (c) 2011 Synaptics Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/rmi.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include "rmi_driver.h"
+#define QUERY_BASE_INDEX 1
+
+/* data specific to fn $09 that needs to be kept around */
+struct f09_query {
+       u8 limit_register_count;
+       union {
+               struct {
+                       u8 result_register_count:3;
+                       u8 reserved:3;
+                       u8 internal_limits:1;
+                       u8 host_test_enable:1;
+               };
+               u8 f09_bist_query1;
+       };
+};
+
+struct f09_control {
+       union {
+               struct {
+                       u8 test1_limit_low:8;
+                       u8 test1_limit_high:8;
+                       u8 test1_limit_diff:8;
+               };
+               u8 f09_control_test1[3];
+       };
+       union {
+               struct {
+                       u8 test2_limit_low:8;
+                       u8 test2_limit_high:8;
+                       u8 test2_limit_diff:8;
+               };
+               u8 f09_control_test2[3];
+       };
+};
+
+struct f09_data {
+       u8 test_number_control;
+       u8 overall_bist_result;
+       u8 test_result1;
+       u8 test_result2;
+       u8 transmitter_number;
+
+       union {
+               struct {
+                       u8 receiver_number:6;
+                       u8 limit_failure_code:2;
+               };
+               u8 f09_bist_data2;
+       };
+};
+
+struct f09_cmd {
+       union {
+               struct {
+                       u8 run_bist:1;
+               };
+               u8 f09_bist_cmd0;
+       };
+};
+
+struct rmi_fn_09_data {
+       struct f09_query query;
+       struct f09_data data;
+       struct f09_cmd cmd;
+       struct f09_control control;
+       signed char status;
+};
+
+
+static ssize_t rmi_f09_status_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f09_status_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+
+static ssize_t rmi_f09_limit_register_count_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f09_host_test_enable_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f09_host_test_enable_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t count);
+
+static ssize_t rmi_f09_internal_limits_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f09_result_register_count_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f09_overall_bist_result_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f09_test_number_control_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f09_test_number_control_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                       const char *buf, size_t count);
+
+static ssize_t rmi_f09_run_bist_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f09_run_bist_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                       const char *buf, size_t count);
+
+static ssize_t rmi_f09_test_result1_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f09_test_result2_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f09_control_test1_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f09_control_test1_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                       const char *buf, size_t count);
+
+static ssize_t rmi_f09_control_test2_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf);
+
+static ssize_t rmi_f09_control_test2_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                       const char *buf, size_t count);
+
+static int rmi_f09_alloc_memory(struct rmi_function_container *fc);
+
+static void rmi_f09_free_memory(struct rmi_function_container *fc);
+
+static int rmi_f09_initialize(struct rmi_function_container *fc);
+
+static int rmi_f09_config(struct rmi_function_container *fc);
+
+static int rmi_f09_reset(struct rmi_function_container *fc);
+
+static int rmi_f09_create_sysfs(struct rmi_function_container *fc);
+
+
+static struct device_attribute attrs[] = {
+       __ATTR(status, RMI_RW_ATTR,
+                  rmi_f09_status_show, rmi_f09_status_store),
+       __ATTR(limitRegisterCount, RMI_RO_ATTR,
+              rmi_f09_limit_register_count_show, rmi_store_error),
+       __ATTR(hostTestEnable, RMI_RW_ATTR,
+              rmi_f09_host_test_enable_show, rmi_f09_host_test_enable_store),
+       __ATTR(internalLimits, RMI_RO_ATTR,
+              rmi_f09_internal_limits_show, rmi_store_error),
+       __ATTR(resultRegisterCount, RMI_RO_ATTR,
+              rmi_f09_result_register_count_show, rmi_store_error),
+       __ATTR(overall_bist_result, RMI_RO_ATTR,
+              rmi_f09_overall_bist_result_show, rmi_store_error),
+       __ATTR(test_number_control, RMI_RW_ATTR,
+              rmi_f09_test_number_control_show,
+              rmi_f09_test_number_control_store),
+       __ATTR(test_result1, RMI_RO_ATTR,
+              rmi_f09_test_result1_show, rmi_store_error),
+       __ATTR(test_result2, RMI_RO_ATTR,
+              rmi_f09_test_result2_show, rmi_store_error),
+       __ATTR(run_bist, RMI_RW_ATTR,
+              rmi_f09_run_bist_show, rmi_f09_run_bist_store),
+       __ATTR(f09_control_test1, RMI_RW_ATTR,
+              rmi_f09_control_test1_show, rmi_f09_control_test1_store),
+       __ATTR(f09_control_test2, RMI_RW_ATTR,
+              rmi_f09_control_test2_show, rmi_f09_control_test2_store),
+};
+
+static int rmi_f09_init(struct rmi_function_container *fc)
+{
+       int rc;
+
+       dev_info(&fc->dev, "Intializing F09 values.");
+
+       rc = rmi_f09_alloc_memory(fc);
+       if (rc < 0)
+               goto error_exit;
+
+       rc = rmi_f09_initialize(fc);
+       if (rc < 0)
+               goto error_exit;
+
+       rc = rmi_f09_create_sysfs(fc);
+       if (rc < 0)
+               goto error_exit;
+
+       return 0;
+
+error_exit:
+       rmi_f09_free_memory(fc);
+
+       return rc;
+}
+
+static int rmi_f09_alloc_memory(struct rmi_function_container *fc)
+{
+       struct rmi_fn_09_data *f09;
+
+       f09 = kzalloc(sizeof(struct rmi_fn_09_data), GFP_KERNEL);
+       if (!f09) {
+               dev_err(&fc->dev, "Failed to allocate rmi_fn_09_data.\n");
+               return -ENOMEM;
+       }
+       fc->data = f09;
+
+       return 0;
+}
+
+static void rmi_f09_free_memory(struct rmi_function_container *fc)
+{
+       kfree(fc->data);
+       fc->data = NULL;
+}
+
+static int rmi_f09_initialize(struct rmi_function_container *fc)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct rmi_device_platform_data *pdata;
+       struct rmi_fn_09_data *f09 = fc->data;
+       u8 query_base_addr;
+       int rc;
+
+
+       pdata = to_rmi_platform_data(rmi_dev);
+       query_base_addr = fc->fd.query_base_addr;
+
+       /* initial all default values for f09 query here */
+       rc = rmi_read_block(rmi_dev, query_base_addr,
+               (u8 *)&f09->query, sizeof(f09->query));
+       if (rc < 0) {
+               dev_err(&fc->dev, "Failed to read query register."
+                       " from 0x%04x\n", query_base_addr);
+               return rc;
+       }
+
+       return 0;
+}
+
+static int rmi_f09_create_sysfs(struct rmi_function_container *fc)
+{
+       int attr_count = 0;
+       int rc;
+
+       dev_dbg(&fc->dev, "Creating sysfs files.");
+       /* Set up sysfs device attributes. */
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               if (sysfs_create_file
+                   (&fc->dev.kobj, &attrs[attr_count].attr) < 0) {
+                       dev_err(&fc->dev, "Failed to create sysfs file for %s.",
+                            attrs[attr_count].attr.name);
+                       rc = -ENODEV;
+                       goto err_remove_sysfs;
+               }
+       }
+
+       return 0;
+
+err_remove_sysfs:
+       for (attr_count--; attr_count >= 0; attr_count--)
+               sysfs_remove_file(&fc->dev.kobj,
+                                 &attrs[attr_count].attr);
+
+       return rc;
+}
+
+static int rmi_f09_config(struct rmi_function_container *fc)
+{
+       /*we do nothing here. instead reset should notify the user.*/
+       return 0;
+}
+
+static int rmi_f09_reset(struct rmi_function_container *fc)
+{
+       struct  rmi_fn_09_data  *instance_data = fc->data;
+
+       instance_data->status = -ECONNRESET;
+
+       return 0;
+}
+
+static void rmi_f09_remove(struct rmi_function_container *fc)
+{
+       int attr_count;
+
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++)
+               sysfs_remove_file(&fc->dev.kobj,
+                                 &attrs[attr_count].attr);
+
+       rmi_f09_free_memory(fc);
+}
+
+static int rmi_f09_attention(struct rmi_function_container *fc, u8 *irq_bits)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct rmi_fn_09_data *data = fc->data;
+       int error;
+       error = rmi_read_block(rmi_dev, fc->fd.command_base_addr,
+                       (u8 *)&data->cmd, sizeof(data->cmd));
+
+       if (error < 0) {
+               dev_err(&fc->dev, "Failed to read command register.\n");
+               return error;
+       }
+       /* If the command register is cleared, meaning the value is 0 */
+       if (data->status == ECONNRESET) {
+               dev_warn(&rmi_dev->dev, "RESET occured: %#04x.\n",
+                       data->status);
+       } else if (data->cmd.run_bist) {
+               dev_warn(&rmi_dev->dev,
+                       "Command register not cleared: %#04x.\n",
+                       data->cmd.run_bist);
+       }
+       return 0;
+}
+
+static struct rmi_function_handler function_handler = {
+       .func = 0x09,
+       .init = rmi_f09_init,
+       .attention = rmi_f09_attention,
+       .config = rmi_f09_config,
+       .reset = rmi_f09_reset,
+       .remove = rmi_f09_remove
+};
+
+static int __init rmi_f09_module_init(void)
+{
+       int error;
+
+       error = rmi_register_function_driver(&function_handler);
+       if (error < 0) {
+               pr_err("%s: register failed!\n", __func__);
+               return error;
+       }
+
+       return 0;
+}
+
+static void rmi_f09_module_exit(void)
+{
+       rmi_unregister_function_driver(&function_handler);
+}
+
+static ssize_t rmi_f09_status_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", instance_data->status);
+}
+
+static ssize_t rmi_f09_status_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       /* any write to status resets 1 */
+       instance_data->status = 0;
+
+       return 0;
+}
+
+static ssize_t rmi_f09_limit_register_count_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->query.limit_register_count);
+}
+
+static ssize_t rmi_f09_host_test_enable_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->query.host_test_enable);
+}
+
+static ssize_t rmi_f09_host_test_enable_store(struct device *dev,
+                                         struct device_attribute *attr,
+                                         const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+       unsigned int new_value;
+       int result;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       if (sscanf(buf, "%u", &new_value) != 1) {
+               dev_err(dev,
+                       "%s: Error - hostTestEnable has an invalid length.\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       if (new_value < 0 || new_value > 1) {
+               dev_err(dev, "%s: Invalid hostTestEnable bit %s.",
+                       __func__, buf);
+               return -EINVAL;
+       }
+       data->query.host_test_enable = new_value;
+       result = rmi_write(fc->rmi_dev, fc->fd.query_base_addr,
+               data->query.host_test_enable);
+       if (result < 0) {
+               dev_err(dev, "%s: Could not write hostTestEnable to 0x%x\n",
+                               __func__, fc->fd.query_base_addr);
+               return result;
+       }
+
+       return count;
+
+}
+
+static ssize_t rmi_f09_internal_limits_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->query.internal_limits);
+}
+
+static ssize_t rmi_f09_result_register_count_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->query.result_register_count);
+}
+
+static ssize_t rmi_f09_overall_bist_result_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->data.overall_bist_result);
+}
+
+static ssize_t rmi_f09_test_result1_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->data.test_result1);
+}
+
+static ssize_t rmi_f09_test_result2_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->data.test_result2);
+}
+
+static ssize_t rmi_f09_run_bist_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->cmd.run_bist);
+}
+
+static ssize_t rmi_f09_run_bist_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+       unsigned int new_value;
+       int result;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       if (sscanf(buf, "%u", &new_value) != 1) {
+               dev_err(dev,
+               "%s: Error - run_bist_store has an "
+               "invalid len.\n",
+               __func__);
+               return -EINVAL;
+       }
+
+       if (new_value < 0 || new_value > 1) {
+               dev_err(dev, "%s: Invalid run_bist bit %s.", __func__, buf);
+               return -EINVAL;
+       }
+       data->cmd.run_bist = new_value;
+       result = rmi_write(fc->rmi_dev, fc->fd.command_base_addr,
+               data->cmd.run_bist);
+       if (result < 0) {
+               dev_err(dev, "%s : Could not write run_bist_store to 0x%x\n",
+                               __func__, fc->fd.command_base_addr);
+               return result;
+       }
+
+       return count;
+
+}
+
+static ssize_t rmi_f09_control_test1_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u %u %u\n",
+                       data->control.test1_limit_low,
+                       data->control.test1_limit_high,
+                       data->control.test1_limit_diff);
+}
+
+static ssize_t rmi_f09_control_test1_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+       unsigned int new_low, new_high, new_diff;
+       int result;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       if (sscanf(buf, "%u %u %u", &new_low, &new_high, &new_diff) != 3) {
+               dev_err(dev,
+               "%s: Error - f09_control_test1_store has an "
+               "invalid len.\n",
+               __func__);
+               return -EINVAL;
+       }
+
+       if (new_low < 0 || new_low > 1 || new_high < 0 || new_high
+                       || new_diff < 0 || new_diff) {
+               dev_err(dev, "%s: Invalid f09_control_test1_diff bit %s.",
+                       __func__, buf);
+               return -EINVAL;
+       }
+       data->control.test1_limit_low = new_low;
+       data->control.test1_limit_high = new_high;
+       data->control.test1_limit_diff = new_diff;
+       result = rmi_write(fc->rmi_dev, fc->fd.control_base_addr,
+               data->control.test1_limit_low);
+       if (result < 0) {
+               dev_err(dev, "%s : Could not write f09_control_test1_limit_low to 0x%x\n",
+                               __func__, fc->fd.control_base_addr);
+               return result;
+       }
+
+       result = rmi_write(fc->rmi_dev, fc->fd.control_base_addr,
+               data->control.test1_limit_high);
+       if (result < 0) {
+               dev_err(dev, "%s : Could not write f09_control_test1_limit_high to 0x%x\n",
+                               __func__, fc->fd.control_base_addr);
+               return result;
+       }
+
+       result = rmi_write(fc->rmi_dev, fc->fd.control_base_addr,
+               data->control.test1_limit_diff);
+       if (result < 0) {
+               dev_err(dev, "%s : Could not write f09_control_test1_limit_diff to 0x%x\n",
+                               __func__, fc->fd.control_base_addr);
+               return result;
+       }
+
+       return count;
+
+}
+
+static ssize_t rmi_f09_control_test2_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u %u %u\n",
+                       data->control.test2_limit_low,
+                       data->control.test2_limit_high,
+                       data->control.test2_limit_diff);
+}
+
+static ssize_t rmi_f09_control_test2_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+       unsigned int new_low, new_high, new_diff;
+       int result;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       if (sscanf(buf, "%u %u %u", &new_low, &new_high, &new_diff) != 3) {
+               dev_err(dev,
+               "%s: Error - f09_control_test1_store has an "
+               "invalid len.\n",
+               __func__);
+               return -EINVAL;
+       }
+
+       if (new_low < 0 || new_low > 1 || new_high < 0 || new_high > 1 ||
+                       new_diff < 0 || new_diff > 1) {
+               dev_err(dev, "%s: Invalid f09_control_test2_diff bit %s.",
+                       __func__, buf);
+               return -EINVAL;
+       }
+       data->control.test2_limit_low = new_low;
+       data->control.test2_limit_high = new_high;
+       data->control.test2_limit_diff = new_diff;
+       result = rmi_write(fc->rmi_dev, fc->fd.control_base_addr,
+               data->control.test2_limit_low);
+       if (result < 0) {
+               dev_err(dev, "%s : Could not write f09_control_test2_limit_low to 0x%x\n",
+                               __func__, fc->fd.control_base_addr);
+               return result;
+       }
+
+       result = rmi_write(fc->rmi_dev, fc->fd.control_base_addr,
+               data->control.test2_limit_high);
+       if (result < 0) {
+               dev_err(dev, "%s : Could not write f09_control_test2_limit_high to 0x%x\n",
+                               __func__, fc->fd.control_base_addr);
+               return result;
+       }
+
+       result = rmi_write(fc->rmi_dev, fc->fd.control_base_addr,
+               data->control.test2_limit_diff);
+       if (result < 0) {
+               dev_err(dev, "%s : Could not write f09_control_test2_limit_diff to 0x%x\n",
+                               __func__, fc->fd.control_base_addr);
+               return result;
+       }
+
+       return count;
+
+}
+
+
+static ssize_t rmi_f09_test_number_control_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->data.test_number_control);
+}
+
+static ssize_t rmi_f09_test_number_control_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_09_data *data;
+       unsigned int new_value;
+       int result;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       if (sscanf(buf, "%u", &new_value) != 1) {
+               dev_err(dev,
+               "%s: Error - test_number_control_store has an "
+               "invalid len.\n",
+               __func__);
+               return -EINVAL;
+       }
+
+       if (new_value < 0 || new_value > 1) {
+               dev_err(dev, "%s: Invalid test_number_control bit %s.",
+                       __func__, buf);
+               return -EINVAL;
+       }
+       data->data.test_number_control = new_value;
+       result = rmi_write(fc->rmi_dev, fc->fd.control_base_addr,
+               data->data.test_number_control);
+       if (result < 0) {
+               dev_err(dev, "%s : Could not write "
+                               "test_number_control_store to 0x%x\n",
+                               __func__, fc->fd.data_base_addr);
+               return result;
+       }
+
+       return count;
+}
+
+module_init(rmi_f09_module_init);
+module_exit(rmi_f09_module_exit);
+
+MODULE_AUTHOR("Allie Xiong <axiong@Synaptics.com>");
+MODULE_DESCRIPTION("RMI F09 module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
diff --git a/drivers/input/touchscreen/rmi4/rmi_f11.c b/drivers/input/touchscreen/rmi4/rmi_f11.c
new file mode 100755 (executable)
index 0000000..e94b570
--- /dev/null
@@ -0,0 +1,1947 @@
+/*
+ * Copyright (c) 2011 Synaptics Incorporated
+ * Copyright (c) 2011 Unixphere
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/rmi.h>
+#include "rmi_driver.h"
+#define RESUME_REZERO (1 && defined(CONFIG_PM))
+#if RESUME_REZERO
+#include <linux/delay.h>
+#define DEFAULT_REZERO_WAIT_MS 40
+#endif
+
+#ifndef MT_TOOL_MAX
+#define MT_TOOL_MAX MT_TOOL_PEN
+#endif
+
+#define F11_MAX_NUM_OF_SENSORS         8
+#define F11_MAX_NUM_OF_FINGERS         10
+#define F11_MAX_NUM_OF_TOUCH_SHAPES    16
+
+#define F11_REL_POS_MIN                -128
+#define F11_REL_POS_MAX                127
+
+#define FINGER_STATE_MASK      0x03
+#define GET_FINGER_STATE(f_states, i) \
+       ((f_states[i / 4] >> (2 * (i % 4))) & FINGER_STATE_MASK)
+
+#define F11_CTRL_SENSOR_MAX_X_POS_OFFSET       6
+#define F11_CTRL_SENSOR_MAX_Y_POS_OFFSET       8
+
+#define F11_CEIL(x, y) (((x) + ((y)-1)) / (y))
+#define INBOX(x, y, box) (x >= box.x && x < (box.x + box.width) \
+                       && y >= box.y && y < (box.y + box.height))
+
+#define DEFAULT_XY_MAX 9999
+#define DEFAULT_MAX_ABS_MT_PRESSURE 255
+#define DEFAULT_MAX_ABS_MT_TOUCH 15
+#define DEFAULT_MAX_ABS_MT_ORIENTATION 1
+#define DEFAULT_MIN_ABS_MT_TRACKING_ID 1
+#define DEFAULT_MAX_ABS_MT_TRACKING_ID 10
+#define MAX_NAME_LENGTH 256
+
+#define SYNAPTICS_MAX_POINTS  (10)
+static ssize_t f11_flip_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf);
+
+static ssize_t f11_flip_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count);
+
+static ssize_t f11_clip_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf);
+
+static ssize_t f11_clip_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count);
+
+static ssize_t f11_offset_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf);
+
+static ssize_t f11_offset_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count);
+
+static ssize_t f11_swap_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf);
+
+static ssize_t f11_swap_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count);
+
+static ssize_t f11_relreport_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf);
+
+static ssize_t f11_relreport_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count);
+
+static ssize_t f11_maxPos_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf);
+
+static ssize_t f11_rezero_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count);
+
+#if RESUME_REZERO
+static ssize_t f11_rezeroOnResume_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf);
+
+static ssize_t f11_rezeroOnResume_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count);
+static ssize_t f11_rezeroWait_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf);
+
+static ssize_t f11_rezeroWait_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count);
+#endif
+
+
+static void rmi_f11_free_memory(struct rmi_function_container *fc);
+
+static int rmi_f11_initialize(struct rmi_function_container *fc);
+
+static int rmi_f11_create_sysfs(struct rmi_function_container *fc);
+
+static int rmi_f11_config(struct rmi_function_container *fc);
+
+static int rmi_f11_reset(struct rmi_function_container *fc);
+
+static int rmi_f11_register_devices(struct rmi_function_container *fc);
+
+static void rmi_f11_free_devices(struct rmi_function_container *fc);
+
+
+static struct device_attribute attrs[] = {
+       __ATTR(flip, RMI_RW_ATTR, f11_flip_show, f11_flip_store),
+       __ATTR(clip, RMI_RW_ATTR, f11_clip_show, f11_clip_store),
+       __ATTR(offset, RMI_RW_ATTR, f11_offset_show, f11_offset_store),
+       __ATTR(swap, RMI_RW_ATTR, f11_swap_show, f11_swap_store),
+       __ATTR(relreport, RMI_RW_ATTR, f11_relreport_show, f11_relreport_store),
+       __ATTR(maxPos, RMI_RO_ATTR, f11_maxPos_show, rmi_store_error),
+#if RESUME_REZERO
+       __ATTR(rezeroOnResume, RMI_RW_ATTR, f11_rezeroOnResume_show,
+               f11_rezeroOnResume_store),
+       __ATTR(rezeroWait, RMI_RW_ATTR, f11_rezeroWait_show,
+               f11_rezeroWait_store),
+#endif
+       __ATTR(rezero, RMI_WO_ATTR, rmi_show_error, f11_rezero_store)
+};
+
+
+union f11_2d_commands {
+       struct {
+               u8 rezero:1;
+       };
+       u8 reg;
+};
+
+struct f11_2d_device_query {
+       union {
+               struct {
+                       u8 nbr_of_sensors:3;
+                       u8 has_query9:1;
+                       u8 has_query11:1;
+               };
+               u8 f11_2d_query0;
+       };
+
+       union {
+               struct {
+                       u8 has_z_tuning:1;
+                       u8 has_pos_interpolation_tuning:1;
+                       u8 has_w_tuning:1;
+                       u8 has_pitch_info:1;
+                       u8 has_default_finger_width:1;
+                       u8 has_segmentation_aggressiveness:1;
+                       u8 has_tx_rw_clip:1;
+                       u8 has_drumming_correction:1;
+               };
+               u8 f11_2d_query11;
+       };
+};
+
+union f11_2d_query9 {
+       struct {
+               u8 has_pen:1;
+               u8 has_proximity:1;
+               u8 has_palm_det_sensitivity:1;
+               u8 has_suppress_on_palm_detect:1;
+               u8 has_two_pen_thresholds:1;
+               u8 has_contact_geometry:1;
+       };
+       u8 reg;
+};
+
+struct f11_2d_sensor_query {
+       union {
+               struct {
+                       /* query1 */
+                       u8 number_of_fingers:3;
+                       u8 has_rel:1;
+                       u8 has_abs:1;
+                       u8 has_gestures:1;
+                       u8 has_sensitivity_adjust:1;
+                       u8 configurable:1;
+                       /* query2 */
+                       u8 num_of_x_electrodes:7;
+                       /* query3 */
+                       u8 num_of_y_electrodes:7;
+                       /* query4 */
+                       u8 max_electrodes:7;
+               };
+               u8 f11_2d_query1__4[4];
+       };
+
+       union {
+               struct {
+                       u8 abs_data_size:3;
+                       u8 has_anchored_finger:1;
+                       u8 has_adj_hyst:1;
+                       u8 has_dribble:1;
+               };
+               u8 f11_2d_query5;
+       };
+
+       u8 f11_2d_query6;
+
+       union {
+               struct {
+                       u8 has_single_tap:1;
+                       u8 has_tap_n_hold:1;
+                       u8 has_double_tap:1;
+                       u8 has_early_tap:1;
+                       u8 has_flick:1;
+                       u8 has_press:1;
+                       u8 has_pinch:1;
+                       u8 padding:1;
+
+                       u8 has_palm_det:1;
+                       u8 has_rotate:1;
+                       u8 has_touch_shapes:1;
+                       u8 has_scroll_zones:1;
+                       u8 has_individual_scroll_zones:1;
+                       u8 has_multi_finger_scroll:1;
+               };
+               u8 f11_2d_query7__8[2];
+       };
+
+       union f11_2d_query9 query9;
+
+       union {
+               struct {
+                       u8 nbr_touch_shapes:5;
+               };
+               u8 f11_2d_query10;
+       };
+};
+
+union f11_2d_ctrl10 {
+       struct {
+               u8 single_tap_int_enable:1;
+               u8 tap_n_hold_int_enable:1;
+               u8 double_tap_int_enable:1;
+               u8 early_tap_int_enable:1;
+               u8 flick_int_enable:1;
+               u8 press_int_enable:1;
+               u8 pinch_int_enable:1;
+       };
+       u8 reg;
+};
+
+union f11_2d_ctrl11 {
+       struct {
+               u8 palm_detect_int_enable:1;
+               u8 rotate_int_enable:1;
+               u8 touch_shape_int_enable:1;
+               u8 scroll_zone_int_enable:1;
+               u8 multi_finger_scroll_int_enable:1;
+       };
+       u8 reg;
+};
+
+union f11_2d_ctrl12 {
+       struct {
+               u8 sensor_map:7;
+               u8 xy_sel:1;
+       };
+       u8 reg;
+};
+
+union f11_2d_ctrl14 {
+       struct {
+               u8 sens_adjustment:5;
+               u8 hyst_adjustment:3;
+       };
+       u8 reg;
+};
+
+union f11_2d_ctrl15 {
+       struct {
+               u8 max_tap_time:8;
+       };
+       u8 reg;
+};
+
+union f11_2d_ctrl16 {
+       struct {
+               u8 min_press_time:8;
+       };
+       u8 reg;
+};
+
+union f11_2d_ctrl17 {
+       struct {
+               u8 max_tap_distance:8;
+       };
+       u8 reg;
+};
+
+union f11_2d_ctrl18_19 {
+       struct {
+               u8 min_flick_distance:8;
+               u8 min_flick_speed:8;
+       };
+       u8 reg[2];
+};
+
+union f11_2d_ctrl20_21 {
+       struct {
+               u8 pen_detect_enable:1;
+               u8 pen_jitter_filter_enable:1;
+               u8 ctrl20_reserved:6;
+               u8 pen_z_threshold:8;
+       };
+       u8 reg[2];
+};
+
+struct  f11_2d_ctrl {
+
+       union {
+               struct {
+                       /* F11_2D_Ctrl0 */
+                       u8 reporting_mode:3;
+                       u8 abs_pos_filt:1;
+                       u8 rel_pos_filt:1;
+                       u8 rel_ballistics:1;
+                       u8 dribble:1;
+                       u8 report_beyond_clip:1;
+                       /* F11_2D_Ctrl1 */
+                       u8 palm_detect_thres:4;
+                       u8 motion_sensitivity:2;
+                       u8 man_track_en:1;
+                       u8 man_tracked_finger:1;
+                       /* F11_2D_Ctrl2 and 3 */
+                       u8 delta_x_threshold:8;
+                       u8 delta_y_threshold:8;
+                       /* F11_2D_Ctrl4 and 5 */
+                       u8 velocity:8;
+                       u8 acceleration:8;
+                       /* F11_2D_Ctrl6 thru 9 */
+                       u16 sensor_max_x_pos:12;
+                       u8 ctrl7_reserved:4;
+                       u16 sensor_max_y_pos:12;
+                       u8 ctrl9_reserved:4;
+               };
+               u8 ctrl0_9[10];
+       };
+
+       union f11_2d_ctrl10             *ctrl10;
+       union f11_2d_ctrl11             *ctrl11;
+       union f11_2d_ctrl12             *ctrl12;
+       u8                              ctrl12_size;
+       union f11_2d_ctrl14             *ctrl14;
+       union f11_2d_ctrl15             *ctrl15;
+       union f11_2d_ctrl16             *ctrl16;
+       union f11_2d_ctrl17             *ctrl17;
+       union f11_2d_ctrl18_19          *ctrl18_19;
+       union f11_2d_ctrl20_21          *ctrl20_21;
+};
+
+struct f11_2d_data_1_5 {
+       u8 x_msb;
+       u8 y_msb;
+       u8 x_lsb:4;
+       u8 y_lsb:4;
+       u8 w_y:4;
+       u8 w_x:4;
+       u8 z;
+};
+
+struct f11_2d_data_6_7 {
+       s8 delta_x;
+       s8 delta_y;
+};
+
+struct f11_2d_data_8 {
+       u8 single_tap:1;
+       u8 tap_and_hold:1;
+       u8 double_tap:1;
+       u8 early_tap:1;
+       u8 flick:1;
+       u8 press:1;
+       u8 pinch:1;
+};
+
+struct f11_2d_data_9 {
+       u8 palm_detect:1;
+       u8 rotate:1;
+       u8 shape:1;
+       u8 scrollzone:1;
+       u8 finger_count:3;
+};
+
+struct f11_2d_data_10 {
+       u8 pinch_motion;
+};
+
+struct f11_2d_data_10_12 {
+       u8 x_flick_dist;
+       u8 y_flick_dist;
+       u8 flick_time;
+};
+
+struct f11_2d_data_11_12 {
+       u8 motion;
+       u8 finger_separation;
+};
+
+struct f11_2d_data_13 {
+       u8 shape_n;
+};
+
+struct f11_2d_data_14_15 {
+       u8 horizontal;
+       u8 vertical;
+};
+
+struct f11_2d_data_14_17 {
+       u8 x_low;
+       u8 y_right;
+       u8 x_upper;
+       u8 y_left;
+};
+
+struct f11_2d_data {
+       u8                              *f_state;
+       const struct f11_2d_data_1_5    *abs_pos;
+       const struct f11_2d_data_6_7    *rel_pos;
+       const struct f11_2d_data_8      *gest_1;
+       const struct f11_2d_data_9      *gest_2;
+       const struct f11_2d_data_10     *pinch;
+       const struct f11_2d_data_10_12  *flick;
+       const struct f11_2d_data_11_12  *rotate;
+       const struct f11_2d_data_13     *shapes;
+       const struct f11_2d_data_14_15  *multi_scroll;
+       const struct f11_2d_data_14_17  *scroll_zones;
+};
+
+struct f11_2d_sensor {
+       struct rmi_f11_2d_axis_alignment axis_align;
+       struct f11_2d_sensor_query sens_query;
+       struct f11_2d_data data;
+       u16 max_x;
+       u16 max_y;
+       u8 nbr_fingers;
+       u8 finger_tracker[F11_MAX_NUM_OF_FINGERS];
+       u8 *data_pkt;
+       int pkt_size;
+       u8 sensor_index;
+       struct rmi_f11_virtualbutton_map virtualbutton_map;
+       char input_name[MAX_NAME_LENGTH];
+       char input_phys[MAX_NAME_LENGTH];
+       struct input_dev *input;
+       struct input_dev *mouse_input;
+};
+
+struct f11_data {
+       struct f11_2d_device_query dev_query;
+       struct f11_2d_ctrl dev_controls;
+#if    RESUME_REZERO
+       u16 rezero_wait_ms;
+       bool rezero_on_resume;
+#endif
+       struct f11_2d_sensor sensors[F11_MAX_NUM_OF_SENSORS];
+};
+
+enum finger_state_values {
+       F11_NO_FINGER   = 0x00,
+       F11_PRESENT     = 0x01,
+       F11_INACCURATE  = 0x02,
+       F11_RESERVED    = 0x03
+};
+
+/** F11_INACCURATE state is overloaded to indicate pen present. */
+#define F11_PEN F11_INACCURATE
+
+static int get_tool_type(struct f11_2d_sensor *sensor, u8 finger_state) {
+       if (sensor->sens_query.query9.has_pen && finger_state == F11_PEN)
+               return MT_TOOL_PEN;
+       return MT_TOOL_FINGER;
+}
+
+static void rmi_f11_rel_pos_report(struct f11_2d_sensor *sensor, u8 n_finger)
+{
+       struct f11_2d_data *data = &sensor->data;
+       struct rmi_f11_2d_axis_alignment *axis_align = &sensor->axis_align;
+       s8 x, y;
+       s8 temp;
+
+       x = data->rel_pos[n_finger].delta_x;
+       y = data->rel_pos[n_finger].delta_y;
+
+       x = min(F11_REL_POS_MAX, max(F11_REL_POS_MIN, (int)x));
+       y = min(F11_REL_POS_MAX, max(F11_REL_POS_MIN, (int)y));
+
+       if (axis_align->swap_axes) {
+               temp = x;
+               x = y;
+               y = temp;
+       }
+       if (axis_align->flip_x)
+               x = min(F11_REL_POS_MAX, -x);
+       if (axis_align->flip_y)
+               y = min(F11_REL_POS_MAX, -y);
+
+       if (x || y) {
+               input_report_rel(sensor->input, REL_X, x);
+               input_report_rel(sensor->input, REL_Y, y);
+               input_report_rel(sensor->mouse_input, REL_X, x);
+               input_report_rel(sensor->mouse_input, REL_Y, y);
+       }
+       input_sync(sensor->mouse_input);
+}
+
+static void rmi_f11_abs_pos_report(struct f11_2d_sensor *sensor,
+                                       u8 finger_state, u8 n_finger)
+{
+       struct f11_2d_data *data = &sensor->data;
+       struct rmi_f11_2d_axis_alignment *axis_align = &sensor->axis_align;
+       int prev_state = sensor->finger_tracker[n_finger];
+       int x, y, z;
+       int w_x, w_y, w_max, w_min, orient;
+       int temp;
+
+       if (prev_state && !finger_state) {
+               /* this is a release */
+               x = y = z = w_max = w_min = orient = 0;
+               input_mt_slot(sensor->input, n_finger);
+               input_mt_report_slot_state(sensor->input, MT_TOOL_FINGER, false);
+               input_report_abs(sensor->input, ABS_MT_TRACKING_ID, -1);
+       } else if (!prev_state && !finger_state) {
+               /* nothing to report */
+               return;
+       } else {
+               x = ((data->abs_pos[n_finger].x_msb << 4) |
+                       data->abs_pos[n_finger].x_lsb);
+               y = ((data->abs_pos[n_finger].y_msb << 4) |
+                       data->abs_pos[n_finger].y_lsb);
+               z = data->abs_pos[n_finger].z;
+               w_x = data->abs_pos[n_finger].w_x;
+               w_y = data->abs_pos[n_finger].w_y;
+               w_max = max(w_x, w_y);
+               w_min = min(w_x, w_y);
+               if (axis_align->swap_axes) {
+                       temp = x;
+                       x = y;
+                       y = temp;
+                       temp = w_x;
+                       w_x = w_y;
+                       w_y = temp;
+               }
+
+               orient = w_x > w_y ? 1 : 0;
+
+               if (axis_align->flip_x)
+                       x = max(sensor->max_x - x, 0);
+
+               if (axis_align->flip_y)
+                       y = max(sensor->max_y - y, 0);
+               //printk("+x:%d, y:%d\n", x , y);
+               /*
+               ** here checking if X offset or y offset are specified is
+               **  redundant.  We just add the offsets or, clip the values
+               **
+               ** note: offsets need to be done before clipping occurs,
+               ** or we could get funny values that are outside
+               ** clipping boundaries.
+               */
+               x += axis_align->offset_X;
+               y += axis_align->offset_Y;
+               x =  max(axis_align->clip_X_low, x);
+               y =  max(axis_align->clip_Y_low, y);
+               if (axis_align->clip_X_high)
+                       x = min(axis_align->clip_X_high, x);
+               if (axis_align->clip_Y_high)
+                       y =  min(axis_align->clip_Y_high, y);
+
+               pr_debug("%s: f_state[%d]:%d - x:%d y:%d z:%d w_max:%d w_min:%d\n",
+                       __func__, n_finger, finger_state, x, y, z, w_max, w_min);
+#ifndef CONFIG_RMI4_F11_PEN
+               /* Some UIs ignore W of zero, so we fudge it to 1 for pens. */
+               if (sensor->sens_query.query9.has_pen &&
+                               get_tool_type(sensor, finger_state) == MT_TOOL_PEN) {
+                       w_max = max(1, w_max);
+                       w_min = max(1, w_min);
+               }
+#endif
+
+               input_mt_slot(sensor->input, n_finger);
+               input_mt_report_slot_state(sensor->input, MT_TOOL_FINGER, true);
+               input_report_abs(sensor->input, ABS_MT_TRACKING_ID, n_finger);
+               input_report_abs(sensor->input, ABS_MT_TOUCH_MAJOR, w_max);
+               input_report_abs(sensor->input, ABS_MT_PRESSURE, z);
+               input_report_abs(sensor->input, ABS_MT_TOUCH_MINOR, w_min);
+               input_report_abs(sensor->input, ABS_MT_ORIENTATION, orient);
+               input_report_abs(sensor->input, ABS_MT_POSITION_X, x);
+               input_report_abs(sensor->input, ABS_MT_POSITION_Y, y);
+
+#ifdef CONFIG_RMI4_F11_PEN
+               if (sensor->sens_query.query9.has_pen) {
+                       input_report_abs(sensor->input, ABS_MT_TOOL_TYPE,
+                                        get_tool_type(sensor, finger_state));
+               }
+#endif
+
+       }
+       sensor->finger_tracker[n_finger] = finger_state;
+}
+
+#ifdef CONFIG_RMI4_VIRTUAL_BUTTON
+static int rmi_f11_virtual_button_handler(struct f11_2d_sensor *sensor)
+{
+       int i;
+       int x;
+       int y;
+       struct rmi_f11_virtualbutton_map *virtualbutton_map;
+       if (sensor->sens_query.has_gestures &&
+               sensor->data.gest_1->single_tap) {
+               virtualbutton_map = &sensor->virtualbutton_map;
+               x = ((sensor->data.abs_pos[0].x_msb << 4) |
+                       sensor->data.abs_pos[0].x_lsb);
+               y = ((sensor->data.abs_pos[0].y_msb << 4) |
+                       sensor->data.abs_pos[0].y_lsb);
+               for (i = 0; i < virtualbutton_map->buttons; i++) {
+                       if (INBOX(x, y, virtualbutton_map->map[i])) {
+                               input_report_key(sensor->input,
+                                       virtualbutton_map->map[i].code, 1);
+                               input_report_key(sensor->input,
+                                       virtualbutton_map->map[i].code, 0);
+                               input_sync(sensor->input);
+                               return 0;
+                       }
+               }
+       }
+       return 0;
+}
+#else
+#define rmi_f11_virtual_button_handler(sensor)
+#endif
+
+static void rmi_f11_finger_handler(struct f11_2d_sensor *sensor)
+{
+       const u8 *f_state = sensor->data.f_state;
+       u8 finger_state;
+       u8 finger_pressed_count;
+       u8 i;
+
+       for (i = 0, finger_pressed_count = 0; i < sensor->nbr_fingers; i++) {
+               /* Possible of having 4 fingers per f_statet register */
+               finger_state = GET_FINGER_STATE(f_state, i);
+
+               if (finger_state == F11_RESERVED) {
+                       pr_err("%s: Invalid finger state[%d]:0x%02x.", __func__,
+                                       i, finger_state);
+                       continue;
+               } else if ((finger_state == F11_PRESENT) ||
+                               (finger_state == F11_INACCURATE)) {
+                       finger_pressed_count++;
+               }
+
+               if (sensor->data.abs_pos)
+                       rmi_f11_abs_pos_report(sensor, finger_state, i);
+
+               if (sensor->data.rel_pos)
+                       rmi_f11_rel_pos_report(sensor, i);
+       }
+       input_report_key(sensor->input, BTN_TOUCH, finger_pressed_count);
+       input_sync(sensor->input);
+}
+
+static int f11_2d_construct_data(struct f11_2d_sensor *sensor)
+{
+       struct f11_2d_sensor_query *query = &sensor->sens_query;
+       struct f11_2d_data *data = &sensor->data;
+       int i;
+
+       sensor->nbr_fingers = (query->number_of_fingers == 5 ? 10 :
+                               query->number_of_fingers + 1);
+
+       sensor->pkt_size = F11_CEIL(sensor->nbr_fingers, 4);
+
+       if (query->has_abs)
+               sensor->pkt_size += (sensor->nbr_fingers * 5);
+
+       if (query->has_rel)
+               sensor->pkt_size +=  (sensor->nbr_fingers * 2);
+
+       /* Check if F11_2D_Query7 is non-zero */
+       if (query->f11_2d_query7__8[0])
+               sensor->pkt_size += sizeof(u8);
+
+       /* Check if F11_2D_Query7 or F11_2D_Query8 is non-zero */
+       if (query->f11_2d_query7__8[0] || query->f11_2d_query7__8[1])
+               sensor->pkt_size += sizeof(u8);
+
+       if (query->has_pinch || query->has_flick || query->has_rotate) {
+               sensor->pkt_size += 3;
+               if (!query->has_flick)
+                       sensor->pkt_size--;
+               if (!query->has_rotate)
+                       sensor->pkt_size--;
+       }
+
+       if (query->has_touch_shapes)
+               sensor->pkt_size += F11_CEIL(query->nbr_touch_shapes + 1, 8);
+
+       sensor->data_pkt = kzalloc(sensor->pkt_size, GFP_KERNEL);
+       if (!sensor->data_pkt)
+               return -ENOMEM;
+
+       data->f_state = sensor->data_pkt;
+       i = F11_CEIL(sensor->nbr_fingers, 4);
+
+       if (query->has_abs) {
+               data->abs_pos = (struct f11_2d_data_1_5 *)
+                               &sensor->data_pkt[i];
+               i += (sensor->nbr_fingers * 5);
+       }
+
+       if (query->has_rel) {
+               data->rel_pos = (struct f11_2d_data_6_7 *)
+                               &sensor->data_pkt[i];
+               i += (sensor->nbr_fingers * 2);
+       }
+
+       if (query->f11_2d_query7__8[0]) {
+               data->gest_1 = (struct f11_2d_data_8 *)&sensor->data_pkt[i];
+               i++;
+       }
+
+       if (query->f11_2d_query7__8[0] || query->f11_2d_query7__8[1]) {
+               data->gest_2 = (struct f11_2d_data_9 *)&sensor->data_pkt[i];
+               i++;
+       }
+
+       if (query->has_pinch) {
+               data->pinch = (struct f11_2d_data_10 *)&sensor->data_pkt[i];
+               i++;
+       }
+
+       if (query->has_flick) {
+               if (query->has_pinch) {
+                       data->flick = (struct f11_2d_data_10_12 *)data->pinch;
+                       i += 2;
+               } else {
+                       data->flick = (struct f11_2d_data_10_12 *)
+                                       &sensor->data_pkt[i];
+                       i += 3;
+               }
+       }
+
+       if (query->has_rotate) {
+               if (query->has_flick) {
+                       data->rotate = (struct f11_2d_data_11_12 *)
+                                       (data->flick + 1);
+               } else {
+                       data->rotate = (struct f11_2d_data_11_12 *)
+                                       &sensor->data_pkt[i];
+                       i += 2;
+               }
+       }
+
+       if (query->has_touch_shapes)
+               data->shapes = (struct f11_2d_data_13 *)&sensor->data_pkt[i];
+
+       return 0;
+}
+
+static void f11_free_control_regs(struct f11_2d_ctrl *ctrl)
+{
+       kfree(ctrl->ctrl10);
+       kfree(ctrl->ctrl11);
+       kfree(ctrl->ctrl14);
+       kfree(ctrl->ctrl15);
+       kfree(ctrl->ctrl16);
+       kfree(ctrl->ctrl17);
+       kfree(ctrl->ctrl18_19);
+       kfree(ctrl->ctrl20_21);
+       ctrl->ctrl10 = NULL;
+       ctrl->ctrl11 = NULL;
+       ctrl->ctrl14 = NULL;
+       ctrl->ctrl15 = NULL;
+       ctrl->ctrl16 = NULL;
+       ctrl->ctrl17 = NULL;
+       ctrl->ctrl18_19 = NULL;
+       ctrl->ctrl20_21 = NULL;
+}
+
+static int f11_read_control_regs(struct rmi_device *rmi_dev,
+                                          struct f11_2d_ctrl *ctrl,
+                                          int ctrl_base_addr) {
+       int read_address = ctrl_base_addr;
+       int error = 0;
+
+       error = rmi_read_block(rmi_dev, read_address, ctrl->ctrl0_9,
+               sizeof(ctrl->ctrl0_9));
+       if (error < 0) {
+               dev_err(&rmi_dev->dev,
+                       "Failed to read F11 ctrl0, code: %d.\n", error);
+               return error;
+       }
+       read_address = read_address + sizeof(ctrl->ctrl0_9);
+
+       if (ctrl->ctrl10) {
+               error = rmi_read_block(rmi_dev, read_address,
+                       &ctrl->ctrl10->reg, sizeof(union f11_2d_ctrl10));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read F11 ctrl10, code: %d.\n",
+                               error);
+                       return error;
+               }
+               read_address = read_address + sizeof(union f11_2d_ctrl10);
+       }
+
+       if (ctrl->ctrl11) {
+               error = rmi_read_block(rmi_dev, read_address,
+                       &ctrl->ctrl11->reg, sizeof(union f11_2d_ctrl11));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read F11 ctrl11, code: %d.\n",
+                               error);
+                       return error;
+               }
+               read_address = read_address + sizeof(union f11_2d_ctrl11);
+       }
+
+       if (ctrl->ctrl14) {
+               error = rmi_read_block(rmi_dev, read_address,
+                       &ctrl->ctrl14->reg, sizeof(union f11_2d_ctrl14));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read F11 ctrl14, code: %d.\n",
+                               error);
+                       return error;
+               }
+               read_address = read_address + sizeof(union f11_2d_ctrl14);
+       }
+
+       if (ctrl->ctrl15) {
+               error = rmi_read_block(rmi_dev, read_address,
+                       &ctrl->ctrl15->reg, sizeof(union f11_2d_ctrl15));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read F11 ctrl15, code: %d.\n",
+                               error);
+                       return error;
+               }
+               read_address = read_address + sizeof(union f11_2d_ctrl15);
+       }
+
+       if (ctrl->ctrl16) {
+               error = rmi_read_block(rmi_dev, read_address,
+                       &ctrl->ctrl16->reg, sizeof(union f11_2d_ctrl16));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read F11 ctrl16, code: %d.\n",
+                               error);
+                       return error;
+               }
+               read_address = read_address + sizeof(union f11_2d_ctrl16);
+       }
+
+       if (ctrl->ctrl17) {
+               error = rmi_read_block(rmi_dev, read_address,
+                       &ctrl->ctrl17->reg, sizeof(union f11_2d_ctrl17));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read F11 ctrl17, code: %d.\n",
+                               error);
+                       return error;
+               }
+               read_address = read_address + sizeof(union f11_2d_ctrl17);
+       }
+
+       if (ctrl->ctrl18_19) {
+               error = rmi_read_block(rmi_dev, read_address,
+                       ctrl->ctrl18_19->reg, sizeof(union f11_2d_ctrl18_19));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read F11 ctrl18_19, code: %d.\n",
+                               error);
+                       return error;
+               }
+               read_address = read_address + sizeof(union f11_2d_ctrl18_19);
+       }
+
+       if (ctrl->ctrl20_21) {
+               error = rmi_read_block(rmi_dev, read_address,
+                       ctrl->ctrl20_21->reg, sizeof(union f11_2d_ctrl20_21));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read F11 ctrl20_21, code: %d.\n",
+                               error);
+                       return error;
+               }
+               read_address = read_address + sizeof(union f11_2d_ctrl20_21);
+       }
+
+       return 0;
+}
+
+static int f11_allocate_control_regs(struct rmi_device *rmi_dev,
+                               struct f11_2d_device_query *device_query,
+                               struct f11_2d_sensor_query *sensor_query,
+                               struct f11_2d_ctrl *ctrl,
+                               int ctrl_base_addr) {
+       int error = 0;
+
+       if (sensor_query->f11_2d_query7__8[0]) {
+               ctrl->ctrl10 = kzalloc(sizeof(union f11_2d_ctrl10),
+                                      GFP_KERNEL);
+               if (!ctrl->ctrl10) {
+                       error = -ENOMEM;
+                       goto error_exit;
+               }
+       }
+
+       if (sensor_query->f11_2d_query7__8[1]) {
+               ctrl->ctrl11 = kzalloc(sizeof(union f11_2d_ctrl11),
+                                      GFP_KERNEL);
+               if (!ctrl->ctrl11) {
+                       error = -ENOMEM;
+                       goto error_exit;
+               }
+       }
+
+       if (device_query->has_query9 && sensor_query->query9.has_pen) {
+               ctrl->ctrl20_21 = kzalloc(sizeof(union f11_2d_ctrl20_21),
+                                         GFP_KERNEL);
+               if (!ctrl->ctrl20_21) {
+                       error = -ENOMEM;
+                       goto error_exit;
+               }
+       }
+
+       return f11_read_control_regs(rmi_dev, ctrl, ctrl_base_addr);
+
+error_exit:
+       f11_free_control_regs(ctrl);
+       return error;
+}
+
+static int f11_write_control_regs(struct rmi_device *rmi_dev,
+                                       struct f11_2d_sensor_query *query,
+                                       struct f11_2d_ctrl *ctrl,
+                                       int ctrl_base_addr)
+{
+       int write_address = ctrl_base_addr;
+       int error;
+
+       error = rmi_write_block(rmi_dev, write_address,
+                               ctrl->ctrl0_9, sizeof(ctrl->ctrl0_9));
+       if (error < 0)
+               return error;
+       write_address += sizeof(ctrl->ctrl0_9);
+
+       if (ctrl->ctrl10) {
+               error = rmi_write_block(rmi_dev, write_address,
+                                       &ctrl->ctrl10->reg, 1);
+               if (error < 0)
+                       return error;
+               write_address++;
+       }
+
+       if (ctrl->ctrl11) {
+               error = rmi_write_block(rmi_dev, write_address,
+                                       &ctrl->ctrl11->reg, 1);
+               if (error < 0)
+                       return error;
+               write_address++;
+       }
+
+       if (ctrl->ctrl12 && ctrl->ctrl12_size && query->configurable) {
+               if (ctrl->ctrl12_size > query->max_electrodes) {
+                       dev_err(&rmi_dev->dev,
+                               "%s: invalid cfg size:%d, should be < %d.\n",
+                               __func__, ctrl->ctrl12_size,
+                               query->max_electrodes);
+                       return -EINVAL;
+               }
+               error = rmi_write_block(rmi_dev, write_address,
+                                               &ctrl->ctrl12->reg,
+                                               ctrl->ctrl12_size);
+               if (error < 0)
+                       return error;
+               write_address += ctrl->ctrl12_size;
+       }
+
+       if (ctrl->ctrl14) {
+               error = rmi_write_block(rmi_dev, write_address,
+                               &ctrl->ctrl14->reg, 1);
+               if (error < 0)
+                       return error;
+               write_address++;
+       }
+
+       if (ctrl->ctrl15) {
+               error = rmi_write_block(rmi_dev, write_address,
+                               &ctrl->ctrl15->reg, 1);
+               if (error < 0)
+                       return error;
+               write_address++;
+       }
+
+       if (ctrl->ctrl16) {
+               error = rmi_write_block(rmi_dev, write_address,
+                               &ctrl->ctrl16->reg, 1);
+               if (error < 0)
+                       return error;
+               write_address++;
+       }
+
+       if (ctrl->ctrl17) {
+               error = rmi_write_block(rmi_dev, write_address,
+                               &ctrl->ctrl17->reg, 1);
+               if (error < 0)
+                       return error;
+               write_address++;
+       }
+
+       if (ctrl->ctrl18_19) {
+               error = rmi_write_block(rmi_dev, write_address,
+                       ctrl->ctrl18_19->reg, sizeof(union f11_2d_ctrl18_19));
+               if (error < 0)
+                       return error;
+               write_address += sizeof(union f11_2d_ctrl18_19);
+       }
+
+       if (ctrl->ctrl20_21) {
+               error = rmi_write_block(rmi_dev, write_address,
+                                       ctrl->ctrl20_21->reg,
+                                       sizeof(union f11_2d_ctrl20_21));
+               if (error < 0)
+                       return error;
+               write_address += sizeof(union f11_2d_ctrl20_21);
+       }
+
+       return 0;
+}
+
+static int rmi_f11_get_query_parameters(struct rmi_device *rmi_dev,
+                       struct f11_2d_sensor_query *query, u8 query_base_addr)
+{
+       int query_size;
+       int rc;
+
+       rc = rmi_read_block(rmi_dev, query_base_addr, query->f11_2d_query1__4,
+                                       sizeof(query->f11_2d_query1__4));
+       if (rc < 0)
+               return rc;
+       query_size = rc;
+
+       if (query->has_abs) {
+               rc = rmi_read(rmi_dev, query_base_addr + query_size,
+                                       &query->f11_2d_query5);
+               if (rc < 0)
+                       return rc;
+               query_size++;
+       }
+
+       if (query->has_rel) {
+               rc = rmi_read(rmi_dev, query_base_addr + query_size,
+                                       &query->f11_2d_query6);
+               if (rc < 0)
+                       return rc;
+               query_size++;
+       }
+
+       if (query->has_gestures) {
+               rc = rmi_read_block(rmi_dev, query_base_addr + query_size,
+                                       query->f11_2d_query7__8,
+                                       sizeof(query->f11_2d_query7__8));
+               if (rc < 0)
+                       return rc;
+               query_size += sizeof(query->f11_2d_query7__8);
+       }
+
+       if (query->has_touch_shapes) {
+               rc = rmi_read(rmi_dev, query_base_addr + query_size,
+                                       &query->f11_2d_query10);
+               if (rc < 0)
+                       return rc;
+               query_size++;
+       }
+
+       return query_size;
+}
+
+/* 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_container *fc, int index)
+{
+       struct f11_data *instance_data =  fc->data;
+       struct f11_2d_sensor *sensor = &instance_data->sensors[index];
+       struct input_dev *input = sensor->input;
+       int device_x_max =
+               instance_data->dev_controls.sensor_max_x_pos;
+       int device_y_max =
+               instance_data->dev_controls.sensor_max_y_pos;
+       int x_min, x_max, y_min, y_max;
+
+       if (sensor->axis_align.swap_axes) {
+               int temp = device_x_max;
+               device_x_max = device_y_max;
+               device_y_max = temp;
+       }
+
+       /* Use the max X and max Y read from the device, or the clip values,
+        * whichever is stricter.
+        */
+       x_min = sensor->axis_align.clip_X_low;
+       if (sensor->axis_align.clip_X_high)
+               x_max = min((int) device_x_max,
+                       sensor->axis_align.clip_X_high);
+       else
+               x_max = device_x_max;
+
+       y_min = sensor->axis_align.clip_Y_low;
+       if (sensor->axis_align.clip_Y_high)
+               y_max = min((int) device_y_max,
+                       sensor->axis_align.clip_Y_high);
+       else
+               y_max = device_y_max;
+
+       dev_dbg(&fc->dev, "Set ranges X=[%d..%d] Y=[%d..%d].",
+                       x_min, x_max, y_min, y_max);
+
+       __set_bit(INPUT_PROP_DIRECT, input->propbit);
+       __set_bit(EV_ABS, input->evbit);
+       input_mt_init_slots(input, SYNAPTICS_MAX_POINTS);
+       input_set_abs_params(input, ABS_MT_PRESSURE, 0, DEFAULT_MAX_ABS_MT_PRESSURE, 0, 0);
+       input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, DEFAULT_MAX_ABS_MT_TOUCH, 0, 0);
+       input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, DEFAULT_MAX_ABS_MT_TOUCH, 0, 0);
+       input_set_abs_params(input, ABS_MT_ORIENTATION, 0, DEFAULT_MAX_ABS_MT_ORIENTATION, 0, 0);
+       input_set_abs_params(input, ABS_MT_TRACKING_ID, 
+                       DEFAULT_MIN_ABS_MT_TRACKING_ID,
+                       DEFAULT_MAX_ABS_MT_TRACKING_ID, 0, 0);
+       /* TODO get max_x_pos (and y) from control registers. */
+       input_set_abs_params(input, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
+       input_set_abs_params(input, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
+#ifdef CONFIG_RMI4_F11_PEN
+       if (sensor->sens_query.query9.has_pen)
+               input_set_abs_params(input, ABS_MT_TOOL_TYPE,
+                                    0, MT_TOOL_MAX, 0, 0);
+#endif
+}
+
+static int rmi_f11_init(struct rmi_function_container *fc)
+{
+       int rc;
+
+       rc = rmi_f11_initialize(fc);
+       if (rc < 0)
+               goto err_free_data;
+
+       rc = rmi_f11_register_devices(fc);
+       if (rc < 0)
+               goto err_free_data;
+
+       rc = rmi_f11_create_sysfs(fc);
+       if (rc < 0)
+               goto err_free_data;
+
+       return 0;
+
+err_free_data:
+       rmi_f11_free_memory(fc);
+
+       return rc;
+}
+
+static void rmi_f11_free_memory(struct rmi_function_container *fc)
+{
+       struct f11_data *f11 = fc->data;
+       int i;
+
+       if (f11) {
+               f11_free_control_regs(&f11->dev_controls);
+               for (i = 0; i < f11->dev_query.nbr_of_sensors + 1; i++)
+                       kfree(f11->sensors[i].virtualbutton_map.map);
+               kfree(f11);
+               fc->data = NULL;
+       }
+}
+
+
+static int rmi_f11_initialize(struct rmi_function_container *fc)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct f11_data *f11;
+       u8 query_offset;
+       u8 query_base_addr;
+       u8 control_base_addr;
+       u16 max_x_pos, max_y_pos, temp;
+       int rc;
+       int i;
+       struct rmi_device_platform_data *pdata = to_rmi_platform_data(rmi_dev);
+
+       dev_dbg(&fc->dev, "Initializing F11 values for %s.\n",
+                pdata->sensor_name);
+
+       /*
+       ** init instance data, fill in values and create any sysfs files
+       */
+       f11 = kzalloc(sizeof(struct f11_data), GFP_KERNEL);
+       if (!f11)
+               return -ENOMEM;
+
+       fc->data = f11;
+#if    RESUME_REZERO
+       f11->rezero_on_resume = true;
+       f11->rezero_wait_ms = DEFAULT_REZERO_WAIT_MS;
+#endif
+
+       query_base_addr = fc->fd.query_base_addr;
+       control_base_addr = fc->fd.control_base_addr;
+
+       rc = rmi_read(rmi_dev, query_base_addr, &f11->dev_query.f11_2d_query0);
+       if (rc < 0)
+               return rc;
+
+       query_offset = (query_base_addr + 1);
+       /* Increase with one since number of sensors is zero based */
+       for (i = 0; i < (f11->dev_query.nbr_of_sensors + 1); i++) {
+               f11->sensors[i].sensor_index = i;
+
+               rc = rmi_f11_get_query_parameters(rmi_dev,
+                                       &f11->sensors[i].sens_query,
+                                       query_offset);
+               if (rc < 0)
+                       return rc;
+               query_offset += rc;
+
+               if (f11->dev_query.has_query9) {
+                       rc = rmi_read(rmi_dev, query_offset,
+                                     &f11->sensors[i].sens_query.query9.reg);
+                       if (rc < 0) {
+                               dev_err(&fc->dev, "Failed to read query 9.\n");
+                               return rc;
+                       }
+                       query_offset += rc;
+               }
+
+               rc = f11_allocate_control_regs(rmi_dev,
+                               &f11->dev_query, &f11->sensors[i].sens_query,
+                               &f11->dev_controls, control_base_addr);
+               if (rc < 0) {
+                       dev_err(&fc->dev,
+                               "Failed to initialize F11 control params.\n");
+                       return rc;
+               }
+
+               f11->sensors[i].axis_align = pdata->axis_align;
+
+               rc = rmi_read_block(rmi_dev,
+                       control_base_addr + F11_CTRL_SENSOR_MAX_X_POS_OFFSET,
+                       (u8 *)&max_x_pos, sizeof(max_x_pos));
+               if (rc < 0)
+                       return rc;
+
+               rc = rmi_read_block(rmi_dev,
+                       control_base_addr + F11_CTRL_SENSOR_MAX_Y_POS_OFFSET,
+                       (u8 *)&max_y_pos, sizeof(max_y_pos));
+               if (rc < 0)
+                       return rc;
+
+               if (pdata->axis_align.swap_axes) {
+                       temp = max_x_pos;
+                       max_x_pos = max_y_pos;
+                       max_y_pos = temp;
+               }
+               f11->sensors[i].max_x = max_x_pos;
+               f11->sensors[i].max_y = max_y_pos;
+
+               rc = f11_2d_construct_data(&f11->sensors[i]);
+               if (rc < 0)
+                       return rc;
+       }
+
+       return 0;
+}
+
+static int rmi_f11_register_devices(struct rmi_function_container *fc)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct f11_data *f11 = fc->data;
+       struct input_dev *input_dev;
+       struct input_dev *input_dev_mouse;
+       int sensors_itertd = 0;
+       int i;
+       int rc;
+#ifdef CONFIG_RMI4_VIRTUAL_BUTTON
+       struct rmi_f11_virtualbutton_map *vm_sensor;
+       struct rmi_f11_virtualbutton_map *vm_pdata;
+       struct rmi_device_platform_data *pdata = to_rmi_platform_data(rmi_dev);
+#endif
+
+       for (i = 0; i < (f11->dev_query.nbr_of_sensors + 1); i++) {
+               sensors_itertd = i;
+               input_dev = input_allocate_device();
+               if (!input_dev) {
+                       rc = -ENOMEM;
+                       goto error_unregister;
+               }
+
+               f11->sensors[i].input = input_dev;
+               /* TODO how to modify the dev name and
+               * phys name for input device */
+               sprintf(f11->sensors[i].input_name, "%sfn%02x",
+                       dev_name(&rmi_dev->dev), fc->fd.function_number);
+               input_dev->name = f11->sensors[i].input_name;
+               sprintf(f11->sensors[i].input_phys, "%s/input0",
+                       input_dev->name);
+               input_dev->phys = f11->sensors[i].input_phys;
+               input_dev->dev.parent = &rmi_dev->dev;
+               input_set_drvdata(input_dev, f11);
+
+               set_bit(EV_SYN, input_dev->evbit);
+               set_bit(EV_KEY, input_dev->evbit);
+               set_bit(EV_ABS, input_dev->evbit);
+
+               f11_set_abs_params(fc, i);
+
+               dev_dbg(&fc->dev, "%s: Sensor %d hasRel %d.\n",
+                       __func__, i, f11->sensors[i].sens_query.has_rel);
+               if (f11->sensors[i].sens_query.has_rel) {
+                       set_bit(EV_REL, input_dev->evbit);
+                       set_bit(REL_X, input_dev->relbit);
+                       set_bit(REL_Y, input_dev->relbit);
+               }
+               rc = input_register_device(input_dev);
+               if (rc < 0) {
+                       input_free_device(input_dev);
+                       f11->sensors[i].input = NULL;
+                       goto error_unregister;
+               }
+
+               /* how to register the virtualbutton device */
+#ifdef CONFIG_RMI4_VIRTUAL_BUTTON
+               if (f11->sensors[i].sens_query.has_gestures) {
+                       int j;
+
+                       vm_sensor = &f11->sensors[i].virtualbutton_map;
+                       vm_pdata = pdata->virtualbutton_map;
+                       if (!vm_pdata) {
+                               dev_err(&fc->dev, "Failed to get the pdata virtualbutton map.\n");
+                               goto error_unregister;
+                       }
+                       vm_sensor->buttons = vm_pdata->buttons;
+                       vm_sensor->map = kcalloc(vm_pdata->buttons,
+                                       sizeof(struct virtualbutton_map),
+                                       GFP_KERNEL);
+                       if (!vm_sensor->map) {
+                               dev_err(&fc->dev, "Failed to allocate the virtualbutton map.\n");
+                               rc = -ENOMEM;
+                               goto error_unregister;
+                       }
+                       /* set bits for each button... */
+                       for (j = 0; j < vm_pdata->buttons; j++) {
+                               memcpy(&vm_sensor->map[j], &vm_pdata->map[j],
+                                       sizeof(struct virtualbutton_map));
+                               set_bit(vm_sensor->map[j].code,
+                                       f11->sensors[i].input->keybit);
+                       }
+               }
+
+#endif
+
+               if (f11->sensors[i].sens_query.has_rel) {
+                       /*create input device for mouse events  */
+                       input_dev_mouse = input_allocate_device();
+                       if (!input_dev_mouse) {
+                               rc = -ENOMEM;
+                               goto error_unregister;
+                       }
+
+                       f11->sensors[i].mouse_input = input_dev_mouse;
+                       input_dev_mouse->name = "rmi_mouse";
+                       input_dev_mouse->phys = "rmi_f11/input0";
+
+                       input_dev_mouse->id.vendor  = 0x18d1;
+                       input_dev_mouse->id.product = 0x0210;
+                       input_dev_mouse->id.version = 0x0100;
+
+                       set_bit(EV_REL, input_dev_mouse->evbit);
+                       set_bit(REL_X, input_dev_mouse->relbit);
+                       set_bit(REL_Y, input_dev_mouse->relbit);
+
+                       set_bit(BTN_MOUSE, input_dev_mouse->evbit);
+                       /* Register device's buttons and keys */
+                       set_bit(EV_KEY, input_dev_mouse->evbit);
+                       set_bit(BTN_LEFT, input_dev_mouse->keybit);
+                       set_bit(BTN_MIDDLE, input_dev_mouse->keybit);
+                       set_bit(BTN_RIGHT, input_dev_mouse->keybit);
+
+                       rc = input_register_device(input_dev_mouse);
+                       if (rc < 0) {
+                               input_free_device(input_dev_mouse);
+                               f11->sensors[i].mouse_input = NULL;
+                               goto error_unregister;
+                       }
+
+                       set_bit(BTN_RIGHT, input_dev_mouse->keybit);
+               }
+
+       }
+
+       return 0;
+
+error_unregister:
+       for (; sensors_itertd > 0; sensors_itertd--) {
+               if (f11->sensors[sensors_itertd].input) {
+                       if (f11->sensors[sensors_itertd].mouse_input) {
+                               input_unregister_device(
+                                  f11->sensors[sensors_itertd].mouse_input);
+                               f11->sensors[sensors_itertd].mouse_input = NULL;
+                       }
+                       input_unregister_device(f11->sensors[i].input);
+                       f11->sensors[i].input = NULL;
+               }
+               kfree(f11->sensors[i].virtualbutton_map.map);
+       }
+
+       return rc;
+}
+
+static void rmi_f11_free_devices(struct rmi_function_container *fc)
+{
+       struct f11_data *f11 = fc->data;
+       int i;
+
+       for (i = 0; i < (f11->dev_query.nbr_of_sensors + 1); i++) {
+               if (f11->sensors[i].input)
+                       input_unregister_device(f11->sensors[i].input);
+               if (f11->sensors[i].sens_query.has_rel &&
+                               f11->sensors[i].mouse_input)
+                       input_unregister_device(f11->sensors[i].mouse_input);
+       }
+}
+
+static int rmi_f11_create_sysfs(struct rmi_function_container *fc)
+{
+       int attr_count = 0;
+       int rc;
+
+       dev_dbg(&fc->dev, "Creating sysfs files.\n");
+       /* Set up sysfs device attributes. */
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               if (sysfs_create_file
+                   (&fc->dev.kobj, &attrs[attr_count].attr) < 0) {
+                       dev_err(&fc->dev,
+                               "Failed to create sysfs file for %s.",
+                               attrs[attr_count].attr.name);
+                       rc = -ENODEV;
+                       goto err_remove_sysfs;
+               }
+       }
+
+       return 0;
+
+err_remove_sysfs:
+       for (attr_count--; attr_count >= 0; attr_count--)
+               sysfs_remove_file(&fc->dev.kobj,
+                                                 &attrs[attr_count].attr);
+       return rc;
+}
+
+static int rmi_f11_config(struct rmi_function_container *fc)
+{
+       struct f11_data *f11 = fc->data;
+       int i;
+       int rc;
+
+       for (i = 0; i < (f11->dev_query.nbr_of_sensors + 1); i++) {
+               rc = f11_write_control_regs(fc->rmi_dev,
+                                  &f11->sensors[i].sens_query,
+                                  &f11->dev_controls,
+                                  fc->fd.query_base_addr);
+               if (rc < 0)
+                       return rc;
+       }
+
+       return 0;
+}
+
+static int rmi_f11_reset(struct rmi_function_container *fc)
+{
+       /* we do nothing here */
+       return 0;
+}
+
+int rmi_f11_attention(struct rmi_function_container *fc, u8 *irq_bits)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct f11_data *f11 = fc->data;
+       u8 data_base_addr = fc->fd.data_base_addr;
+       int data_base_addr_offset = 0;
+       int error;
+       int i;
+
+       for (i = 0; i < f11->dev_query.nbr_of_sensors + 1; i++) {
+               error = rmi_read_block(rmi_dev,
+                               data_base_addr + data_base_addr_offset,
+                               f11->sensors[i].data_pkt,
+                               f11->sensors[i].pkt_size);
+               if (error < 0)
+                       return error;
+
+               rmi_f11_finger_handler(&f11->sensors[i]);
+               rmi_f11_virtual_button_handler(&f11->sensors[i]);
+               data_base_addr_offset += f11->sensors[i].pkt_size;
+       }
+
+       return 0;
+}
+
+#if RESUME_REZERO
+static int rmi_f11_resume(struct rmi_function_container *fc)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct f11_data *data = fc->data;
+       /* Command register always reads as 0, so we can just use a local. */
+       union f11_2d_commands commands = {};
+       int retval = 0;
+
+       dev_dbg(&fc->dev, "Resuming...\n");
+       if (!data->rezero_on_resume)
+               return 0;
+
+       if (data->rezero_wait_ms)
+               mdelay(data->rezero_wait_ms);
+
+       commands.rezero = 1;
+       retval = rmi_write_block(rmi_dev, fc->fd.command_base_addr,
+                       &commands.reg, sizeof(commands.reg));
+       if (retval < 0) {
+               dev_err(&rmi_dev->dev, "%s: failed to issue rezero command, error = %d.",
+                       __func__, retval);
+               return retval;
+       }
+
+       return retval;
+}
+#endif /* RESUME_REZERO */
+
+static void rmi_f11_remove(struct rmi_function_container *fc)
+{
+       int attr_count = 0;
+
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               sysfs_remove_file(&fc->dev.kobj,
+                                 &attrs[attr_count].attr);
+       }
+
+       rmi_f11_free_devices(fc);
+
+       rmi_f11_free_memory(fc);
+
+}
+
+static struct rmi_function_handler function_handler = {
+       .func = 0x11,
+       .init = rmi_f11_init,
+       .config = rmi_f11_config,
+       .reset = rmi_f11_reset,
+       .attention = rmi_f11_attention,
+       .remove = rmi_f11_remove
+#if    RESUME_REZERO
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       ,
+       .late_resume = rmi_f11_resume
+#else
+       .resume = rmi_f11_resume
+#endif  /* CONFIG_HAS_EARLYSUSPEND */
+#endif
+};
+
+static int __init rmi_f11_module_init(void)
+{
+       int error;
+
+       error = rmi_register_function_driver(&function_handler);
+       if (error < 0) {
+               pr_err("%s: register failed!\n", __func__);
+               return error;
+       }
+
+       return 0;
+}
+
+static void __exit rmi_f11_module_exit(void)
+{
+       rmi_unregister_function_driver(&function_handler);
+}
+
+static ssize_t f11_maxPos_show(struct device *dev,
+                                    struct device_attribute *attr,
+                                    char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f11_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u %u\n",
+                       data->sensors[0].max_x, data->sensors[0].max_y);
+}
+
+static ssize_t f11_flip_show(struct device *dev,
+                                  struct device_attribute *attr,
+                                  char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f11_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u %u\n",
+                       data->sensors[0].axis_align.flip_x,
+                       data->sensors[0].axis_align.flip_y);
+}
+
+static ssize_t f11_flip_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf,
+                                   size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f11_data *instance_data;
+       unsigned int new_X, new_Y;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+
+       if (sscanf(buf, "%u %u", &new_X, &new_Y) != 2)
+               return -EINVAL;
+       if (new_X < 0 || new_X > 1 || new_Y < 0 || new_Y > 1)
+               return -EINVAL;
+       instance_data->sensors[0].axis_align.flip_x = new_X;
+       instance_data->sensors[0].axis_align.flip_y = new_Y;
+
+       return count;
+}
+
+static ssize_t f11_swap_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f11_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       instance_data->sensors[0].axis_align.swap_axes);
+}
+
+static ssize_t f11_swap_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f11_data *instance_data;
+       unsigned int newSwap;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+
+       if (sscanf(buf, "%u", &newSwap) != 1)
+               return -EINVAL;
+       if (newSwap < 0 || newSwap > 1)
+               return -EINVAL;
+       instance_data->sensors[0].axis_align.swap_axes = newSwap;
+
+       f11_set_abs_params(fc, 0);
+
+       return count;
+}
+
+static ssize_t f11_relreport_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f11_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       instance_data->
+                       sensors[0].axis_align.rel_report_enabled);
+}
+
+static ssize_t f11_relreport_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf,
+                                        size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f11_data *instance_data;
+       unsigned int new_value;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+
+       if (sscanf(buf, "%u", &new_value) != 1)
+               return -EINVAL;
+       if (new_value < 0 || new_value > 1)
+               return -EINVAL;
+       instance_data->sensors[0].axis_align.rel_report_enabled = new_value;
+
+       return count;
+}
+
+static ssize_t f11_offset_show(struct device *dev,
+                                    struct device_attribute *attr,
+                                    char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f11_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%d %d\n",
+                       instance_data->sensors[0].axis_align.offset_X,
+                       instance_data->sensors[0].axis_align.offset_Y);
+}
+
+static ssize_t f11_offset_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf,
+                                     size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f11_data *instance_data;
+       int new_X, new_Y;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+
+       if (sscanf(buf, "%d %d", &new_X, &new_Y) != 2)
+               return -EINVAL;
+       instance_data->sensors[0].axis_align.offset_X = new_X;
+       instance_data->sensors[0].axis_align.offset_Y = new_Y;
+
+       return count;
+}
+
+static ssize_t f11_clip_show(struct device *dev,
+                                  struct device_attribute *attr,
+                                  char *buf)
+{
+
+       struct rmi_function_container *fc;
+       struct f11_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u %u %u %u\n",
+                       instance_data->sensors[0].axis_align.clip_X_low,
+                       instance_data->sensors[0].axis_align.clip_X_high,
+                       instance_data->sensors[0].axis_align.clip_Y_low,
+                       instance_data->sensors[0].axis_align.clip_Y_high);
+}
+
+static ssize_t f11_clip_store(struct device *dev,
+                                   struct device_attribute *attr,
+                                   const char *buf,
+                                   size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f11_data *instance_data;
+       unsigned int new_X_low, new_X_high, new_Y_low, new_Y_high;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       if (sscanf(buf, "%u %u %u %u",
+                  &new_X_low, &new_X_high, &new_Y_low, &new_Y_high) != 4)
+               return -EINVAL;
+       if (new_X_low < 0 || new_X_low >= new_X_high || new_Y_low < 0
+           || new_Y_low >= new_Y_high)
+               return -EINVAL;
+       instance_data->sensors[0].axis_align.clip_X_low = new_X_low;
+       instance_data->sensors[0].axis_align.clip_X_high = new_X_high;
+       instance_data->sensors[0].axis_align.clip_Y_low = new_Y_low;
+       instance_data->sensors[0].axis_align.clip_Y_high = new_Y_high;
+
+       /*
+       ** for now, we assume this is sensor index 0
+       */
+       f11_set_abs_params(fc, 0);
+
+       return count;
+}
+
+static ssize_t f11_rezero_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct rmi_function_container *fc = NULL;
+       unsigned int rezero;
+       int retval = 0;
+       /* Command register always reads as 0, so we can just use a local. */
+       union f11_2d_commands commands = {};
+
+       fc = to_rmi_function_container(dev);
+
+       if (sscanf(buf, "%u", &rezero) != 1)
+               return -EINVAL;
+       if (rezero < 0 || rezero > 1)
+               return -EINVAL;
+
+       /* Per spec, 0 has no effect, so we skip it entirely. */
+       if (rezero) {
+               commands.rezero = 1;
+               retval = rmi_write_block(fc->rmi_dev, fc->fd.command_base_addr,
+                               &commands.reg, sizeof(commands.reg));
+               if (retval < 0) {
+                       dev_err(dev, "%s: failed to issue rezero command, error = %d.",
+                               __func__, retval);
+                       return retval;
+               }
+       }
+
+       return count;
+}
+
+#if RESUME_REZERO
+static ssize_t f11_rezeroOnResume_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct rmi_function_container *fc = NULL;
+       unsigned int newValue;
+       struct f11_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       if (sscanf(buf, "%u", &newValue) != 1)
+               return -EINVAL;
+       if (newValue < 0 || newValue > 1) {
+               dev_err(dev, "rezeroOnResume must be either 1 or 0.\n");
+               return -EINVAL;
+       }
+
+       instance_data->rezero_on_resume = (newValue != 0);
+
+       return count;
+}
+
+static ssize_t f11_rezeroOnResume_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f11_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       instance_data->rezero_on_resume);
+}
+
+static ssize_t f11_rezeroWait_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct rmi_function_container *fc = NULL;
+       unsigned int newValue;
+       struct f11_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       if (sscanf(buf, "%u", &newValue) != 1)
+               return -EINVAL;
+       if (newValue < 0) {
+               dev_err(dev, "rezeroWait must be 0 or greater.\n");
+               return -EINVAL;
+       }
+
+       instance_data->rezero_wait_ms = (newValue != 0);
+
+       return count;
+}
+
+static ssize_t f11_rezeroWait_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f11_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       instance_data->rezero_wait_ms);
+}
+#endif
+
+module_init(rmi_f11_module_init);
+module_exit(rmi_f11_module_exit);
+
+MODULE_AUTHOR("Christopher Heiny <cheiny@synaptics.com");
+MODULE_DESCRIPTION("RMI F11 module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
+
diff --git a/drivers/input/touchscreen/rmi4/rmi_f17.c b/drivers/input/touchscreen/rmi4/rmi_f17.c
new file mode 100755 (executable)
index 0000000..2b99e5c
--- /dev/null
@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 2012 Synaptics Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/rmi.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include "rmi_driver.h"
+#define QUERY_BASE_INDEX 1
+#define MAX_NAME_LENGTH 256
+
+union f17_device_query {
+       struct {
+               u8 number_of_sticks:3;
+       };
+       u8 regs[1];
+};
+
+#define F17_MANUFACTURER_SYNAPTICS 0
+#define F17_MANUFACTURER_NMB 1
+#define F17_MANUFACTURER_ALPS 2
+
+struct f17_stick_query {
+       union {
+               struct {
+                       u8 manufacturer:4;
+                       u8 resistive:1;
+                       u8 ballistics:1;
+                       u8 reserved1:2;
+                       u8 has_relative:1;
+                       u8 has_absolute:1;
+                       u8 has_gestures:1;
+                       u8 has_dribble:1;
+                       u8 reserved2:4;
+               };
+               u8 regs[2];
+       } general;
+
+       union {
+               struct {
+                       u8 has_single_tap:1;
+                       u8 has_tap_and_hold:1;
+                       u8 has_double_tap:1;
+                       u8 has_early_tap:1;
+                       u8 has_press:1;
+               };
+               u8 regs[1];
+       } gestures;
+};
+
+union f17_device_controls {
+       struct {
+               u8 reporting_mode:3;
+               u8 dribble:1;
+       };
+       u8 regs[1];
+};
+
+struct f17_stick_controls {
+       union {
+               struct {
+                       u8 z_force_threshold;
+                       u8 radial_force_threshold;
+               };
+               u8 regs[3];
+       } general;
+
+       union {
+               struct {
+                       u8 motion_sensitivity:4;
+                       u8 antijitter:1;
+               };
+               u8 regs[1];
+       } relative;
+
+       union {
+               struct {
+                       u8 single_tap:1;
+                       u8 tap_and_hold:1;
+
+                       u8 double_tap:1;
+                       u8 early_tap:1;
+                       u8 press:1;
+               };
+               u8 regs[1];
+       } enable;
+
+       u8 maximum_tap_time;
+       u8 minimum_press_time;
+       u8 maximum_radial_force;
+};
+
+
+union f17_device_commands {
+       struct {
+               u8 rezero:1;
+       };
+       u8 regs[1];
+};
+
+struct f17_stick_data {
+       union {
+               struct {
+                       u8 x_force_high;
+                       u8 y_force_high;
+                       u8 y_force_low:4;
+                       u8 x_force_low:4;
+                       u8 z_force;
+               };
+               u8 regs[4];
+       } abs;
+       union {
+               struct {
+                       s8 x_delta;
+                       s8 y_delta;
+               };
+               u8 regs[2];
+       } rel;
+       union {
+               struct {
+                       u8 single_tap:1;
+                       u8 tap_and_hold:1;
+                       u8 double_tap:1;
+                       u8 early_tap:1;
+                       u8 press:1;
+               };
+               u8 regs[1];
+       } gestures;
+};
+
+
+/* data specific to f17 that needs to be kept around */
+
+struct rmi_f17_stick_data {
+       struct f17_stick_query query;
+       struct f17_stick_controls controls;
+       struct f17_stick_data data;
+
+       u16 abs_data_address;
+       u16 rel_data_address;
+       u16 gesture_data_address;
+       u16 control_address;
+
+       int index;
+
+       char input_name[MAX_NAME_LENGTH];
+       char input_phys[MAX_NAME_LENGTH];
+       struct input_dev *input;
+       char mouse_name[MAX_NAME_LENGTH];
+       char mouse_phys[MAX_NAME_LENGTH];
+       struct input_dev *mouse;
+};
+
+struct rmi_f17_device_data {
+       u16 control_address;
+
+       union f17_device_query query;
+       union f17_device_commands commands;
+       union f17_device_controls controls;
+
+       struct rmi_f17_stick_data *sticks;
+
+};
+
+static ssize_t f17_rezero_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf);
+static ssize_t f17_rezero_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count);
+
+
+
+static int f17_alloc_memory(struct rmi_function_container *fc);
+
+static void f17_free_memory(struct rmi_function_container *fc);
+
+static int f17_initialize(struct rmi_function_container *fc);
+
+static int f17_register_devices(struct rmi_function_container *fc);
+
+static int f17_create_sysfs(struct rmi_function_container *fc);
+
+static int f17_config(struct rmi_function_container *fc);
+
+static int f17_reset(struct rmi_function_container *fc);
+
+static struct device_attribute attrs[] = {
+       __ATTR(rezero, RMI_RW_ATTR,
+               f17_rezero_show, f17_rezero_store),
+};
+
+
+int f17_read_control_parameters(struct rmi_device *rmi_dev,
+       struct rmi_f17_device_data *f17)
+{
+       int retval = 0;
+
+       // TODO: read this or delete the function
+
+       return retval;
+}
+
+
+static int f17_init(struct rmi_function_container *fc)
+{
+       int retval;
+
+       retval = f17_alloc_memory(fc);
+       if (retval < 0)
+               goto err_free_data;
+
+       retval = f17_initialize(fc);
+       if (retval < 0)
+               goto err_free_data;
+
+       retval = f17_register_devices(fc);
+       if (retval < 0)
+               goto err_free_data;
+
+       retval = f17_create_sysfs(fc);
+       if (retval < 0)
+               goto err_free_data;
+
+       return 0;
+
+err_free_data:
+       f17_free_memory(fc);
+
+       return retval;
+}
+
+static int f17_alloc_memory(struct rmi_function_container *fc)
+{
+       struct rmi_f17_device_data *f17;
+       int retval;
+       int i;
+
+       f17 = kzalloc(sizeof(struct rmi_f17_device_data), GFP_KERNEL);
+       if (!f17) {
+               dev_err(&fc->dev, "Failed to allocate function data.\n");
+               return -ENOMEM;
+       }
+       fc->data = f17;
+
+       retval = rmi_read_block(fc->rmi_dev, fc->fd.query_base_addr,
+                               f17->query.regs, sizeof(f17->query.regs));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to read query register.\n");
+               goto error_exit;
+       }
+       dev_info(&fc->dev, "Found F17 with %d sticks.\n",
+                f17->query.number_of_sticks + 1);
+
+       f17->sticks = kcalloc(f17->query.number_of_sticks + 1,
+                       sizeof(struct rmi_f17_stick_data), GFP_KERNEL);
+       if (!f17->sticks) {
+               dev_err(&fc->dev, "Failed to allocate per stick data.\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < f17->query.number_of_sticks + 1; i++) {
+               // TODO: allocate any per stick stuff (or remove this loop)
+       }
+
+       return 0;
+
+error_exit:
+       kfree(f17);
+       fc->data = NULL;
+       return retval;
+}
+
+static void f17_free_memory(struct rmi_function_container *fc)
+{
+       struct rmi_f17_device_data *f17 = fc->data;
+       int i;
+
+       if (f17) {
+               if (f17->sticks) {
+                       for (i = 0; i < f17->query.number_of_sticks + 1; i++) {
+                               // TODO: Free stick stuff
+                       }
+               }
+               kfree(f17->sticks);
+               f17->sticks = NULL;
+       }
+       kfree(f17);
+       fc->data = NULL;
+}
+
+static int f17_init_stick(struct rmi_device *rmi_dev,
+                         struct rmi_f17_stick_data *stick,
+                         u16 *next_query_reg, u16 *next_data_reg,
+                         u16 *next_control_reg) {
+       int retval = 0;
+
+       retval = rmi_read_block(rmi_dev, *next_query_reg,
+               stick->query.general.regs,
+               sizeof(stick->query.general.regs));
+       if (retval < 0) {
+               dev_err(&rmi_dev->dev, "Failed to read stick general query.\n");
+               return retval;
+       }
+       *next_query_reg += sizeof(stick->query.general.regs);
+
+       dev_info(&rmi_dev->dev, "Stick %d found\n", stick->index);
+       dev_info(&rmi_dev->dev, "    Manufacturer: %d.\n", stick->query.general.manufacturer);
+       dev_info(&rmi_dev->dev, "    Resistive:    %d.\n", stick->query.general.resistive);
+       dev_info(&rmi_dev->dev, "    Ballistics:   %d.\n", stick->query.general.ballistics);
+       dev_info(&rmi_dev->dev, "    Manufacturer: %d.\n", stick->query.general.ballistics);
+       dev_info(&rmi_dev->dev, "    Has relative: %d.\n", stick->query.general.has_relative);
+       dev_info(&rmi_dev->dev, "    Has absolute: %d.\n", stick->query.general.has_absolute);
+       dev_info(&rmi_dev->dev, "    Had dribble:  %d.\n", stick->query.general.has_dribble);
+       dev_info(&rmi_dev->dev, "    Has gestures: %d.\n", stick->query.general.has_gestures);
+
+       if (stick->query.general.has_gestures) {
+               retval = rmi_read_block(rmi_dev, *next_query_reg,
+                       stick->query.gestures.regs,
+                       sizeof(stick->query.gestures.regs));
+               if (retval < 0) {
+                       dev_err(&rmi_dev->dev, "Failed to read stick gestures query.\n");
+                       return retval;
+               }
+               *next_query_reg += sizeof(stick->query.gestures.regs);
+               dev_info(&rmi_dev->dev, "        single tap: %d.\n", stick->query.gestures.has_single_tap);
+               dev_info(&rmi_dev->dev, "        tap & hold: %d.\n", stick->query.gestures.has_tap_and_hold);
+               dev_info(&rmi_dev->dev, "        double tap: %d.\n", stick->query.gestures.has_double_tap);
+               dev_info(&rmi_dev->dev, "        early tap:  %d.\n", stick->query.gestures.has_early_tap);
+               dev_info(&rmi_dev->dev, "        press:      %d.\n", stick->query.gestures.has_press);
+       }
+       if (stick->query.general.has_absolute) {
+               stick->abs_data_address = *next_data_reg;
+               *next_data_reg += sizeof(stick->data.abs.regs);
+       }
+       if (stick->query.general.has_relative) {
+               stick->rel_data_address = *next_data_reg;
+               *next_data_reg += sizeof(stick->data.rel.regs);
+       }
+       if (stick->query.general.has_gestures) {
+               stick->gesture_data_address = *next_data_reg;
+               *next_data_reg += sizeof(stick->data.gestures.regs);
+       }
+
+       return retval;
+}
+
+static int f17_initialize(struct rmi_function_container *fc)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct rmi_f17_device_data *f17 = fc->data;
+       int i;
+       int retval;
+       u16 next_query_reg = fc->fd.query_base_addr;
+       u16 next_data_reg = fc->fd.data_base_addr;
+       u16 next_control_reg = fc->fd.control_base_addr;
+
+       dev_info(&fc->dev, "Intializing F17 values.");
+
+       retval = rmi_read_block(fc->rmi_dev, fc->fd.query_base_addr,
+                               f17->query.regs, sizeof(f17->query.regs));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to read query register.\n");
+               return retval;
+       }
+       dev_info(&fc->dev, "Found F17 with %d sticks.\n",
+                f17->query.number_of_sticks + 1);
+       next_query_reg += sizeof(f17->query.regs);
+
+       retval = rmi_read_block(rmi_dev, fc->fd.command_base_addr,
+               f17->commands.regs, sizeof(f17->commands.regs));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to read command register.\n");
+               return retval;
+       }
+
+       f17->control_address = fc->fd.control_base_addr;
+       retval = f17_read_control_parameters(rmi_dev, f17);
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to initialize F17 control params.\n");
+               return retval;
+       }
+
+       for (i = 0; i < f17->query.number_of_sticks + 1; i++) {
+               f17->sticks[i].index = i;
+               retval = f17_init_stick(rmi_dev, &f17->sticks[i],
+                                       &next_query_reg, &next_data_reg,
+                                       &next_control_reg);
+               if (!retval) {
+                       dev_err(&fc->dev, "Failed to init stick %d.\n", i);
+                       return retval;
+               }
+       }
+
+       return retval;
+}
+
+static int f17_register_stick(struct rmi_function_container *fc,
+                             struct rmi_f17_stick_data *stick) {
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       int retval = 0;
+
+       if (stick->query.general.has_absolute) {
+               struct input_dev *input_dev;
+               input_dev = input_allocate_device();
+               if (!input_dev) {
+                       dev_err(&rmi_dev->dev, "Failed to allocate stick device %d.\n",
+                               stick->index);
+                       return -ENOMEM;
+               }
+
+               snprintf(stick->input_name, sizeof(stick->input_name),
+                       "RMI F%02x Stick %d", 0x17, stick->index);
+               snprintf(stick->input_phys, sizeof(stick->input_phys),
+                        "sensor00fn%02x/stick%d", 0x17, stick->index);
+               input_dev->name = stick->input_name;
+               input_dev->phys = stick->input_phys;
+               input_dev->dev.parent = &fc->dev;
+               input_set_drvdata(input_dev, stick);
+
+               retval = input_register_device(input_dev);
+               if (retval < 0) {
+                       dev_err(&rmi_dev->dev, "Failed to register stick device %d.\n",
+                               stick->index);
+                       goto error_free_device;
+               }
+               stick->input = input_dev;
+       }
+
+       if (stick->query.general.has_relative) {
+               struct input_dev *input_dev_mouse;
+               /*create input device for mouse events  */
+               input_dev_mouse = input_allocate_device();
+               if (!input_dev_mouse) {
+                       retval = -ENOMEM;
+                       goto error_free_device;
+               }
+
+               snprintf(stick->mouse_name, sizeof(stick->mouse_name),
+                       "RMI F%02x Mouse %d", 0x17, stick->index);
+               snprintf(stick->mouse_phys, sizeof(stick->mouse_name),
+                        "sensor00fn%02x/mouse%d", 0x17, stick->index);
+               input_dev_mouse->name = stick->mouse_name;
+               input_dev_mouse->phys = stick->mouse_phys;
+               input_dev_mouse->dev.parent = &fc->dev;
+
+               input_dev_mouse->id.vendor  = 0x18d1;
+               input_dev_mouse->id.product = 0x0210;
+               input_dev_mouse->id.version = 0x0100;
+
+               set_bit(EV_REL, input_dev_mouse->evbit);
+               set_bit(REL_X, input_dev_mouse->relbit);
+               set_bit(REL_Y, input_dev_mouse->relbit);
+
+               set_bit(BTN_MOUSE, input_dev_mouse->evbit);
+               /* Register device's buttons and keys */
+               set_bit(EV_KEY, input_dev_mouse->evbit);
+               set_bit(BTN_LEFT, input_dev_mouse->keybit);
+               set_bit(BTN_MIDDLE, input_dev_mouse->keybit);
+               set_bit(BTN_RIGHT, input_dev_mouse->keybit);
+
+               retval = input_register_device(input_dev_mouse);
+               if (retval < 0)
+                       goto error_free_device;
+               stick->mouse = input_dev_mouse;
+       }
+
+       return 0;
+
+error_free_device:
+       if (stick->input) {
+               input_free_device(stick->input);
+               stick->input = NULL;
+       }
+       if (stick->mouse) {
+               input_free_device(stick->mouse);
+               stick->mouse = NULL;
+       }
+       return retval;
+}
+
+static int f17_register_devices(struct rmi_function_container *fc)
+{
+       struct rmi_f17_device_data *f17 = fc->data;
+       int i;
+       int retval = 0;
+
+       for (i = 0; i < f17->query.number_of_sticks + 1 && !retval; i++) {
+               retval = f17_register_stick(fc, &f17->sticks[i]);
+       }
+
+       return retval;
+}
+
+static int f17_create_sysfs(struct rmi_function_container *fc)
+{
+       int attr_count = 0;
+       int rc;
+
+       dev_dbg(&fc->dev, "Creating sysfs files.\n");
+       /* Set up sysfs device attributes. */
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               if (sysfs_create_file
+                   (&fc->dev.kobj, &attrs[attr_count].attr) < 0) {
+                       dev_err(&fc->dev,
+                               "Failed to create sysfs file for %s.",
+                               attrs[attr_count].attr.name);
+                       rc = -ENODEV;
+                       goto err_remove_sysfs;
+               }
+       }
+
+       return 0;
+
+err_remove_sysfs:
+       for (attr_count--; attr_count >= 0; attr_count--)
+               sysfs_remove_file(&fc->dev.kobj, &attrs[attr_count].attr);
+       return rc;
+
+}
+
+static int f17_config(struct rmi_function_container *fc)
+{
+       struct rmi_f17_device_data *f17 = fc->data;
+       int retval;
+       int i;
+
+       retval = rmi_write_block(fc->rmi_dev, f17->control_address,
+               f17->controls.regs, sizeof(f17->controls.regs));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Could not write stick controls to 0x%04x\n",
+                               f17->control_address);
+               return retval;
+       }
+
+#if 0
+       if (f17->query.has_relative) {
+               retval = rmi_write_block(fc->rmi_dev,
+                       f17->relative_control_address,
+                       f17->controls.relative.regs,
+                       sizeof(f17->controls.relative.regs));
+               if (retval < 0) {
+                       dev_err(&fc->dev, "Could not write stick controls to 0x%04x\n",
+                                       f17->control_address);
+                       return retval;
+               }
+       }
+#endif
+
+       for (i = 0; i < f17->query.number_of_sticks + 1; i++) {
+               // TODO: Configure each styk
+       }
+
+       return retval;
+}
+
+static int f17_reset(struct rmi_function_container *fc)
+{
+       /* we do nothing here */
+       return 0;
+}
+
+static void f17_remove(struct rmi_function_container *fc)
+{
+       struct rmi_f17_device_data *f17 = fc->data;
+       int i = 0;
+
+       for (i = 0; i < ARRAY_SIZE(attrs); i++)
+               sysfs_remove_file(&fc->dev.kobj, &attrs[i].attr);
+
+       for (i = 0; i < f17->query.number_of_sticks + 1; i++) {
+               input_unregister_device(f17->sticks[i].input);
+       }
+
+       f17_free_memory(fc);
+}
+
+static int f17_process_stick(struct rmi_device *rmi_dev,
+                            struct rmi_f17_stick_data *stick) {
+       int retval = 0;
+
+       if (stick->query.general.has_absolute) {
+               retval = rmi_read_block(rmi_dev, stick->abs_data_address,
+                       stick->data.abs.regs, sizeof(stick->data.abs.regs));
+               if (retval < 0) {
+                       dev_err(&rmi_dev->dev, "Failed to read abs data for stick %d.\n",
+                               stick->index);
+                       goto error_exit;
+               }
+       }
+       if (stick->query.general.has_relative) {
+               retval = rmi_read_block(rmi_dev, stick->rel_data_address,
+                       stick->data.rel.regs, sizeof(stick->data.rel.regs));
+               if (retval < 0) {
+                       dev_err(&rmi_dev->dev, "Failed to read rel data for stick %d.\n",
+                               stick->index);
+                       goto error_exit;
+               }
+               dev_info(&rmi_dev->dev, "Reporting dX: %d, dy: %d\n", stick->data.rel.x_delta, stick->data.rel.y_delta);
+               input_report_rel(stick->mouse, REL_X, stick->data.rel.x_delta);
+               input_report_rel(stick->mouse, REL_Y, stick->data.rel.y_delta);
+       }
+       if (stick->query.general.has_gestures) {
+               retval = rmi_read_block(rmi_dev, stick->gesture_data_address,
+                       stick->data.gestures.regs, sizeof(stick->data.gestures.regs));
+               if (retval < 0) {
+                       dev_err(&rmi_dev->dev, "Failed to read gesture data for stick %d.\n",
+                               stick->index);
+                       goto error_exit;
+               }
+       }
+       retval = 0;
+
+error_exit:
+       if (stick->input)
+               input_sync(stick->input);
+       if (stick->mouse)
+               input_sync(stick->mouse);
+       return retval;
+}
+
+static int f17_attention(struct rmi_function_container *fc, u8 *irq_bits)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct rmi_f17_device_data *f17 = fc->data;
+       int i;
+       int retval = 0;
+
+       for (i = 0; i < f17->query.number_of_sticks + 1 && !retval; i++) {
+               retval = f17_process_stick(rmi_dev, &f17->sticks[i]);
+       }
+
+       return retval;
+}
+
+static struct rmi_function_handler function_handler = {
+       .func = 0x17,
+       .init = f17_init,
+       .config = f17_config,
+       .reset = f17_reset,
+       .attention = f17_attention,
+       .remove = f17_remove
+};
+
+static int __init f17_module_init(void)
+{
+       int error;
+
+       error = rmi_register_function_driver(&function_handler);
+       if (error < 0) {
+               pr_err("%s: register failed!\n", __func__);
+               return error;
+       }
+
+       return 0;
+}
+
+static void f17_module_exit(void)
+{
+       rmi_unregister_function_driver(&function_handler);
+}
+
+
+static ssize_t f17_rezero_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_f17_device_data *f17;
+
+       fc = to_rmi_function_container(dev);
+       f17 = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       f17->commands.rezero);
+
+}
+
+static ssize_t f17_rezero_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf,
+                                        size_t count)
+{
+       struct rmi_function_container *fc;
+       struct rmi_f17_device_data *data;
+       unsigned int new_value;
+       int len;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       len = sscanf(buf, "%u", &new_value);
+       if (new_value != 0 && new_value != 1) {
+               dev_err(dev,
+                       "%s: Error - rezero is not a valid value 0x%x.\n",
+                       __func__, new_value);
+               return -EINVAL;
+       }
+       data->commands.rezero = new_value;
+       len = rmi_write(fc->rmi_dev, fc->fd.command_base_addr,
+               data->commands.rezero);
+
+       if (len < 0) {
+               dev_err(dev, "%s : Could not write rezero to 0x%x\n",
+                               __func__, fc->fd.command_base_addr);
+               return -EINVAL;
+       }
+       return count;
+}
+
+
+module_init(f17_module_init);
+module_exit(f17_module_exit);
+
+MODULE_AUTHOR("Christopher Heiny <cheiny@synaptics.com>");
+MODULE_DESCRIPTION("RMI F17 module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
diff --git a/drivers/input/touchscreen/rmi4/rmi_f19.c b/drivers/input/touchscreen/rmi4/rmi_f19.c
new file mode 100755 (executable)
index 0000000..37b3419
--- /dev/null
@@ -0,0 +1,1505 @@
+/*
+ * Copyright (c) 2011 Synaptics Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/rmi.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include "rmi_driver.h"
+#define QUERY_BASE_INDEX 1
+#define MAX_LEN 256
+#define MAX_BUFFER_LEN 80
+
+#define SENSOR_MAP_MIN                 0
+#define SENSOR_MAP_MAX                 127
+#define SENSITIVITY_ADJ_MIN            0
+#define SENSITIVITY_ADJ_MAX            31
+#define HYSTERESIS_THRESHOLD_MIN       0
+#define HYSTERESIS_THRESHOLD_MAX       15
+
+union f19_0d_query {
+       struct {
+               u8 configurable:1;
+               u8 has_sensitivity_adjust:1;
+               u8 has_hysteresis_threshold:1;
+               u8 reserved_1:5;
+
+               u8 button_count:5;
+               u8 reserved_2:3;
+       };
+       u8 regs[2];
+};
+
+union f19_0d_control_0 {
+       struct {
+               u8 button_usage:2;
+               u8 filter_mode:2;
+       };
+       u8 regs[1];
+};
+
+struct f19_0d_control_3 {
+       u8 sensor_map_button:7;
+       /*u8 sensitivity_button;*/
+};
+
+struct f19_0d_control_5 {
+       u8 sensitivity_adj:5;
+};
+
+struct f19_0d_control_6 {
+       u8 hysteresis_threshold:4;
+};
+
+struct f19_0d_control {
+       union f19_0d_control_0 general_control;
+       u8 *int_enabled_button;
+       u8 *single_button;
+       struct f19_0d_control_3 *sensor_map;
+       struct f19_0d_control_5 all_button_sensitivity_adj;
+       struct f19_0d_control_6 all_button_hysteresis_threshold;
+};
+/* data specific to fn $19 that needs to be kept around */
+struct f19_data {
+       struct f19_0d_control button_control;
+       union f19_0d_query button_query;
+       u8 button_rezero;
+       unsigned char button_count;
+       unsigned char button_bitmask_size;
+       unsigned char *button_data_buffer;
+       unsigned short *button_map;
+       char input_name[MAX_LEN];
+       char input_phys[MAX_LEN];
+       struct input_dev *input;
+       int general_control_address;
+       int int_enable_button_address;
+       int single_button_address;
+       int sensor_map_address;
+       int all_button_sensitivity_address;
+       int all_button_threshold_address;
+};
+
+static ssize_t rmi_f19_button_count_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf);
+static ssize_t rmi_f19_button_map_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f19_button_map_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+static ssize_t rmi_f19_rezero_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf);
+static ssize_t rmi_f19_rezero_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+static ssize_t rmi_f19_has_hysteresis_threshold_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f19_has_sensitivity_adjust_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f19_configurable_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f19_filter_mode_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf);
+static ssize_t rmi_f19_filter_mode_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+static ssize_t rmi_f19_button_usage_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf);
+static ssize_t rmi_f19_button_usage_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+static ssize_t rmi_f19_interrupt_enable_button_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf);
+static ssize_t rmi_f19_interrupt_enable_button_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+static ssize_t rmi_f19_single_button_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf);
+static ssize_t rmi_f19_single_button_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+static ssize_t rmi_f19_sensor_map_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf);
+static ssize_t rmi_f19_sensor_map_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+static ssize_t rmi_f19_sensitivity_adjust_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf);
+static ssize_t rmi_f19_sensitivity_adjust_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+static ssize_t rmi_f19_hysteresis_threshold_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf);
+static ssize_t rmi_f19_hysteresis_threshold_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+
+
+
+static int rmi_f19_alloc_memory(struct rmi_function_container *fc);
+
+static void rmi_f19_free_memory(struct rmi_function_container *fc);
+
+static int rmi_f19_initialize(struct rmi_function_container *fc);
+
+static int rmi_f19_register_device(struct rmi_function_container *fc);
+
+static int rmi_f19_create_sysfs(struct rmi_function_container *fc);
+
+static int rmi_f19_config(struct rmi_function_container *fc);
+
+static int rmi_f19_reset(struct rmi_function_container *fc);
+
+static struct device_attribute attrs[] = {
+       __ATTR(button_count, RMI_RO_ATTR,
+               rmi_f19_button_count_show, rmi_store_error),
+       __ATTR(button_map, RMI_RW_ATTR,
+               rmi_f19_button_map_show, rmi_f19_button_map_store),
+       __ATTR(rezero, RMI_RW_ATTR,
+               rmi_f19_rezero_show, rmi_f19_rezero_store),
+       __ATTR(has_hysteresis_threshold, RMI_RO_ATTR,
+               rmi_f19_has_hysteresis_threshold_show, rmi_store_error),
+       __ATTR(has_sensitivity_adjust, RMI_RO_ATTR,
+               rmi_f19_has_sensitivity_adjust_show, rmi_store_error),
+       __ATTR(configurable, RMI_RO_ATTR,
+               rmi_f19_configurable_show, rmi_store_error),
+       __ATTR(filter_mode, RMI_RW_ATTR,
+               rmi_f19_filter_mode_show, rmi_f19_filter_mode_store),
+       __ATTR(button_usage, RMI_RW_ATTR,
+               rmi_f19_button_usage_show, rmi_f19_button_usage_store),
+       __ATTR(interrupt_enable_button, RMI_RW_ATTR,
+               rmi_f19_interrupt_enable_button_show,
+               rmi_f19_interrupt_enable_button_store),
+       __ATTR(single_button, RMI_RW_ATTR,
+               rmi_f19_single_button_show, rmi_f19_single_button_store),
+       __ATTR(sensor_map, RMI_RW_ATTR,
+               rmi_f19_sensor_map_show, rmi_f19_sensor_map_store),
+       __ATTR(sensitivity_adjust, RMI_RW_ATTR,
+               rmi_f19_sensitivity_adjust_show,
+               rmi_f19_sensitivity_adjust_store),
+       __ATTR(hysteresis_threshold, RMI_RW_ATTR,
+               rmi_f19_hysteresis_threshold_show,
+               rmi_f19_hysteresis_threshold_store)
+};
+
+
+int rmi_f19_read_control_parameters(struct rmi_device *rmi_dev,
+       struct f19_data *f19)
+{
+       int error = 0;
+       struct f19_0d_control *button_control = &f19->button_control;
+       union f19_0d_query *button_query = &f19->button_query;
+
+       int ctrl_base_addr = f19->general_control_address;
+
+       error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                       (u8 *)&button_control->general_control,
+                       sizeof(union f19_0d_control_0));
+       if (error < 0) {
+               dev_err(&rmi_dev->dev,
+                       "Failed to read f19_0d_control_0, code:"
+                       " %d.\n", error);
+               return error;
+       }
+       ctrl_base_addr = ctrl_base_addr +
+                       sizeof(union f19_0d_control_0);
+
+       f19->int_enable_button_address = ctrl_base_addr;
+       if (button_control->int_enabled_button) {
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                       button_control->int_enabled_button,
+                       f19->button_bitmask_size);
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read f19_0d_control_2,"
+                               " code: %d.\n", error);
+                       return error;
+               }
+               ctrl_base_addr = ctrl_base_addr + f19->button_bitmask_size;
+       }
+
+       if (button_control->single_button) {
+               f19->single_button_address = ctrl_base_addr;
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                               button_control->single_button,
+                               f19->button_bitmask_size);
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read f19_0d_control_2,"
+                               " code: %d.\n", error);
+                       return error;
+               }
+               ctrl_base_addr = ctrl_base_addr + f19->button_bitmask_size;
+       }
+
+       if (button_control->sensor_map) {
+               f19->sensor_map_address = ctrl_base_addr;
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                       (u8 *)(button_control->sensor_map),
+                       sizeof(struct f19_0d_control_3)*f19->button_count);
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                       "Failed to read f19_0d_control_3,"
+                       " code: %d.\n", error);
+                       return error;
+               }
+               ctrl_base_addr = ctrl_base_addr +
+                       (sizeof(struct f19_0d_control_3)*f19->button_count);
+               ctrl_base_addr += (sizeof(u8)*f19->button_count);
+       }
+
+       if (button_query->has_sensitivity_adjust) {
+               f19->all_button_sensitivity_address = ctrl_base_addr;
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                               (u8 *)&button_control->
+                                       all_button_sensitivity_adj,
+                               sizeof(struct f19_0d_control_5));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read f19_0d_control_5,"
+                               " code: %d.\n", error);
+                       return error;
+               }
+               ctrl_base_addr = ctrl_base_addr +
+                       sizeof(struct f19_0d_control_5);
+       }
+       if (button_query->has_hysteresis_threshold) {
+               f19->all_button_threshold_address = ctrl_base_addr;
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                               (u8 *)&button_control->
+                                       all_button_hysteresis_threshold,
+                               sizeof(struct f19_0d_control_6));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read f19_0d_control_6,"
+                               " code: %d.\n", error);
+                       return error;
+               }
+               ctrl_base_addr = ctrl_base_addr +
+                       sizeof(struct f19_0d_control_6);
+       }
+       return 0;
+}
+
+
+static int rmi_f19_init(struct rmi_function_container *fc)
+{
+       int rc;
+
+       rc = rmi_f19_alloc_memory(fc);
+       if (rc < 0)
+               goto err_free_data;
+
+       rc = rmi_f19_initialize(fc);
+       if (rc < 0)
+               goto err_free_data;
+
+       rc = rmi_f19_register_device(fc);
+       if (rc < 0)
+               goto err_free_data;
+
+       rc = rmi_f19_create_sysfs(fc);
+       if (rc < 0)
+               goto err_free_data;
+
+       return 0;
+
+err_free_data:
+       rmi_f19_free_memory(fc);
+
+       return rc;
+}
+
+
+static int rmi_f19_alloc_memory(struct rmi_function_container *fc)
+{
+       struct f19_data *f19;
+       int rc;
+
+       f19 = kzalloc(sizeof(struct f19_data), GFP_KERNEL);
+       if (!f19) {
+               dev_err(&fc->dev, "Failed to allocate function data.\n");
+               return -ENOMEM;
+       }
+       fc->data = f19;
+
+       rc = rmi_read_block(fc->rmi_dev,
+                                               fc->fd.query_base_addr,
+                                               (u8 *)&f19->button_query,
+                                               sizeof(union f19_0d_query));
+       if (rc < 0) {
+               dev_err(&fc->dev, "Failed to read query register.\n");
+               return rc;
+       }
+
+       f19->button_count = f19->button_query.button_count;
+       f19->button_bitmask_size = sizeof(u8)*(f19->button_count + 7) / 8;
+       f19->button_data_buffer =
+           kcalloc(f19->button_bitmask_size,
+                   sizeof(unsigned char), GFP_KERNEL);
+       if (!f19->button_data_buffer) {
+               dev_err(&fc->dev, "Failed to allocate button data buffer.\n");
+               return -ENOMEM;
+       }
+
+       f19->button_map = kcalloc(f19->button_count,
+                               sizeof(unsigned short), GFP_KERNEL);
+       if (!f19->button_map) {
+               dev_err(&fc->dev, "Failed to allocate button map.\n");
+               return -ENOMEM;
+       }
+
+       f19->button_control.int_enabled_button =
+               kzalloc(f19->button_bitmask_size, GFP_KERNEL);
+       if (!f19->button_control.int_enabled_button) {
+               dev_err(&fc->dev, "Failed to allocate interrupt button.\n");
+               return -ENOMEM;
+       }
+
+       f19->button_control.single_button =
+               kzalloc(f19->button_bitmask_size, GFP_KERNEL);
+       if (!f19->button_control.single_button) {
+               dev_err(&fc->dev, "Failed to allocate"
+                       " single button.\n");
+               return -ENOMEM;
+       }
+
+       f19->button_control.sensor_map = kzalloc(f19->button_count *
+                               sizeof(struct f19_0d_control_3), GFP_KERNEL);
+       if (!f19->button_control.sensor_map) {
+               dev_err(&fc->dev, "Failed to allocate"
+                       " f19_0d_control_3.\n");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+
+
+static void rmi_f19_free_memory(struct rmi_function_container *fc)
+{
+       struct f19_data *f19 = fc->data;
+
+       if (f19) {
+               kfree(f19->button_data_buffer);
+               kfree(f19->button_map);
+               kfree(f19->button_control.int_enabled_button);
+               kfree(f19->button_control.single_button);
+               kfree(f19->button_control.sensor_map);
+               kfree(f19);
+               fc->data = NULL;
+       }
+}
+
+
+static int rmi_f19_initialize(struct rmi_function_container *fc)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct rmi_device_platform_data *pdata;
+       struct f19_data *f19 = fc->data;
+       int i;
+       int rc;
+
+       dev_info(&fc->dev, "Intializing F19 values.");
+
+       /* initial all default values for f19 data here */
+       rc = rmi_read(rmi_dev, fc->fd.command_base_addr,
+               (u8 *)&f19->button_rezero);
+       if (rc < 0) {
+               dev_err(&fc->dev, "Failed to read command register.\n");
+               return rc;
+       }
+       f19->button_rezero = f19->button_rezero & 1;
+
+       pdata = to_rmi_platform_data(rmi_dev);
+       if (pdata) {
+               if (!pdata->button_map) {
+                       dev_warn(&fc->dev, "%s - button_map is NULL", __func__);
+               } else if (pdata->button_map->nbuttons != f19->button_count) {
+                       dev_warn(&fc->dev,
+                               "Platformdata button map size (%d) != number "
+                               "of buttons on device (%d) - ignored.\n",
+                               pdata->button_map->nbuttons,
+                               f19->button_count);
+               } else if (!pdata->button_map->map) {
+                       dev_warn(&fc->dev,
+                                "Platformdata button map is missing!\n");
+               } else {
+                       for (i = 0; i < pdata->button_map->nbuttons; i++)
+                               f19->button_map[i] = pdata->button_map->map[i];
+               }
+       }
+
+       f19->general_control_address = fc->fd.control_base_addr;
+       rc = rmi_f19_read_control_parameters(rmi_dev, f19);
+       if (rc < 0) {
+               dev_err(&fc->dev,
+                       "Failed to initialize F19 control params.\n");
+               return rc;
+       }
+
+       return 0;
+}
+
+
+
+static int rmi_f19_register_device(struct rmi_function_container *fc)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct input_dev *input_dev;
+       struct f19_data *f19 = fc->data;
+       int i;
+       int rc;
+
+       input_dev = input_allocate_device();
+       if (!input_dev) {
+               dev_err(&fc->dev, "Failed to allocate input device.\n");
+               return -ENOMEM;
+       }
+
+       f19->input = input_dev;
+       snprintf(f19->input_name, MAX_LEN, "%sfn%02x", dev_name(&rmi_dev->dev),
+               fc->fd.function_number);
+       input_dev->name = f19->input_name;
+       snprintf(f19->input_phys, MAX_LEN, "%s/input0", input_dev->name);
+       input_dev->phys = f19->input_phys;
+       input_dev->dev.parent = &rmi_dev->dev;
+       input_set_drvdata(input_dev, f19);
+
+       /* Set up any input events. */
+       set_bit(EV_SYN, input_dev->evbit);
+       set_bit(EV_KEY, input_dev->evbit);
+       /* set bits for each button... */
+       for (i = 0; i < f19->button_count; i++)
+               set_bit(f19->button_map[i], input_dev->keybit);
+       rc = input_register_device(input_dev);
+       if (rc < 0) {
+               dev_err(&fc->dev, "Failed to register input device.\n");
+               goto error_free_device;
+       }
+
+       return 0;
+
+error_free_device:
+       input_free_device(input_dev);
+
+       return rc;
+}
+
+
+static int rmi_f19_create_sysfs(struct rmi_function_container *fc)
+{
+       int attr_count = 0;
+       int rc;
+       char *name;
+       struct f19_data *data;
+       union f19_0d_query *button_query;
+
+       data = fc->data;
+       button_query = &data->button_query;
+
+       dev_dbg(&fc->dev, "Creating sysfs files.\n");
+       /* Set up sysfs device attributes. */
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               name = (char *) attrs[attr_count].attr.name;
+               if (!button_query->has_sensitivity_adjust &&
+                       !strcmp(name, "sensitivity_adjust"))
+                       continue;
+               if (!button_query->has_hysteresis_threshold &&
+                       !strcmp(name, "hysteresis_threshold"))
+                       continue;
+               if (sysfs_create_file
+                   (&fc->dev.kobj, &attrs[attr_count].attr) < 0) {
+                       dev_err(&fc->dev,
+                               "Failed to create sysfs file for %s.",
+                               attrs[attr_count].attr.name);
+                       rc = -ENODEV;
+                       goto err_remove_sysfs;
+               }
+       }
+
+       return 0;
+
+err_remove_sysfs:
+       for (attr_count--; attr_count >= 0; attr_count--)
+               sysfs_remove_file(&fc->dev.kobj,
+                                                 &attrs[attr_count].attr);
+       return rc;
+
+}
+
+
+
+static int rmi_f19_config(struct rmi_function_container *fc)
+{
+       struct f19_data *data;
+       int retval;
+       union f19_0d_query *button_query;
+
+       data = fc->data;
+       button_query = &data->button_query;
+       retval = rmi_write_block(fc->rmi_dev, data->general_control_address,
+               (u8 *)&data->button_control.general_control,
+                       sizeof(union f19_0d_control_0));
+       if (retval < 0) {
+               dev_err(&fc->dev, "%s : Could not write general_control to 0x%x\n",
+                               __func__, fc->fd.control_base_addr);
+               return retval;
+       }
+
+       retval = rmi_write_block(fc->rmi_dev, data->int_enable_button_address,
+               data->button_control.int_enabled_button,
+               data->button_bitmask_size);
+       if (retval < 0) {
+               dev_err(&fc->dev, "%s : Could not write interrupt_enable_store"
+                       " to 0x%x\n", __func__,
+                               data->int_enable_button_address);
+               return retval;
+       }
+
+       retval = rmi_write_block(fc->rmi_dev, data->single_button_address,
+               data->button_control.single_button,
+               data->button_bitmask_size);
+       if (retval < 0) {
+               dev_err(&fc->dev,
+                               "%s : Could not write interrupt_enable_store to"
+                               " 0x%x\n", __func__,
+                               data->single_button_address);
+               return -EINVAL;
+       }
+
+       retval = rmi_write_block(fc->rmi_dev,  data->sensor_map_address,
+               (u8 *)data->button_control.sensor_map,
+                       sizeof(struct f19_0d_control_3)*data->button_count);
+       if (retval < 0) {
+               dev_err(&fc->dev, "%s : Could not sensor_map_store to 0x%x\n",
+                               __func__, data->sensor_map_address);
+               return -EINVAL;
+       }
+       if (button_query->has_sensitivity_adjust) {
+               retval = rmi_write_block(fc->rmi_dev,
+                       data->all_button_sensitivity_address,
+                       (u8 *)&data->button_control.all_button_sensitivity_adj,
+                       sizeof(struct f19_0d_control_5));
+               if (retval < 0) {
+                       dev_err(&fc->dev, "%s : Could not sensitivity_adjust_store to"
+                               " 0x%x\n", __func__,
+                               data->all_button_sensitivity_address);
+                       return retval;
+               }
+       }
+       if (!button_query->has_hysteresis_threshold) {
+               retval = rmi_write_block(fc->rmi_dev,
+                       data->all_button_threshold_address,
+                       (u8 *)&data->button_control.
+                               all_button_hysteresis_threshold,
+                       sizeof(struct f19_0d_control_6));
+               if (retval < 0) {
+                       dev_err(&fc->dev, "%s : Could not write all_button hysteresis "
+                               "threshold to 0x%x\n", __func__,
+                               data->all_button_threshold_address);
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
+
+static int rmi_f19_reset(struct rmi_function_container *fc)
+{
+       /* we do nnothing here */
+       return 0;
+}
+
+
+static void rmi_f19_remove(struct rmi_function_container *fc)
+{
+       struct f19_data *f19 = fc->data;
+       int attr_count = 0;
+
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++)
+               sysfs_remove_file(&fc->dev.kobj,
+                                 &attrs[attr_count].attr);
+
+       input_unregister_device(f19->input);
+
+       rmi_f19_free_memory(fc);
+}
+
+int rmi_f19_attention(struct rmi_function_container *fc, u8 *irq_bits)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct f19_data *f19 = fc->data;
+       int data_base_addr = fc->fd.data_base_addr;
+       int error;
+       int button;
+
+       /* Read the button data. */
+
+       error = rmi_read_block(rmi_dev, data_base_addr, f19->button_data_buffer,
+                       f19->button_bitmask_size);
+       if (error < 0) {
+               dev_err(&fc->dev, "%s: Failed to read button data registers.\n",
+                       __func__);
+               return error;
+       }
+
+       /* Generate events for buttons that change state. */
+       for (button = 0; button < f19->button_count;
+            button++) {
+               int button_reg;
+               int button_shift;
+               bool button_status;
+
+               /* determine which data byte the button status is in */
+               button_reg = button / 8;
+               /* bit shift to get button's status */
+               button_shift = button % 8;
+               button_status =
+                   ((f19->button_data_buffer[button_reg] >> button_shift)
+                       & 0x01) != 0;
+
+               /* if the button state changed from the last time report it
+                * and store the new state */
+                       /* Generate an event here. */
+               input_report_key(f19->input, f19->button_map[button],
+                                button_status);
+       }
+
+       input_sync(f19->input); /* sync after groups of events */
+       return 0;
+}
+
+static struct rmi_function_handler function_handler = {
+       .func = 0x19,
+       .init = rmi_f19_init,
+       .config = rmi_f19_config,
+       .reset = rmi_f19_reset,
+       .attention = rmi_f19_attention,
+       .remove = rmi_f19_remove
+};
+
+static int __init rmi_f19_module_init(void)
+{
+       int error;
+
+       error = rmi_register_function_driver(&function_handler);
+       if (error < 0) {
+               pr_err("%s: register failed!\n", __func__);
+               return error;
+       }
+
+       return 0;
+}
+
+static void rmi_f19_module_exit(void)
+{
+       rmi_unregister_function_driver(&function_handler);
+}
+
+static ssize_t rmi_f19_filter_mode_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_control.general_control.filter_mode);
+
+}
+
+static ssize_t rmi_f19_filter_mode_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       unsigned int new_value;
+       unsigned int old_value;
+       int result;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       if (sscanf(buf, "%u", &new_value) < 1) {
+               dev_err(dev,
+                       "%s: Error - filter_mode_store has an invalid len.\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       if (new_value < 0 || new_value > 4) {
+               dev_err(dev, "%s: Error - filter_mode_store has an invalid value %d.\n",
+                       __func__, new_value);
+               return -EINVAL;
+       }
+       old_value = data->button_control.general_control.filter_mode;
+       data->button_control.general_control.filter_mode = new_value;
+       result = rmi_write_block(fc->rmi_dev, data->general_control_address,
+               (u8 *)&(data->button_control.general_control),
+                       sizeof(union f19_0d_control_0));
+       if (result < 0) {
+               data->button_control.general_control.filter_mode = old_value;
+               dev_err(dev, "%s : Could not write filter_mode_store to 0x%x\n",
+                       __func__, fc->fd.control_base_addr);
+               return result;
+       }
+
+       return count;
+}
+
+static ssize_t rmi_f19_button_usage_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_control.general_control.button_usage);
+
+}
+
+static ssize_t rmi_f19_button_usage_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       unsigned int new_value;
+       unsigned int old_value;
+       int result;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       if (sscanf(buf, "%u", &new_value) < 1) {
+               dev_err(dev,
+                       "%s: Error - button_usage_store has an invalid len.\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       if (new_value < 0 || new_value > 4) {
+               dev_err(dev, "%s: Error - button_usage_store has an invalid value %d.\n",
+                       __func__, new_value);
+               return -EINVAL;
+       }
+       old_value = data->button_control.general_control.button_usage;
+       data->button_control.general_control.button_usage = new_value;
+       result = rmi_write_block(fc->rmi_dev, data->general_control_address,
+               (u8 *)&(data->button_control.general_control),
+                       sizeof(union f19_0d_control_0));
+       if (result < 0) {
+               data->button_control.general_control.button_usage = old_value;
+               dev_err(dev, "%s : Could not write button_usage_store to 0x%x\n",
+                       __func__, fc->fd.control_base_addr);
+               return result;
+       }
+
+       return count;
+
+}
+
+static ssize_t rmi_f19_interrupt_enable_button_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       int i, len, total_len = 0;
+       char *current_buf = buf;
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       /* loop through each button map value and copy its
+        * string representation into buf */
+       for (i = 0; i < data->button_count; i++) {
+               int button_reg;
+               int button_shift;
+               int interrupt_button;
+
+               button_reg = i / 8;
+               button_shift = i % 8;
+               interrupt_button =
+                       ((data->button_control.int_enabled_button[button_reg]
+                               >> button_shift) & 0x01);
+
+               /* get next button mapping value and write it to buf */
+               len = snprintf(current_buf, PAGE_SIZE - total_len,
+                       "%u ", interrupt_button);
+               /* bump up ptr to next location in buf if the
+                * snprintf was valid.  Otherwise issue an error
+                * and return. */
+               if (len > 0) {
+                       current_buf += len;
+                       total_len += len;
+               } else {
+                       dev_err(dev, "%s: Failed to build interrupt button buffer, code = %d.\n",
+                               __func__, len);
+                       return snprintf(buf, PAGE_SIZE, "unknown\n");
+               }
+       }
+       len = snprintf(current_buf, PAGE_SIZE - total_len, "\n");
+       if (len > 0)
+               total_len += len;
+       else
+               dev_warn(dev, "%s: Failed to append carriage return.\n", __func__);
+       return total_len;
+
+}
+
+static ssize_t rmi_f19_interrupt_enable_button_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       int i;
+       int button_count = 0;
+       int retval = count;
+       int button_reg = 0;
+       u8 *new_value;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       new_value = kzalloc(data->button_bitmask_size, GFP_KERNEL);
+       if (!new_value) {
+               dev_err(dev, "%s: Error - failed to allocate button interrupt enable.\n", __func__);
+               return -ENOMEM;
+       }
+       for (i = 0; i < data->button_count && *buf != 0;
+            i++, buf += 2) {
+               int button_shift;
+               int button;
+               int result;
+
+               button_reg = i / 8;
+               button_shift = i % 8;
+               /* get next button mapping value and store and bump up to
+                * point to next item in buf */
+               result = sscanf(buf, "%u", &button);
+
+               if ((result != 1) || (button != 0 && button != 1)) {
+                       dev_err(dev,
+                               "%s: Error-int enable button for button %d is not a valid value 0x%x.\n",
+                               __func__, i, button);
+                       return -EINVAL;
+               }
+
+               if (button)
+                       new_value[button_reg] |= (1 << button_shift);
+
+               button_count++;
+       }
+
+       /* Make sure the button count matches */
+       if (button_count != data->button_count) {
+               dev_err(dev,
+                       "%s: Error-int enable button count of %d doesn't match device button count of %d.\n",
+                        __func__, button_count, data->button_count);
+               kfree(new_value);
+               return -EINVAL;
+       }
+
+       /* write back to the control register */
+       retval = rmi_write_block(fc->rmi_dev, data->int_enable_button_address,
+                       new_value,
+                       data->button_bitmask_size);
+       if (retval < 0) {
+               dev_err(dev, "%s : Could not write interrupt_enable_store to 0x%x\n", __func__,
+                       data->int_enable_button_address);
+               kfree(new_value);
+               return retval;
+       }
+       memcpy(data->button_control.int_enabled_button,
+               new_value, data->button_bitmask_size);
+
+       kfree(new_value);
+
+       return count;
+}
+
+static ssize_t rmi_f19_single_button_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       int i, len, total_len = 0;
+       char *current_buf = buf;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       /* loop through each button map value and copy its
+        * string representation into buf */
+       for (i = 0; i < data->button_count; i++) {
+               int button_reg;
+               int button_shift;
+               int single_button;
+
+               button_reg = i / 8;
+               button_shift = i % 8;
+               single_button =
+                       ((data->button_control.single_button[button_reg]
+                               >> button_shift) & 0x01);
+
+               /* get next button mapping value and write it to buf */
+               len = snprintf(current_buf, PAGE_SIZE - total_len,
+                       "%u ", single_button);
+               /* bump up ptr to next location in buf if the
+                * snprintf was valid.  Otherwise issue an error
+                * and return. */
+               if (len > 0) {
+                       current_buf += len;
+                       total_len += len;
+               } else {
+                       dev_err(dev, "%s: Failed to build signle button buffer, code = %d.\n",
+                               __func__, len);
+                       return snprintf(buf, PAGE_SIZE, "unknown\n");
+               }
+       }
+       len = snprintf(current_buf, PAGE_SIZE - total_len, "\n");
+       if (len > 0)
+               total_len += len;
+       else
+               dev_warn(dev, "%s: Failed to append carriage return.\n", __func__);
+
+       return total_len;
+
+}
+
+static ssize_t rmi_f19_single_button_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       int i;
+       int button_count = 0;
+       int retval = count;
+       int button_reg = 0;
+       u8 *new_value;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       new_value = kzalloc(data->button_bitmask_size, GFP_KERNEL);
+       if (!new_value) {
+               dev_err(dev, "%s: Error - failed to allocate button interrupt enable.\n", __func__);
+               return -ENOMEM;
+       }
+       for (i = 0; i < data->button_count && *buf != 0;
+            i++, buf += 2) {
+               int button_shift;
+               int button;
+               int result;
+
+               button_reg = i / 8;
+               button_shift = i % 8;
+               /* get next button mapping value and store and bump up to
+                * point to next item in buf */
+               result = sscanf(buf, "%u", &button);
+
+               if ((result != 1) || (button != 0 && button != 1)) {
+                       dev_err(dev,
+                               "%s: Error - single button for button %d is not a valid value 0x%x.\n",
+                               __func__, i, button);
+                       kfree(new_value);
+                       return -EINVAL;
+               }
+
+               if (button) {
+                       new_value[button_reg] |=
+                               (1 << button_shift);
+               }
+               button_count++;
+       }
+
+       /* Make sure the button count matches */
+       if (button_count != data->button_count) {
+               dev_err(dev,
+                       "%s:Error-single button count of %d doesn't match device button count of %d\n",
+                       __func__, button_count, data->button_count);
+               kfree(new_value);
+               return -EINVAL;
+       }
+       /* write back to the control register */
+       retval = rmi_write_block(fc->rmi_dev, data->single_button_address,
+                       new_value,
+                       data->button_bitmask_size);
+       if (retval < 0) {
+               dev_err(dev, "%s : Could not write interrupt_enable_store to 0x%x\n",
+                       __func__, data->single_button_address);
+               kfree(new_value);
+               return -EINVAL;
+       }
+       memcpy(data->button_control.single_button,
+               new_value, data->button_bitmask_size);
+
+       kfree(new_value);
+       return count;
+}
+
+static ssize_t rmi_f19_sensor_map_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       int i, len, total_len = 0;
+       char *current_buf = buf;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       for (i = 0; i < data->button_count; i++) {
+               len = snprintf(current_buf, PAGE_SIZE - total_len,
+                       "%u ", data->button_control.sensor_map[i].
+                       sensor_map_button);
+               /* bump up ptr to next location in buf if the
+                * snprintf was valid.  Otherwise issue an error
+                * and return. */
+               if (len > 0) {
+                       current_buf += len;
+                       total_len += len;
+               } else {
+                       dev_err(dev, "%s: Failed to build sensor map buffer, code = %d.\n", __func__, len);
+                       return snprintf(buf, PAGE_SIZE, "unknown\n");
+               }
+       }
+       len = snprintf(current_buf, PAGE_SIZE - total_len, "\n");
+       if (len > 0)
+               total_len += len;
+       else
+               dev_warn(dev, "%s: Failed to append carriage return.\n", __func__);
+       return total_len;
+
+
+}
+
+static ssize_t rmi_f19_sensor_map_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       int i;
+       int retval = count;
+       int button_count = 0;
+       u8 *new_value;
+       char *tail;
+       char *p = (char *) buf;
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       new_value = kzalloc(data->button_count, GFP_KERNEL);
+       if (!new_value) {
+               dev_err(dev, "%s: Error - failed to allocate sensor map.\n", __func__);
+               return -ENOMEM;
+       }
+
+       if (data->button_query.configurable == 0) {
+               dev_err(dev, "%s: Error - sensor map is not configuralbe at run-time", __func__);
+               return -EINVAL;
+       }
+
+       for (i = 0; i < data->button_count && *p != 0; i++) {
+               new_value[i] = simple_strtoul(p, &tail, 10);
+               if (new_value[i] == 0  && p[0] != '0') {
+                       dev_err(dev, "%s: Error - reading sensor map is invalid\n", __func__);
+                       return -EINVAL;
+               }
+               if (new_value[i] > INT_MAX) {
+                       dev_err(dev, "%s: Error - reading sensor map is out for range\n", __func__);
+                       return -ERANGE;
+               }
+               p = tail;
+               /* Make sure the key is a valid key */
+               if (new_value[i] < SENSOR_MAP_MIN ||
+                       new_value[i] > SENSOR_MAP_MAX) {
+                       dev_err(dev,
+                               "%s: Error - sensor map for button %d is not a valid value 0x%x.\n",
+                               __func__, i, new_value[i]);
+                       return -EINVAL;
+               }
+               button_count++;
+               while (p[0] == ' ')
+                       p++;
+       }
+
+       if (button_count != data->button_count) {
+               dev_err(dev,
+                       "%s: Error - button map count of %d doesn't match device button count of %d.\n",                                __func__, button_count, data->button_count);
+               return -EINVAL;
+       }
+
+       /* write back to the control register */
+       retval = rmi_write_block(fc->rmi_dev, data->sensor_map_address,
+                       new_value,
+                       sizeof(struct f19_0d_control_3)*button_count);
+       if (retval < 0) {
+               dev_err(dev, "%s : Could not sensor_map_store to 0x%x\n",
+                               __func__,  data->sensor_map_address);
+               return -EINVAL;
+       }
+       memcpy(data->button_control.sensor_map, new_value, data->button_count);
+       kfree(new_value);
+       return count;
+}
+
+static ssize_t rmi_f19_sensitivity_adjust_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", data->button_control.
+               all_button_sensitivity_adj.sensitivity_adj);
+
+}
+
+static ssize_t rmi_f19_sensitivity_adjust_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       unsigned int old_value;
+       unsigned int new_value;
+       int len;
+       struct f19_0d_control_5 *all_button_sensitivity_adj;
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       all_button_sensitivity_adj =
+                        &data->button_control.all_button_sensitivity_adj;
+
+       if (data->button_query.configurable == 0) {
+               dev_err(dev,
+                       "%s: Error - sensitivity_adjust is not configuralbe at run-time", __func__);
+               return -EINVAL;
+       }
+
+       len = sscanf(buf, "%u", &new_value);
+       if (len < 1 || new_value < SENSITIVITY_ADJ_MIN ||
+               new_value > SENSITIVITY_ADJ_MAX)
+               return -EINVAL;
+       old_value = all_button_sensitivity_adj->sensitivity_adj;
+       all_button_sensitivity_adj->sensitivity_adj = new_value;
+       /* write back to the control register */
+       len = rmi_write_block(fc->rmi_dev, data->all_button_sensitivity_address,
+               (u8 *)all_button_sensitivity_adj,
+                       sizeof(struct f19_0d_control_5));
+       if (len < 0) {
+               all_button_sensitivity_adj->sensitivity_adj = old_value;
+               dev_err(dev, "%s : Could not sensitivity_adjust_store to 0x%x\n", __func__,
+                       data->all_button_sensitivity_address);
+               return len;
+       }
+
+       return len;
+}
+
+static ssize_t rmi_f19_hysteresis_threshold_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", data->button_control.
+               all_button_hysteresis_threshold.hysteresis_threshold);
+
+}
+static ssize_t rmi_f19_hysteresis_threshold_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       unsigned int new_value;
+       unsigned int old_value;
+       int len;
+       struct f19_0d_control_6 *all_button_hysteresis_threshold;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       all_button_hysteresis_threshold =
+               &data->button_control.all_button_hysteresis_threshold;
+       len = sscanf(buf, "%u", &new_value);
+       if (new_value < HYSTERESIS_THRESHOLD_MIN ||
+               new_value > HYSTERESIS_THRESHOLD_MAX) {
+               dev_err(dev, "%s: Error - hysteresis_threshold_store has an invalid value %d.\n",
+                       __func__, new_value);
+               return -EINVAL;
+       }
+       old_value = all_button_hysteresis_threshold->hysteresis_threshold;
+       all_button_hysteresis_threshold->hysteresis_threshold = new_value;
+       /* write back to the control register */
+       len = rmi_write_block(fc->rmi_dev, data->all_button_threshold_address,
+               (u8 *)all_button_hysteresis_threshold,
+                       sizeof(struct f19_0d_control_6));
+       if (len < 0) {
+               all_button_hysteresis_threshold->hysteresis_threshold =
+                                                               old_value;
+               dev_err(dev, "%s : Could not write all_button hysteresis threshold to 0x%x.\n", __func__,
+                       data->all_button_threshold_address);
+               return -EINVAL;
+       }
+       return count;
+}
+
+static ssize_t rmi_f19_has_hysteresis_threshold_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_query.has_hysteresis_threshold);
+}
+
+static ssize_t rmi_f19_has_sensitivity_adjust_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_query.has_sensitivity_adjust);
+}
+
+static ssize_t rmi_f19_configurable_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_query.configurable);
+}
+
+static ssize_t rmi_f19_rezero_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_rezero);
+
+}
+
+static ssize_t rmi_f19_rezero_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf,
+                                        size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       unsigned int new_value;
+       int len;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       len = sscanf(buf, "%u", &new_value);
+       if (new_value != 0 && new_value != 1) {
+               dev_err(dev, "%s: Error - rezero is not a valid value 0x%x.\n",
+                       __func__, new_value);
+               return -EINVAL;
+       }
+       data->button_rezero = new_value & 1;
+       len = rmi_write(fc->rmi_dev, fc->fd.command_base_addr,
+               data->button_rezero);
+
+       if (len < 0) {
+               dev_err(dev, "%s : Could not write rezero to 0x%x\n",
+                               __func__, fc->fd.command_base_addr);
+               return -EINVAL;
+       }
+       return count;
+}
+
+static ssize_t rmi_f19_button_count_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_count);
+}
+
+static ssize_t rmi_f19_button_map_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       int i, len, total_len = 0;
+       char *current_buf = buf;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       /* loop through each button map value and copy its
+        * string representation into buf */
+       for (i = 0; i < data->button_count; i++) {
+               /* get next button mapping value and write it to buf */
+               len = snprintf(current_buf, PAGE_SIZE - total_len,
+                       "%u ", data->button_map[i]);
+               /* bump up ptr to next location in buf if the
+                * snprintf was valid.  Otherwise issue an error
+                * and return. */
+               if (len > 0) {
+                       current_buf += len;
+                       total_len += len;
+               } else {
+                       dev_err(dev, "%s: Failed to build button map buffer, code = %d.\n", __func__, len);
+                       return snprintf(buf, PAGE_SIZE, "unknown\n");
+               }
+       }
+       len = snprintf(current_buf, PAGE_SIZE - total_len, "\n");
+       if (len > 0)
+               total_len += len;
+       else
+               dev_warn(dev, "%s: Failed to append carriage return.\n",
+                        __func__);
+       return total_len;
+}
+
+static ssize_t rmi_f19_button_map_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf,
+                               size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f19_data *data;
+       int i;
+       int retval = count;
+       int button_count = 0;
+       unsigned short *temp_button_map;
+       char *p = (char *) buf;
+       char *tail;
+
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       temp_button_map = kcalloc(data->button_count,
+                               sizeof(unsigned short), GFP_KERNEL);
+
+       if (!temp_button_map) {
+               dev_err(dev, "%s: Error - failed to allocate button map.\n", __func__);
+               return -ENOMEM;
+       }
+       /* 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. */
+       for (i = 0; i < data->button_count && *p != 0; i++) {
+               temp_button_map[i] = simple_strtoul(p, &tail, 10);
+               if (temp_button_map[i] == 0  && p[0] != '0') {
+                       dev_err(dev, "%s: Error - reading button map is invalid\n", __func__);
+                       retval = -EINVAL;
+                       goto err_ret;
+               }
+               if (temp_button_map[i] > INT_MAX) {
+                       dev_err(dev, "%s: Error - reading button map is out for range\n", __func__);
+                       retval = -ERANGE;
+                       goto err_ret;
+               }
+               p = tail;
+
+               /* Make sure the key is a valid key */
+               if (temp_button_map[i] > KEY_MAX) {
+                       dev_err(dev,
+                               "%s: Error - button map for button %d is not avalid value 0x%x.\n",
+                                __func__, i, temp_button_map[i]);
+                       retval = -EINVAL;
+                       goto err_ret;
+               }
+               button_count++;
+               while (p[0] == ' ')
+                       p++;
+       }
+
+       /* Make sure the button count matches */
+       if (button_count != data->button_count) {
+               dev_err(dev,
+                       "%s: Error - button map count of %d doesn't match device button count of %d.\n",
+                       __func__, button_count, data->button_count);
+               retval = -EINVAL;
+               goto err_ret;
+       }
+
+       /* Clear the key bits for the old button map. */
+       for (i = 0; i < button_count; i++)
+               clear_bit(data->button_map[i], data->input->keybit);
+
+       /* Loop through the key map and set the key bit for the new mapping. */
+       for (i = 0; i < button_count; i++) {
+               data->button_map[i] = temp_button_map[i];
+               set_bit(data->button_map[i], data->input->keybit);
+       }
+
+err_ret:
+       kfree(temp_button_map);
+       return retval;
+}
+
+module_init(rmi_f19_module_init);
+module_exit(rmi_f19_module_exit);
+
+MODULE_AUTHOR("Vivian Ly <vly@synaptics.com>");
+MODULE_DESCRIPTION("RMI F19 module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
diff --git a/drivers/input/touchscreen/rmi4/rmi_f1a.c b/drivers/input/touchscreen/rmi4/rmi_f1a.c
new file mode 100755 (executable)
index 0000000..7e93e2c
--- /dev/null
@@ -0,0 +1,1809 @@
+/*
+ * Copyright (c) 2012 Synaptics Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/rmi.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include "rmi_driver.h"
+#define QUERY_BASE_INDEX 1
+#define MAX_NAME_LEN 256
+#define MAX_BUFFER_LEN 80
+
+#define FILTER_MODE_MIN                                0
+#define FILTER_MODE_MAX                                3
+#define MULTI_BUTTON_REPORT_MIN                        0
+#define MULTI_BUTTON_REPORT_MAX                        3
+#define TX_RX_BUTTON_MIN                       0
+#define TX_RX_BUTTON_MAX                       255
+#define THREADHOLD_BUTTON_MIN                  0
+#define THREADHOLD_BUTTON_MAX                  255
+#define RELEASE_THREADHOLD_BUTTON_MIN          0
+#define RELEASE_THREADHOLD_BUTTON_MAX          255
+#define STRONGEST_BUTTON_HYSTERESIS_MIN                0
+#define STRONGEST_BUTTON_HYSTERESIS_MAX                255
+#define FILTER_STRENGTH_MIN                    0
+#define FILTER_STRENGTH_MAX                    255
+
+union f1a_0d_query {
+       struct {
+               u8 max_button_count:3;
+               u8 reserved:5;
+
+               u8 has_general_control:1;
+               u8 has_interrupt_enable:1;
+               u8 has_multibutton_select:1;
+               u8 has_tx_rx_map:1;
+               u8 has_perbutton_threshold:1;
+               u8 has_release_threshold:1;
+               u8 has_strongestbtn_hysteresis:1;
+               u8 has_filter_strength:1;
+       };
+       u8 regs[2];
+};
+
+union f1a_0d_control_0 {
+       struct {
+               u8 multibutton_report:2;
+               u8 filter_mode:2;
+       };
+       u8 regs[1];
+};
+
+struct f1a_0d_control_3_4 {
+       u8 transmitterbutton;
+       u8 receiverbutton;
+};
+
+struct f1a_0d_control {
+       union f1a_0d_control_0 general_control;
+       u8 *button_int_enable;
+       u8 *multi_button;
+       struct f1a_0d_control_3_4 *electrode_map;
+       u8 *button_threshold;
+       u8 button_release_threshold;
+       u8 strongest_button_hysteresis;
+       u8 filter_strength;
+};
+
+/* data specific to fn $1a that needs to be kept around */
+struct f1a_data {
+       struct f1a_0d_control button_control;
+       union f1a_0d_query button_query;
+       u8 button_count;
+       int button_bitmask_size;
+       u8 *button_data_buffer;
+       u8 *button_map;
+       char input_name[MAX_NAME_LEN];
+       char input_phys[MAX_NAME_LEN];
+       struct input_dev *input;
+       int general_control_address;
+       int button_int_enable_address;
+       int multi_button_address;
+       int electrode_map_address;
+       int button_threshold_address;
+       int button_release_threshold_address;
+       int strongest_button_hysteresis_address;
+       int filter_strength_address;
+};
+
+static ssize_t rmi_f1a_button_count_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf);
+static ssize_t rmi_f1a_button_map_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f1a_button_map_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+static ssize_t rmi_f1a_has_general_control_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f1a_has_interrupt_enable_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f1a_has_multibutton_select_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f1a_has_tx_rx_map_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f1a_has_perbutton_threshold_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f1a_has_release_threshold_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f1a_has_strongestbtn_hysteresis_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f1a_has_filter_strength_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f1a_multibutton_report_show(struct device *dev,
+                               struct device_attribute *attr, char *buf);
+static ssize_t rmi_f1a_multibutton_report_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count);
+static ssize_t rmi_f1a_filter_mode_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf);
+static ssize_t rmi_f1a_filter_mode_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count);
+static ssize_t rmi_f1a_button_int_enable_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf);
+static ssize_t rmi_f1a_button_int_enable_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count);
+static ssize_t rmi_f1a_multibutton_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf);
+static ssize_t rmi_f1a_multibutton_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count);
+static ssize_t rmi_f1a_electrode_map_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf);
+static ssize_t rmi_f1a_electrode_map_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count);
+static ssize_t rmi_f1a_threshold_button_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf);
+static ssize_t rmi_f1a_threshold_button_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count);
+static ssize_t rmi_f1a_button_release_threshold_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf);
+static ssize_t rmi_f1a_button_release_threshold_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count);
+static ssize_t rmi_f1a_strongest_button_hysteresis_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf);
+static ssize_t rmi_f1a_strongest_button_hysteresis_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count);
+static ssize_t rmi_f1a_filter_strength_show(struct device *dev,
+                                struct device_attribute *attr,
+                                char *buf);
+static ssize_t rmi_f1a_filter_strength_store(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count);
+
+static int rmi_f1a_alloc_memory(struct rmi_function_container *fc);
+
+static void rmi_f1a_free_memory(struct rmi_function_container *fc);
+
+static int rmi_f1a_initialize(struct rmi_function_container *fc);
+
+static int rmi_f1a_register_device(struct rmi_function_container *fc);
+
+static int rmi_f1a_create_sysfs(struct rmi_function_container *fc);
+
+static int rmi_f1a_config(struct rmi_function_container *fc);
+
+static int rmi_f1a_reset(struct rmi_function_container *fc);
+
+static struct device_attribute attrs[] = {
+       __ATTR(button_count, RMI_RO_ATTR,
+               rmi_f1a_button_count_show, rmi_store_error),
+       __ATTR(button_map, RMI_RW_ATTR,
+               rmi_f1a_button_map_show, rmi_f1a_button_map_store),
+       __ATTR(has_general_control, RMI_RO_ATTR,
+               rmi_f1a_has_general_control_show, rmi_store_error),
+       __ATTR(has_interrupt_enable, RMI_RO_ATTR,
+               rmi_f1a_has_interrupt_enable_show, rmi_store_error),
+       __ATTR(has_multibutton_select, RMI_RO_ATTR,
+               rmi_f1a_has_multibutton_select_show, rmi_store_error),
+       __ATTR(has_tx_rx_map, RMI_RO_ATTR,
+               rmi_f1a_has_tx_rx_map_show, rmi_store_error),
+       __ATTR(has_perbutton_threshold, RMI_RO_ATTR,
+               rmi_f1a_has_perbutton_threshold_show, rmi_store_error),
+       __ATTR(has_release_threshold, RMI_RO_ATTR,
+               rmi_f1a_has_release_threshold_show, rmi_store_error),
+       __ATTR(has_strongestbtn_hysteresis, RMI_RO_ATTR,
+               rmi_f1a_has_strongestbtn_hysteresis_show, rmi_store_error),
+       __ATTR(has_filter_strength, RMI_RO_ATTR,
+               rmi_f1a_has_filter_strength_show, rmi_store_error),
+       __ATTR(multibutton_report, RMI_RW_ATTR,
+               rmi_f1a_multibutton_report_show,
+               rmi_f1a_multibutton_report_store),
+       __ATTR(filter_mode, RMI_RW_ATTR,
+               rmi_f1a_filter_mode_show, rmi_f1a_filter_mode_store),
+       __ATTR(button_int_enable, RMI_RW_ATTR,
+               rmi_f1a_button_int_enable_show,
+               rmi_f1a_button_int_enable_store),
+       __ATTR(multibutton, RMI_RW_ATTR,
+               rmi_f1a_multibutton_show, rmi_f1a_multibutton_store),
+       __ATTR(electrode_map, RMI_RW_ATTR,
+               rmi_f1a_electrode_map_show,
+               rmi_f1a_electrode_map_store),
+       __ATTR(threshold_button, RMI_RW_ATTR,
+               rmi_f1a_threshold_button_show,
+               rmi_f1a_threshold_button_store),
+       __ATTR(button_release_threshold, RMI_RW_ATTR,
+               rmi_f1a_button_release_threshold_show,
+               rmi_f1a_button_release_threshold_store),
+       __ATTR(strongest_button_hysteresis, RMI_RW_ATTR,
+               rmi_f1a_strongest_button_hysteresis_show,
+               rmi_f1a_strongest_button_hysteresis_store),
+       __ATTR(filter_strength, RMI_RW_ATTR,
+               rmi_f1a_filter_strength_show,
+               rmi_f1a_filter_strength_store)
+};
+
+static int rmi_f1a_read_control_parameters(struct rmi_device *rmi_dev,
+       struct f1a_data *f1a)
+{
+       int error = 0;
+       struct f1a_0d_control *button_control = &f1a->button_control;
+       union f1a_0d_query *button_query = &f1a->button_query;
+       int ctrl_base_addr = f1a->general_control_address;
+       int button_bitmask_size = f1a->button_bitmask_size;
+
+       if (button_query->has_general_control) {
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                               (u8 *)&button_control->general_control,
+                               sizeof(union f1a_0d_control_0));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read f1a_0d_control_0, code: %d.\n", error);
+                       return error;
+               }
+               ctrl_base_addr = ctrl_base_addr +
+                               sizeof(union f1a_0d_control_0);
+       }
+
+       if (button_query->has_interrupt_enable &&
+               button_control->button_int_enable) {
+               f1a->button_int_enable_address = ctrl_base_addr;
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                       button_control->button_int_enable,
+                       button_bitmask_size);
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read f1a_0d_control_1, code: %d.\n", error);
+                       return error;
+               }
+               ctrl_base_addr = ctrl_base_addr + button_bitmask_size;
+       }
+
+       if (button_query->has_multibutton_select &&
+               button_control->multi_button) {
+               f1a->multi_button_address = ctrl_base_addr;
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                               button_control->multi_button,
+                               button_bitmask_size);
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read f1a_0d_control_2, code: %d.\n", error);
+                       return error;
+               }
+               ctrl_base_addr = ctrl_base_addr + button_bitmask_size;
+       }
+
+       if (button_query->has_tx_rx_map &&
+               button_control->electrode_map) {
+               f1a->electrode_map_address = ctrl_base_addr;
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                       (u8 *)(button_control->electrode_map),
+                       sizeof(struct f1a_0d_control_3_4)*f1a->button_count);
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                       "Failed to read f1a_0d_control_3_4, code: %d.\n", error);
+                       return error;
+               }
+               ctrl_base_addr = ctrl_base_addr +
+                       (sizeof(struct f1a_0d_control_3_4)*f1a->button_count);
+       }
+       if (button_query->has_perbutton_threshold &&
+               button_control->button_threshold) {
+               f1a->button_threshold_address = ctrl_base_addr;
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                       button_control->button_threshold,
+                       f1a->button_count);
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                       "Failed to read f1a_0d_control_5, code: %d.\n", error);
+                       return error;
+               }
+               ctrl_base_addr = ctrl_base_addr +
+                       (sizeof(u8)*f1a->button_count);
+       }
+
+       if (button_query->has_release_threshold) {
+               f1a->button_release_threshold_address = ctrl_base_addr;
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                               &button_control->button_release_threshold,
+                               sizeof(u8));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read f1a_0d_control_6, code: %d.\n", error);
+                       return error;
+               }
+               ctrl_base_addr = ctrl_base_addr + sizeof(u8);
+       }
+
+       if (button_query->has_strongestbtn_hysteresis) {
+               f1a->strongest_button_hysteresis_address = ctrl_base_addr;
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                               &button_control->
+                                       strongest_button_hysteresis,
+                               sizeof(u8));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read f1a_0d_control_7, code: %d.\n", error);
+                       return error;
+               }
+               ctrl_base_addr = ctrl_base_addr + sizeof(u8);
+       }
+
+       if (button_query->has_filter_strength) {
+               f1a->filter_strength_address = ctrl_base_addr;
+               error = rmi_read_block(rmi_dev, ctrl_base_addr,
+                               (u8 *)&button_control->filter_strength,
+                               sizeof(u8));
+               if (error < 0) {
+                       dev_err(&rmi_dev->dev,
+                               "Failed to read f1a_0d_control_8, code: %d.\n", error);
+                       return error;
+               }
+       }
+       return 0;
+}
+
+
+static int rmi_f1a_init(struct rmi_function_container *fc)
+{
+       int rc;
+
+       rc = rmi_f1a_alloc_memory(fc);
+       if (rc < 0)
+               goto err_free_data;
+
+       rc = rmi_f1a_initialize(fc);
+       if (rc < 0)
+               goto err_free_data;
+
+       rc = rmi_f1a_register_device(fc);
+       if (rc < 0)
+               goto err_free_data;
+
+       rc = rmi_f1a_create_sysfs(fc);
+       if (rc < 0)
+               goto err_free_data;
+
+       return 0;
+
+err_free_data:
+       rmi_f1a_free_memory(fc);
+
+       return rc;
+}
+
+
+static int rmi_f1a_alloc_memory(struct rmi_function_container *fc)
+{
+       struct f1a_data *f1a;
+       int rc;
+
+       f1a = kzalloc(sizeof(struct f1a_data), GFP_KERNEL);
+       if (!f1a) {
+               dev_err(&fc->dev, "Failed to allocate function data.\n");
+               return -ENOMEM;
+       }
+       fc->data = f1a;
+
+       rc = rmi_read_block(fc->rmi_dev, fc->fd.query_base_addr,
+                       (u8 *)&f1a->button_query,
+                       sizeof(union f1a_0d_query));
+       if (rc < 0) {
+               dev_err(&fc->dev, "Failed to read query register.\n");
+               return rc;
+       }
+
+       f1a->button_count = f1a->button_query.max_button_count+1;
+
+       f1a->button_bitmask_size = sizeof(u8)*(f1a->button_count + 7) / 8;
+       f1a->button_data_buffer = kcalloc(f1a->button_bitmask_size,
+                               sizeof(u8), GFP_KERNEL);
+       if (!f1a->button_data_buffer) {
+               dev_err(&fc->dev, "Failed to allocate button data buffer.\n");
+               return -ENOMEM;
+       }
+
+       f1a->button_map = kcalloc(f1a->button_count,
+                               sizeof(unsigned char), GFP_KERNEL);
+       if (!f1a->button_map) {
+               dev_err(&fc->dev, "Failed to allocate button map.\n");
+               return -ENOMEM;
+       }
+       if (f1a->button_query.has_interrupt_enable) {
+               f1a->button_control.button_int_enable =
+                               kzalloc(f1a->button_bitmask_size, GFP_KERNEL);
+               if (!f1a->button_control.button_int_enable) {
+                       dev_err(&fc->dev, "Failed to allocate interrupt button.\n");
+                       return -ENOMEM;
+               }
+       }
+       if (f1a->button_query.has_multibutton_select) {
+               f1a->button_control.multi_button =
+                       kzalloc(f1a->button_bitmask_size, GFP_KERNEL);
+               if (!f1a->button_control.multi_button) {
+                       dev_err(&fc->dev, "Failed to allocate multi button group select.\n");
+                       return -ENOMEM;
+               }
+       }
+       if (f1a->button_query.has_tx_rx_map) {
+               f1a->button_control.electrode_map =
+                       kzalloc(f1a->button_count *
+                               sizeof(struct f1a_0d_control_3_4), GFP_KERNEL);
+               if (!f1a->button_control.electrode_map) {
+                       dev_err(&fc->dev, "Failed to allocate f1a_0d_control_3_4.\n");
+                       return -ENOMEM;
+               }
+       }
+       if (f1a->button_query.has_perbutton_threshold) {
+               f1a->button_control.button_threshold =
+                       kzalloc(f1a->button_count, GFP_KERNEL);
+               if (!f1a->button_control.button_threshold) {
+                       dev_err(&fc->dev, "Failed to allocate button threshold.\n");
+                       return -ENOMEM;
+               }
+       }
+       return 0;
+}
+
+
+
+static void rmi_f1a_free_memory(struct rmi_function_container *fc)
+{
+       struct f1a_data *f1a = fc->data;
+
+       if (f1a) {
+               kfree(f1a->button_data_buffer);
+               kfree(f1a->button_map);
+               kfree(f1a->button_control.button_int_enable);
+               kfree(f1a->button_control.multi_button);
+               kfree(f1a->button_control.electrode_map);
+               kfree(f1a->button_control.button_threshold);
+               kfree(f1a);
+               fc->data = NULL;
+       }
+}
+
+
+static int rmi_f1a_initialize(struct rmi_function_container *fc)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct rmi_device_platform_data *pdata;
+       struct f1a_data *f1a = fc->data;
+       int i;
+       int rc;
+
+       dev_info(&fc->dev, "Intializing F1a values.");
+
+       /* initial all default values for f1a data here */
+       pdata = to_rmi_platform_data(rmi_dev);
+       if (pdata) {
+               if (!pdata->f1a_button_map)
+                       dev_warn(&fc->dev, "%s - button_map is NULL", __func__);
+               else if (pdata->f1a_button_map->nbuttons !=
+                               f1a->button_count)
+                       dev_warn(&fc->dev,
+                               "Platformdata button map size (%d) != number "
+                               "of buttons on device (%d) - ignored.\n",
+                               pdata->f1a_button_map->nbuttons,
+                               f1a->button_count);
+               else if (!pdata->f1a_button_map->map)
+                       dev_warn(&fc->dev,
+                                "Platformdata button map is missing!\n");
+               else
+                       for (i = 0; i < pdata->f1a_button_map->nbuttons; i++)
+                               f1a->button_map[i] =
+                                       pdata->f1a_button_map->map[i];
+       }
+
+       f1a->general_control_address = fc->fd.control_base_addr;
+       rc = rmi_f1a_read_control_parameters(rmi_dev, f1a);
+       if (rc < 0) {
+               dev_err(&fc->dev,
+                       "Failed to initialize F1a control params.\n");
+               return rc;
+       }
+
+       return 0;
+}
+
+
+
+static int rmi_f1a_register_device(struct rmi_function_container *fc)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct input_dev *input_dev;
+       struct f1a_data *f1a = fc->data;
+       int i;
+       int rc;
+
+       input_dev = input_allocate_device();
+       if (!input_dev) {
+               dev_err(&fc->dev, "Failed to allocate input device.\n");
+               return -ENOMEM;
+       }
+
+       f1a->input = input_dev;
+       snprintf(f1a->input_name, MAX_NAME_LEN, "%sfn%02x",
+                       dev_name(&rmi_dev->dev),
+                       fc->fd.function_number);
+       input_dev->name = f1a->input_name;
+       snprintf(f1a->input_phys, MAX_NAME_LEN, "%s/input0", input_dev->name);
+       input_dev->phys = f1a->input_phys;
+       input_dev->dev.parent = &rmi_dev->dev;
+       input_set_drvdata(input_dev, f1a);
+
+       /* Set up any input events. */
+       set_bit(EV_SYN, input_dev->evbit);
+       set_bit(EV_KEY, input_dev->evbit);
+       /* set bits for each button... */
+       for (i = 0; i < f1a->button_count; i++)
+               set_bit(f1a->button_map[i], input_dev->keybit);
+       rc = input_register_device(input_dev);
+       if (rc < 0) {
+               dev_err(&fc->dev, "Failed to register input device.\n");
+               goto error_free_device;
+       }
+
+       return 0;
+
+error_free_device:
+       input_free_device(input_dev);
+
+       return rc;
+}
+
+
+static int rmi_f1a_create_sysfs(struct rmi_function_container *fc)
+{
+       int attr_count = 0;
+       int rc;
+       struct f1a_data *data;
+       union f1a_0d_query *button_query;
+       char *name;
+       data = fc->data;
+       button_query = &data->button_query;
+
+       dev_dbg(&fc->dev, "Creating sysfs files.\n");
+       /* Set up sysfs device attributes. */
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               name = (char *) attrs[attr_count].attr.name;
+               if (!button_query->has_general_control &&
+                       (!strcmp(name, "multibutton_report") ||
+                       !strcmp(name, "filter_mode")))
+                       continue;
+               if (!button_query->has_interrupt_enable &&
+                       !strcmp(name, "button_int_enable"))
+                       continue;
+               if (!button_query->has_multibutton_select &&
+                       !strcmp(name, "multibutton"))
+                       continue;
+               if (!button_query->has_tx_rx_map &&
+                       !strcmp(name, "electrode_map"))
+                       continue;
+               if (!button_query->has_perbutton_threshold &&
+                       !strcmp(name, "threshold_button"))
+                       continue;
+               if (!button_query->has_release_threshold &&
+                       !strcmp(name, "button_release_threshold"))
+                       continue;
+               if (!button_query->has_strongestbtn_hysteresis &&
+                       !strcmp(name, "strongest_button_hysteresis"))
+                       continue;
+               if (!button_query->has_filter_strength &&
+                       !strcmp(name, "filter_strength"))
+                       continue;
+               if (sysfs_create_file
+                   (&fc->dev.kobj, &attrs[attr_count].attr) < 0) {
+                       dev_err(&fc->dev,
+                               "Failed to create sysfs file for %s.",
+                               attrs[attr_count].attr.name);
+                       rc = -ENODEV;
+                       goto err_remove_sysfs;
+               }
+       }
+
+       return 0;
+
+err_remove_sysfs:
+       for (attr_count--; attr_count >= 0; attr_count--)
+               sysfs_remove_file(&fc->dev.kobj,
+                                                 &attrs[attr_count].attr);
+       return rc;
+
+}
+
+
+
+static int rmi_f1a_config(struct rmi_function_container *fc)
+{
+       struct f1a_data *data;
+       int retval;
+       union f1a_0d_query *button_query;
+
+       data = fc->data;
+       button_query = &data->button_query;
+       if (button_query->has_general_control) {
+               retval = rmi_write_block(fc->rmi_dev,
+                               data->general_control_address,
+                               (u8 *)&data->button_control.general_control,
+                               sizeof(union f1a_0d_control_0));
+               if (retval < 0) {
+                       dev_err(&fc->dev, "%s : Could not write general_control to 0x%x\n",
+                                       __func__, fc->fd.control_base_addr);
+                       return retval;
+               }
+       }
+       if (button_query->has_interrupt_enable) {
+               retval = rmi_write_block(fc->rmi_dev,
+                               data->button_int_enable_address,
+                               data->button_control.button_int_enable,
+                               data->button_bitmask_size);
+               if (retval < 0) {
+                       dev_err(&fc->dev, "%s : Could not write interrupt_enable_store to 0x%x\n",
+                               __func__, data->button_int_enable_address);
+                       return retval;
+               }
+       }
+       if (button_query->has_multibutton_select) {
+               retval = rmi_write_block(fc->rmi_dev,
+                               data->multi_button_address,
+                               data->button_control.multi_button,
+                               data->button_bitmask_size);
+               if (retval < 0) {
+                       dev_err(&fc->dev, "%s : Could not write multi_button_store to 0x%x\n",
+                               __func__, data->multi_button_address);
+                       return -EINVAL;
+               }
+       }
+       if (button_query->has_tx_rx_map) {
+               retval = rmi_write_block(fc->rmi_dev,
+                               data->electrode_map_address,
+                               (u8 *)data->button_control.electrode_map,
+                               sizeof(struct f1a_0d_control_3_4)*
+                               data->button_count);
+               if (retval < 0) {
+                       dev_err(&fc->dev, "%s : Could not electrode_map_store to 0x%x\n",
+                                       __func__, data->electrode_map_address);
+                       return -EINVAL;
+               }
+       }
+       if (button_query->has_perbutton_threshold) {
+               retval = rmi_write_block(fc->rmi_dev,
+                               data->button_threshold_address,
+                               data->button_control.button_threshold,
+                               data->button_count);
+               if (retval < 0) {
+                       dev_err(&fc->dev, "%s : Could not button_threshold_store to 0x%x\n",
+                               __func__, data->button_threshold_address);
+                       return retval;
+               }
+       }
+       if (button_query->has_release_threshold) {
+               retval = rmi_write_block(fc->rmi_dev,
+                       data->button_release_threshold_address,
+                       &data->button_control.button_release_threshold,
+                       sizeof(u8));
+               if (retval < 0) {
+                       dev_err(&fc->dev, "%s : Could not write  button_release_threshold store to 0x%x\n",
+                               __func__,
+                               data->button_release_threshold_address);
+                       return -EINVAL;
+               }
+       }
+       if (button_query->has_strongestbtn_hysteresis) {
+               retval = rmi_write_block(fc->rmi_dev,
+                       data->strongest_button_hysteresis_address,
+                       &data->button_control.strongest_button_hysteresis,
+                       sizeof(u8));
+               if (retval < 0) {
+                       dev_err(&fc->dev, "%s : Could not write strongest_button_hysteresis store"
+                               " to 0x%x\n",
+                               __func__,
+                               data->strongest_button_hysteresis_address);
+                       return -EINVAL;
+               }
+       }
+       if (button_query->has_filter_strength) {
+               retval = rmi_write_block(fc->rmi_dev,
+                               data->filter_strength_address,
+                               &data->button_control.filter_strength,
+                               sizeof(u8));
+               if (retval < 0) {
+                       dev_err(&fc->dev, "%s : Could not write filter_strength store to 0x%x\n", __func__,
+                               data->filter_strength_address);
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
+
+static int rmi_f1a_reset(struct rmi_function_container *fc)
+{
+       /* we do nnothing here */
+       return 0;
+}
+
+
+static void rmi_f1a_remove(struct rmi_function_container *fc)
+{
+       struct f1a_data *f1a = fc->data;
+       int attr_count = 0;
+
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++)
+               sysfs_remove_file(&fc->dev.kobj,
+                                 &attrs[attr_count].attr);
+
+       input_unregister_device(f1a->input);
+
+       rmi_f1a_free_memory(fc);
+}
+
+int rmi_f1a_attention(struct rmi_function_container *fc, u8 *irq_bits)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct f1a_data *f1a = fc->data;
+       u16 data_base_addr = fc->fd.data_base_addr;
+       int error;
+       int button;
+       //char buf[256];
+       /* Read the button data. */
+       error = rmi_read_block(rmi_dev, data_base_addr, f1a->button_data_buffer,
+                       f1a->button_bitmask_size);
+       if (error < 0) {
+               dev_err(&fc->dev, "%s: Failed to read button data registers.\n",
+                       __func__);
+               return error;
+       }
+       //printk("++++++++++++button_data_buffer:%x\n", f1a->button_data_buffer[0]);
+       /* Generate events for buttons that change state. */
+       for (button = 0; button < f1a->button_count; button++) {
+               int button_reg;
+               int button_shift;
+               bool button_status;
+
+               /* determine which data byte the button status is in */
+               button_reg = button / 8;
+               /* bit shift to get button's status */
+               button_shift = button % 8;
+               button_status =
+                   ((f1a->button_data_buffer[button_reg] >> button_shift)
+                       & 0x01) != 0;
+
+               dev_dbg(&fc->dev, "%s: Button %d (code %d) -> %d.\n",
+                       __func__, button, f1a->button_map[button],
+                               button_status);
+               /* Generate an event here. */
+               input_report_key(f1a->input, f1a->button_map[button],
+                                       button_status);
+       }
+
+       input_sync(f1a->input); /* sync after groups of events */
+       return 0;
+}
+
+static struct rmi_function_handler function_handler = {
+       .func = 0x1a,
+       .init = rmi_f1a_init,
+       .config = rmi_f1a_config,
+       .reset = rmi_f1a_reset,
+       .attention = rmi_f1a_attention,
+       .remove = rmi_f1a_remove
+};
+
+static int __init rmi_f1a_module_init(void)
+{
+       int error;
+
+       error = rmi_register_function_driver(&function_handler);
+       if (error < 0) {
+               pr_err("%s: register failed!\n", __func__);
+               return error;
+       }
+
+       return 0;
+}
+
+static void rmi_f1a_module_exit(void)
+{
+       rmi_unregister_function_driver(&function_handler);
+}
+
+static ssize_t rmi_f1a_filter_mode_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_control.general_control.filter_mode);
+
+}
+
+static ssize_t rmi_f1a_filter_mode_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       unsigned int new_value;
+       unsigned int old_value;
+       int result;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       if (sscanf(buf, "%u", &new_value) < 1) {
+               dev_err(dev, "%s: Error - filter_mode_store has an invalid len.\n", __func__);
+               return -EINVAL;
+       }
+
+       if (new_value < FILTER_MODE_MIN || new_value > FILTER_MODE_MAX) {
+               dev_err(dev, "%s: Error - filter_mode_store has an "
+               "invalid value %d.\n",
+               __func__, new_value);
+               return -EINVAL;
+       }
+       old_value = data->button_control.general_control.filter_mode;
+       data->button_control.general_control.filter_mode = new_value;
+       result = rmi_write_block(fc->rmi_dev, data->general_control_address,
+               (u8 *)&(data->button_control.general_control),
+                       sizeof(union f1a_0d_control_0));
+       if (result < 0) {
+               data->button_control.general_control.filter_mode = old_value;
+               dev_err(dev, "%s : Could not write filter_mode_store to 0x%x\n",
+                               __func__, fc->fd.control_base_addr);
+               return result;
+       }
+
+       return count;
+}
+
+static ssize_t rmi_f1a_multibutton_report_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+               data->button_control.general_control.multibutton_report);
+
+}
+
+static ssize_t rmi_f1a_multibutton_report_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       unsigned int new_value;
+       unsigned int old_value;
+       int result;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       if (sscanf(buf, "%u", &new_value) < 1) {
+               dev_err(dev,
+               "%s: Error - multibutton_report_store has an "
+               "invalid len.\n",
+               __func__);
+               return -EINVAL;
+       }
+
+       if (new_value < MULTI_BUTTON_REPORT_MIN ||
+               new_value > MULTI_BUTTON_REPORT_MAX) {
+               dev_err(dev, "%s: Error - multibutton_report_store has an "
+               "invalid value %d.\n",
+               __func__, new_value);
+               return -EINVAL;
+       }
+       old_value = data->button_control.general_control.multibutton_report;
+       data->button_control.general_control.multibutton_report = new_value;
+       result = rmi_write_block(fc->rmi_dev, data->general_control_address,
+               (u8 *)&(data->button_control.general_control),
+                       sizeof(union f1a_0d_control_0));
+       if (result < 0) {
+               data->button_control.general_control.multibutton_report =
+                               old_value;
+               dev_err(dev, "%s : Could not write multibutton_report_store to 0x%x\n",
+                               __func__, fc->fd.control_base_addr);
+               return result;
+       }
+
+       return count;
+
+}
+
+static ssize_t rmi_f1a_button_int_enable_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       int i, len, total_len = 0;
+       char *current_buf = buf;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       /* loop through each button map value and copy its
+        * string representation into buf */
+       for (i = 0; i < data->button_count; i++) {
+               int button_reg;
+               int button_shift;
+               int interrupt_button;
+
+               button_reg = i / 8;
+               button_shift = i % 8;
+               interrupt_button =
+                   ((data->button_control.button_int_enable[button_reg] >>
+                               button_shift) & 0x01);
+
+               /* get next button mapping value and write it to buf */
+               len = snprintf(current_buf, PAGE_SIZE - total_len,
+                       "%u ", interrupt_button);
+               /* bump up ptr to next location in buf if the
+                * snprintf was valid.  Otherwise issue an error
+                * and return. */
+               if (len > 0) {
+                       current_buf += len;
+                       total_len += len;
+               } else {
+                       dev_err(dev, "%s: Failed to build interrupt button"
+                               " buffer, code = %d.\n", __func__, len);
+                       return snprintf(buf, PAGE_SIZE, "unknown\n");
+               }
+       }
+       len = snprintf(current_buf, PAGE_SIZE - total_len, "\n");
+       if (len > 0)
+               total_len += len;
+       else
+               dev_warn(dev, "%s: Failed to append carriage return.\n",
+                        __func__);
+       return total_len;
+
+}
+
+static ssize_t rmi_f1a_button_int_enable_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       int i;
+       int button_count = 0;
+       int retval = count;
+       int button_reg = 0;
+       u8 *new_value;
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       new_value = kzalloc(data->button_bitmask_size, GFP_KERNEL);
+       if (!new_value) {
+               dev_err(dev, "%s: Error - failed to allocate button interrupt enable.\n", __func__);
+               return -ENOMEM;
+       }
+       for (i = 0; i < data->button_count && *buf != 0;
+            i++, buf += 2) {
+               int button_shift;
+               int button;
+               int result;
+
+               button_reg = i / 8;
+               button_shift = i % 8;
+               /* get next button mapping value and store and bump up to
+                * point to next item in buf */
+               result = sscanf(buf, "%u", &button);
+
+               if ((result != 1) || (button != 0 && button != 1)) {
+                       dev_err(dev,
+                               "%s: Error - interrupt enable button for"
+                               "button %d is not a valid value 0x%x.\n",
+                               __func__, i, button);
+                       kfree(new_value);
+                       return -EINVAL;
+               }
+               if (button)
+                       new_value[button_reg] |= (1 << button_shift);
+
+               button_count++;
+       }
+
+       /* Make sure the button count matches */
+       if (button_count != data->button_count) {
+               dev_err(dev,
+                       "%s: Error - interrupt enable button count of %d"
+                       " doesn't match device button count of %d.\n",
+                        __func__, button_count, data->button_count);
+               kfree(new_value);
+               return -EINVAL;
+       }
+       /* write back to the control register */
+       retval = rmi_write_block(fc->rmi_dev,
+                       data->button_int_enable_address,
+                       new_value, data->button_bitmask_size);
+       if (retval < 0) {
+               dev_err(dev, "%s : Could not write interrupt_enable_store to 0x%x\n",
+                       __func__, data->button_int_enable_address);
+               return retval;
+       }
+       memcpy(data->button_control.button_int_enable,
+               new_value, data->button_bitmask_size);
+
+       kfree(new_value);
+       return count;
+}
+
+static ssize_t rmi_f1a_multibutton_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       int i, len, total_len = 0;
+       char *current_buf = buf;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       /* loop through each button map value and copy its
+        * string representation into buf */
+       for (i = 0; i < data->button_count; i++) {
+               int button_reg;
+               int button_shift;
+               int multibutton;
+
+               button_reg = i / 8;
+               button_shift = i % 8;
+               multibutton = ((data->button_control.
+                       multi_button[button_reg] >> button_shift) & 0x01);
+
+               /* get next button mapping value and write it to buf */
+               len = snprintf(current_buf, PAGE_SIZE - total_len,
+                       "%u ", multibutton);
+               /* bump up ptr to next location in buf if the
+                * snprintf was valid.  Otherwise issue an error
+                * and return. */
+               if (len > 0) {
+                       current_buf += len;
+                       total_len += len;
+               } else {
+                       dev_err(dev, "%s: Failed to build multibutton buffer"
+                               ", code = %d.\n", __func__, len);
+                       return snprintf(buf, PAGE_SIZE, "unknown\n");
+               }
+       }
+       len = snprintf(current_buf, PAGE_SIZE - total_len, "\n");
+       if (len > 0)
+               total_len += len;
+       else
+               dev_warn(dev, "%s: Failed to append carriage return.\n",
+                        __func__);
+
+       return total_len;
+
+}
+
+static ssize_t rmi_f1a_multibutton_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       int i;
+       int button_count = 0;
+       int retval = count;
+       int button_reg = 0;
+       u8 *new_value;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       new_value = kzalloc(data->button_bitmask_size, GFP_KERNEL);
+       if (!new_value) {
+               dev_err(dev, "%s: Error - failed to allocate multi button.\n", __func__);
+               return -ENOMEM;
+       }
+       for (i = 0; i < data->button_count && *buf != 0;
+            i++, buf += 2) {
+               int button_shift;
+               int button;
+               int result;
+
+               button_reg = i / 8;
+               button_shift = i % 8;
+               /* get next button mapping value and store and bump up to
+                * point to next item in buf */
+               result = sscanf(buf, "%u", &button);
+
+               if ((result < 1) || (button < 0 || button > 1)) {
+                       dev_err(dev,
+                               "%s: Error - multibutton for button %d"
+                               " is not a valid value 0x%x.\n",
+                               __func__, i, button);
+                       kfree(new_value);
+                       return -EINVAL;
+               }
+
+               if (button)
+                       new_value[button_reg] |= (1 << button_shift);
+
+               button_count++;
+       }
+
+       /* Make sure the button count matches */
+       if (button_count != data->button_count) {
+               dev_err(dev,
+                   "%s: Error - multibutton count of %d doesn't match"
+                    " device button count of %d.\n", __func__, button_count,
+                    data->button_count);
+               kfree(new_value);
+               return -EINVAL;
+       }
+       /* write back to the control register */
+       retval = rmi_write_block(fc->rmi_dev, data->multi_button_address,
+                       new_value,
+                       data->button_bitmask_size);
+       if (retval < 0) {
+               dev_err(dev, "%s : Could not write multibutton_store to"
+                       " 0x%x\n", __func__, data->multi_button_address);
+               kfree(new_value);
+               return -EINVAL;
+       }
+       memcpy(data->button_control.multi_button, new_value,
+               data->button_bitmask_size);
+       kfree(new_value);
+       return count;
+}
+
+static ssize_t rmi_f1a_electrode_map_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       int i, len, total_len = 0;
+       char *current_buf = buf;
+       struct f1a_0d_control *button_control;
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       button_control = &data->button_control;
+       for (i = 0; i < data->button_count; i++) {
+               len = snprintf(current_buf, PAGE_SIZE - total_len, "%u:%u ",
+                       button_control->electrode_map[i].transmitterbutton,
+                       button_control->electrode_map[i].receiverbutton);
+               /* bump up ptr to next location in buf if the
+                * snprintf was valid.  Otherwise issue an error
+                * and return. */
+               if (len > 0) {
+                       current_buf += len;
+                       total_len += len;
+               } else {
+                       dev_err(dev, "%s: Failed to build electrode map buffer, code = %d.\n",
+                               __func__, len);
+                       return snprintf(buf, PAGE_SIZE, "unknown\n");
+               }
+       }
+       len = snprintf(current_buf, PAGE_SIZE - total_len, "\n");
+       if (len > 0)
+               total_len += len;
+       else
+               dev_warn(dev, "%s: Failed to append carriage return.\n",
+                        __func__);
+       return total_len;
+
+
+}
+
+static ssize_t rmi_f1a_electrode_map_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       char colon;
+       int i;
+       int result;
+       int retval = count;
+       int button_count = 0;
+       char tx_rx[MAX_BUFFER_LEN];
+       struct f1a_0d_control_3_4  *new_value;
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       new_value = kzalloc(data->button_count *
+                       sizeof(struct f1a_0d_control_3_4), GFP_KERNEL);
+       if (!new_value) {
+               dev_err(dev, "%s: Error - failed to allocate eletrode map.\n", __func__);
+               return -ENOMEM;
+       }
+       for (i = 0; i < data->button_count && *buf != 0; i++) {
+               /* get next button mapping value and store and bump up to
+                * point to next item in buf */
+               result = sscanf(buf, "%s ", tx_rx);
+               if (result < 1) {
+                       dev_err(dev, "%s: Error - scanf threshold button\n", __func__);
+                       kfree(new_value);
+                       return -EINVAL;
+               }
+               result = sscanf(tx_rx, "%u%c%u",
+                       (unsigned int *)&new_value[i].transmitterbutton,
+                       &colon,
+                       (unsigned int *)&new_value[i].receiverbutton);
+               buf += strlen(tx_rx)+1;
+               /* Make sure the key is a valid key */
+               if ((result < 3) || (colon != ':') ||
+                       (new_value[i].transmitterbutton < TX_RX_BUTTON_MIN ||
+                       new_value[i].transmitterbutton > TX_RX_BUTTON_MAX) ||
+                       (new_value[i].receiverbutton < TX_RX_BUTTON_MIN ||
+                       new_value[i].receiverbutton > TX_RX_BUTTON_MAX)) {
+                       dev_err(dev, "%s: Error - electrode map for button %d "
+                               "is not a valid value 0x%x:0x%x.\n",
+                               __func__, i, new_value[i].transmitterbutton,
+                               new_value[i].receiverbutton);
+                       kfree(new_value);
+                       return -EINVAL;
+               }
+               button_count++;
+       }
+
+       if (button_count != data->button_count) {
+               dev_err(dev,
+                   "%s: Error - button map count of %d doesn't match device "
+                    "button count of %d.\n", __func__, button_count,
+                    data->button_count);
+               kfree(new_value);
+               return -EINVAL;
+       }
+       /* write back to the control register */
+       retval = rmi_write_block(fc->rmi_dev, data->electrode_map_address,
+                       (u8 *)new_value,
+                       sizeof(struct f1a_0d_control_3_4)*button_count);
+       if (retval < 0) {
+               dev_err(dev, "%s : Could not transmitter_btn_store to 0x%x\n",
+                               __func__,  data->electrode_map_address);
+               return -EINVAL;
+               kfree(new_value);
+       }
+       for (i = 0; i < data->button_count; i++) {
+               data->button_control.electrode_map[i].transmitterbutton =
+                       new_value[i].transmitterbutton;
+               data->button_control.electrode_map[i].receiverbutton =
+                       new_value[i].receiverbutton;
+       }
+       kfree(new_value);
+       return count;
+}
+
+static ssize_t rmi_f1a_threshold_button_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       int i, len, total_len = 0;
+       char *current_buf = buf;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       for (i = 0; i < data->button_count; i++) {
+               len = snprintf(current_buf, PAGE_SIZE - total_len, "%u ",
+                       data->button_control.button_threshold[i]);
+               /* bump up ptr to next location in buf if the
+                * snprintf was valid.  Otherwise issue an error
+                * and return. */
+               if (len > 0) {
+                       current_buf += len;
+                       total_len += len;
+               } else {
+                       dev_err(dev, "%s: Failed to build threshold_button, "
+                               "code = %d.\n", __func__, len);
+                       return snprintf(buf, PAGE_SIZE, "unknown\n");
+               }
+       }
+       len = snprintf(current_buf, PAGE_SIZE - total_len, "\n");
+       if (len > 0)
+               total_len += len;
+       else
+               dev_warn(dev, "%s: Failed to append carriage return.\n",
+                        __func__);
+       return total_len;
+
+
+}
+
+static ssize_t rmi_f1a_threshold_button_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       int i;
+       int result;
+       int retval = count;
+       int button_count = 0;
+       char threshold_button[MAX_BUFFER_LEN];
+       u8 *new_value;
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       new_value = kzalloc(data->button_count, GFP_KERNEL);
+       if (!new_value) {
+               dev_err(dev, "%s: Error - failed to allocate threshold button.\n", __func__);
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < data->button_count && *buf != 0; i++) {
+               /* get next button mapping value and store and bump up to
+                * point to next item in buf */
+               result = sscanf(buf, "%s ", threshold_button);
+               if (result < 1) {
+                       dev_err(dev, "%s: Error - scanf threshold button\n", __func__);
+                       kfree(new_value);
+                       return -EINVAL;
+               }
+               result = sscanf(threshold_button, "%u",
+                               (unsigned int *)&new_value[i]);
+               buf += strlen(threshold_button)+1;
+               /* Make sure the key is a valid key */
+               if ((result < 1) ||
+                       (new_value[i] < THREADHOLD_BUTTON_MIN ||
+                       new_value[i] > THREADHOLD_BUTTON_MAX)) {
+                       dev_err(dev,
+                               "%s: Error - threshold_button for button %d "
+                               "is not a valid value 0x%x.\n",
+                               __func__, i, new_value[i]);
+                       kfree(new_value);
+                       return -EINVAL;
+               }
+               button_count++;
+       }
+
+       if (button_count != data->button_count) {
+               dev_err(dev,
+                   "%s: Error - button map count of %d doesn't match device "
+                    "button count of %d.\n", __func__, button_count,
+                    data->button_count);
+               kfree(new_value);
+               return -EINVAL;
+       }
+
+       /* write back to the control register */
+       retval = rmi_write_block(fc->rmi_dev, data->button_threshold_address,
+               new_value, data->button_count);
+       if (retval < 0) {
+               dev_err(dev, "%s : Could not threshold_button_store to 0x%x\n",
+                               __func__,  data->button_threshold_address);
+               kfree(new_value);
+               return -EINVAL;
+       }
+       memcpy(data->button_control.button_threshold, new_value,
+               data->button_count);
+       kfree(new_value);
+       return count;
+}
+
+
+static ssize_t rmi_f1a_button_release_threshold_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", data->button_control.
+               button_release_threshold);
+
+}
+static ssize_t rmi_f1a_button_release_threshold_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       u8 new_value;
+       u8 old_value;
+       int len;
+
+       fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       len = sscanf(buf, "%u", (unsigned int *)&new_value);
+       if ((len < 1) ||
+               (new_value < RELEASE_THREADHOLD_BUTTON_MIN ||
+               new_value > RELEASE_THREADHOLD_BUTTON_MAX)) {
+               dev_err(dev,
+                       "%s: Error - release threshold_button "
+                       "is not a valid value 0x%x.\n",
+                       __func__, new_value);
+               return -EINVAL;
+       }
+       old_value = data->button_control.button_release_threshold;
+       data->button_control.button_release_threshold = new_value;
+       /* write back to the control register */
+       len = rmi_write_block(fc->rmi_dev,
+               data->button_release_threshold_address,
+               (u8 *)&(data->button_control.button_release_threshold),
+                       sizeof(u8));
+       if (len < 0) {
+               data->button_control.button_release_threshold = old_value;
+               dev_err(dev, "%s : Could not button_release_threshold_store to"
+                       " 0x%x\n", __func__,
+                       data->button_release_threshold_address);
+               return len;
+       }
+
+       return count;
+}
+
+static ssize_t rmi_f1a_strongest_button_hysteresis_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", data->button_control.
+               strongest_button_hysteresis);
+
+}
+static ssize_t rmi_f1a_strongest_button_hysteresis_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       u8 new_value;
+       u8 old_value;
+       int len;
+
+       fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       len = sscanf(buf, "%u", (unsigned int *)&new_value);
+       if ((len < 1) ||
+               (new_value < STRONGEST_BUTTON_HYSTERESIS_MIN ||
+               new_value > STRONGEST_BUTTON_HYSTERESIS_MAX)) {
+               dev_err(dev,
+                       "%s: Error - strongest button hysteresis is not a valid value 0x%x.\n",
+                       __func__, new_value);
+               return -EINVAL;
+       }
+       old_value = data->button_control.strongest_button_hysteresis;
+       data->button_control.strongest_button_hysteresis = new_value;
+       /* write back to the control register */
+       len = rmi_write_block(fc->rmi_dev,
+               data->strongest_button_hysteresis_address,
+               (u8 *)&(data->button_control.strongest_button_hysteresis),
+                       sizeof(u8));
+       if (len < 0) {
+               data->button_control.strongest_button_hysteresis = old_value;
+               dev_err(dev, "%s : Could not strongest_button_hysteresis_store"
+                       " to 0x%x\n", __func__,
+                       data->strongest_button_hysteresis_address);
+               return len;
+       }
+
+       return count;
+}
+
+static ssize_t rmi_f1a_filter_strength_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", data->button_control.
+               filter_strength);
+
+}
+
+static ssize_t rmi_f1a_filter_strength_store(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       int new_value;
+       int old_value;
+       int len;
+
+       fc = to_rmi_function_container(dev);
+
+       data = fc->data;
+
+       len = sscanf(buf, "%u", &new_value);
+       if ((len < 1) ||
+               (new_value < FILTER_STRENGTH_MIN ||
+               new_value > FILTER_STRENGTH_MAX)) {
+               dev_err(dev,
+                       "%s: Error - filter strength button is not a valid value 0x%x.\n",
+                       __func__, new_value);
+               return -EINVAL;
+       }
+       old_value = data->button_control.filter_strength;
+       data->button_control.filter_strength = new_value;
+       /* write back to the control register */
+       len = rmi_write_block(fc->rmi_dev,
+               data->filter_strength_address,
+               (u8 *)&(data->button_control.filter_strength),
+                       sizeof(u8));
+       if (len < 0) {
+               data->button_control.filter_strength = old_value;
+               dev_err(dev, "%s : Could not filter_strength_store to 0x%x\n", __func__,
+                       data->filter_strength_address);
+               return len;
+       }
+
+       return count;
+}
+
+
+static ssize_t rmi_f1a_button_count_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_query.max_button_count);
+}
+
+static ssize_t rmi_f1a_has_general_control_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_query.has_general_control);
+}
+
+static ssize_t rmi_f1a_has_interrupt_enable_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_query.has_interrupt_enable);
+}
+
+static ssize_t rmi_f1a_has_multibutton_select_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_query.has_multibutton_select);
+}
+
+static ssize_t rmi_f1a_has_tx_rx_map_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_query.has_tx_rx_map);
+}
+
+static ssize_t rmi_f1a_has_perbutton_threshold_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_query.has_perbutton_threshold);
+}
+
+static ssize_t rmi_f1a_has_release_threshold_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_query.has_release_threshold);
+}
+
+static ssize_t rmi_f1a_has_strongestbtn_hysteresis_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_query.has_strongestbtn_hysteresis);
+}
+
+static ssize_t rmi_f1a_has_filter_strength_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       data->button_query.has_filter_strength);
+}
+
+static ssize_t rmi_f1a_button_map_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       int i, len, total_len = 0;
+       char *current_buf = buf;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       /* loop through each button map value and copy its
+        * string representation into buf */
+       for (i = 0; i < data->button_count; i++) {
+               /* get next button mapping value and write it to buf */
+               len = snprintf(current_buf, PAGE_SIZE - total_len,
+                       "%u ", data->button_map[i]);
+               /* bump up ptr to next location in buf if the
+                * snprintf was valid.  Otherwise issue an error
+                * and return. */
+               if (len > 0) {
+                       current_buf += len;
+                       total_len += len;
+               } else {
+                       dev_err(dev, "%s: Failed to build button map buffer, "
+                               "code = %d.\n", __func__, len);
+                       return snprintf(buf, PAGE_SIZE, "unknown\n");
+               }
+       }
+       len = snprintf(current_buf, PAGE_SIZE - total_len, "\n");
+       if (len > 0)
+               total_len += len;
+       else
+               dev_warn(dev, "%s: Failed to append carriage return.\n",
+                        __func__);
+       return total_len;
+}
+
+static ssize_t rmi_f1a_button_map_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf,
+                               size_t count)
+{
+       struct rmi_function_container *fc;
+       struct f1a_data *data;
+       unsigned int button;
+       int i;
+       int retval = count;
+       int button_count = 0;
+       unsigned char temp_button_map[KEY_MAX];
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       /* 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. */
+       for (i = 0; i < data->button_count && *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) {
+                       dev_err(dev,
+                               "%s: Error - button map for button %d is not a"
+                               " valid value 0x%x.\n", __func__, i, button);
+                       retval = -EINVAL;
+                       goto err_ret;
+               }
+
+               temp_button_map[i] = button;
+               button_count++;
+
+               /* 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 (button_count != data->button_count) {
+               dev_err(dev,
+                   "%s: Error - button map count of %d doesn't match device "
+                    "button count of %d.\n", __func__, button_count,
+                    data->button_count);
+               retval = -EINVAL;
+               goto err_ret;
+       }
+
+       /* Clear the key bits for the old button map. */
+       for (i = 0; i < button_count; i++)
+               clear_bit(data->button_map[i], data->input->keybit);
+
+       /* Switch to the new map. */
+       memcpy(data->button_map, temp_button_map,
+              data->button_count);
+
+       /* Loop through the key map and set the key bit for the new mapping. */
+       for (i = 0; i < button_count; i++)
+               set_bit(data->button_map[i], data->input->keybit);
+
+err_ret:
+       return retval;
+}
+
+module_init(rmi_f1a_module_init);
+module_exit(rmi_f1a_module_exit);
+
+MODULE_AUTHOR("Vivian Ly <vly@synaptics.com>");
+MODULE_DESCRIPTION("RMI F1a module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
diff --git a/drivers/input/touchscreen/rmi4/rmi_f21.c b/drivers/input/touchscreen/rmi4/rmi_f21.c
new file mode 100755 (executable)
index 0000000..a8a163b
--- /dev/null
@@ -0,0 +1,751 @@
+
+/*
+ * Copyright (c) 2012 Synaptics Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#define FUNCTION_DATA rmi_fn_21_data
+#define FNUM 21
+
+#include <linux/kernel.h>
+#include <linux/rmi.h>
+#include <linux/slab.h>
+#include "rmi_driver.h"
+
+union f21_2df_query {
+       struct {
+               /* Query 0 */
+               u8 max_force_sensor_count:3;
+               u8 f21_2df_query0_b3__6:4;
+               u8 has_high_resolution:1;
+       };
+       struct {
+               u8 regs[1];
+               u16 address;
+       };
+};
+
+union f21_2df_control_0__3 {
+       struct {
+               /* Control 0 */
+               u8 reporting_mode:2;
+               u8 no_rezero:1;
+               u8 f21_2df_control0_b5__7:4;
+
+               /* Control 1 */
+               u8 force_click_threshold;
+
+               /* Control 2 */
+               u8 int_en_force_0:1;
+               u8 int_en_force_1:1;
+               u8 int_en_force_2:1;
+               u8 int_en_force_3:1;
+               u8 int_en_force_4:1;
+               u8 int_en_force_5:1;
+               u8 int_en_force_6:1;
+               u8 f21_ap_control2_b4__6:3;
+               u8 int_en_click:1;
+
+               /* Control 3 */
+               u8 force_interrupt_threshold;
+       };
+       struct {
+               u8 regs[4];
+               u16 address;
+       };
+};
+
+struct f21_2df_control_4n {
+       /*Control 4.* */
+       u8 one_newton_calibration:7;
+       u8 use_cfg_cal:1;
+};
+
+struct f21_2df_control_4{
+               struct f21_2df_control_4n *regs;
+               u16 address;
+               u8 length;
+};
+
+struct f21_2df_control_5n {
+       /*Control 5.* */
+       u8 x_location;
+};
+
+struct f21_2df_control_5{
+               struct f21_2df_control_5n *regs;
+               u16 address;
+               u8 length;
+};
+
+struct f21_2df_control_6n {
+       /*Control 6.* */
+       u8 y_location;
+};
+
+struct f21_2df_control_6{
+               struct f21_2df_control_6n *regs;
+               u16 address;
+               u8 length;
+};
+
+struct f21_2df_control_7n {
+       /*Control 7.* */
+       u8 transmitter_force_sensor;
+};
+
+struct f21_2df_control_7{
+               struct f21_2df_control_7n *regs;
+               u16 address;
+               u8 length;
+};
+
+struct f21_2df_control_8n {
+       /*Control 8.* */
+       u8 receiver_force_sensor;
+};
+
+struct f21_2df_control_8{
+               struct f21_2df_control_8n *regs;
+               u16 address;
+               u8 length;
+};
+
+
+#define RMI_F21_NUM_CTRL_REGS 8
+struct f21_2df_control {
+       /* Control 0-3 */
+       union f21_2df_control_0__3 *reg_0__3;
+
+       /* Control 4 */
+       struct f21_2df_control_4 *reg_4;
+
+       /* Control 5 */
+       struct f21_2df_control_5 *reg_5;
+
+       /* Control 6 */
+       struct f21_2df_control_6 *reg_6;
+
+       /* Control 7 */
+       struct f21_2df_control_7 *reg_7;
+
+       /* Control 8 */
+       struct f21_2df_control_8 *reg_8;
+};
+
+union f21_2df_data_2 {
+       struct {
+               /* Data 2 */
+               u8 force_click:1;
+               u8 f21_2df_control0_b2__7:7;
+       };
+       struct {
+               u8 regs[1];
+               u16 address;
+       };
+};
+
+struct f21_2df_data {
+       /* Data 0 */
+       struct {
+               u8 *force_hi_lo;
+               u16 address;
+       } reg_0__1;
+
+       /* Data 2 */
+       union f21_2df_data_2 *reg_2;
+};
+
+#define F21_REZERO_CMD 0x01
+
+/* data specific to fn $21 that needs to be kept around */
+struct rmi_fn_21_data {
+       union f21_2df_query query;
+       struct f21_2df_control control;
+       struct f21_2df_data data;
+       
+       struct mutex control_mutex;
+       struct mutex data_mutex;
+};
+
+static int rmi_f21_alloc_memory(struct rmi_function_container *fc);
+
+static void rmi_f21_free_memory(struct rmi_function_container *fc);
+
+static int rmi_f21_initialize(struct rmi_function_container *fc);
+
+static int rmi_f21_config(struct rmi_function_container *fc);
+
+static int rmi_f21_create_sysfs(struct rmi_function_container *fc);
+
+/* Sysfs files */
+
+/* Query sysfs files */
+
+
+show_union_struct_prototype(max_force_sensor_count)
+show_union_struct_prototype(has_high_resolution)
+
+static struct attribute *attrs[] = {
+       attrify(max_force_sensor_count),
+       attrify(has_high_resolution),
+       NULL
+};
+static struct attribute_group attrs_query = GROUP(attrs);
+/* Control sysfs files */
+
+show_store_union_struct_prototype(reporting_mode)
+show_store_union_struct_prototype(no_rezero)
+show_store_union_struct_prototype(force_click_threshold)
+show_store_union_struct_prototype(int_en_force_0)
+show_store_union_struct_prototype(int_en_force_1)
+show_store_union_struct_prototype(int_en_force_2)
+show_store_union_struct_prototype(int_en_force_3)
+show_store_union_struct_prototype(int_en_force_4)
+show_store_union_struct_prototype(int_en_force_5)
+show_store_union_struct_prototype(int_en_force_6)
+show_store_union_struct_prototype(int_en_click)
+show_store_union_struct_prototype(force_interrupt_threshold)
+
+show_store_union_struct_prototype(use_cfg_cal)
+show_store_union_struct_prototype(one_newton_calibration)
+show_store_union_struct_prototype(x_location)
+show_store_union_struct_prototype(y_location)
+show_store_union_struct_prototype(transmitter_force_sensor)
+show_store_union_struct_prototype(receiver_force_sensor)
+
+
+static struct attribute *attrs2[] = {
+       attrify(reporting_mode),
+       attrify(no_rezero),
+       attrify(force_click_threshold),
+       attrify(int_en_click),
+       attrify(force_interrupt_threshold),
+       attrify(use_cfg_cal),
+       attrify(one_newton_calibration),
+       attrify(x_location),
+       attrify(y_location),
+       attrify(transmitter_force_sensor),
+       attrify(receiver_force_sensor),
+       NULL
+};
+static struct attribute_group attrs_control = GROUP(attrs2);
+
+/* Data sysfs files */
+show_union_struct_prototype(force)
+show_union_struct_prototype(force_click)
+
+static struct attribute *attrs3[] = {
+       attrify(force),
+       attrify(force_click),
+       NULL
+};
+static struct attribute_group attrs_data = GROUP(attrs3);
+
+/* Command sysfs files */
+
+static ssize_t rmi_fn_21_rezero_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count);
+DEVICE_ATTR(rezero, RMI_WO_ATTR,
+               rmi_show_error,
+               rmi_fn_21_rezero_store);
+
+static struct attribute *attrs4[] = {
+       attrify(rezero),
+       NULL
+};
+static struct attribute_group attrs_command = GROUP(attrs4);
+
+static int rmi_f21_init(struct rmi_function_container *fc)
+{
+       int retval = 0;
+
+       dev_info(&fc->dev, "Intializing F21.");
+
+       retval = rmi_f21_alloc_memory(fc);
+       if (retval < 0)
+               goto error_exit;
+
+       retval = rmi_f21_initialize(fc);
+       if (retval < 0)
+               goto error_exit;
+
+       retval = rmi_f21_create_sysfs(fc);
+       if (retval < 0)
+               goto error_exit;
+
+       return retval;
+
+error_exit:
+       rmi_f21_free_memory(fc);
+
+       return retval;
+}
+
+static int rmi_f21_alloc_memory(struct rmi_function_container *fc)
+{
+       struct rmi_fn_21_data *f21;
+
+       f21 = kzalloc(sizeof(struct rmi_fn_21_data), GFP_KERNEL);
+       if (!f21) {
+               dev_err(&fc->dev, "Failed to allocate rmi_fn_21_data.\n");
+               return -ENOMEM;
+       }
+       fc->data = f21;
+
+       return 0;
+}
+
+
+static void rmi_f21_free_memory(struct rmi_function_container *fc)
+{
+       struct rmi_fn_21_data *f21 = fc->data;
+       u8 int_num = f21->query.max_force_sensor_count;
+       sysfs_remove_group(&fc->dev.kobj, &attrs_query);
+       sysfs_remove_group(&fc->dev.kobj, &attrs_control);
+       switch(int_num) {
+       case 7:
+               sysfs_remove_file(&fc->dev.kobj, attrify(int_en_force_6));
+       case 6:
+               sysfs_remove_file(&fc->dev.kobj, attrify(int_en_force_5));
+       case 5:
+               sysfs_remove_file(&fc->dev.kobj, attrify(int_en_force_4));
+       case 4:
+               sysfs_remove_file(&fc->dev.kobj, attrify(int_en_force_3));
+       case 3:
+               sysfs_remove_file(&fc->dev.kobj, attrify(int_en_force_2));
+       case 2:
+               sysfs_remove_file(&fc->dev.kobj, attrify(int_en_force_1));
+       case 1:
+               sysfs_remove_file(&fc->dev.kobj, attrify(int_en_force_0));
+       default:
+               break;
+       }
+       sysfs_remove_group(&fc->dev.kobj, &attrs_data);
+       sysfs_remove_group(&fc->dev.kobj, &attrs_command);
+       if (f21) {
+               kfree(f21->control.reg_0__3);
+               kfree(f21->control.reg_4->regs);
+               kfree(f21->control.reg_4);
+               kfree(f21->control.reg_5->regs);
+               kfree(f21->control.reg_5);
+               kfree(f21->control.reg_6->regs);
+               kfree(f21->control.reg_6);
+               kfree(f21->control.reg_7->regs);
+               kfree(f21->control.reg_7);
+               kfree(f21->control.reg_8->regs);
+               kfree(f21->control.reg_8);
+               kfree(f21);
+               fc->data = NULL;
+       }
+}
+
+
+static int rmi_f21_initialize(struct rmi_function_container *fc)
+{
+       struct rmi_fn_21_data *instance_data = fc->data;
+       int retval = 0;
+       u16 next_loc;
+
+       /* Read F21 Query Data */
+       instance_data->query.address = fc->fd.query_base_addr;
+       retval = rmi_read_block(fc->rmi_dev, instance_data->query.address,
+               (u8 *)&instance_data->query, sizeof(instance_data->query.regs));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Could not read query registers from 0x%04x\n", instance_data->query.address);
+               return retval;
+       }
+
+       /* Initialize Control Data */
+       next_loc = fc->fd.control_base_addr;
+
+       instance_data->control.reg_0__3 = 
+                       kzalloc(sizeof(union f21_2df_control_0__3), GFP_KERNEL);
+       if (!instance_data->control.reg_0__3) {
+               dev_err(&fc->dev, "Failed to allocate control registers.");
+               return -ENOMEM;
+       }
+       instance_data->control.reg_0__3->address = next_loc;
+       next_loc += sizeof(instance_data->control.reg_0__3->regs);
+       
+       instance_data->control.reg_4 = 
+                       kzalloc(sizeof(struct f21_2df_control_4), GFP_KERNEL);
+       if (!instance_data->control.reg_4) {
+               dev_err(&fc->dev, "Failed to allocate control register.");
+               return -ENOMEM;
+       }
+       instance_data->control.reg_4->length = instance_data->query.max_force_sensor_count;
+       instance_data->control.reg_4->regs = 
+                       kzalloc(sizeof(struct f21_2df_control_4n)
+                               * instance_data->control.reg_4->length, GFP_KERNEL);
+       if (!instance_data->control.reg_4->regs) {
+               dev_err(&fc->dev, "Failed to allocate control registers.");
+               return -ENOMEM;
+       }
+       instance_data->control.reg_4->address = next_loc;
+       next_loc += instance_data->control.reg_4->length;
+
+       instance_data->control.reg_5 = 
+                       kzalloc(sizeof(struct f21_2df_control_5), GFP_KERNEL);
+       if (!instance_data->control.reg_5) {
+               dev_err(&fc->dev, "Failed to allocate control registers.");
+               return -ENOMEM;
+       }
+       instance_data->control.reg_5->length = instance_data->query.max_force_sensor_count;
+       instance_data->control.reg_5->regs = 
+                       kzalloc(sizeof(struct f21_2df_control_5n)
+                               * instance_data->control.reg_5->length, GFP_KERNEL);
+       if (!instance_data->control.reg_5->regs) {
+               dev_err(&fc->dev, "Failed to allocate control registers.");
+               return -ENOMEM;
+       }
+       instance_data->control.reg_5->address = next_loc;
+       next_loc += instance_data->control.reg_5->length;
+
+       instance_data->control.reg_6 = 
+                       kzalloc(sizeof(struct f21_2df_control_6), GFP_KERNEL);
+       if (!instance_data->control.reg_6) {
+               dev_err(&fc->dev, "Failed to allocate control registers.");
+               return -ENOMEM;
+       }
+       instance_data->control.reg_6->length = instance_data->query.max_force_sensor_count;
+       instance_data->control.reg_6->regs = 
+                       kzalloc(sizeof(struct f21_2df_control_6n)
+                       * instance_data->control.reg_6->length, GFP_KERNEL);
+       if (!instance_data->control.reg_6->regs) {
+               dev_err(&fc->dev, "Failed to allocate control registers.");
+               return -ENOMEM;
+       }
+       instance_data->control.reg_6->address = next_loc;
+       next_loc += instance_data->control.reg_6->length;
+
+       instance_data->control.reg_7 = 
+                       kzalloc(sizeof(struct f21_2df_control_7), GFP_KERNEL);
+       if (!instance_data->control.reg_7) {
+               dev_err(&fc->dev, "Failed to allocate control registers.");
+               return -ENOMEM;
+       }
+       instance_data->control.reg_7->length = instance_data->query.max_force_sensor_count;
+       instance_data->control.reg_7->regs = 
+                       kzalloc(sizeof(struct f21_2df_control_7n)
+                       * instance_data->control.reg_7->length, GFP_KERNEL);
+       if (!instance_data->control.reg_7->regs) {
+               dev_err(&fc->dev, "Failed to allocate control registers.");
+               return -ENOMEM;
+       }
+       instance_data->control.reg_7->address = next_loc;
+       next_loc += instance_data->control.reg_7->length;
+
+       instance_data->control.reg_8 = 
+                       kzalloc(sizeof(struct f21_2df_control_8), GFP_KERNEL);
+       if (!instance_data->control.reg_8) {
+               dev_err(&fc->dev, "Failed to allocate control registers.");
+               return -ENOMEM;
+       }
+       instance_data->control.reg_8->length = instance_data->query.max_force_sensor_count;
+       instance_data->control.reg_8->regs = 
+                       kzalloc(sizeof(struct f21_2df_control_8n)
+                       * instance_data->control.reg_8->length, GFP_KERNEL);
+       if (!instance_data->control.reg_8->regs) {
+               dev_err(&fc->dev, "Failed to allocate control registers.");
+               return -ENOMEM;
+       }
+       instance_data->control.reg_8->address = next_loc;
+       
+       
+       /* initialize data registers */
+       next_loc = fc->fd.data_base_addr;
+
+       instance_data->data.reg_0__1.force_hi_lo = kzalloc(
+               2 * instance_data->query.max_force_sensor_count * sizeof(u8),
+                                                               GFP_KERNEL);
+       if (!instance_data->data.reg_0__1.force_hi_lo) {
+               dev_err(&fc->dev, "Failed to allocate data registers.");
+               return -ENOMEM;
+       }
+       instance_data->data.reg_0__1.address = next_loc;
+       next_loc += 2 * instance_data->query.max_force_sensor_count;
+
+       instance_data->data.reg_2 = 
+                       kzalloc(sizeof(union f21_2df_data_2), GFP_KERNEL);
+       if (!instance_data->data.reg_2) {
+               dev_err(&fc->dev, "Failed to allocate data registers.");
+               return -ENOMEM;
+       }
+       instance_data->control.reg_0__3->address = next_loc;
+
+       mutex_init(&instance_data->control_mutex);
+       return 0;
+}
+
+
+static int rmi_f21_create_sysfs(struct rmi_function_container *fc)
+{
+       struct rmi_fn_21_data *instance_data = fc->data;
+       u8 int_num = instance_data->query.max_force_sensor_count;
+       if (int_num > 7)
+               int_num = 7;
+       dev_dbg(&fc->dev, "Creating sysfs files.");
+
+       /* Set up sysfs device attributes. */
+       if (sysfs_create_group(&fc->dev.kobj, &attrs_query) < 0 ) {
+           dev_err(&fc->dev, "Failed to create query sysfs files.");
+               return -ENODEV;
+       }
+       if (sysfs_create_group(&fc->dev.kobj, &attrs_control) < 0 ) {
+           dev_err(&fc->dev, "Failed to create control sysfs files.");
+               return -ENODEV;
+       }
+       switch(int_num) {
+       case 7:
+               if (sysfs_create_file(&fc->dev.kobj, attrify(int_en_force_6)) < 0) {
+                       dev_err(&fc->dev, "Failed to create control sysfs files.");
+                       return -ENODEV;
+               }
+       case 6:
+               if (sysfs_create_file(&fc->dev.kobj, attrify(int_en_force_5)) < 0) {
+                       dev_err(&fc->dev, "Failed to create control sysfs files.");
+                       return -ENODEV;
+               }
+       case 5:
+               if (sysfs_create_file(&fc->dev.kobj, attrify(int_en_force_4)) < 0) {
+                       dev_err(&fc->dev, "Failed to create control sysfs files.");
+                       return -ENODEV;
+               }
+       case 4:
+               if (sysfs_create_file(&fc->dev.kobj, attrify(int_en_force_3)) < 0) {
+                       dev_err(&fc->dev, "Failed to create control sysfs files.");
+                       return -ENODEV;
+               }
+       case 3:
+               if (sysfs_create_file(&fc->dev.kobj, attrify(int_en_force_2)) < 0) {
+                       dev_err(&fc->dev, "Failed to create control sysfs files.");
+                       return -ENODEV;
+               }
+       case 2:
+               if (sysfs_create_file(&fc->dev.kobj, attrify(int_en_force_1)) < 0) {
+                       dev_err(&fc->dev, "Failed to create control sysfs files.");
+                       return -ENODEV;
+               }
+       case 1:
+               if (sysfs_create_file(&fc->dev.kobj, attrify(int_en_force_0)) < 0) {
+                       dev_err(&fc->dev, "Failed to create control sysfs files.");
+                       return -ENODEV;
+               }
+       default:
+               break;
+       }
+       if (sysfs_create_group(&fc->dev.kobj, &attrs_data) < 0 ) {
+           dev_err(&fc->dev, "Failed to create data sysfs files.");
+               return -ENODEV;
+       }
+       if (sysfs_create_group(&fc->dev.kobj, &attrs_command) < 0 ) {
+           dev_err(&fc->dev, "Failed to create command sysfs files.");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+
+static int rmi_f21_config(struct rmi_function_container *fc)
+{
+       struct rmi_fn_21_data *data = fc->data;
+/* repeated register functions */
+
+       /* Write Control Register values back to device */
+       rmi_write_block(fc->rmi_dev, data->control.reg_0__3->address,
+                               (u8 *)data->control.reg_0__3,
+                               sizeof(data->control.reg_0__3->regs));
+       
+       rmi_write_block(fc->rmi_dev, data->control.reg_4->address,
+                       (u8*) data->control.reg_4->regs,
+                       data->query.max_force_sensor_count * sizeof(u8));
+
+       rmi_write_block(fc->rmi_dev, data->control.reg_5->address,
+                       (u8*) data->control.reg_5->regs,
+                       data->query.max_force_sensor_count * sizeof(u8));
+
+       rmi_write_block(fc->rmi_dev, data->control.reg_6->address,
+                       (u8*) data->control.reg_6->regs,
+                       data->query.max_force_sensor_count * sizeof(u8));
+
+       rmi_write_block(fc->rmi_dev, data->control.reg_7->address,
+                       (u8*) data->control.reg_7->regs,
+                       data->query.max_force_sensor_count * sizeof(u8));
+
+       rmi_write_block(fc->rmi_dev, data->control.reg_8->address,
+                       (u8*) data->control.reg_8->regs,
+                       data->query.max_force_sensor_count * sizeof(u8));
+
+
+       return 0;
+}
+
+static void rmi_f21_remove(struct rmi_function_container *fc)
+{
+
+       dev_info(&fc->dev, "Removing F21.");
+       rmi_f21_free_memory(fc);
+}
+
+/* sysfs functions */
+/* Query */
+simple_show_union_struct_unsigned(query, max_force_sensor_count)
+simple_show_union_struct_unsigned(query, has_high_resolution)
+
+/* Control */
+show_store_union_struct_unsigned(control, reg_0__3, reporting_mode)
+show_store_union_struct_unsigned(control, reg_0__3, no_rezero)
+
+show_store_union_struct_unsigned(control, reg_0__3, force_click_threshold)
+
+show_store_union_struct_unsigned(control, reg_0__3, int_en_force_0)
+show_store_union_struct_unsigned(control, reg_0__3, int_en_force_1)
+show_store_union_struct_unsigned(control, reg_0__3, int_en_force_2)
+show_store_union_struct_unsigned(control, reg_0__3, int_en_force_3)
+show_store_union_struct_unsigned(control, reg_0__3, int_en_force_4)
+show_store_union_struct_unsigned(control, reg_0__3, int_en_force_5)
+show_store_union_struct_unsigned(control, reg_0__3, int_en_force_6)
+show_store_union_struct_unsigned(control, reg_0__3, int_en_click)
+show_store_union_struct_unsigned(control, reg_0__3, force_interrupt_threshold)
+
+
+/* repeated register functions */
+show_store_repeated_union_struct_unsigned(control, reg_4, use_cfg_cal)
+show_store_repeated_union_struct_unsigned(control, reg_4, one_newton_calibration)
+show_store_repeated_union_struct_unsigned(control, reg_5, x_location)
+show_store_repeated_union_struct_unsigned(control, reg_6, y_location)
+show_store_repeated_union_struct_unsigned(control, reg_7, transmitter_force_sensor)
+show_store_repeated_union_struct_unsigned(control, reg_8, receiver_force_sensor)
+
+/* Data */
+static ssize_t rmi_fn_21_force_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf) {
+       struct rmi_function_container *fc;
+       struct FUNCTION_DATA *data;
+       int reg_length;
+       int result, size = 0;
+       char *temp;
+       int i;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       /* Read current regtype values */
+       reg_length = data->query.max_force_sensor_count;
+       result = rmi_read_block(fc->rmi_dev, data->data.reg_0__1.address,
+                       data->data.reg_0__1.force_hi_lo,
+                       2 *reg_length * sizeof(u8));
+
+       if (result < 0) {
+               dev_err(dev, "%s : Could not read regtype at 0x%x\nData may be outdated.", __func__,
+                                       data->data.reg_0__1.address);
+       }
+       temp = buf;
+       for (i = 0; i < reg_length; i++) {
+               result = snprintf(temp, PAGE_SIZE - size, "%d ",
+                       data->data.reg_0__1.force_hi_lo[i] * (2 << 3)
+                       + data->data.reg_0__1.force_hi_lo[i + reg_length]);
+               if (result < 0) {
+                       dev_err(dev, "%s : Could not write output.", __func__);
+                       return result;
+               }
+               size += result;
+               temp += result;
+       }
+       result = snprintf(temp, PAGE_SIZE - size, "\n");
+       if (result < 0) {
+                       dev_err(dev, "%s : Could not write output.", __func__);
+                       return result;
+       }
+       return size + result;
+}
+
+show_union_struct_unsigned(data, reg_2, force_click)
+
+/* Command */
+
+static ssize_t rmi_fn_21_rezero_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count) {
+       unsigned long val;
+       int error, result;
+       struct rmi_function_container *fc;
+       struct rmi_fn_21_data *instance_data;
+       struct rmi_driver *driver;
+       u8 command;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+       driver = fc->rmi_dev->driver;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+       if (error)
+               return error;
+       /* Do nothing if not set to 1. This prevents accidental commands. */
+       if (val != 1)
+               return count;
+
+       command = (unsigned char)F21_REZERO_CMD;
+
+       /* Write the command to the command register */
+       result = rmi_write_block(fc->rmi_dev, fc->fd.command_base_addr,
+                                               &command, 1);
+       if (result < 0) {
+               dev_err(dev, "%s : Could not write command to 0x%x\n",
+                               __func__, fc->fd.command_base_addr);
+               return result;
+       }
+       return count;
+}
+
+static struct rmi_function_handler function_handler = {
+       .func = 0x21,
+       .init = rmi_f21_init,
+       .config = rmi_f21_config,
+       .reset = NULL,
+       .attention = NULL,
+       .remove = rmi_f21_remove
+};
+
+static int __init rmi_f21_module_init(void)
+{
+       int error;
+
+       error = rmi_register_function_driver(&function_handler);
+       if (error < 0) {
+               pr_err("%s: register failed!\n", __func__);
+               return error;
+       }
+       return 0;
+}
+
+static void rmi_f21_module_exit(void)
+{
+       rmi_unregister_function_driver(&function_handler);
+}
+
+module_init(rmi_f21_module_init);
+module_exit(rmi_f21_module_exit);
+
+MODULE_AUTHOR("Daniel Rosenberg <daniel.rosenberg@synaptics.com>");
+MODULE_DESCRIPTION("RMI F21 module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
diff --git a/drivers/input/touchscreen/rmi4/rmi_f34.c b/drivers/input/touchscreen/rmi4/rmi_f34.c
new file mode 100755 (executable)
index 0000000..3a93a32
--- /dev/null
@@ -0,0 +1,962 @@
+/*
+ * Copyright (c) 2011 Synaptics Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/rmi.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include "rmi_driver.h"
+
+/* define fn $34 commands */
+#define WRITE_FW_BLOCK            0x2
+#define ERASE_ALL                 0x3
+#define READ_CONFIG_BLOCK         0x5
+#define WRITE_CONFIG_BLOCK        0x6
+#define ERASE_CONFIG              0x7
+#define ENABLE_FLASH_PROG         0xf
+
+#define STATUS_IN_PROGRESS        0xff
+#define STATUS_IDLE              0x80
+
+#define PDT_START_SCAN_LOCATION        0x00e9
+#define PDT_END_SCAN_LOCATION  0x0005
+
+#define BLK_SZ_OFF     3
+#define IMG_BLK_CNT_OFF        5
+#define CFG_BLK_CNT_OFF        7
+
+#define BLK_NUM_OFF 2
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+#define KERNEL_VERSION_ABOVE_2_6_32 1
+#endif
+
+/* 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;
+       unsigned short imageblockcount;
+       unsigned short configblockcount;
+       unsigned short blocknum;
+       bool inflashprogmode;
+       struct mutex attn_mutex;
+};
+
+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);
+
+#ifdef KERNEL_VERSION_ABOVE_2_6_32
+static ssize_t rmi_fn_34_data_read(struct file *data_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 *data_file,
+                                   struct kobject *kobj,
+                                   struct bin_attribute *attributes, char *buf,
+                                   loff_t pos, size_t count);
+#else
+static ssize_t rmi_fn_34_data_read(struct kobject *kobj,
+                                  struct bin_attribute *attributes,
+                                  char *buf, loff_t pos, size_t count);
+
+static ssize_t rmi_fn_34_data_write(struct kobject *kobj,
+                                   struct bin_attribute *attributes, char *buf,
+                                   loff_t pos, size_t count);
+#endif
+
+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_imageblockcount_show(struct device *dev,
+                                             struct device_attribute *attr,
+                                             char *buf);
+
+static ssize_t rmi_fn_34_configblockcount_show(struct device *dev,
+                                              struct device_attribute *attr,
+                                              char *buf);
+
+static ssize_t rmi_fn_34_blocknum_show(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf);
+
+static ssize_t rmi_fn_34_blocknum_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count);
+
+static ssize_t rmi_fn_34_rescanPDT_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count);
+
+
+static int rmi_f34_alloc_memory(struct rmi_function_container *fc);
+
+static void rmi_f34_free_memory(struct rmi_function_container *fc);
+
+static int rmi_f34_initialize(struct rmi_function_container *fc);
+
+static int rmi_f34_config(struct rmi_function_container *fc);
+
+static int rmi_f34_reset(struct rmi_function_container *fc);
+
+static int rmi_f34_create_sysfs(struct rmi_function_container *fc);
+
+
+
+static struct device_attribute attrs[] = {
+       __ATTR(status, RMI_RW_ATTR,
+              rmi_fn_34_status_show, rmi_fn_34_status_store),
+
+       /* Also, sysfs will need to have a file set up to distinguish
+        * between commands - like Config write/read, Image write/verify. */
+       __ATTR(cmd, RMI_RW_ATTR,
+              rmi_fn_34_cmd_show, rmi_fn_34_cmd_store),
+       __ATTR(bootloaderid, RMI_RW_ATTR,
+              rmi_fn_34_bootloaderid_show, rmi_fn_34_bootloaderid_store),
+       __ATTR(blocksize, RMI_RO_ATTR,
+              rmi_fn_34_blocksize_show, rmi_store_error),
+       __ATTR(imageblockcount, RMI_RO_ATTR,
+              rmi_fn_34_imageblockcount_show, rmi_store_error),
+       __ATTR(configblockcount, RMI_RO_ATTR,
+              rmi_fn_34_configblockcount_show, rmi_store_error),
+       __ATTR(blocknum, RMI_RW_ATTR,
+              rmi_fn_34_blocknum_show, rmi_fn_34_blocknum_store),
+       __ATTR(rescanPDT, RMI_WO_ATTR,
+              rmi_show_error, rmi_fn_34_rescanPDT_store)
+};
+
+struct bin_attribute dev_attr_data = {
+       .attr = {
+                .name = "data",
+                .mode = 0666},
+       .size = 0,
+       .read = rmi_fn_34_data_read,
+       .write = rmi_fn_34_data_write,
+};
+
+
+static int rmi_f34_init(struct rmi_function_container *fc)
+{
+       int retval;
+
+       dev_info(&fc->dev, "Intializing f34 values.");
+
+       /* init instance data, fill in values and create any sysfs files */
+       retval = rmi_f34_alloc_memory(fc);
+       if (retval < 0)
+               goto exit_free_data;
+
+       retval = rmi_f34_initialize(fc);
+       if (retval < 0)
+               goto exit_free_data;
+
+       retval = rmi_f34_create_sysfs(fc);
+       if (retval < 0)
+               goto exit_free_data;
+
+       return 0;
+
+exit_free_data:
+       rmi_f34_free_memory(fc);
+
+       return retval;
+}
+
+static int rmi_f34_alloc_memory(struct rmi_function_container *fc)
+{
+       struct rmi_fn_34_data *f34;
+
+       f34 = kzalloc(sizeof(struct rmi_fn_34_data), GFP_KERNEL);
+       if (!f34) {
+               dev_err(&fc->dev, "Failed to allocate rmi_fn_34_data.\n");
+               return -ENOMEM;
+       }
+       fc->data = f34;
+
+       return 0;
+}
+
+static void rmi_f34_free_memory(struct rmi_function_container *fc)
+{
+       kfree(fc->data);
+       fc->data = NULL;
+}
+
+static int rmi_f34_initialize(struct rmi_function_container *fc)
+{
+       struct rmi_device *rmi_dev = fc->rmi_dev;
+       struct rmi_device_platform_data *pdata;
+       int retval = 0;
+       struct rmi_fn_34_data *f34 = fc->data;
+       u16 query_base_addr;
+       u16 control_base_addr;
+       unsigned char buf[2];
+
+       pdata = to_rmi_platform_data(rmi_dev);
+       dev_dbg(&fc->dev, "Initializing F34 values for %s.\n",
+               pdata->sensor_name);
+
+       mutex_init(&f34->attn_mutex);
+
+       /* get the Bootloader ID and Block Size. */
+       query_base_addr = fc->fd.query_base_addr;
+       control_base_addr = fc->fd.control_base_addr;
+
+       retval = rmi_read_block(fc->rmi_dev, query_base_addr, buf,
+                       ARRAY_SIZE(buf));
+
+       if (retval < 0) {
+               dev_err(&fc->dev, "Could not read bootloaderid from 0x%04x.\n",
+                       query_base_addr);
+               return retval;
+       }
+
+       batohs(&f34->bootloaderid, buf);
+
+       retval = rmi_read_block(fc->rmi_dev, query_base_addr + BLK_SZ_OFF, buf,
+                       ARRAY_SIZE(buf));
+
+       if (retval < 0) {
+               dev_err(&fc->dev, "Could not read block size from 0x%04x, "
+                       "error=%d.\n", query_base_addr + BLK_SZ_OFF, retval);
+               return retval;
+       }
+       batohs(&f34->blocksize, buf);
+
+       /* Get firmware image block count and store it in the instance data */
+       retval = rmi_read_block(fc->rmi_dev, query_base_addr + IMG_BLK_CNT_OFF,
+                       buf, ARRAY_SIZE(buf));
+
+       if (retval < 0) {
+               dev_err(&fc->dev, "Couldn't read image block count from 0x%x, "
+                       "error=%d.\n", query_base_addr + IMG_BLK_CNT_OFF,
+                       retval);
+               return retval;
+       }
+       batohs(&f34->imageblockcount, buf);
+
+       /* Get config block count and store it in the instance data */
+       retval = rmi_read_block(fc->rmi_dev, query_base_addr + 7, buf,
+                       ARRAY_SIZE(buf));
+
+       if (retval < 0) {
+               dev_err(&fc->dev, "Couldn't read config block count from 0x%x, "
+                       "error=%d.\n", query_base_addr + CFG_BLK_CNT_OFF,
+                       retval);
+               return retval;
+       }
+       batohs(&f34->configblockcount, buf);
+
+       return 0;
+}
+
+static int rmi_f34_create_sysfs(struct rmi_function_container *fc)
+{
+       int attr_count = 0;
+       int rc;
+
+       dev_dbg(&fc->dev, "Creating sysfs files.");
+
+       /* We 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. */
+       rc = sysfs_create_bin_file(&fc->dev.kobj,
+                               &dev_attr_data);
+       if (rc < 0) {
+               dev_err(&fc->dev, "Failed to create sysfs file for F34 data "
+                    "(error = %d).\n", rc);
+               return -ENODEV;
+       }
+
+       /* Set up sysfs device attributes. */
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+               if (sysfs_create_file
+                   (&fc->dev.kobj, &attrs[attr_count].attr) < 0) {
+                       dev_err(&fc->dev, "Failed to create sysfs file for %s.",
+                            attrs[attr_count].attr.name);
+                       rc = -ENODEV;
+                       goto err_remove_sysfs;
+               }
+       }
+
+       return 0;
+
+err_remove_sysfs:
+       sysfs_remove_bin_file(&fc->dev.kobj, &dev_attr_data);
+
+       for (attr_count--; attr_count >= 0; attr_count--)
+               sysfs_remove_file(&fc->dev.kobj,
+                                 &attrs[attr_count].attr);
+       return rc;
+}
+
+static int rmi_f34_config(struct rmi_function_container *fc)
+{
+       /* for this function we should do nothing here */
+       return 0;
+}
+
+
+static int rmi_f34_reset(struct rmi_function_container *fc)
+{
+       struct  rmi_fn_34_data  *instance_data = fc->data;
+
+       instance_data->status = ECONNRESET;
+
+       return 0;
+}
+
+static void rmi_f34_remove(struct rmi_function_container *fc)
+{
+       int attr_count;
+
+       sysfs_remove_bin_file(&fc->dev.kobj,
+                                                 &dev_attr_data);
+
+       for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++)
+               sysfs_remove_file(&fc->dev.kobj,
+                                 &attrs[attr_count].attr);
+
+       rmi_f34_free_memory(fc);
+}
+
+static int f34_read_status(struct rmi_function_container *fc)
+{
+       struct rmi_fn_34_data *instance_data = fc->data;
+       u16 data_base_addr = fc->fd.data_base_addr;
+       u8 status;
+       int retval;
+
+       if (instance_data->status == ECONNRESET)
+               return instance_data->status;
+
+       /* Read the Fn $34 status from F34_Flash_Data3 to see the previous
+        * commands status. F34_Flash_Data3 will be the address after the
+        * 2 block number registers plus blocksize Data registers.
+        *  inform user space - through a sysfs param. */
+       retval = rmi_read(fc->rmi_dev,
+                         data_base_addr + instance_data->blocksize +
+                         BLK_NUM_OFF, &status);
+
+       if (retval < 0) {
+               dev_err(&fc->dev, "Could not read status from 0x%x\n",
+                      data_base_addr + instance_data->blocksize + BLK_NUM_OFF);
+               status = 0xff;  /* failure */
+       }
+
+       /* set a sysfs value that the user mode can read - only
+        * upper 4 bits are the status. successful is $80, anything
+        * else is failure */
+       instance_data->status = status & 0xf0;
+
+       /* put mode into Flash Prog Mode when we successfully do
+        * an Enable Flash Prog cmd. */
+       if ((instance_data->status == STATUS_IDLE) &&
+               (instance_data->cmd == ENABLE_FLASH_PROG))
+               instance_data->inflashprogmode = true;
+
+       return retval;
+}
+
+int rmi_f34_attention(struct rmi_function_container *fc, u8 *irq_bits)
+{
+       int retval;
+       struct rmi_fn_34_data *data = fc->data;
+
+       mutex_lock(&data->attn_mutex);
+       retval = f34_read_status(fc);
+       mutex_unlock(&data->attn_mutex);
+       return retval;
+}
+
+static struct rmi_function_handler function_handler = {
+       .func = 0x34,
+       .init = rmi_f34_init,
+       .config = rmi_f34_config,
+       .reset = rmi_f34_reset,
+       .attention = rmi_f34_attention,
+       .remove = rmi_f34_remove
+};
+
+static ssize_t rmi_fn_34_bootloaderid_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->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 data[2];
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+       u16 data_base_addr;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+
+       if (error)
+               return error;
+
+       instance_data->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). */
+       hstoba(data, (unsigned short)val);
+       data_base_addr = fc->fd.data_base_addr;
+
+       error = rmi_write_block(fc->rmi_dev,
+                               data_base_addr + BLK_NUM_OFF,
+                               data,
+                               ARRAY_SIZE(data));
+
+       if (error < 0) {
+               dev_err(dev, "%s : Could not write bootloader id to 0x%x\n",
+                      __func__, data_base_addr + BLK_NUM_OFF);
+               return error;
+       }
+
+       return count;
+}
+
+static ssize_t rmi_fn_34_blocksize_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->blocksize);
+}
+
+static ssize_t rmi_fn_34_imageblockcount_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       instance_data->imageblockcount);
+}
+
+static ssize_t rmi_fn_34_configblockcount_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                       instance_data->configblockcount);
+}
+
+static ssize_t rmi_fn_34_status_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+       int retval;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       mutex_lock(&instance_data->attn_mutex);
+       retval = f34_read_status(fc);
+       mutex_unlock(&instance_data->attn_mutex);
+
+       if (retval < 0)
+               return retval;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->status);
+}
+
+
+static ssize_t rmi_fn_34_status_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       instance_data->status = 0;
+
+       return 0;
+}
+
+
+static ssize_t rmi_fn_34_cmd_show(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->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_container *fc;
+       struct rmi_fn_34_data *instance_data;
+       unsigned long val;
+       u16 data_base_addr;
+       int error;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+       data_base_addr = fc->fd.data_base_addr;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+       if (error)
+               return error;
+
+       /* make sure we are in Flash Prog mode for all cmds except the
+        * Enable Flash Programming cmd - otherwise we are in error */
+       if ((val != ENABLE_FLASH_PROG) && !instance_data->inflashprogmode) {
+               dev_err(dev, "%s: CANNOT SEND CMD %d TO SENSOR - "
+                       "NOT IN FLASH PROG MODE\n"
+                       , __func__, data_base_addr);
+               return -EINVAL;
+       }
+
+       instance_data->cmd = val;
+
+       /* Validate command value and (if necessary) write it to the command
+        * register.
+        */
+       switch (instance_data->cmd) {
+       case ENABLE_FLASH_PROG:
+       case ERASE_ALL:
+       case ERASE_CONFIG:
+       case WRITE_FW_BLOCK:
+       case READ_CONFIG_BLOCK:
+       case WRITE_CONFIG_BLOCK:
+               /* Reset the status to indicate we are in progress on a cmd. */
+               /* The status will change when the ATTN interrupt happens
+                  and the status of the cmd that was issued is read from
+                  the F34_Flash_Data3 register - result should be 0x80 for
+                  success - any other value indicates an error */
+
+               /* Issue the command to the device. */
+               error = rmi_write(fc->rmi_dev,
+                               data_base_addr + instance_data->blocksize +
+                               BLK_NUM_OFF, instance_data->cmd);
+
+               if (error < 0) {
+                       dev_err(dev, "%s: Could not write command 0x%02x "
+                               "to 0x%04x\n", __func__, instance_data->cmd,
+                               data_base_addr + instance_data->blocksize +
+                               BLK_NUM_OFF);
+                       return error;
+               }
+
+               if (instance_data->cmd == ENABLE_FLASH_PROG)
+                       instance_data->inflashprogmode = true;
+
+               /* set status to indicate we are in progress */
+               instance_data->status = STATUS_IN_PROGRESS;
+               break;
+       default:
+               dev_dbg(dev, "%s: RMI4 function $34 - "
+                               "unknown command 0x%02lx.\n", __func__, val);
+               count = -EINVAL;
+               break;
+       }
+
+       return count;
+}
+
+static ssize_t rmi_fn_34_blocknum_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->blocknum);
+}
+
+static ssize_t rmi_fn_34_blocknum_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf,
+                                       size_t count)
+{
+       int error;
+       unsigned long val;
+       unsigned char data[2];
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+       u16 data_base_addr;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+       data_base_addr = fc->fd.data_base_addr;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+
+       if (error)
+               return error;
+
+       instance_data->blocknum = val;
+
+       /* Write the Block Number data back to the first two Block
+        * Data registers (F34_Flash_Data_0 and F34_Flash_Data_1). */
+       hstoba(data, (unsigned short)val);
+
+       error = rmi_write_block(fc->rmi_dev,
+                               data_base_addr,
+                               data,
+                               ARRAY_SIZE(data));
+
+       if (error < 0) {
+               dev_err(dev, "%s : Could not write block number %u to 0x%x\n",
+                      __func__, instance_data->blocknum, data_base_addr);
+               return error;
+       }
+
+       return count;
+}
+
+static ssize_t rmi_fn_34_rescanPDT_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+       struct rmi_device *rmi_dev;
+       struct rmi_driver_data *driver_data;
+       struct pdt_entry pdt_entry;
+       bool fn01found = false;
+       bool fn34found = false;
+       unsigned int rescan;
+       int irq_count = 0;
+       int retval = 0;
+       int i;
+
+       /* Rescan of the PDT is needed since issuing the Flash Enable cmd
+        * the device registers for Fn$01 and Fn$34 moving around because
+        * of the change from Bootloader mode to Flash Programming mode
+        * may change to a different PDT with only Fn$01 and Fn$34 that
+        * could have addresses for query, control, data, command registers
+        * that differ from the PDT scan done at device initialization. */
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+       rmi_dev = fc->rmi_dev;
+       driver_data = rmi_get_driverdata(rmi_dev);
+
+       /* Make sure we are only in Flash Programming mode  - DON'T
+        * ALLOW THIS IN UI MODE. */
+       if (instance_data->cmd != ENABLE_FLASH_PROG) {
+               dev_err(dev, "%s: NOT IN FLASH PROG MODE - CAN'T RESCAN PDT.\n"
+                               , __func__);
+               return -EINVAL;
+       }
+
+       /* The only good value to write to this is 1, we allow 0, but with
+        * no effect (this is consistent with the way the command bit works. */
+       if (sscanf(buf, "%u", &rescan) != 1)
+               return -EINVAL;
+       if (rescan < 0 || rescan > 1)
+               return -EINVAL;
+
+       /* 0 has no effect, so we skip it entirely. */
+       if (rescan) {
+               /* rescan the PDT - filling in Fn01 and Fn34 addresses -
+                * this is only temporary - the device will need to be reset
+                * to return the PDT to the normal values. */
+
+               /* mini-parse the PDT - we only have to get Fn$01 and Fn$34 and
+                  since we are Flash Programming mode we only have page 0. */
+               for (i = PDT_START_SCAN_LOCATION; i >= PDT_END_SCAN_LOCATION;
+                       i -= sizeof(pdt_entry)) {
+                       retval = rmi_read_block(rmi_dev, i, (u8 *)&pdt_entry,
+                                              sizeof(pdt_entry));
+                       if (retval != sizeof(pdt_entry)) {
+                               dev_err(dev, "%s: err frm rmi_read_block pdt "
+                                       "entry data from PDT, "
+                                       "error = %d.", __func__, retval);
+                               return retval;
+                       }
+
+                       if ((pdt_entry.function_number == 0x00) ||
+                               (pdt_entry.function_number == 0xff))
+                               break;
+
+                       dev_dbg(dev, "%s: Found F%.2X\n",
+                               __func__, pdt_entry.function_number);
+
+                       /* f01 found - just fill in the new addresses in
+                        * the existing fc. */
+                       if (pdt_entry.function_number == 0x01) {
+                               struct rmi_function_container *f01_fc =
+                                       driver_data->f01_container;
+                               fn01found = true;
+                               f01_fc->fd.query_base_addr =
+                                       pdt_entry.query_base_addr;
+                               f01_fc->fd.command_base_addr =
+                                 pdt_entry.command_base_addr;
+                               f01_fc->fd.control_base_addr =
+                                 pdt_entry.control_base_addr;
+                               f01_fc->fd.data_base_addr =
+                                 pdt_entry.data_base_addr;
+                               f01_fc->fd.function_number =
+                                 pdt_entry.function_number;
+                               f01_fc->fd.interrupt_source_count =
+                                 pdt_entry.interrupt_source_count;
+                               f01_fc->num_of_irqs =
+                                 pdt_entry.interrupt_source_count;
+                               f01_fc->irq_pos = irq_count;
+
+                               irq_count += f01_fc->num_of_irqs;
+
+                               if (fn34found)
+                                       break;
+                       }
+
+                       /* f34 found - just fill in the new addresses in
+                        * the existing fc. */
+                       if (pdt_entry.function_number == 0x34) {
+                               fn34found = true;
+                               fc->fd.query_base_addr =
+                                 pdt_entry.query_base_addr;
+                               fc->fd.command_base_addr =
+                                 pdt_entry.command_base_addr;
+                               fc->fd.control_base_addr =
+                                 pdt_entry.control_base_addr;
+                               fc->fd.data_base_addr =
+                                 pdt_entry.data_base_addr;
+                               fc->fd.function_number =
+                                 pdt_entry.function_number;
+                               fc->fd.interrupt_source_count =
+                                 pdt_entry.interrupt_source_count;
+                               fc->num_of_irqs =
+                                 pdt_entry.interrupt_source_count;
+                               fc->irq_pos = irq_count;
+
+                               irq_count += fc->num_of_irqs;
+
+                               if (fn01found)
+                                       break;
+                       }
+
+               }
+
+               if (!fn01found || !fn34found) {
+                       dev_err(dev, "%s: failed to find fn$01 or fn$34 trying "
+                               "to do rescan PDT.\n"
+                               , __func__);
+                       return -EINVAL;
+               }
+       }
+
+       return count;
+}
+
+#ifdef KERNEL_VERSION_ABOVE_2_6_32
+static ssize_t rmi_fn_34_data_read(struct file *data_file,
+                               struct kobject *kobj,
+                               struct bin_attribute *attributes,
+                               char *buf,
+                               loff_t pos,
+                               size_t count)
+#else
+static ssize_t rmi_fn_34_data_read(struct kobject *kobj,
+                               struct bin_attribute *attributes,
+                               char *buf,
+                               loff_t pos,
+                               size_t count)
+#endif
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+       u16 data_base_addr;
+       int error;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       data_base_addr = fc->fd.data_base_addr;
+
+       if (count != instance_data->blocksize) {
+               dev_err(dev,
+                       "%s : Incorrect F34 block size %d. "
+                       "Expected size %d.\n",
+                       __func__, count, instance_data->blocksize);
+               return -EINVAL;
+       }
+
+       /* 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_block(fc->rmi_dev, data_base_addr + BLK_NUM_OFF,
+                       (unsigned char *)buf, count);
+
+       if (error < 0) {
+               dev_err(dev, "%s : Could not read data from 0x%04x\n",
+                      __func__, data_base_addr + BLK_NUM_OFF);
+               return error;
+       }
+
+       return count;
+}
+
+#ifdef KERNEL_VERSION_ABOVE_2_6_32
+static ssize_t rmi_fn_34_data_write(struct file *data_file,
+                               struct kobject *kobj,
+                               struct bin_attribute *attributes,
+                               char *buf,
+                               loff_t pos,
+                               size_t count)
+#else
+static ssize_t rmi_fn_34_data_write(struct kobject *kobj,
+                               struct bin_attribute *attributes,
+                               char *buf,
+                               loff_t pos,
+                               size_t count)
+#endif
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct rmi_function_container *fc;
+       struct rmi_fn_34_data *instance_data;
+       u16 data_base_addr;
+       int error;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       data_base_addr = fc->fd.data_base_addr;
+
+       /* 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. */
+
+       if (count != instance_data->blocksize) {
+               dev_err(dev,
+                       "%s : Incorrect F34 block size %d. "
+                       "Expected size %d.\n",
+                       __func__, count, instance_data->blocksize);
+               return -EINVAL;
+       }
+
+       /* Write the data block - only if the count is non-zero  */
+       if (count) {
+               error = rmi_write_block(fc->rmi_dev,
+                               data_base_addr + BLK_NUM_OFF,
+                               (unsigned char *)buf,
+                               count);
+
+               if (error < 0) {
+                       dev_err(dev, "%s : Could not write block data "
+                               "to 0x%x\n", __func__,
+                               data_base_addr + BLK_NUM_OFF);
+                       return error;
+               }
+       }
+
+       return count;
+}
+
+static int __init rmi_f34_module_init(void)
+{
+       int error;
+
+       error = rmi_register_function_driver(&function_handler);
+       if (error < 0) {
+               pr_err("%s : register failed !\n", __func__);
+               return error;
+       }
+
+       return 0;
+}
+
+static void rmi_f34_module_exit(void)
+{
+       rmi_unregister_function_driver(&function_handler);
+}
+
+module_init(rmi_f34_module_init);
+module_exit(rmi_f34_module_exit);
+
+MODULE_AUTHOR("William Manson <wmanson@synaptics.com");
+MODULE_DESCRIPTION("RMI F34 module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
\ No newline at end of file
diff --git a/drivers/input/touchscreen/rmi4/rmi_f54.c b/drivers/input/touchscreen/rmi4/rmi_f54.c
new file mode 100755 (executable)
index 0000000..bae5e78
--- /dev/null
@@ -0,0 +1,2272 @@
+/*
+ * Copyright (c) 2011 Synaptics Incorporated
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/hrtimer.h>
+#include <linux/kernel.h>
+#include <linux/rmi.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#define FUNCTION_DATA rmi_fn_54_data
+#define FNUM 54
+
+#include "rmi_driver.h"
+
+/* Set this to 1 for raw hex dump of returned data. */
+#define RAW_HEX 0
+/* Set this to 1 for human readable dump of returned data. */
+#define HUMAN_READABLE 0
+/* The watchdog timer can be useful when debugging certain firmware related
+ * issues.
+ */
+#define F54_WATCHDOG 1
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 32)
+#define KERNEL_VERSION_ABOVE_2_6_32 1
+#endif
+
+/* define fn $54 commands */
+#define GET_REPORT                1
+#define FORCE_CAL                 2
+
+#define NO_AUTO_CAL_MASK 1
+/* status */
+#define BUSY 1
+#define IDLE 0
+
+/* Offsets for data */
+#define RMI_F54_REPORT_DATA_OFFSET     3
+#define RMI_F54_FIFO_OFFSET            1
+#define RMI_F54_NUM_TX_OFFSET          1
+#define RMI_F54_NUM_RX_OFFSET          0
+
+/* Fixed sizes of reports */
+#define RMI_54_FULL_RAW_CAP_MIN_MAX_SIZE 4
+#define RMI_54_HIGH_RESISTANCE_SIZE 6
+
+/* definitions for F54 Query Registers */
+union f54_ad_query {
+       struct {
+               /* query 0 */
+               u8 num_of_rx_electrodes;
+
+               /* query 1 */
+               u8 num_of_tx_electrodes;
+
+               /* query2 */
+               u8 f54_ad_query2_b0__1:2;
+               u8 has_baseline:1;
+               u8 has_image8:1;
+               u8 f54_ad_query2_b4__5:2;
+               u8 has_image16:1;
+               u8 f54_ad_query2_b7:1;
+               
+               /* query 3.0 and 3.1 */
+               u16 clock_rate;
+
+               /* query 4 */
+               u8 touch_controller_family;
+
+               /* query 5 */
+               u8 has_pixel_touch_threshold_adjustment:1;
+               u8 f54_ad_query5_b1__7:7;
+
+               /* query 6 */
+               u8 has_sensor_assignment:1;
+               u8 has_interference_metric:1;
+               u8 has_sense_frequency_control:1;
+               u8 has_firmware_noise_mitigation:1;
+               u8 f54_ad_query6_b4:1;
+               u8 has_two_byte_report_rate:1;
+               u8 has_one_byte_report_rate:1;
+               u8 has_relaxation_control:1;
+
+               /* query 7 */
+               u8 curve_compensation_mode:2;
+               u8 f54_ad_query7_b2__7:6;
+
+               /* query 8 */
+               u8 f54_ad_query2_b0:1;
+               u8 has_iir_filter:1;
+               u8 has_cmn_removal:1;
+               u8 has_cmn_maximum:1;
+               u8 has_touch_hysteresis:1;
+               u8 has_edge_compensation:1;
+               u8 has_per_frequency_noise_control:1;
+               u8 f54_ad_query8_b7:1;
+
+               u8 f54_ad_query9;
+               u8 f54_ad_query10;
+               u8 f54_ad_query11;
+
+               /* query 12 */
+               u8 number_of_sensing_frequencies:4;
+               u8 f54_ad_query12_b4__7:4;
+       };
+       struct {
+               u8 regs[14];
+               u16 address;
+       };
+};
+
+/* And now for the very large amount of control registers */
+
+/* Ctrl registers */
+
+union f54_ad_control_0 {
+       /* control 0 */
+       struct {
+               u8 no_relax:1;
+               u8 no_scan:1;
+               u8 f54_ad_ctrl0_b2__7:6;
+       };
+       struct {
+               u8 regs[1];
+               u16 address;
+       };
+};
+
+union f54_ad_control_1 {
+       /* control 1 */
+       struct {
+               /* control 1 */
+               u8 bursts_per_cluster:4;
+               u8 f54_ad_ctrl1_b4__7:4;
+       };
+       struct {
+               u8 regs[1];
+               u16 address;
+       };
+};
+
+union f54_ad_control_2 {
+       /* control 2 */
+       struct {
+               u16 saturation_cap;
+               u16 f54_ctrl2;
+       };
+       struct {
+               u8 regs[4];
+               u16 address;
+       };
+};
+
+union f54_ad_control_3 {
+       /* control 3 */
+       struct {
+               u16 pixel_touch_threshold;
+               u16 f54_ctrl3;
+       };
+       struct {
+               u8 regs[4];
+               u16 address;
+       };
+};
+
+union f54_ad_control_4__6 {
+       struct {
+               /* control 4 */
+               u8 rx_feedback_cap:2;
+               u8 f54_ad_ctrl4_b2__7:6;
+
+               /* control 5 */
+               u8 low_ref_cap:2;
+               u8 low_ref_feedback_cap:2;
+               u8 low_ref_polarity:1;
+               u8 f54_ad_ctrl5_b5__7:3;
+               
+               /* control 6 */
+                       u8 high_ref_cap:2;
+               u8 high_ref_feedback_cap:2;
+               u8 high_ref_polarity:1;
+               u8 f54_ad_ctrl6_b5__7:3;
+       };
+       struct {
+               u8 regs[3];
+               u16 address;
+       };
+};
+
+union f54_ad_control_7 {
+       struct {
+               /* control 7 */
+               u8 cbc_cap:2;
+               u8 cbc_polarity:2;
+               u8 cbc_tx_carrier_selection:1;
+               u8 f54_ad_ctrl6_b5__7:3;
+       };
+       struct {
+               u8 regs[1];
+               u16 address;
+       };
+};
+
+union f54_ad_control_8__9 {
+       struct {
+               /* control 8 */
+               u16 integration_duration:10;
+               u16 f54_ad_ctrl8_b10__15:6;
+               /* control 9 */
+               u8 reset_duration;
+               u8 f54_ctrl9;
+       };
+       struct {
+               u8 regs[4];
+               u16 address;
+       };
+};
+
+union f54_ad_control_10 {
+       struct {
+               /* control 10 */
+               u8 noise_sensing_bursts_per_image:4;
+               u8 f54_ad_ctrl10_b4__7:4;
+       };
+       struct {
+               u8 regs[1];
+               u16 address;
+       };
+};
+
+union f54_ad_control_11 {
+       struct {
+               /* control 11 */
+               u8 reserved;
+               u8 f54_ctrl11;
+       };
+       struct {
+               u8 regs[2];
+               u16 address;
+       };
+};
+
+union f54_ad_control_12__13 {
+       struct {
+               /* control 12 */
+               u8 slow_relaxation_rate;
+               u8 f54_ctrl12;
+
+               /* control 13 */
+               u8 fast_relaxation_rate;
+               u8 f54_ctrl13;
+       };
+       struct {
+               u8 regs[4];
+               u16 address;
+       };
+};
+
+union f54_ad_control_14 {
+       struct {
+               /* control 14 */
+                       u8 rxs_on_xaxis:1;
+                       u8 curve_comp_on_txs:1;
+                       u8 f54_ad_ctrl14b2__7:6;
+       };
+       struct {
+               u8 regs[1];
+               u16 address;
+       };
+};
+
+struct f54_ad_control_15n {
+       /*Control 15.* */
+       u8 sensor_rx_assignment;
+};
+
+struct f54_ad_control_15{
+               struct f54_ad_control_15n *regs;
+               u16 address;
+               u8 length;
+};
+
+struct f54_ad_control_16n {
+       /*Control 16.* */
+       u8 sensor_tx_assignment;
+};
+
+struct f54_ad_control_16{
+               struct f54_ad_control_16n *regs;
+               u16 address;
+               u8 length;
+};
+
+
+/* control 17 */
+struct f54_ad_control_17n {
+       u8 burst_countb10__8:3;
+       u8 disable:1;
+       u8 f54_ad_ctrlb4:1;
+       u8 filter_bandwidth:3;
+};
+
+struct f54_ad_control_17{
+               struct f54_ad_control_17n *regs;
+               u16 address;
+               u8 length;
+};
+
+struct f54_ad_control_18n {
+       /*Control 18.* */
+       u8 burst_countb7__0n;
+};
+
+struct f54_ad_control_18{
+               struct f54_ad_control_18n *regs;
+               u16 address;
+               u8 length;
+};
+
+struct f54_ad_control_19n {
+       /*Control 19.* */
+       u8 stretch_duration;
+};
+
+struct f54_ad_control_19{
+               struct f54_ad_control_19n *regs;
+               u16 address;
+               u8 length;
+};
+
+union f54_ad_control_20 {
+       struct {
+               /* control 20 */
+               u8 disable_noise_mitigation:1;
+               u8 f54_ad_ctrl20b2__7:7;
+       };
+       struct {
+               u8 regs[1];
+               u16 address;
+       };
+};
+
+union f54_ad_control_21 {
+       struct {
+               /* control 21 */
+               u16 freq_shift_noise_threshold;
+               u16 f54_ctrl21;
+       };
+       struct {
+               u8 regs[4];
+               u16 address;
+       };
+};
+
+union f54_ad_control_22__26 {
+       struct {
+               /* control 22 */
+               u8 noise_density_threshold;
+               u8 f54_ctrl22;
+
+               /* control 23 */
+               u16 medium_noise_threshold;
+               u8 f54_ctrl23;
+
+               /* control 24 */
+               u16 high_noise_threshold;
+               u16 f54_ctrl24;
+
+               /* control 25 */
+               u8 noise_density;
+               u8 f54_ctrl25;
+
+               /* control 26 */
+               u8 frame_count;
+               u8 f54_ctrl26;
+       };
+       struct {
+               u8 regs[13];
+               u16 address;
+       };
+};
+
+union f54_ad_control_27 {
+       struct {
+               /* control 27 */
+               u8 iir_filter_coef;
+               u8 f54_ctrl27;
+       };
+       struct {
+               u8 regs[2];
+               u16 address;
+       };
+};
+
+union f54_ad_control_28 {
+       struct {
+               /* control 28 */
+               u16 quiet_threshold;
+               u16 f54_ctrl28;
+       };
+       struct {
+               u8 regs[4];
+               u16 address;
+       };
+};
+
+
+union f54_ad_control_29 {
+       struct {
+               /* control 29 */
+               u8 f54_ad_ctrl20b0__6:7;
+               u8 cmn_filter_disable:1;
+       };
+       struct {
+               u8 regs[1];
+               u16 address;
+       };
+};
+
+union f54_ad_control_30 {
+       struct {
+               /* control 30 */
+               u8 cmn_filter_max;
+               u8 f54_ctrl30;
+       };
+       struct {
+               u8 regs[2];
+               u16 address;
+       };
+};
+
+union f54_ad_control_31 {
+       struct {
+               /* control 31 */
+               u8 touch_hysteresis;
+               u8 f54_ctrl31;
+       };
+       struct {
+               u8 regs[2];
+               u16 address;
+       };
+};
+
+union f54_ad_control_32__35 {
+       struct {
+               /* control 32 */
+               u16 rx_low_edge_comp;
+               u16 f54_ctrl32;
+
+               /* control 33 */
+               u16 rx_high_edge_comp;
+               u16 f54_ctrl33;
+
+               /* control 34 */
+               u16 tx_low_edge_comp;
+               u16 f54_ctrl34;
+
+               /* control 35 */
+               u16 tx_high_edge_comp;
+               u16 f54_ctrl35;
+       };
+       struct {
+               u8 regs[16];
+               u16 address;
+       };
+};
+
+struct f54_ad_control_36n {
+       /*Control 36.* */
+       u8 axis1_comp;
+};
+
+struct f54_ad_control_36{
+               struct f54_ad_control_36n *regs;
+               u16 address;
+               u8 length;
+};
+
+struct f54_ad_control_37n {
+       /*Control 37.* */
+       u8 axis2_comp;
+};
+
+struct f54_ad_control_37{
+               struct f54_ad_control_37n *regs;
+               u16 address;
+               u8 length;
+};
+
+struct f54_ad_control_38n {
+       /*Control 38.* */
+       u8 noise_control_1;
+};
+
+struct f54_ad_control_38{
+               struct f54_ad_control_38n *regs;
+               u16 address;
+               u8 length;
+};
+
+struct f54_ad_control_39n {
+       /*Control 39.* */
+       u8 noise_control_2;
+};
+
+struct f54_ad_control_39{
+               struct f54_ad_control_39n *regs;
+               u16 address;
+               u8 length;
+};
+
+struct f54_ad_control_40n {
+       /*Control 40.* */
+       u8 noise_control_3;
+};
+
+struct f54_ad_control_40{
+               struct f54_ad_control_40n *regs;
+               u16 address;
+               u8 length;
+};
+
+struct f54_ad_control {
+       union f54_ad_control_0 *reg_0;
+       union f54_ad_control_1 *reg_1;
+       union f54_ad_control_2 *reg_2;
+       union f54_ad_control_3 *reg_3;
+       union f54_ad_control_4__6 *reg_4__6;
+       union f54_ad_control_7 *reg_7;
+       union f54_ad_control_8__9 *reg_8__9;
+       union f54_ad_control_10 *reg_10;
+       union f54_ad_control_11 *reg_11;
+       union f54_ad_control_12__13 *reg_12__13;
+       union f54_ad_control_14 *reg_14;
+       /* control 15 */
+       struct f54_ad_control_15 *reg_15;
+       /* control 16 */
+       struct f54_ad_control_16 *reg_16;
+
+       /* This register is n repetitions of f54_ad_control_17 */
+       struct f54_ad_control_17 *reg_17;
+
+       /* control 18 */
+       struct f54_ad_control_18 *reg_18;
+
+       /* control 19 */
+       struct f54_ad_control_19 *reg_19;
+       
+       union f54_ad_control_20 *reg_20;
+       union f54_ad_control_21 *reg_21;
+       union f54_ad_control_22__26 *reg_22__26;
+       union f54_ad_control_27 *reg_27;
+       union f54_ad_control_28 *reg_28;
+       union f54_ad_control_29 *reg_29;
+       union f54_ad_control_30 *reg_30;
+       union f54_ad_control_31 *reg_31;
+       union f54_ad_control_32__35 *reg_32__35;
+       /* control 36 */
+       struct f54_ad_control_36 *reg_36;
+
+       /* control 37 */
+       struct f54_ad_control_37 *reg_37;
+
+       /* control 38 */
+       struct f54_ad_control_38 *reg_38;
+
+       /* control 39 */
+       struct f54_ad_control_39 *reg_39;
+
+       /* control 40 */
+       struct f54_ad_control_40 *reg_40;
+};
+
+/* define report types */
+enum f54_report_types {
+       F54_8BIT_IMAGE = 1,
+       F54_16BIT_IMAGE = 2,
+       F54_RAW_16BIT_IMAGE = 3,
+       F54_HIGH_RESISTANCE = 4,
+       F54_TX_TO_TX_SHORT = 5,
+       F54_RX_TO_RX1 = 7,
+       F54_TRUE_BASELINE = 9,
+       F54_FULL_RAW_CAP_MIN_MAX = 13,
+       F54_RX_OPENS1 = 14,
+       F54_TX_OPEN = 15,
+       F54_TX_TO_GROUND = 16,
+       F54_RX_TO_RX2 = 17,
+       F54_RX_OPENS2 = 18,
+       F54_FULL_RAW_CAP = 19,
+       F54_FULL_RAW_CAP_RX_COUPLING_COMP = 20
+};
+
+/* data specific to fn $54 that needs to be kept around */
+struct rmi_fn_54_data {
+       union f54_ad_query query;
+       struct f54_ad_control control;
+       enum f54_report_types report_type;
+       u16 fifoindex;
+       signed char status;
+       bool no_auto_cal;
+       unsigned int report_size;
+       unsigned char *report_data;
+       unsigned int bufsize;
+       struct mutex data_mutex;
+       struct mutex status_mutex;
+       struct mutex control_mutex;
+#if F54_WATCHDOG
+       struct hrtimer watchdog;
+#endif
+       struct rmi_function_container *fc;
+       struct work_struct work;
+};
+
+/* sysfs functions */
+show_store_union_struct_prototype(report_type)
+
+store_union_struct_prototype(get_report)
+
+store_union_struct_prototype(force_cal)
+
+show_union_struct_prototype(status)
+
+#ifdef KERNEL_VERSION_ABOVE_2_6_32
+static ssize_t rmi_fn_54_data_read(struct file *data_file, struct kobject *kobj,
+                                       struct bin_attribute *attributes,
+                                       char *buf, loff_t pos, size_t count);
+#else
+static ssize_t rmi_fn_54_data_read(struct kobject *kobj,
+                                       struct bin_attribute *attributes,
+                                       char *buf, loff_t pos, size_t count);
+#endif
+
+show_union_struct_prototype(num_of_rx_electrodes)
+show_union_struct_prototype(num_of_tx_electrodes)
+show_union_struct_prototype(has_image16)
+show_union_struct_prototype(has_image8)
+show_union_struct_prototype(has_baseline)
+show_union_struct_prototype(clock_rate)
+show_union_struct_prototype(touch_controller_family)
+show_union_struct_prototype(has_pixel_touch_threshold_adjustment)
+show_union_struct_prototype(has_sensor_assignment)
+show_union_struct_prototype(has_interference_metric)
+show_union_struct_prototype(has_sense_frequency_control)
+show_union_struct_prototype(has_firmware_noise_mitigation)
+show_union_struct_prototype(has_two_byte_report_rate)
+show_union_struct_prototype(has_one_byte_report_rate)
+show_union_struct_prototype(has_relaxation_control)
+show_union_struct_prototype(curve_compensation_mode)
+show_union_struct_prototype(has_iir_filter)
+show_union_struct_prototype(has_cmn_removal)
+show_union_struct_prototype(has_cmn_maximum)
+show_union_struct_prototype(has_touch_hysteresis)
+show_union_struct_prototype(has_edge_compensation)
+show_union_struct_prototype(has_per_frequency_noise_control)
+show_union_struct_prototype(number_of_sensing_frequencies)
+show_store_union_struct_prototype(no_auto_cal)
+show_store_union_struct_prototype(fifoindex)
+
+/* Repeated Control Registers */
+show_union_struct_prototype(sensor_rx_assignment)
+show_union_struct_prototype(sensor_tx_assignment)
+show_union_struct_prototype(filter_bandwidth)
+show_union_struct_prototype(disable)
+show_union_struct_prototype(burst_count)
+show_union_struct_prototype(stretch_duration)
+show_store_union_struct_prototype(axis1_comp)
+show_store_union_struct_prototype(axis2_comp)
+show_union_struct_prototype(noise_control_1)
+show_union_struct_prototype(noise_control_2)
+show_union_struct_prototype(noise_control_3)
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+show_store_union_struct_prototype(no_relax)
+show_store_union_struct_prototype(no_scan)
+show_store_union_struct_prototype(bursts_per_cluster)
+show_store_union_struct_prototype(saturation_cap)
+show_store_union_struct_prototype(pixel_touch_threshold)
+show_store_union_struct_prototype(rx_feedback_cap)
+show_store_union_struct_prototype(low_ref_cap)
+show_store_union_struct_prototype(low_ref_feedback_cap)
+show_store_union_struct_prototype(low_ref_polarity)
+show_store_union_struct_prototype(high_ref_cap)
+show_store_union_struct_prototype(high_ref_feedback_cap)
+show_store_union_struct_prototype(high_ref_polarity)
+show_store_union_struct_prototype(cbc_cap)
+show_store_union_struct_prototype(cbc_polarity)
+show_store_union_struct_prototype(cbc_tx_carrier_selection)
+show_store_union_struct_prototype(integration_duration)
+show_store_union_struct_prototype(reset_duration)
+show_store_union_struct_prototype(noise_sensing_bursts_per_image)
+show_store_union_struct_prototype(slow_relaxation_rate)
+show_store_union_struct_prototype(fast_relaxation_rate)
+show_store_union_struct_prototype(rxs_on_xaxis)
+show_store_union_struct_prototype(curve_comp_on_txs)
+show_store_union_struct_prototype(disable_noise_mitigation)
+show_store_union_struct_prototype(freq_shift_noise_threshold)
+show_store_union_struct_prototype(noise_density_threshold)
+show_store_union_struct_prototype(medium_noise_threshold)
+show_store_union_struct_prototype(high_noise_threshold)
+show_store_union_struct_prototype(noise_density)
+show_store_union_struct_prototype(frame_count)
+show_store_union_struct_prototype(iir_filter_coef)
+show_store_union_struct_prototype(quiet_threshold)
+show_store_union_struct_prototype(cmn_filter_disable)
+show_store_union_struct_prototype(cmn_filter_max)
+show_store_union_struct_prototype(touch_hysteresis)
+show_store_union_struct_prototype(rx_low_edge_comp)
+show_store_union_struct_prototype(rx_high_edge_comp)
+show_store_union_struct_prototype(tx_low_edge_comp)
+show_store_union_struct_prototype(tx_high_edge_comp)
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+static struct attribute *attrs[] = {
+       attrify(report_type),
+       attrify(get_report),
+       attrify(force_cal),
+       attrify(status),
+       attrify(num_of_rx_electrodes),
+       attrify(num_of_tx_electrodes),
+       attrify(has_image16),
+       attrify(has_image8),
+       attrify(has_baseline),
+       attrify(clock_rate),
+       attrify(touch_controller_family),
+       attrify(has_pixel_touch_threshold_adjustment),
+       attrify(has_sensor_assignment),
+       attrify(has_interference_metric),
+       attrify(has_sense_frequency_control),
+       attrify(has_firmware_noise_mitigation),
+       attrify(has_two_byte_report_rate),
+       attrify(has_one_byte_report_rate),
+       attrify(has_relaxation_control),
+       attrify(curve_compensation_mode),
+       attrify(has_iir_filter),
+       attrify(has_cmn_removal),
+       attrify(has_cmn_maximum),
+       attrify(has_touch_hysteresis),
+       attrify(has_edge_compensation),
+       attrify(has_per_frequency_noise_control),
+       attrify(number_of_sensing_frequencies),
+       attrify(no_auto_cal),
+       attrify(fifoindex),
+       NULL
+};
+
+static struct attribute_group attrs_query = GROUP(attrs);
+
+struct bin_attribute dev_rep_data = {
+       .attr = {
+                .name = "rep_data",
+                .mode = RMI_RO_ATTR},
+       .size = 0,
+       .read = rmi_fn_54_data_read,
+};
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+static struct attribute *attrs_reg_0[] = {
+       attrify(no_relax),
+       attrify(no_scan),
+       NULL
+};
+
+static struct attribute *attrs_reg_1[] = {
+       attrify(bursts_per_cluster),
+       NULL
+};
+
+static struct attribute *attrs_reg_2[] = {
+       attrify(saturation_cap),
+       NULL
+};
+
+static struct attribute *attrs_reg_3[] = {
+       attrify(pixel_touch_threshold),
+       NULL
+};
+
+static struct attribute *attrs_reg_4__6[] = {
+       attrify(rx_feedback_cap),
+       attrify(low_ref_cap),
+       attrify(low_ref_feedback_cap),
+       attrify(low_ref_polarity),
+       attrify(high_ref_cap),
+       attrify(high_ref_feedback_cap),
+       attrify(high_ref_polarity),
+       NULL
+};
+
+static struct attribute *attrs_reg_7[] = {
+       attrify(cbc_cap),
+       attrify(cbc_polarity),
+       attrify(cbc_tx_carrier_selection),
+       NULL
+};
+
+static struct attribute *attrs_reg_8__9[] = {
+       attrify(integration_duration),
+       attrify(reset_duration),
+       NULL
+};
+
+static struct attribute *attrs_reg_10[] = {
+       attrify(noise_sensing_bursts_per_image),
+       NULL
+};
+
+static struct attribute *attrs_reg_12__13[] = {
+       attrify(slow_relaxation_rate),
+       attrify(fast_relaxation_rate),
+       NULL
+};
+
+static struct attribute *attrs_reg_14__16[] = {
+       attrify(rxs_on_xaxis),
+       attrify(curve_comp_on_txs),
+       attrify(sensor_rx_assignment),
+       attrify(sensor_tx_assignment),
+       NULL
+};
+
+static struct attribute *attrs_reg_17__19[] = {
+       attrify(filter_bandwidth),
+       attrify(disable),
+       attrify(burst_count),
+       attrify(stretch_duration),
+};
+
+static struct attribute *attrs_reg_20[] = {
+       attrify(disable_noise_mitigation),
+       NULL
+};
+
+static struct attribute *attrs_reg_21[] = {
+       attrify(freq_shift_noise_threshold),
+       NULL
+};
+
+static struct attribute *attrs_reg_22__26[] = {
+       attrify(noise_density_threshold),
+       attrify(medium_noise_threshold),
+       attrify(high_noise_threshold),
+       attrify(noise_density),
+       attrify(frame_count),
+       NULL
+};
+
+static struct attribute *attrs_reg_27[] = {
+       attrify(iir_filter_coef),
+       NULL
+};
+
+static struct attribute *attrs_reg_28[] = {
+       attrify(quiet_threshold),
+       NULL
+};
+
+static struct attribute *attrs_reg_29[] = {
+       attrify(cmn_filter_disable),
+       NULL
+};
+
+static struct attribute *attrs_reg_30[] = {
+       attrify(cmn_filter_max),
+       NULL
+};
+
+static struct attribute *attrs_reg_31[] = {
+       attrify(touch_hysteresis),
+       NULL
+};
+
+static struct attribute *attrs_reg_32__35[] = {
+       attrify(rx_low_edge_comp),
+       attrify(rx_high_edge_comp),
+       attrify(tx_low_edge_comp),
+       attrify(tx_high_edge_comp),
+       NULL
+};
+
+static struct attribute *attrs_reg_36[] = {
+       attrify(axis1_comp),
+       NULL
+ };
+static struct attribute *attrs_reg_37[] = {
+       attrify(axis2_comp),
+       NULL
+ };
+static struct attribute *attrs_reg_38__40[] = {
+       attrify(noise_control_1),
+       attrify(noise_control_2),
+       attrify(noise_control_3),
+       NULL
+ };
+
+static struct attribute_group attrs_ctrl_regs[] = {
+       GROUP(attrs_reg_0),
+       GROUP(attrs_reg_1),
+       GROUP(attrs_reg_2),
+       GROUP(attrs_reg_3),
+       GROUP(attrs_reg_4__6),
+       GROUP(attrs_reg_7),
+       GROUP(attrs_reg_8__9),
+       GROUP(attrs_reg_10),
+       GROUP(attrs_reg_12__13),
+       GROUP(attrs_reg_14__16),
+       GROUP(attrs_reg_17__19),
+       GROUP(attrs_reg_20),
+       GROUP(attrs_reg_21),
+       GROUP(attrs_reg_22__26),
+       GROUP(attrs_reg_27),
+       GROUP(attrs_reg_28),
+       GROUP(attrs_reg_29),
+       GROUP(attrs_reg_30),
+       GROUP(attrs_reg_31),
+       GROUP(attrs_reg_32__35),
+       GROUP(attrs_reg_36),
+       GROUP(attrs_reg_37),
+       GROUP(attrs_reg_38__40)
+};
+
+bool attrs_ctrl_regs_exist[ARRAY_SIZE(attrs_ctrl_regs)];
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+#if F54_WATCHDOG
+static enum hrtimer_restart clear_status(struct hrtimer *timer);
+
+static void clear_status_worker(struct work_struct *work);
+#endif
+
+static int rmi_f54_alloc_memory(struct rmi_function_container *fc);
+
+static void rmi_f54_free_memory(struct rmi_function_container *fc);
+
+static int rmi_f54_initialize(struct rmi_function_container *fc);
+
+static int rmi_f54_reset(struct rmi_function_container *fc);
+
+static int rmi_f54_create_sysfs(struct rmi_function_container *fc);
+
+static int rmi_f54_init(struct rmi_function_container *fc)
+{
+       int retval = 0;
+       struct rmi_fn_54_data *f54;
+
+       dev_info(&fc->dev, "Intializing F54.");
+
+       retval = rmi_f54_alloc_memory(fc);
+       if (retval < 0)
+               goto error_exit;
+
+       retval = rmi_f54_initialize(fc);
+       if (retval < 0)
+               goto error_exit;
+
+       retval = rmi_f54_create_sysfs(fc);
+       if (retval < 0)
+               goto error_exit;
+       f54 = fc->data;
+       f54->status = IDLE;
+       return retval;
+
+error_exit:
+       rmi_f54_free_memory(fc);
+
+       return retval;
+}
+
+static int rmi_f54_alloc_memory(struct rmi_function_container *fc)
+{
+       struct rmi_fn_54_data *f54;
+
+       f54 = kzalloc(sizeof(struct rmi_fn_54_data), GFP_KERNEL);
+       if (!f54) {
+               dev_err(&fc->dev, "Failed to allocate rmi_fn_54_data.\n");
+               return -ENOMEM;
+       }
+       fc->data = f54;
+       f54->fc = fc;
+
+
+       return 0;
+}
+
+static void rmi_f54_free_memory(struct rmi_function_container *fc)
+{
+       int reg_num;
+       struct rmi_fn_54_data *f54 = fc->data;
+       sysfs_remove_group(&fc->dev.kobj, &attrs_query);
+       for (reg_num = 0; reg_num < ARRAY_SIZE(attrs_ctrl_regs); reg_num++)
+               sysfs_remove_group(&fc->dev.kobj, &attrs_ctrl_regs[reg_num]);
+       sysfs_remove_bin_file(&fc->dev.kobj, &dev_rep_data);
+       if (f54) {
+               kfree(f54->report_data);
+               kfree(f54);
+               fc->data = NULL;
+       }
+}
+
+static int rmi_f54_reset(struct rmi_function_container *fc)
+{
+       struct rmi_fn_54_data *data = fc->data;
+       struct rmi_driver *driver = fc->rmi_dev->driver;
+
+#if F54_WATCHDOG
+       hrtimer_cancel(&data->watchdog);
+#endif
+
+       mutex_lock(&data->status_mutex);
+       if (driver->restore_irq_mask) {
+               dev_dbg(&fc->dev, "Restoring interupts!\n");
+               driver->restore_irq_mask(fc->rmi_dev);
+       } else {
+               dev_err(&fc->dev, "No way to restore interrupts!\n");
+       }
+       data->status = -ECONNRESET;
+       mutex_unlock(&data->status_mutex);
+
+       return 0;
+}
+
+static void rmi_f54_remove(struct rmi_function_container *fc)
+{
+       struct rmi_fn_54_data *data = fc->data;
+
+       dev_info(&fc->dev, "Removing F54.");
+
+       #if F54_WATCHDOG
+       /* Stop timer */
+       hrtimer_cancel(&data->watchdog);
+       #endif
+
+       rmi_f54_free_memory(fc);
+}
+
+static int rmi_f54_create_sysfs(struct rmi_function_container *fc) {
+       int reg_num;
+       int retval;
+       dev_dbg(&fc->dev, "Creating sysfs files.");
+       /* Set up sysfs device attributes. */
+       
+       if (sysfs_create_group(&fc->dev.kobj, &attrs_query) < 0 ) {
+           dev_err(&fc->dev, "Failed to create query sysfs files.");
+               return -ENODEV;
+       }
+       for (reg_num = 0; reg_num < ARRAY_SIZE(attrs_ctrl_regs);
+                                                               reg_num++) {
+               if (attrs_ctrl_regs_exist[reg_num]) {
+                       if (sysfs_create_group(&fc->dev.kobj,
+                                       &attrs_ctrl_regs[reg_num]) < 0) {
+                               dev_err(&fc->dev,
+                                       "Failed to create "
+                                       "sysfs file group for reg"
+                                       "group %d.",
+                                       reg_num);
+                               return -ENODEV;
+                       }
+               }
+       }
+
+       /* Binary sysfs file to report the data back */
+       retval = sysfs_create_bin_file(&fc->dev.kobj, &dev_rep_data);
+       if (retval < 0) {
+               dev_err(&fc->dev, "Failed to create sysfs file for F54 data "
+                                       "(error = %d).\n", retval);
+               return -ENODEV;
+       }
+       return 0;
+}
+
+
+
+static int rmi_f54_initialize(struct rmi_function_container *fc)
+{
+       struct rmi_fn_54_data *instance_data= fc->data;
+       struct f54_ad_control *control;
+       int retval = 0;
+       u8 size = 0;
+       u16 next_loc;
+       u8 reg_num;
+
+       dev_info(&fc->dev, "Intializing F54.");
+       
+#if F54_WATCHDOG
+       /* Set up watchdog timer to catch unanswered get_report commands */
+       hrtimer_init(&instance_data->watchdog, CLOCK_MONOTONIC,
+                                                       HRTIMER_MODE_REL);
+       instance_data->watchdog.function = clear_status;
+
+       /* work function to do unlocking */
+       INIT_WORK(&instance_data->work, clear_status_worker);
+#endif
+
+       /* Read F54 Query Data */
+       retval = rmi_read_block(fc->rmi_dev, fc->fd.query_base_addr,
+               (u8 *)&instance_data->query, sizeof(instance_data->query));
+       if (retval < 0) {
+               dev_err(&fc->dev, "Could not read query registers"
+                       " from 0x%04x\n", fc->fd.query_base_addr);
+               return retval;
+       }
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+       /* Initialize the control registers */
+       next_loc = fc->fd.control_base_addr;
+       reg_num = 0;
+       control = &instance_data->control;
+
+       attrs_ctrl_regs_exist[reg_num] = true;
+       reg_num++;
+       control->reg_0 = kzalloc(sizeof(union f54_ad_control_0), GFP_KERNEL);
+       if (!control->reg_0) {
+               dev_err(&fc->dev, "Failed to allocate control registers.");
+               return -ENOMEM;
+       }
+       control->reg_0->address = next_loc;
+       next_loc++;
+
+       if (instance_data->query.touch_controller_family == 0
+                       || instance_data->query.touch_controller_family == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_1 = kzalloc(sizeof(union f54_ad_control_1),
+                                                               GFP_KERNEL);
+               if (!control->reg_1) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_1->address = next_loc;
+               next_loc++;
+       }
+       reg_num++;
+
+       attrs_ctrl_regs_exist[reg_num] = true;
+       reg_num++;
+       control->reg_2 = kzalloc(sizeof(union f54_ad_control_2), GFP_KERNEL);
+       if (!control->reg_2) {
+               dev_err(&fc->dev, "Failed to allocate control registers.");
+               return -ENOMEM;
+       }
+       control->reg_2->address = next_loc += 2;
+
+       if (instance_data->query.has_pixel_touch_threshold_adjustment == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+
+               control->reg_3 = kzalloc(sizeof(union f54_ad_control_3),
+                                                               GFP_KERNEL);
+               if (!control->reg_3) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_3->address = next_loc;
+               next_loc++;
+       }
+       reg_num++;
+
+       if (instance_data->query.touch_controller_family == 0
+               || instance_data->query.touch_controller_family == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_4__6 = kzalloc(sizeof(union f54_ad_control_4__6),
+                                                               GFP_KERNEL);
+               if (!control->reg_4__6) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_4__6->address = next_loc;
+               next_loc+=3;
+       }
+       reg_num++;
+
+       if (instance_data->query.touch_controller_family == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_7 = kzalloc(sizeof(union f54_ad_control_7),
+                                                               GFP_KERNEL);
+               if (!control->reg_7) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_7->address = next_loc;
+               next_loc++;
+       }
+       reg_num++;
+
+       if (instance_data->query.touch_controller_family == 0
+               || instance_data->query.touch_controller_family == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_8__9 = kzalloc(sizeof(union f54_ad_control_8__9),
+                                                               GFP_KERNEL);
+               if (!control->reg_8__9) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_8__9->address = next_loc;
+               next_loc+=sizeof(control->reg_8__9->regs);
+       }
+       reg_num++;
+
+       if (instance_data->query.has_interference_metric == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_10 = kzalloc(sizeof(union f54_ad_control_10),
+                                                               GFP_KERNEL);
+               if (!control->reg_10) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_10->address = next_loc;
+               next_loc++;
+       }
+       reg_num++;
+
+       /* F54 Control Register 11 is reserved */
+       next_loc++;
+
+       if (instance_data->query.has_relaxation_control == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_12__13 = kzalloc(
+                       sizeof(union f54_ad_control_12__13), GFP_KERNEL);
+               if (!control->reg_12__13) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_12__13->address = next_loc;
+               next_loc+=sizeof(control->reg_12__13->regs);
+       }
+       reg_num++;
+
+       if (instance_data->query.has_sensor_assignment == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_14 = kzalloc(sizeof(union f54_ad_control_14),
+                                                               GFP_KERNEL);
+               if (!control->reg_14) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               
+               control->reg_15 = 
+                       kzalloc(sizeof(struct f54_ad_control_15), GFP_KERNEL);
+               if (!control->reg_15) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_15->length = instance_data->query.num_of_rx_electrodes;
+               control->reg_15->regs = 
+                               kzalloc(control->reg_15->length
+                               * sizeof(struct f54_ad_control_15n), GFP_KERNEL);
+               if (!control->reg_15->regs) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               
+               control->reg_16 = 
+                       kzalloc(sizeof(struct f54_ad_control_16), GFP_KERNEL);
+               if (!control->reg_16) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_16->length = instance_data->query.num_of_tx_electrodes;
+               control->reg_16->regs = 
+                               kzalloc(control->reg_16->length
+                               * sizeof(struct f54_ad_control_16n), GFP_KERNEL);
+               if (!control->reg_16->regs) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               
+               control->reg_14->address = next_loc;
+               next_loc++;
+               control->reg_15->address = next_loc;
+               next_loc += control->reg_15->length;
+               control->reg_16->address = next_loc;
+               next_loc += control->reg_16->length;
+       }
+       reg_num++;
+
+       if (instance_data->query.has_sense_frequency_control == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               size = instance_data->query.number_of_sensing_frequencies;
+               
+               control->reg_17 = 
+                       kzalloc(sizeof(struct f54_ad_control_17), GFP_KERNEL);
+               if (!control->reg_17) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_17->length = size;
+               control->reg_17->regs = kzalloc(size * sizeof(struct f54_ad_control_17n), GFP_KERNEL);
+               if (!control->reg_17->regs) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               
+               control->reg_18 = 
+                       kzalloc(sizeof(struct f54_ad_control_18), GFP_KERNEL);
+               if (!control->reg_18) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_18->length = size;
+               control->reg_18->regs = kzalloc(size * sizeof(struct f54_ad_control_18n), GFP_KERNEL);
+               if (!control->reg_18->regs) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               
+               control->reg_19 = 
+                       kzalloc(sizeof(struct f54_ad_control_19), GFP_KERNEL);
+               if (!control->reg_19) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_19->length = size;
+               control->reg_19->regs = kzalloc(size * sizeof(struct f54_ad_control_19n), GFP_KERNEL);
+               if (!control->reg_19->regs) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               
+               control->reg_17->address = next_loc;
+               next_loc += size;
+               control->reg_18->address = next_loc;
+               next_loc += size;
+               control->reg_19->address = next_loc;
+               next_loc += size;
+       }
+       reg_num++;
+
+       attrs_ctrl_regs_exist[reg_num] = true;
+       reg_num++;
+       control->reg_20 = kzalloc(sizeof(union f54_ad_control_20), GFP_KERNEL);
+       control->reg_20->address = next_loc;
+       next_loc++;
+
+       if (instance_data->query.has_sense_frequency_control == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_21 = kzalloc(sizeof(union f54_ad_control_21),
+                                                               GFP_KERNEL);
+               control->reg_21->address = next_loc;
+               next_loc += sizeof(control->reg_21->regs);
+       }
+       reg_num++;
+
+       if (instance_data->query.has_sense_frequency_control == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_22__26 = kzalloc(
+                       sizeof(union f54_ad_control_22__26), GFP_KERNEL);
+               control->reg_22__26->address = next_loc;
+               next_loc+=sizeof(control->reg_22__26->regs);
+       }
+       reg_num++;
+
+       if (instance_data->query.has_iir_filter == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_27 = kzalloc(sizeof(union f54_ad_control_27),
+                                                               GFP_KERNEL);
+               control->reg_27->address = next_loc;
+               next_loc++;
+       }
+       reg_num++;
+
+       if (instance_data->query.has_firmware_noise_mitigation == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_28 = kzalloc(sizeof(union f54_ad_control_28),
+                                                               GFP_KERNEL);
+               control->reg_28->address = next_loc;
+               next_loc += sizeof(control->reg_28->regs);
+       }
+       reg_num++;
+
+       if (instance_data->query.has_cmn_removal == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_29 = kzalloc(sizeof(union f54_ad_control_29),
+                                                               GFP_KERNEL);
+               control->reg_29->address = next_loc;
+               next_loc++;
+       }
+       reg_num++;
+
+       if (instance_data->query.has_cmn_maximum == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_30 = kzalloc(sizeof(union f54_ad_control_30),
+                                                               GFP_KERNEL);
+               control->reg_30->address = next_loc;
+               next_loc++;
+       }
+       reg_num++;
+
+       if (instance_data->query.has_touch_hysteresis == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_31 = kzalloc(sizeof(union f54_ad_control_31),
+                                                               GFP_KERNEL);
+               control->reg_31->address = next_loc;
+               next_loc++;
+       }
+       reg_num++;
+
+       if (instance_data->query.has_interference_metric == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               control->reg_32__35 = kzalloc(
+                       sizeof(union f54_ad_control_32__35), GFP_KERNEL);
+               control->reg_32__35->address = next_loc;
+               next_loc += 8;
+       }
+       reg_num++;
+
+       if (instance_data->query.curve_compensation_mode == 1) {
+               size = max(instance_data->query.num_of_rx_electrodes,
+                               instance_data->query.num_of_tx_electrodes);
+       }
+       if (instance_data->query.curve_compensation_mode == 2)
+               size = instance_data->query.num_of_rx_electrodes;
+       if (instance_data->query.curve_compensation_mode == 1
+                       || instance_data->query.curve_compensation_mode == 2) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               
+               control->reg_36 = 
+                       kzalloc(sizeof(struct f54_ad_control_36), GFP_KERNEL);
+               if (!control->reg_36) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_36->length = size;
+               control->reg_36->regs = kzalloc(size * sizeof(struct f54_ad_control_36n), GFP_KERNEL);
+               if (!control->reg_36->regs) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+
+               control->reg_36->address = next_loc;
+               next_loc += size;
+       }
+       reg_num++;
+
+       if (instance_data->query.curve_compensation_mode == 2) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               
+               control->reg_37 = 
+                       kzalloc(sizeof(struct f54_ad_control_37), GFP_KERNEL);
+               if (!control->reg_37) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_37->length = instance_data->query.num_of_tx_electrodes;
+               control->reg_37->regs = kzalloc(control->reg_37->length
+                                       * sizeof(struct f54_ad_control_37n), GFP_KERNEL);
+               if (!control->reg_37->regs) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+
+               control->reg_37->address = next_loc;
+               next_loc += control->reg_37->length;
+       }
+       reg_num++;
+
+       if (instance_data->query.has_per_frequency_noise_control == 1) {
+               attrs_ctrl_regs_exist[reg_num] = true;
+               
+               control->reg_38 = 
+                       kzalloc(sizeof(struct f54_ad_control_38), GFP_KERNEL);
+               if (!control->reg_38) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_38->length = instance_data->query.number_of_sensing_frequencies;
+               control->reg_38->regs = kzalloc(control->reg_38->length
+                                                       * sizeof(struct f54_ad_control_38n), GFP_KERNEL);
+               if (!control->reg_38->regs) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+
+               control->reg_39 = 
+                       kzalloc(sizeof(struct f54_ad_control_39), GFP_KERNEL);
+               if (!control->reg_39) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_39->length = instance_data->query.number_of_sensing_frequencies;
+               control->reg_39->regs = kzalloc(control->reg_39->length
+                                       * sizeof(struct f54_ad_control_39n), GFP_KERNEL);
+               if (!control->reg_39->regs) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+
+               control->reg_40 = 
+                       kzalloc(sizeof(struct f54_ad_control_40), GFP_KERNEL);
+               if (!control->reg_40) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+               control->reg_40->length = instance_data->query.number_of_sensing_frequencies;
+               control->reg_40->regs = kzalloc(control->reg_40->length
+                                       * sizeof(struct f54_ad_control_40n), GFP_KERNEL);
+               if (!control->reg_40->regs) {
+                       dev_err(&fc->dev, "Failed to allocate control registers.");
+                       return -ENOMEM;
+               }
+
+               control->reg_38->address = next_loc;
+               next_loc += control->reg_38->length;
+               control->reg_39->address = next_loc;
+               next_loc += control->reg_39->length;
+               control->reg_40->address = next_loc;
+               next_loc += control->reg_40->length;
+       }
+       reg_num++;
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+       mutex_init(&instance_data->data_mutex);
+
+       mutex_init(&instance_data->status_mutex);
+
+       mutex_init(&instance_data->control_mutex);
+       
+       return retval;
+}
+
+static void set_report_size(struct rmi_fn_54_data *data)
+{
+       u8 rx = data->query.num_of_rx_electrodes;
+       u8 tx = data->query.num_of_tx_electrodes;
+       switch (data->report_type) {
+       case F54_8BIT_IMAGE:
+               data->report_size = rx * tx;
+               break;
+       case F54_16BIT_IMAGE:
+       case F54_RAW_16BIT_IMAGE:
+       case F54_TRUE_BASELINE:
+       case F54_FULL_RAW_CAP:
+       case F54_FULL_RAW_CAP_RX_COUPLING_COMP:
+               data->report_size = 2 * rx * tx;
+               break;
+       case F54_HIGH_RESISTANCE:
+               data->report_size = RMI_54_HIGH_RESISTANCE_SIZE;
+               break;
+       case F54_FULL_RAW_CAP_MIN_MAX:
+               data->report_size = RMI_54_FULL_RAW_CAP_MIN_MAX_SIZE;
+               break;
+       case F54_TX_TO_TX_SHORT:
+       case F54_TX_OPEN:
+       case F54_TX_TO_GROUND:
+               data->report_size =  (tx + 7) / 8;
+               break;
+       case F54_RX_TO_RX1:
+       case F54_RX_OPENS1:
+               if (rx < tx)
+                       data->report_size = 2 * rx * rx;
+               else
+                       data->report_size = 2 * rx * tx;
+               break;
+       case F54_RX_TO_RX2:
+       case F54_RX_OPENS2:
+               if (rx <= tx)
+                       data->report_size = 0;
+               else
+                       data->report_size = 2 * rx * (rx - tx);
+               break;
+       default:
+               data->report_size = 0;
+       }
+}
+
+int rmi_f54_attention(struct rmi_function_container *fc, u8 *irq_bits)
+{
+       struct rmi_driver *driver = fc->rmi_dev->driver;
+       char fifo[2];
+       struct rmi_fn_54_data *data = fc->data;
+       int error = 0;
+
+       set_report_size(data);
+       if (data->report_size == 0) {
+               dev_err(&fc->dev, "Invalid report type set in %s. "
+                               "This should never happen.\n", __func__);
+               error = -EINVAL;
+               goto error_exit;
+       }
+       /*
+        * We need to ensure the buffer is big enough. A Buffer size of 0 means
+        * that the buffer has not been allocated.
+        */
+       if (data->bufsize < data->report_size) {
+               mutex_lock(&data->data_mutex);
+               if (data->bufsize > 0)
+                       kfree(data->report_data);
+               data->report_data = kzalloc(data->report_size, GFP_KERNEL);
+               if (!data->report_data) {
+                       dev_err(&fc->dev, "Failed to allocate report_data.\n");
+                       error = -ENOMEM;
+                       data->bufsize = 0;
+                       mutex_unlock(&data->data_mutex);
+                       goto error_exit;
+               }
+               data->bufsize = data->report_size;
+               mutex_unlock(&data->data_mutex);
+       }
+       dev_vdbg(&fc->dev, "F54 Interrupt handler is running.\nSize: %d\n",
+                data->report_size);
+       /* Write 0 to fifohi and fifolo. */
+       fifo[0] = 0;
+       fifo[1] = 0;
+       error = rmi_write_block(fc->rmi_dev, fc->fd.data_base_addr
+                               + RMI_F54_FIFO_OFFSET, fifo,    sizeof(fifo));
+       if (error < 0)
+               dev_err(&fc->dev, "Failed to write fifo to zero!\n");
+       else
+               error = rmi_read_block(fc->rmi_dev,
+                       fc->fd.data_base_addr + RMI_F54_REPORT_DATA_OFFSET,
+                       data->report_data, data->report_size);
+       if (error < 0)
+               dev_err(&fc->dev, "F54 data read failed. Code: %d.\n", error);
+       else if (error != data->report_size) {
+               error = -EINVAL;
+               goto error_exit;
+       }
+#if RAW_HEX
+       int l;
+       /* Debugging: Print out the file in hex. */
+       pr_info("Report data (raw hex):\n");
+       for (l = 0; l < data->report_size; l += 2) {
+               pr_info("%03d: 0x%02x%02x\n", l/2,
+                       data->report_data[l+1], data->report_data[l]);
+       }
+#endif
+#if HUMAN_READABLE
+       /* Debugging: Print out file in human understandable image */
+       switch (data->report_type) {
+       case F54_16BIT_IMAGE:
+       case F54_RAW_16BIT_IMAGE:
+       case F54_TRUE_BASELINE:
+       case F54_FULL_RAW_CAP:
+       case F54_FULL_RAW_CAP_RX_COUPLING_COMP:
+               pr_info("Report data (Image):\n");
+               int i, j, k;
+               char c[2];
+               short s;
+               k = 0;
+               for (i = 0; i < data->query.num_of_tx_electrodes;
+                                                                       i++) {
+                       for (j = 0; j <
+                            data->query.num_of_rx_electrodes; j++) {
+                               c[0] = data->report_data[k];
+                               c[1] = data->report_data[k+1];
+                               memcpy(&s, &c, 2);
+                               if (s < -64)
+                                       printk(".");
+                               else if (s < 0)
+                                       printk("-");
+                               else if (s > 64)
+                                       printk("*");
+                               else if (s > 0)
+                                       printk("+");
+                               else
+                                       printk("0");
+                               k += 2;
+                       }
+                       pr_info("\n");
+               }
+               pr_info("EOF\n");
+               break;
+       default:
+               pr_info("Report type %d debug image not supported",
+                                                       data->report_type);
+       }
+#endif
+       error = IDLE;
+error_exit:
+       mutex_lock(&data->status_mutex);
+       /* Turn back on other interupts, if it
+        * appears that we turned them off. */
+       if (driver->restore_irq_mask) {
+               dev_dbg(&fc->dev, "Restoring interupts!\n");
+               driver->restore_irq_mask(fc->rmi_dev);
+       } else {
+               dev_err(&fc->dev, "No way to restore interrupts!\n");
+       }
+       data->status = error;
+       mutex_unlock(&data->status_mutex);
+       return data->status;
+}
+
+
+#if F54_WATCHDOG
+static void clear_status_worker(struct work_struct *work)
+{
+       struct rmi_fn_54_data *data = container_of(work,
+                                       struct rmi_fn_54_data, work);
+       struct rmi_function_container *fc = data->fc;
+       struct rmi_driver *driver = fc->rmi_dev->driver;
+       char command;
+       int result;
+
+       mutex_lock(&data->status_mutex);
+       if (data->status == BUSY) {
+               pr_info("F54 Timout Occured: Determining status.\n");
+               result = rmi_read_block(fc->rmi_dev, fc->fd.command_base_addr,
+                                                               &command, 1);
+               if (result < 0) {
+                       dev_err(&fc->dev, "Could not read get_report register "
+                               "from 0x%04x\n", fc->fd.command_base_addr);
+                       data->status = -ETIMEDOUT;
+               } else {
+                       if (command & GET_REPORT) {
+                               dev_warn(&fc->dev, "Report type unsupported!");
+                               data->status = -EINVAL;
+                       } else {
+                               data->status = -ETIMEDOUT;
+                       }
+               }
+               if (driver->restore_irq_mask) {
+                       dev_dbg(&fc->dev, "Restoring interupts!\n");
+                       driver->restore_irq_mask(fc->rmi_dev);
+               } else {
+                       dev_err(&fc->dev, "No way to restore interrupts!\n");
+               }
+       }
+       mutex_unlock(&data->status_mutex);
+}
+
+static enum hrtimer_restart clear_status(struct hrtimer *timer)
+{
+       struct rmi_fn_54_data *data = container_of(timer,
+                                       struct rmi_fn_54_data, watchdog);
+       schedule_work(&(data->work));
+       return HRTIMER_NORESTART;
+}
+#endif
+
+/* Check if report_type is valid */
+static bool is_report_type_valid(enum f54_report_types reptype)
+{
+       /* Basic checks on report_type to ensure we write a valid type
+        * to the sensor.
+        * TODO: Check Query3 to see if some specific reports are
+        * available. This is currently listed as a reserved register.
+        */
+       switch (reptype) {
+       case F54_8BIT_IMAGE:
+       case F54_16BIT_IMAGE:
+       case F54_RAW_16BIT_IMAGE:
+       case F54_HIGH_RESISTANCE:
+       case F54_TX_TO_TX_SHORT:
+       case F54_RX_TO_RX1:
+       case F54_TRUE_BASELINE:
+       case F54_FULL_RAW_CAP_MIN_MAX:
+       case F54_RX_OPENS1:
+       case F54_TX_OPEN:
+       case F54_TX_TO_GROUND:
+       case F54_RX_TO_RX2:
+       case F54_RX_OPENS2:
+       case F54_FULL_RAW_CAP:
+       case F54_FULL_RAW_CAP_RX_COUPLING_COMP:
+               return true;
+               break;
+       default:
+               return false;
+       }
+}
+
+/* SYSFS file show/store functions */
+static ssize_t rmi_fn_54_report_type_show(struct device *dev,
+                               struct device_attribute *attr, char *buf) {
+       struct rmi_function_container *fc;
+       struct rmi_fn_54_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->report_type);
+}
+
+static ssize_t rmi_fn_54_report_type_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count) {
+       int result;
+       unsigned long val;
+       unsigned char data;
+       struct rmi_function_container *fc;
+       struct rmi_fn_54_data *instance_data;
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       /* need to convert the string data to an actual value */
+       result = strict_strtoul(buf, 10, &val);
+       if (result)
+               return result;
+       if (!is_report_type_valid(val)) {
+               dev_err(dev, "%s : Report type %d is invalid.\n",
+                                       __func__, (u8) val);
+               return -EINVAL;
+       }
+       mutex_lock(&instance_data->status_mutex);
+       if (instance_data->status != BUSY) {
+               instance_data->report_type = (enum f54_report_types)val;
+               data = (char)val;
+               /* Write the Report Type back to the first Block
+                * Data registers (F54_AD_Data0). */
+               result =
+                   rmi_write_block(fc->rmi_dev, fc->fd.data_base_addr,
+                                                               &data, 1);
+               mutex_unlock(&instance_data->status_mutex);
+               if (result < 0) {
+                       dev_err(dev, "%s : Could not write report type to"
+                               " 0x%x\n", __func__, fc->fd.data_base_addr);
+                       return result;
+               }
+               return count;
+       } else {
+               dev_err(dev, "%s : Report type cannot be changed in the middle"
+                               " of command.\n", __func__);
+               mutex_unlock(&instance_data->status_mutex);
+               return -EINVAL;
+       }
+}
+
+static ssize_t rmi_fn_54_get_report_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count) {
+       unsigned long val;
+       int error, result;
+       struct rmi_function_container *fc;
+       struct rmi_fn_54_data *instance_data;
+       struct rmi_driver *driver;
+       u8 command;
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+       driver = fc->rmi_dev->driver;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+       if (error)
+               return error;
+       /* Do nothing if not set to 1. This prevents accidental commands. */
+       if (val != 1)
+               return count;
+       command = (unsigned char)GET_REPORT;
+       /* Basic checks on report_type to ensure we write a valid type
+        * to the sensor.
+        * TODO: Check Query3 to see if some specific reports are
+        * available. This is currently listed as a reserved register.
+        */
+       if (!is_report_type_valid(instance_data->report_type)) {
+               dev_err(dev, "%s : Report type %d is invalid.\n",
+                               __func__, instance_data->report_type);
+               return -EINVAL;
+       }
+       mutex_lock(&instance_data->status_mutex);
+       if (instance_data->status != IDLE) {
+               if (instance_data->status != BUSY) {
+                       dev_err(dev, "F54 status is in an abnormal state: 0x%x",
+                                                       instance_data->status);
+               }
+               mutex_unlock(&instance_data->status_mutex);
+               return count;
+       }
+       /* Store interrupts */
+       /* Do not exit if we fail to turn off interupts. We are likely
+        * to still get useful data. The report data can, however, be
+        * corrupted, and there may be unexpected behavior.
+        */
+       dev_dbg(dev, "Storing and overriding interupts\n");
+       if (driver->store_irq_mask)
+               driver->store_irq_mask(fc->rmi_dev,
+                                       fc->irq_mask);
+       else
+               dev_err(dev, "No way to store interupts!\n");
+       instance_data->status = BUSY;
+
+       /* small delay to avoid race condition in firmare. This value is a bit
+        * higher than absolutely necessary. Should be removed once issue is
+        * resolved in firmware. */
+
+       mdelay(2);
+
+       /* Write the command to the command register */
+       result = rmi_write_block(fc->rmi_dev, fc->fd.command_base_addr,
+                                               &command, 1);
+       mutex_unlock(&instance_data->status_mutex);
+       if (result < 0) {
+               dev_err(dev, "%s : Could not write command to 0x%x\n",
+                               __func__, fc->fd.command_base_addr);
+               return result;
+       }
+#if F54_WATCHDOG
+       /* start watchdog timer */
+       hrtimer_start(&instance_data->watchdog, ktime_set(1, 0),
+                                                       HRTIMER_MODE_REL);
+#endif
+       return count;
+}
+
+static ssize_t rmi_fn_54_force_cal_store(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t count) {
+       unsigned long val;
+       int error, result;
+       struct rmi_function_container *fc;
+       struct rmi_fn_54_data *instance_data;
+       struct rmi_driver *driver;
+       u8 command;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+       driver = fc->rmi_dev->driver;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+       if (error)
+               return error;
+       /* Do nothing if not set to 1. This prevents accidental commands. */
+       if (val != 1)
+               return count;
+
+       command = (unsigned char)FORCE_CAL;
+
+       if (instance_data->status == BUSY)
+               return -EBUSY;
+       /* Write the command to the command register */
+       result = rmi_write_block(fc->rmi_dev, fc->fd.command_base_addr,
+                                               &command, 1);
+       if (result < 0) {
+               dev_err(dev, "%s : Could not write command to 0x%x\n",
+                               __func__, fc->fd.command_base_addr);
+               return result;
+       }
+       return count;
+}
+
+static ssize_t rmi_fn_54_status_show(struct device *dev,
+                               struct device_attribute *attr, char *buf) {
+       struct rmi_function_container *fc;
+       struct rmi_fn_54_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", instance_data->status);
+}
+
+simple_show_union_struct_unsigned(query, num_of_rx_electrodes)
+simple_show_union_struct_unsigned(query, num_of_tx_electrodes)
+simple_show_union_struct_unsigned(query, has_image16)
+simple_show_union_struct_unsigned(query, has_image8)
+simple_show_union_struct_unsigned(query, has_baseline)
+simple_show_union_struct_unsigned(query, clock_rate)
+simple_show_union_struct_unsigned(query, touch_controller_family)
+simple_show_union_struct_unsigned(query, has_pixel_touch_threshold_adjustment)
+simple_show_union_struct_unsigned(query, has_sensor_assignment)
+simple_show_union_struct_unsigned(query, has_interference_metric)
+simple_show_union_struct_unsigned(query, has_sense_frequency_control)
+simple_show_union_struct_unsigned(query, has_firmware_noise_mitigation)
+simple_show_union_struct_unsigned(query, has_two_byte_report_rate)
+simple_show_union_struct_unsigned(query, has_one_byte_report_rate)
+simple_show_union_struct_unsigned(query, has_relaxation_control)
+simple_show_union_struct_unsigned(query, curve_compensation_mode)
+simple_show_union_struct_unsigned(query, has_iir_filter)
+simple_show_union_struct_unsigned(query, has_cmn_removal)
+simple_show_union_struct_unsigned(query, has_cmn_maximum)
+simple_show_union_struct_unsigned(query, has_touch_hysteresis)
+simple_show_union_struct_unsigned(query, has_edge_compensation)
+simple_show_union_struct_unsigned(query, has_per_frequency_noise_control)
+simple_show_union_struct_unsigned(query, number_of_sensing_frequencies)
+
+static ssize_t rmi_fn_54_no_auto_cal_show(struct device *dev,
+                               struct device_attribute *attr, char *buf) {
+       struct rmi_function_container *fc;
+       struct rmi_fn_54_data *data;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+
+       return snprintf(buf, PAGE_SIZE, "%u\n",
+                               data->no_auto_cal ? 1 : 0);
+}
+
+static ssize_t rmi_fn_54_no_auto_cal_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t count) {
+       int result;
+       unsigned long val;
+       unsigned char data;
+       struct rmi_function_container *fc;
+       struct rmi_fn_54_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       /* need to convert the string data to an actual value */
+       result = strict_strtoul(buf, 10, &val);
+
+       /* if an error occured, return it */
+       if (result)
+               return result;
+       /* Do nothing if not 0 or 1. This prevents accidental commands. */
+       if (val > 1)
+               return -EINVAL;
+       /* Read current control values */
+       result =
+           rmi_read_block(fc->rmi_dev, fc->fd.control_base_addr, &data, 1);
+
+       /* if the current control registers are already set as we want them, do
+        * nothing to them */
+       if ((data & NO_AUTO_CAL_MASK) == val)
+               return count;
+       /* Write the control back to the control register (F54_AD_Ctrl0)
+        * Ignores everything but bit 0 */
+       data = (data & ~NO_AUTO_CAL_MASK) | (val & NO_AUTO_CAL_MASK);
+       result =
+           rmi_write_block(fc->rmi_dev, fc->fd.control_base_addr, &data, 1);
+       if (result < 0) {
+               dev_err(dev, "%s : Could not write control to 0x%x\n",
+                      __func__, fc->fd.control_base_addr);
+               return result;
+       }
+       /* update our internal representation iff the write succeeds */
+       instance_data->no_auto_cal = (val == 1);
+       return count;
+}
+
+static ssize_t rmi_fn_54_fifoindex_show(struct device *dev,
+                                 struct device_attribute *attr, char *buf) {
+       struct rmi_function_container *fc;
+       struct rmi_fn_54_data *instance_data;
+       struct rmi_driver *driver;
+       unsigned char temp_buf[2];
+       int retval;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+       driver = fc->rmi_dev->driver;
+
+       /* Read fifoindex from device */
+       retval = rmi_read_block(fc->rmi_dev,
+                               fc->fd.data_base_addr + RMI_F54_FIFO_OFFSET,
+                               temp_buf, ARRAY_SIZE(temp_buf));
+
+       if (retval < 0) {
+               dev_err(dev, "Could not read fifoindex from 0x%04x\n",
+                      fc->fd.data_base_addr + RMI_F54_FIFO_OFFSET);
+               return retval;
+       }
+       batohs(&instance_data->fifoindex, temp_buf);
+       return snprintf(buf, PAGE_SIZE, "%u\n", instance_data->fifoindex);
+}
+static ssize_t rmi_fn_54_fifoindex_store(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf,
+                                       size_t count)
+{
+       int error;
+       unsigned long val;
+       unsigned char data[2];
+       struct rmi_function_container *fc;
+       struct rmi_fn_54_data *instance_data;
+
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+
+       /* need to convert the string data to an actual value */
+       error = strict_strtoul(buf, 10, &val);
+
+       if (error)
+               return error;
+
+       instance_data->fifoindex = val;
+
+       /* Write the FifoIndex back to the first data registers. */
+       hstoba(data, (unsigned short)val);
+
+       error = rmi_write_block(fc->rmi_dev,
+                               fc->fd.data_base_addr + RMI_F54_FIFO_OFFSET,
+                               data,
+                               ARRAY_SIZE(data));
+
+       if (error < 0) {
+               dev_err(dev, "%s : Could not write fifoindex to 0x%x\n",
+                      __func__, fc->fd.data_base_addr + RMI_F54_FIFO_OFFSET);
+               return error;
+       }
+       return count;
+}
+
+/* Provide access to last report */
+#ifdef KERNEL_VERSION_ABOVE_2_6_32
+static ssize_t rmi_fn_54_data_read(struct file *data_file, struct kobject *kobj,
+                               struct bin_attribute *attributes,
+                               char *buf, loff_t pos, size_t count)
+#else
+static ssize_t rmi_fn_54_data_read(struct kobject *kobj,
+                               struct bin_attribute *attributes,
+                               char *buf, loff_t pos, size_t count)
+#endif
+{
+       struct device *dev;
+       struct rmi_function_container *fc;
+       struct rmi_fn_54_data *instance_data;
+
+       dev = container_of(kobj, struct device, kobj);
+       fc = to_rmi_function_container(dev);
+       instance_data = fc->data;
+       mutex_lock(&instance_data->data_mutex);
+       if (count < instance_data->report_size) {
+               dev_err(dev,
+                       "%s: F54 report size too large for buffer: %d."
+                               " Need at least: %d for Report type: %d.\n",
+                       __func__, count, instance_data->report_size,
+                       instance_data->report_type);
+               mutex_unlock(&instance_data->data_mutex);
+               return -EINVAL;
+       }
+       if (instance_data->report_data) {
+               /* Copy data from instance_data to buffer */
+               memcpy(buf, instance_data->report_data,
+                                       instance_data->report_size);
+               mutex_unlock(&instance_data->data_mutex);
+               dev_dbg(dev, "%s: Presumably successful.", __func__);
+               return instance_data->report_size;
+       } else {
+               dev_err(dev, "%s: F54 report_data does not exist!\n", __func__);
+               mutex_unlock(&instance_data->data_mutex);
+               return -EINVAL;
+       }
+}
+
+/* Repeated Register sysfs functions */
+show_repeated_union_struct_unsigned(control, reg_15, sensor_rx_assignment)
+show_repeated_union_struct_unsigned(control, reg_16, sensor_tx_assignment)
+
+show_repeated_union_struct_unsigned(control, reg_17, filter_bandwidth)
+show_repeated_union_struct_unsigned(control, reg_17, disable)
+
+
+static ssize_t rmi_fn_54_burst_count_show(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf) {
+       struct rmi_function_container *fc;
+       struct rmi_fn_54_data *data;
+       int result, size = 0;
+       char *temp;
+       int i;
+
+       fc = to_rmi_function_container(dev);
+       data = fc->data;
+       mutex_lock(&data->control_mutex);
+       /* Read current control values */
+       result = rmi_read_block(fc->rmi_dev, data->control.reg_17->address,
+                       (u8 *) data->control.reg_17->regs,
+                       data->control.reg_17->length * sizeof(u8));
+       if (result < 0) {
+               dev_err(dev, "%s : Could not read control at 0x%x\n"
+                                       "Data may be outdated.", __func__,
+                                       data->control.reg_17->address);
+       }
+
+       result = rmi_read_block(fc->rmi_dev, data->control.reg_18->address,
+                       (u8 *)data->control.reg_18->regs,
+                       data->control.reg_18->length * sizeof(u8));
+       if (result < 0) {
+               dev_err(dev, "%s : Could not read control at 0x%x\n"
+                                       "Data may be outdated.", __func__,
+                                       data->control.reg_18->address);
+       }
+       mutex_unlock(&data->control_mutex);
+       temp = buf;
+       for (i = 0; i < data->control.reg_17->length; i++) {
+               result = snprintf(temp, PAGE_SIZE - size, "%u ",
+                       (1<<8) * data->control.reg_17->regs[i].burst_countb10__8
+                               + data->control.reg_18->regs[i].burst_countb7__0n);
+               size += result;
+               temp += result;
+       }
+       return size + snprintf(temp, PAGE_SIZE - size, "\n");
+}
+
+show_repeated_union_struct_unsigned(control, reg_19, stretch_duration)
+show_store_repeated_union_struct_unsigned(control, reg_36, axis1_comp)
+show_store_repeated_union_struct_unsigned(control, reg_37, axis2_comp)
+
+show_repeated_union_struct_unsigned(control, reg_38, noise_control_1)
+show_repeated_union_struct_unsigned(control, reg_39, noise_control_2)
+show_repeated_union_struct_unsigned(control, reg_40, noise_control_3)
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+show_store_union_struct_unsigned(control, reg_0, no_relax)
+show_store_union_struct_unsigned(control, reg_0, no_scan)
+show_store_union_struct_unsigned(control, reg_1, bursts_per_cluster)
+show_store_union_struct_unsigned(control, reg_2, saturation_cap)
+show_store_union_struct_unsigned(control, reg_3, pixel_touch_threshold)
+show_store_union_struct_unsigned(control, reg_4__6, rx_feedback_cap)
+show_store_union_struct_unsigned(control, reg_4__6, low_ref_cap)
+show_store_union_struct_unsigned(control, reg_4__6, low_ref_feedback_cap)
+show_store_union_struct_unsigned(control, reg_4__6, low_ref_polarity)
+show_store_union_struct_unsigned(control, reg_4__6, high_ref_cap)
+show_store_union_struct_unsigned(control, reg_4__6, high_ref_feedback_cap)
+show_store_union_struct_unsigned(control, reg_4__6, high_ref_polarity)
+show_store_union_struct_unsigned(control, reg_7, cbc_cap)
+show_store_union_struct_unsigned(control, reg_7, cbc_polarity)
+show_store_union_struct_unsigned(control, reg_7, cbc_tx_carrier_selection)
+show_store_union_struct_unsigned(control, reg_8__9, integration_duration)
+show_store_union_struct_unsigned(control, reg_8__9, reset_duration)
+show_store_union_struct_unsigned(control, reg_10, noise_sensing_bursts_per_image)
+show_store_union_struct_unsigned(control, reg_12__13, slow_relaxation_rate)
+show_store_union_struct_unsigned(control, reg_12__13, fast_relaxation_rate)
+show_store_union_struct_unsigned(control, reg_14, rxs_on_xaxis)
+show_store_union_struct_unsigned(control, reg_14, curve_comp_on_txs)
+show_store_union_struct_unsigned(control, reg_20, disable_noise_mitigation)
+show_store_union_struct_unsigned(control, reg_21, freq_shift_noise_threshold)
+show_store_union_struct_unsigned(control, reg_22__26, noise_density_threshold)
+show_store_union_struct_unsigned(control, reg_22__26, medium_noise_threshold)
+show_store_union_struct_unsigned(control, reg_22__26, high_noise_threshold)
+show_store_union_struct_unsigned(control, reg_22__26, noise_density)
+show_store_union_struct_unsigned(control, reg_22__26, frame_count)
+show_store_union_struct_unsigned(control, reg_27, iir_filter_coef)
+show_store_union_struct_unsigned(control, reg_28, quiet_threshold)
+show_store_union_struct_unsigned(control, reg_29, cmn_filter_disable)
+show_store_union_struct_unsigned(control, reg_30, cmn_filter_max)
+show_store_union_struct_unsigned(control, reg_31, touch_hysteresis)
+show_store_union_struct_unsigned(control, reg_32__35, rx_low_edge_comp)
+show_store_union_struct_unsigned(control, reg_32__35, rx_high_edge_comp)
+show_store_union_struct_unsigned(control, reg_32__35, tx_low_edge_comp)
+show_store_union_struct_unsigned(control, reg_32__35, tx_high_edge_comp)
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+static struct rmi_function_handler function_handler = {
+       .func = 0x54,
+       .init = rmi_f54_init,
+       .config = NULL,
+       .reset = rmi_f54_reset,
+       .attention = rmi_f54_attention,
+       .remove = rmi_f54_remove
+};
+
+static int __init rmi_f54_module_init(void)
+{
+       int error;
+
+       error = rmi_register_function_driver(&function_handler);
+       if (error < 0) {
+               pr_err("%s: register failed!\n", __func__);
+               return error;
+       }
+       return 0;
+}
+
+static void rmi_f54_module_exit(void)
+{
+       rmi_unregister_function_driver(&function_handler);
+}
+
+module_init(rmi_f54_module_init);
+module_exit(rmi_f54_module_exit);
+
+MODULE_AUTHOR("Daniel Rosenberg <daniel.rosenberg@synaptics.com>");
+MODULE_DESCRIPTION("RMI F54 module");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
+
diff --git a/drivers/input/touchscreen/rmi4/rmi_i2c.c b/drivers/input/touchscreen/rmi4/rmi_i2c.c
new file mode 100755 (executable)
index 0000000..52c308f
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2011 Synaptics Incorporated
+ * Copyright (c) 2011 Unixphere
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#define COMMS_DEBUG 0
+
+#define IRQ_DEBUG 0
+
+#if COMMS_DEBUG || IRQ_DEBUG
+#define DEBUG
+#endif
+
+#include <linux/kernel.h>
+#include <linux/lockdep.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/gpio.h>
+#include <linux/rmi.h>
+#include "rmi_driver.h"
+#define RMI_PAGE_SELECT_REGISTER 0xff
+#define RMI_I2C_PAGE(addr) (((addr) >> 8) & 0xff)
+#ifndef CONFIG_RMI4_I2C_SCL_RATE
+#define CONFIG_RMI4_I2C_SCL_RATE 100000  // 100kHz
+#endif
+
+
+static char *phys_proto_name = "i2c";
+
+struct rmi_i2c_data {
+       struct mutex page_mutex;
+       int page;
+       int enabled;
+       int irq;
+       int irq_flags;
+       struct rmi_phys_device *phys;
+};
+
+static irqreturn_t rmi_i2c_irq_thread(int irq, void *p)
+{
+       struct rmi_phys_device *phys = p;
+       struct rmi_device *rmi_dev = phys->rmi_dev;
+       struct rmi_driver *driver = rmi_dev->driver;
+       struct rmi_device_platform_data *pdata = phys->dev->platform_data;
+
+#if IRQ_DEBUG
+       dev_dbg(phys->dev, "ATTN gpio, value: %d.\n",
+                       gpio_get_value(pdata->attn_gpio));
+#endif
+       if (gpio_get_value(pdata->attn_gpio) == pdata->attn_polarity) {
+               phys->info.attn_count++;
+               if (driver && driver->irq_handler && rmi_dev)
+                       driver->irq_handler(rmi_dev, irq);
+       }
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * rmi_set_page - Set RMI page
+ * @phys: The pointer to the rmi_phys_device struct
+ * @page: The new page address.
+ *
+ * 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.
+ *
+ * The page_mutex lock must be held when this function is entered.
+ *
+ * Returns zero on success, non-zero on failure.
+ */
+static int rmi_set_page(struct rmi_phys_device *phys, unsigned int page)
+{
+       struct i2c_client *client = to_i2c_client(phys->dev);
+       struct rmi_i2c_data *data = phys->data;
+       char txbuf[2] = {RMI_PAGE_SELECT_REGISTER, page};
+       int retval;
+
+#if COMMS_DEBUG
+       dev_dbg(&client->dev, "RMI4 I2C writes 3 bytes: %02x %02x\n",
+               txbuf[0], txbuf[1]);
+#endif
+       phys->info.tx_count++;
+       phys->info.tx_bytes += sizeof(txbuf);
+       retval = i2c_master_normal_send(client, txbuf, sizeof(txbuf), CONFIG_RMI4_I2C_SCL_RATE);
+       if (retval != sizeof(txbuf)) {
+               phys->info.tx_errs++;
+               dev_err(&client->dev,
+                       "%s: set page failed: %d.", __func__, retval);
+               return (retval < 0) ? retval : -EIO;
+       }
+       data->page = page;
+       return 0;
+}
+
+int rmi_i2c_write_block(struct rmi_phys_device *phys, u16 addr, u8 *buf,
+                              int len)
+{
+       struct i2c_client *client = to_i2c_client(phys->dev);
+       struct rmi_i2c_data *data = phys->data;
+       u8 txbuf[len + 1];
+       int retval;
+#if    COMMS_DEBUG
+       int i;
+#endif
+
+       txbuf[0] = addr & 0xff;
+       memcpy(txbuf + 1, buf, len);
+
+       mutex_lock(&data->page_mutex);
+
+       if (RMI_I2C_PAGE(addr) != data->page) {
+               retval = rmi_set_page(phys, RMI_I2C_PAGE(addr));
+               if (retval < 0)
+                       goto exit;
+       }
+
+#if COMMS_DEBUG
+       dev_dbg(&client->dev, "RMI4 I2C writes %d bytes: ", sizeof(txbuf));
+       for (i = 0; i < sizeof(txbuf); i++)
+               dev_dbg(&client->dev, "%02x ", txbuf[i]);
+       dev_dbg(&client->dev, "\n");
+#endif
+
+       phys->info.tx_count++;
+       phys->info.tx_bytes += sizeof(txbuf);
+       retval = i2c_master_normal_send(client, txbuf, sizeof(txbuf), CONFIG_RMI4_I2C_SCL_RATE);
+       if (retval < 0)
+               phys->info.tx_errs++;
+       else
+               retval--; /* don't count the address byte */
+
+exit:
+       mutex_unlock(&data->page_mutex);
+       return retval;
+}
+
+static int rmi_i2c_write(struct rmi_phys_device *phys, u16 addr, u8 data)
+{
+       int retval = rmi_i2c_write_block(phys, addr, &data, 1);
+       return (retval < 0) ? retval : 0;
+}
+
+int rmi_i2c_read_block(struct rmi_phys_device *phys, u16 addr, u8 *buf,
+                             int len)
+{
+       struct i2c_client *client = to_i2c_client(phys->dev);
+       struct rmi_i2c_data *data = phys->data;
+       u8 txbuf[1] = {addr & 0xff};
+       int retval;
+#if    COMMS_DEBUG
+       int i;
+#endif
+
+       mutex_lock(&data->page_mutex);
+
+       if (RMI_I2C_PAGE(addr) != data->page) {
+               retval = rmi_set_page(phys, RMI_I2C_PAGE(addr));
+               if (retval < 0)
+                       goto exit;
+       }
+
+#if COMMS_DEBUG
+       dev_dbg(&client->dev, "RMI4 I2C writes 1 bytes: %02x\n", txbuf[0]);
+#endif
+       phys->info.tx_count++;
+       phys->info.tx_bytes += sizeof(txbuf);
+       retval = i2c_master_normal_send(client, txbuf, sizeof(txbuf), CONFIG_RMI4_I2C_SCL_RATE);
+       if (retval != sizeof(txbuf)) {
+               phys->info.tx_errs++;
+               retval = (retval < 0) ? retval : -EIO;
+               goto exit;
+       }
+
+       retval = i2c_master_normal_recv(client, buf, len, CONFIG_RMI4_I2C_SCL_RATE);
+
+       phys->info.rx_count++;
+       phys->info.rx_bytes += len;
+       if (retval < 0)
+               phys->info.rx_errs++;
+#if COMMS_DEBUG
+       else {
+               dev_dbg(&client->dev, "RMI4 I2C received %d bytes: ", len);
+               for (i = 0; i < len; i++)
+                       dev_dbg(&client->dev, "%02x ", buf[i]);
+               dev_dbg(&client->dev, "\n");
+       }
+#endif
+
+exit:
+       mutex_unlock(&data->page_mutex);
+       return retval;
+}
+
+static int rmi_i2c_read(struct rmi_phys_device *phys, u16 addr, u8 *buf)
+{
+       int retval = rmi_i2c_read_block(phys, addr, buf, 1);
+       return (retval < 0) ? retval : 0;
+}
+
+static int acquire_attn_irq(struct rmi_i2c_data *data)
+{
+       return request_threaded_irq(data->irq, NULL, rmi_i2c_irq_thread,
+                       data->irq_flags, dev_name(data->phys->dev), data->phys);
+}
+
+static int enable_device(struct rmi_phys_device *phys)
+{
+       int retval = 0;
+
+       struct rmi_i2c_data *data = phys->data;
+
+       if (data->enabled)
+               return 0;
+
+       retval = acquire_attn_irq(data);
+       if (retval)
+               goto error_exit;
+
+       data->enabled = true;
+       dev_dbg(phys->dev, "Physical device enabled.\n");
+       return 0;
+
+error_exit:
+       dev_err(phys->dev, "Failed to enable physical device. Code=%d.\n",
+               retval);
+       return retval;
+}
+
+static void disable_device(struct rmi_phys_device *phys)
+{
+       struct rmi_i2c_data *data = phys->data;
+
+       if (!data->enabled)
+               return;
+
+       disable_irq(data->irq);
+       free_irq(data->irq, data->phys);
+
+       dev_dbg(phys->dev, "Physical device disabled.\n");
+       data->enabled = false;
+}
+
+void CompleteReflash(struct rmi_phys_device *phys);
+
+static int __devinit rmi_i2c_probe(struct i2c_client *client,
+                                 const struct i2c_device_id *id)
+{
+       struct rmi_phys_device *rmi_phys;
+       struct rmi_i2c_data *data;
+       struct rmi_device_platform_data *pdata = client->dev.platform_data;
+       int error;
+
+       if (!pdata) {
+               dev_err(&client->dev, "no platform data\n");
+               return -EINVAL;
+       }
+       pr_info("%s: Probing %s at %#02x (IRQ %d).\n", __func__,
+               pdata->sensor_name ? pdata->sensor_name : "-no name-",
+               client->addr, pdata->attn_gpio);
+
+       error = i2c_check_functionality(client->adapter, I2C_FUNC_I2C);
+       if (!error) {
+               dev_err(&client->dev, "i2c_check_functionality error %d.\n",
+                       error);
+               return error;
+       }
+
+       rmi_phys = kzalloc(sizeof(struct rmi_phys_device), GFP_KERNEL);
+       if (!rmi_phys)
+               return -ENOMEM;
+
+       data = kzalloc(sizeof(struct rmi_i2c_data), GFP_KERNEL);
+       if (!data) {
+               error = -ENOMEM;
+               goto err_phys;
+       }
+
+       data->enabled = true;   /* We plan to come up enabled. */
+       data->irq = gpio_to_irq(pdata->attn_gpio);
+       if (pdata->level_triggered) {
+               data->irq_flags = IRQF_ONESHOT |
+                       ((pdata->attn_polarity == RMI_ATTN_ACTIVE_HIGH) ?
+                       IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW);
+       } else {
+               data->irq_flags =
+                       (pdata->attn_polarity == RMI_ATTN_ACTIVE_HIGH) ?
+                       IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
+       }
+       data->phys = rmi_phys;
+
+       rmi_phys->data = data;
+       rmi_phys->dev = &client->dev;
+
+       rmi_phys->write = rmi_i2c_write;
+       rmi_phys->write_block = rmi_i2c_write_block;
+       rmi_phys->read = rmi_i2c_read;
+       rmi_phys->read_block = rmi_i2c_read_block;
+       rmi_phys->enable_device = enable_device;
+       rmi_phys->disable_device = disable_device;
+
+       rmi_phys->info.proto = phys_proto_name;
+
+       mutex_init(&data->page_mutex);
+
+       /* Setting the page to zero will (a) make sure the PSR is in a
+        * known state, and (b) make sure we can talk to the device.
+        */
+       error = rmi_set_page(rmi_phys, 0);
+       if (error) {
+               dev_err(&client->dev, "Failed to set page select to 0.\n");
+               goto err_data;
+       }
+
+       if (pdata->gpio_config) {
+               error = pdata->gpio_config(pdata->gpio_data, true);
+               if (error < 0) {
+                       dev_err(&client->dev, "failed to setup irq %d\n",
+                               pdata->attn_gpio);
+                       goto err_data;
+               }
+       }
+
+       error = rmi_register_phys_device(rmi_phys);
+       if (error) {
+               dev_err(&client->dev,
+                       "failed to register physical driver at 0x%.2X.\n",
+                       client->addr);
+               goto err_gpio;
+       }
+       i2c_set_clientdata(client, rmi_phys);
+
+       if (pdata->attn_gpio > 0) {
+               error = acquire_attn_irq(data);
+               if (error < 0) {
+                       dev_err(&client->dev,
+                               "request_threaded_irq failed %d\n",
+                               pdata->attn_gpio);
+                       goto err_unregister;
+               }
+       }
+
+#if defined(CONFIG_RMI4_DEV)
+       error = gpio_export(pdata->attn_gpio, false);
+       if (error) {
+               dev_warn(&client->dev, "%s: WARNING: Failed to "
+                                "export ATTN gpio!\n", __func__);
+               error = 0;
+       } else {
+               error = gpio_export_link(&(rmi_phys->rmi_dev->dev), "attn",
+                                       pdata->attn_gpio);
+               if (error) {
+                       dev_warn(&(rmi_phys->rmi_dev->dev),
+                                "%s: WARNING: Failed to symlink ATTN gpio!\n",
+                                __func__);
+                       error = 0;
+               } else {
+                       dev_info(&(rmi_phys->rmi_dev->dev),
+                               "%s: Exported GPIO %d.", __func__,
+                               pdata->attn_gpio);
+               }
+       }
+#endif /* CONFIG_RMI4_DEV */
+
+       dev_info(&client->dev, "registered rmi i2c driver at 0x%.2X.\n",
+                       client->addr);
+       //reflash the new firmware revision  hhb@rock-chips.com
+#ifdef CONFIG_RMI4_REFLASH_WHEN_BOOT
+       CompleteReflash(rmi_phys);
+#endif
+       return 0;
+
+err_unregister:
+       rmi_unregister_phys_device(rmi_phys);
+err_gpio:
+       if (pdata->gpio_config)
+               pdata->gpio_config(pdata->gpio_data, false);
+err_data:
+       kfree(data);
+err_phys:
+       kfree(rmi_phys);
+       return error;
+}
+
+static int __devexit rmi_i2c_remove(struct i2c_client *client)
+{
+       struct rmi_phys_device *phys = i2c_get_clientdata(client);
+       struct rmi_device_platform_data *pd = client->dev.platform_data;
+
+       disable_device(phys);
+       rmi_unregister_phys_device(phys);
+       kfree(phys->data);
+       kfree(phys);
+
+       if (pd->gpio_config)
+               pd->gpio_config(&pd->gpio_data, false);
+
+       return 0;
+}
+
+static const struct i2c_device_id rmi_id[] = {
+       { "rmi", 0 },
+       { "rmi_i2c", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, rmi_id);
+
+static struct i2c_driver rmi_i2c_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "rmi_i2c"
+       },
+       .id_table       = rmi_id,
+       .probe          = rmi_i2c_probe,
+       .remove         = __devexit_p(rmi_i2c_remove),
+};
+
+static int __init rmi_i2c_init(void)
+{
+       return i2c_add_driver(&rmi_i2c_driver);
+}
+
+static void __exit rmi_i2c_exit(void)
+{
+       i2c_del_driver(&rmi_i2c_driver);
+}
+
+module_init(rmi_i2c_init);
+module_exit(rmi_i2c_exit);
+
+MODULE_AUTHOR("Christopher Heiny <cheiny@synaptics.com>");
+MODULE_DESCRIPTION("RMI I2C driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
diff --git a/drivers/input/touchscreen/rmi4/rmi_reflash.c b/drivers/input/touchscreen/rmi4/rmi_reflash.c
new file mode 100644 (file)
index 0000000..c10525f
--- /dev/null
@@ -0,0 +1,670 @@
+/*
+   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   Copyright (c) 2011 Synaptics, Inc.
+
+   Permission is hereby granted, free of charge, to any person obtaining a copy of
+   this software and associated documentation files (the "Software"), to deal in
+   the Software without restriction, including without limitation the rights to use,
+   copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
+   Software, and to permit persons to whom the Software is furnished to do so,
+   subject to the following conditions:
+
+   The above copyright notice and this permission notice shall be included in all
+   copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+   SOFTWARE.
+
+
+   +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+*/
+
+// SynaFirmwareImage.h contains the data for both the entire image and the config block
+//#include "SynaFirmwareImage.h"
+//#include "config.h"
+
+#include <linux/string.h>
+//#include <linux/printk.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/rmi.h>
+#include "rmi_reflash.h"
+
+//need
+#define ASSERT 1
+#define  TOUCH_CONTROLLER  "s3202"
+#define FW_REVISION  "DS4 R3.0"
+
+void eraseConfigBlock(void);
+void SynaInitialize(void);
+void SynaReadConfigInfo(void);
+void SynaReadFirmwareInfo(void);
+int TouchControllerTypeCheck(void);
+void SynaEnableFlashing(void);
+int fimrwareRevisionCheck(void);
+void SynaBootloaderLock(void);
+void SynaProgramConfiguration(void);
+void SynaProgramFirmware(void);
+void SynaFinalizeReflash(void);
+void SynaWaitForATTN(void);
+void convertConfigBlockData(void);
+int rmi_i2c_read_block(struct rmi_phys_device *phys, u16 addr, u8 *buf,
+                             int len);
+int rmi_i2c_write_block(struct rmi_phys_device *phys, u16 addr, u8 *buf,
+                              int len);
+/* Variables for F34 functionality */
+unsigned short SynaF34DataBase;
+unsigned short SynaF34QueryBase;
+unsigned short SynaF01DataBase;
+unsigned short SynaF01CommandBase;
+unsigned short SynaF01QueryBase;
+
+unsigned short SynaF34Reflash_BlockNum;
+unsigned short SynaF34Reflash_BlockData;
+unsigned short SynaF34ReflashQuery_BootID;
+unsigned short SynaF34ReflashQuery_FlashPropertyQuery;
+unsigned short SynaF34ReflashQuery_FirmwareBlockSize;
+unsigned short SynaF34ReflashQuery_FirmwareBlockCount;
+unsigned short SynaF34ReflashQuery_ConfigBlockSize;
+unsigned short SynaF34ReflashQuery_ConfigBlockCount;
+
+unsigned short SynaFirmwareBlockSize;
+unsigned short SynaFirmwareBlockCount;
+unsigned long SynaImageSize;
+
+unsigned short SynaConfigBlockSize;
+unsigned short SynaConfigBlockCount;
+unsigned long SynaConfigImageSize;
+
+unsigned short SynaBootloadID;
+
+unsigned short SynaF34_FlashControl;
+
+unsigned char *SynafirmwareImgData;
+unsigned char *SynaconfigImgData;
+unsigned char *SynalockImgData;
+unsigned int SynafirmwareImgVersion;
+
+unsigned char *ConfigBlock;
+
+unsigned char *ConfigBlockData;
+struct rmi_phys_device *rmi_phys;
+
+
+
+int readRMI(u16 addr, u8 *buf, int len) {
+       rmi_i2c_read_block(rmi_phys, addr, buf, len);
+       return 0;
+}
+
+int writeRMI(u16 addr, u8 *buf, int len) {
+       rmi_i2c_write_block(rmi_phys, addr, buf, len);
+       return 0;
+}
+
+int waitATTN(u8 n, u16 delay) {
+#if 1
+       unsigned char uStatus;
+       do{
+               readRMI((SynaF01DataBase + 1), &uStatus, 1);
+       }while((uStatus & 0x01) == 0);
+#else
+       msleep(1);
+#endif
+       return 0;
+}
+
+/* End: Variables for F34 functionality */
+
+/* CompleteReflash reflashes the entire user image, including the configuration block and firmware
+*/
+void CompleteReflash(struct rmi_phys_device *phys)
+{
+       rmi_phys = phys;
+       SynaInitialize();
+
+       //if (TouchControllerTypeCheck())
+       {
+               if (fimrwareRevisionCheck())
+               {
+                       printk("rmi find the current firmware revision is old, reflash now...");
+                       SynaReadConfigInfo();
+                       SynaReadFirmwareInfo();
+                       SynaF34_FlashControl = SynaF34DataBase + SynaFirmwareBlockSize + 2;
+                       SynaEnableFlashing();
+                       SynaBootloaderLock();
+                       SynaProgramFirmware();
+                       SynaProgramConfiguration();
+                       SynaFinalizeReflash();
+               }
+       }
+}
+
+/* SynaSetup scans the Page Description Table (PDT) and sets up the necessary variables
+ * for the reflash process. This function is a "slim" version of the PDT scan function in
+ * in PDT.c, since only F34 and F01 are needed for reflash.
+ */
+void SynaSetup(void)
+{
+    unsigned char address;
+    unsigned char buffer[6] = {0};
+
+       for (address = 0xe9; address > 0xc0; address = address - 6)
+       {
+       readRMI(address, buffer, 6);
+
+               switch (buffer[5])
+               {
+                       case 0x34:
+                               SynaF34DataBase = buffer[3];
+                               SynaF34QueryBase = buffer[0];
+                               break;
+                       case 0x01:
+                               SynaF01DataBase = buffer[3];
+                               SynaF01CommandBase = buffer[1];
+                               SynaF01QueryBase = buffer[0];
+                               break;
+               }
+       }
+
+    SynaF34Reflash_BlockNum = SynaF34DataBase;
+       SynaF34Reflash_BlockData = SynaF34DataBase + 2;
+       SynaF34ReflashQuery_BootID = SynaF34QueryBase;
+       SynaF34ReflashQuery_FlashPropertyQuery = SynaF34QueryBase + 2;
+       SynaF34ReflashQuery_FirmwareBlockSize = SynaF34QueryBase + 3;
+       SynaF34ReflashQuery_FirmwareBlockCount = SynaF34QueryBase +5;
+       SynaF34ReflashQuery_ConfigBlockSize = SynaF34QueryBase + 3;
+       SynaF34ReflashQuery_ConfigBlockCount = SynaF34QueryBase + 7;
+
+       SynafirmwareImgData = (unsigned char *)((&SynaFirmware[0])+0x100);
+    SynaconfigImgData   = (unsigned char *)(SynafirmwareImgData+SynaImageSize);
+    SynafirmwareImgVersion = (unsigned int)(SynaFirmware[7]);
+    ConfigBlockData =  SynaconfigImgData;
+       switch (SynafirmwareImgVersion)
+       {
+          case 2:
+              SynalockImgData = (unsigned char *)((&SynaFirmware[0]) + 0xD0);
+                  break;
+       case 3:
+          case 4:
+              SynalockImgData = (unsigned char *)((&SynaFirmware[0]) + 0xC0);
+                  break;
+          case 5:
+                  SynalockImgData = (unsigned char *)((&SynaFirmware[0]) + 0xB0);
+       default: break;
+       }
+}
+
+/* SynaInitialize sets up the reflahs process
+ */
+void SynaInitialize(void)
+{
+       unsigned char uData[2];
+       unsigned char uStatus = 0;
+
+    //printk("\nInitializing Reflash Process...");
+    uData[0] = 0;
+       writeRMI(0xff, uData, 1); // switch to page0    //hhb
+
+       do {
+               readRMI(0, &uStatus, 1);
+
+               if (uStatus & 0x80)
+               {
+                       break;
+               }
+       } while (uStatus & 0x40);
+       SynaSetup();
+
+       SynafirmwareImgData = 0;
+
+       SynaconfigImgData = 0;
+
+       readRMI(SynaF34ReflashQuery_FirmwareBlockSize, &uData[0], 2);
+
+       SynaFirmwareBlockSize = uData[0] | (uData[1] << 8);
+}
+
+/* SynaReadFirmwareInfo reads the F34 query registers and retrieves the block size and count
+ * of the firmware section of the image to be reflashed
+ */
+void SynaReadFirmwareInfo(void)
+{
+       unsigned char uData[2];
+
+    printk("Read Firmware Info\n");
+
+       readRMI(SynaF34ReflashQuery_FirmwareBlockSize, &uData[0], 2);
+       SynaFirmwareBlockSize = uData[0] | (uData[1] << 8);
+
+       readRMI(SynaF34ReflashQuery_FirmwareBlockCount, &uData[0], 2);
+       SynaFirmwareBlockCount = uData[0] | (uData[1] << 8);
+       SynaImageSize = SynaFirmwareBlockCount * SynaFirmwareBlockSize;
+       printk("SynaFirmwareBlockSize:%d,SynaFirmwareBlockCount:%d \n", SynaFirmwareBlockSize, SynaFirmwareBlockCount);
+}
+
+/* SynaReadConfigInfo reads the F34 query registers and retrieves the block size and count
+ * of the configuration section of the image to be reflashed
+ */
+void SynaReadConfigInfo(void)
+{
+       unsigned char uData[2];
+
+    printk("Read Config Info\n");
+
+       readRMI(SynaF34ReflashQuery_ConfigBlockSize, &uData[0], 2);
+       SynaConfigBlockSize = uData[0] | (uData[1] << 8);
+
+       readRMI(SynaF34ReflashQuery_ConfigBlockCount, &uData[0], 2);
+       SynaConfigBlockCount = uData[0] | (uData[1] << 8);
+       SynaConfigImageSize = SynaConfigBlockCount * SynaConfigBlockSize;
+       printk("SynaConfigBlockSize:%d,SynaConfigBlockCount:%d \n", SynaConfigBlockSize, SynaConfigBlockCount);
+}
+
+
+/* SynaReadBootloadID reads the F34 query registers and retrieves the bootloader ID of the firmware
+ */
+void SynaReadBootloadID(void)
+{
+       unsigned char uData[2];
+
+       readRMI(SynaF34ReflashQuery_BootID, &uData[0], 2);
+       SynaBootloadID = uData[0] + uData[1] * 0x100;
+}
+
+/* SynaWriteBootloadID writes the bootloader ID to the F34 data register to unlock the reflash process
+ */
+void SynaWriteBootloadID(void)
+{
+       unsigned char uData[2];
+
+       uData[0] = SynaBootloadID % 0x100;
+       uData[1] = SynaBootloadID / 0x100;
+
+       writeRMI(SynaF34Reflash_BlockData, &uData[0], 2);
+}
+
+/* SynaEnableFlashing kicks off the reflash process
+ */
+void SynaEnableFlashing(void)
+{
+       unsigned char uData = 0;
+       unsigned char uStatus = 0;
+
+    printk("Enable Reflash...\n");
+
+       // Reflash is enabled by first reading the bootloader ID from the firmware and write it back
+       SynaReadBootloadID();
+       SynaWriteBootloadID();
+       // Make sure Reflash is not already enabled
+       do {
+               readRMI(SynaF34_FlashControl, &uData, 1);
+       } while (((uData & 0x0f) != 0x00));
+       // Clear ATTN
+    readRMI (SynaF01DataBase, &uStatus, 1);
+
+       if ((uStatus & 0x40) == 0)
+       {
+               // Write the "Enable Flash Programming command to F34 Control register
+               // Wait for ATTN and then clear the ATTN.
+               readRMI(SynaF34_FlashControl, &uData, 1);
+               uData &= 0xf0;
+               uData |= 0x0f;
+               writeRMI(SynaF34_FlashControl, &uData, 1);
+               SynaWaitForATTN();
+               readRMI((SynaF01DataBase + 1), &uStatus, 1);
+
+               // Scan the PDT again to ensure all register offsets are correct
+               SynaSetup();
+
+               // Read the "Program Enabled" bit of the F34 Control register, and proceed only if the
+               // bit is set.
+               readRMI(SynaF34_FlashControl, &uData, 1);
+
+               while (uData != 0x80)
+               {
+                       // In practice, if uData!=0x80 happens for multiple counts, it indicates reflash
+                       // is failed to be enabled, and program should quit
+                       ;
+               }
+       }
+}
+
+/* SynaWaitForATTN waits for ATTN to be asserted within a certain time threshold.
+ */
+void SynaWaitForATTN(void)
+{
+    unsigned int error;
+
+       error = waitATTN(ASSERT, 300);
+}
+
+/* SynaWaitATTN waits for ATTN to be asserted within a certain time threshold.
+ * The function also checks for the F34 "Program Enabled" bit and clear ATTN accordingly.
+ */
+void SynaWaitATTN(void)
+{
+       unsigned char uData = 0;
+       unsigned char uStatus = 0;
+
+       waitATTN(ASSERT, 300);
+       do {
+               readRMI(SynaF34_FlashControl, &uData, 1);
+               readRMI((SynaF01DataBase + 1), &uStatus, 1);
+       } while (uData != 0x80);
+}
+
+/* SynaProgramConfiguration writes the configuration section of the image block by block
+ */
+void SynaProgramConfiguration(void)
+{
+       unsigned char uData[2];
+       unsigned char *puData = ConfigBlockData;
+       unsigned short blockNum;
+
+   // eraseConfigBlock();
+       for (blockNum = 0; blockNum < SynaConfigBlockCount; blockNum++)
+       {
+           uData[0] = blockNum & 0xff;
+               uData[1] = (blockNum & 0xff00) >> 8;
+
+               //Block by blcok, write the block number and data to the corresponding F34 data registers
+               writeRMI(SynaF34Reflash_BlockNum, &uData[0], 2);
+               writeRMI(SynaF34Reflash_BlockData, puData, SynaConfigBlockSize);
+               puData += SynaConfigBlockSize;
+
+               // Issue the "Write Configuration Block" command
+               readRMI(SynaF34_FlashControl, &uData[0], 1);
+               uData[0] &= 0xf0;
+               uData[0] |= 0x06;
+               writeRMI(SynaF34_FlashControl, &uData[0], 1);
+               SynaWaitATTN();
+               printk(".");
+       }
+       printk("\n");
+       readRMI(SynaF01DataBase, uData, 1);
+       printk("+++++++SynaProgramConfiguration++uData:%x+++++++%s:%d\n", uData[0], __func__, __LINE__);
+
+}
+
+/* SynaFinalizeReflash finalizes the reflash process
+ */
+void SynaFinalizeReflash(void)
+{
+       unsigned char uData = 0;
+       unsigned char uStatus = 0;
+
+       printk("Finalizing Reflash...\n");
+
+       // Issue the "Reset" command to F01 command register to reset the chip
+       // This command will also test the new firmware image and check if its is valid
+       uData = 1;
+       writeRMI(SynaF01CommandBase, &uData, 1);
+       msleep(100);
+       //SynaWaitForATTN();
+       readRMI(SynaF01DataBase, &uData, 1);
+       printk("+++++++++uData:%x+++++++%s:%d\n", uData, __func__, __LINE__);
+       // Sanity check that the reflash process is still enabled
+       do {
+          readRMI(SynaF34_FlashControl, &uStatus, 1);
+       } while ((uStatus & 0x0f) != 0x00);
+       printk("+++++++++uStatus:%x+++++++%s:%d\n", uStatus, __func__, __LINE__);
+       readRMI((SynaF01DataBase + 1), &uStatus, 1);
+
+       SynaSetup();
+
+    uData = 0;
+       // Check if the "Program Enabled" bit in F01 data register is cleared
+       // Reflash is completed, and the image passes testing when the bit is cleared
+       do {
+               readRMI(SynaF01DataBase, &uData, 1);
+       } while ((uData & 0x40) != 0);
+       // Rescan PDT the update any changed register offsets
+       SynaSetup();
+       printk("\nReflash Completed. Please reboot.");
+}
+
+/* SynaFlashFirmwareWrite writes the firmware section of the image block by block
+ */
+void SynaFlashFirmwareWrite(void)
+{
+       unsigned char *puFirmwareData = (unsigned char *)(SynaFirmware+0x100); //SynafirmwareImgData; //hhb
+       unsigned char uData[2];
+       unsigned short blockNum;
+
+       for (blockNum = 0; blockNum < SynaFirmwareBlockCount; ++blockNum)
+       {
+               //Block by blcok, write the block number and data to the corresponding F34 data registers
+           uData[0] = blockNum & 0xff;
+               uData[1] = (blockNum & 0xff00) >> 8;
+               writeRMI(SynaF34Reflash_BlockNum, &uData[0], 2);
+               writeRMI(SynaF34Reflash_BlockData, puFirmwareData, SynaFirmwareBlockSize);
+               puFirmwareData += SynaFirmwareBlockSize;
+               // Issue the "Write Firmware Block" command
+               readRMI(SynaF34_FlashControl, &uData[0], 1);
+               uData[0] &= 0xf0;
+               uData[0] |= 0x02;
+               writeRMI(SynaF34_FlashControl, &uData[0], 1);
+               if(blockNum % 128 == 0)
+                       printk(".");
+           SynaWaitATTN();
+       }
+
+}
+
+/* SynaProgramFirmware prepares the firmware writing process
+ */
+void SynaProgramFirmware(void)
+{
+    unsigned char uData;
+
+       printk("Program Firmware Section...\n");
+
+    SynaReadBootloadID();
+       SynaWriteBootloadID();
+       readRMI(SynaF34_FlashControl, &uData, 1);
+       uData &= 0xf0;
+       uData |= 0x03;
+       writeRMI(SynaF34_FlashControl, &uData, 1);
+       msleep(5000);
+       SynaWaitATTN();
+       SynaFlashFirmwareWrite();
+       readRMI(SynaF01DataBase, &uData, 1);
+       printk("+++++++SynaProgramFirmware++uData:%x+++++++%s:%d\n", uData, __func__, __LINE__);
+}
+
+/* SynaBootloaderLock locks down the bootloader
+*/
+void SynaBootloaderLock(void)
+{
+       unsigned short lockBlockCount;
+    unsigned char *puFirmwareData = SynalockImgData;
+    unsigned char uData[2];
+    unsigned short uBlockNum;
+
+       // Check if device is in unlocked state
+       readRMI((SynaF34QueryBase+ 2), &uData[0], 1);
+
+       //Device is unlocked
+    if (uData[0] & 0x02)
+       {
+               printk("Device unlocked. Lock it first...\n");
+               // Different bootloader version has different block count for the lockdown data
+               // Need to check the bootloader version from the image file being reflashed
+               switch (SynafirmwareImgVersion)
+               {
+                       case 2:
+                               lockBlockCount = 3;
+                               break;
+                       case 3:
+                       case 4:
+                               lockBlockCount = 4;
+                               break;
+                       case 5:
+                               lockBlockCount = 5;
+                               break;
+                       default:
+                               lockBlockCount = 0;
+                               break;
+               }
+
+               // Write the lockdown info block by block
+               // This reference code of lockdown process does not check for bootloader version
+               // currently programmed on the ASIC against the bootloader version of the image to
+               // be reflashed. Such case should not happen in practice. Reflashing cross different
+               // bootloader versions is not supported.
+               for (uBlockNum = 0; uBlockNum < lockBlockCount; ++uBlockNum)
+               {
+                       uData[0] = uBlockNum & 0xff;
+                       uData[1] = (uBlockNum & 0xff00) >> 8;
+
+                       /* Write Block Number */
+                       readRMI(SynaF34Reflash_BlockNum, &uData[0], 2);
+
+                       /* Write Data Block */
+                       writeRMI(SynaF34Reflash_BlockData, puFirmwareData, SynaFirmwareBlockSize);
+
+                       /* Move to next data block */
+                       puFirmwareData += SynaFirmwareBlockSize;
+
+                       /* Issue Write Lockdown Block command */
+                       readRMI(SynaF34_FlashControl, &uData[0], 1);
+                       uData[0] &= 0xf0;
+                       uData[0] |= 0x04;
+                       writeRMI(SynaF34_FlashControl, &uData[0], 1);
+
+                       /* Wait ATTN until device is done writing the block and is ready for the next. */
+                       SynaWaitATTN();
+               }
+               printk("Device locking done.\n");
+
+               // Enable reflash again to finish the lockdown process.
+               // Since this lockdown process is part of the reflash process, we are enabling
+               // reflash instead, rather than resetting the device to finish the unlock procedure.
+               SynaEnableFlashing();
+       }
+       else printk("Device already locked.\n");
+}
+
+/* ConfigBlockReflash reflashes the config block only
+*/
+void ConfigBlockReflash(void)
+{
+    unsigned char uData[2];
+
+       convertConfigBlockData();
+
+    SynaInitialize();
+
+       SynaReadConfigInfo();
+
+       SynaReadFirmwareInfo();
+
+       SynaF34_FlashControl = SynaF34DataBase + SynaFirmwareBlockSize + 2;
+
+       SynaEnableFlashing();
+
+       SynaBootloaderLock();
+
+    // Check if device is in unlocked state
+       readRMI((SynaF34QueryBase + 2), &uData[0], 1);
+
+       //Device is unlocked
+    if (uData[0] & 0x02)
+       {
+          SynaFinalizeReflash();
+          return;
+          // Do not reflash config block if not locked.
+       }
+
+    eraseConfigBlock();
+    SynaconfigImgData = (unsigned char *)ConfigBlock;
+
+    SynaProgramConfiguration();
+
+    SynaFinalizeReflash();
+}
+
+/* eraseConfigBlock erases the config block
+*/
+void eraseConfigBlock(void)
+{
+       unsigned char uData;
+
+       // Erase of config block is done by first entering into bootloader mode
+    SynaReadBootloadID();
+       SynaWriteBootloadID();
+
+       // Command 7 to erase config block
+       readRMI(SynaF34_FlashControl, &uData, 1);
+       uData &= 0xf0;
+       uData |= 0x07;
+       writeRMI(SynaF34_FlashControl, &uData, 1);
+
+       SynaWaitATTN();
+}
+
+// This function is intended to convert the config data struct output by DS4 (read config.h) into an array that
+// the reflash code uses (read SynaFirmwareImage.h)
+// DS4 will output the array format in the next release and this function will not be necessary
+void convertConfigBlockData(void)
+{
+#if 0
+       int i = 0;
+       char value[32];    //hhb
+       for (i = 0; value[i]!=NULL; i++)
+       {
+               ConfigBlock[i] = value[i].Value;
+       }
+#endif
+}
+
+// This function is to check the touch controller type of the touch controller matches with the firmware image
+int TouchControllerTypeCheck(void)
+{
+       unsigned char uData[4];
+       char buffer[4];
+
+       char controllerType[20];
+
+    int ID;
+       //int revision;
+
+       readRMI((SynaF01QueryBase + 43), &uData[0], 1);
+       if ((uData[0] & 0x0f) > 0)
+       {
+               readRMI((SynaF01QueryBase + 44), &uData[0], 1);
+               if (uData[0] & 0x01)
+               {
+                       readRMI((SynaF01QueryBase + 17), &uData[0], 2);
+
+                       ID = (int)(uData[1] & (uData[0] << 8));
+                       sprintf(buffer, "%d", ID);
+                       if (strstr(controllerType, TOUCH_CONTROLLER) != 0)
+                               return true;
+                       else
+                               return false;
+               }
+               else
+                       return false;
+       }
+       else
+               return false;
+}
+
+int fimrwareRevisionCheck(void)
+{
+       unsigned char uData[10];
+       readRMI((SynaF01QueryBase + 11), uData, 10);
+       return strcmp(uData, FW_REVISION);
+}
+
diff --git a/drivers/input/touchscreen/rmi4/rmi_reflash.h b/drivers/input/touchscreen/rmi4/rmi_reflash.h
new file mode 100644 (file)
index 0000000..131baf1
--- /dev/null
@@ -0,0 +1,2916 @@
+
+unsigned char SynaFirmware[46592] = {
+       0x9F, 0x45, 0x60, 0x37, 0x00, 0x00, 0x00, 0x05, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
+       0x53, 0x33, 0x32, 0x30, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x49, 0x32, 0x43, 0x00, 0x0B, 0x00, 0xFF, 0x00, 0x0C, 0x0D, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x49, 0x32, 0x43, 0x00, 0x0B, 0x00, 0xFF, 0x00, 0x0C, 0x0D, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x2A, 0x89, 0x34, 0x06, 0x57, 0x8E, 0xAF, 0x99, 0x1D, 0x93, 0xE1, 0x46, 0x6E, 0x54, 0x4E, 0xBF,
+       0x61, 0x8E, 0x56, 0x70, 0x30, 0x3F, 0x97, 0xC2, 0x8D, 0xD5, 0x9B, 0xB3, 0xCB, 0x3A, 0xB2, 0xAC,
+       0xCD, 0x8D, 0xF3, 0xF5, 0x66, 0x6C, 0xDB, 0xB5, 0x5C, 0xDA, 0xC3, 0xB0, 0xA0, 0x8D, 0x53, 0xA1,
+       0xD2, 0x5F, 0xBA, 0xB8, 0x02, 0xF1, 0x51, 0xA1, 0xC5, 0x23, 0xAF, 0x6E, 0x8B, 0x2D, 0x5E, 0x08,
+       0xBD, 0x91, 0xEC, 0x65, 0xBA, 0x7E, 0x40, 0x2E, 0x89, 0xEF, 0xA2, 0x8B, 0x37, 0x46, 0xC4, 0x1E,
+       0xDB, 0x20, 0x93, 0x98, 0x9B, 0xA3, 0x60, 0x34, 0x66, 0x6A, 0x69, 0xC2, 0x4B, 0x67, 0xFE, 0x79,
+       0x14, 0x15, 0x01, 0x83, 0x5C, 0xB4, 0xFB, 0x4D, 0x75, 0x63, 0xC4, 0x05, 0x16, 0x74, 0xCF, 0x65,
+       0x6E, 0xCC, 0xDC, 0xFE, 0x1A, 0xD0, 0xF6, 0x28, 0x4F, 0xE6, 0xD8, 0x2D, 0x90, 0xAA, 0x78, 0x1D,
+       0xD1, 0xDA, 0x89, 0x9C, 0x39, 0xF3, 0x1C, 0x4A, 0x6C, 0xD2, 0x99, 0xEA, 0x6C, 0xBE, 0x57, 0x53,
+       0x39, 0x92, 0x43, 0x4B, 0x4E, 0x17, 0x79, 0x0C, 0x3A, 0x20, 0xAA, 0xF8, 0xCE, 0x46, 0xD8, 0xEE,
+       0x28, 0x68, 0x11, 0x9B, 0xA0, 0xCA, 0x61, 0xC0, 0x46, 0x78, 0xE4, 0x6F, 0x73, 0xC7, 0x31, 0x14,
+       0x63, 0xE7, 0xEB, 0xC7, 0xB0, 0x8C, 0x96, 0xAD, 0x69, 0x0C, 0xFF, 0xFC, 0x0E, 0xAF, 0x0B, 0x1B,
+       0x19, 0x80, 0xFC, 0xE1, 0xBE, 0xFC, 0xC2, 0xBC, 0xC6, 0x9B, 0x55, 0xBC, 0xBA, 0x91, 0xFE, 0x84,
+       0x90, 0x4F, 0xE9, 0xE8, 0x6E, 0xDA, 0x1F, 0x65, 0x49, 0x7C, 0x5A, 0xE0, 0x06, 0x0D, 0x49, 0xB7,
+       0x92, 0x0F, 0x52, 0x01, 0x03, 0xC0, 0x88, 0x27, 0x48, 0xA0, 0x78, 0x83, 0x84, 0x40, 0x9B, 0xB0,
+       0x50, 0xAE, 0x0B, 0x29, 0xFC, 0x47, 0x22, 0xFC, 0x7A, 0x7B, 0xEA, 0xBC, 0x75, 0x5C, 0xC5, 0x7D,
+       0x10, 0xAC, 0xE1, 0x27, 0x3F, 0x59, 0x96, 0xE8, 0x9E, 0x0F, 0x04, 0x29, 0x25, 0xAC, 0x4A, 0x14,
+       0x7E, 0x14, 0x1D, 0xA5, 0x85, 0xDD, 0x1C, 0x40, 0xDA, 0xD2, 0x7E, 0x6D, 0x45, 0xE0, 0x0A, 0xEB,
+       0xF7, 0x88, 0x02, 0x7D, 0x97, 0x68, 0x14, 0x12, 0x45, 0x73, 0x1C, 0xD2, 0x56, 0x52, 0xD0, 0x60,
+       0x4E, 0x24, 0xA5, 0x61, 0x27, 0xC5, 0x34, 0x43, 0xEE, 0xDA, 0xA7, 0x83, 0xD5, 0x8A, 0xF2, 0x85,
+       0xCE, 0x7B, 0xC6, 0x9C, 0x15, 0xDE, 0x67, 0x9D, 0xC4, 0xC1, 0x9C, 0x00, 0xC7, 0xFF, 0x8E, 0x67,
+       0xEF, 0xDC, 0x9F, 0xF0, 0x43, 0xC9, 0x29, 0xD5, 0x9A, 0x13, 0x5B, 0xE6, 0xA4, 0x65, 0x76, 0x9A,
+       0xB7, 0xA1, 0x9B, 0x54, 0xC4, 0x69, 0x58, 0x1F, 0xC2, 0x28, 0x90, 0x11, 0xD1, 0x58, 0x50, 0x8B,
+       0xC6, 0x2D, 0x9D, 0x26, 0x90, 0xA2, 0x2F, 0xD5, 0x89, 0x31, 0x7F, 0x6C, 0x8A, 0xB7, 0x66, 0x78,
+       0x6D, 0x69, 0xBB, 0x2E, 0x21, 0xA0, 0xE7, 0x34, 0x85, 0xC4, 0xF6, 0xC3, 0x4B, 0x45, 0x9A, 0x58,
+       0xF9, 0x5D, 0x14, 0x4F, 0x78, 0xE0, 0x2A, 0x4D, 0xC2, 0xD8, 0x09, 0x0F, 0x9A, 0xB9, 0xB0, 0x00,
+       0x48, 0x6A, 0x9D, 0x20, 0x0D, 0x6A, 0xF1, 0x52, 0xEF, 0xCC, 0xC6, 0x17, 0x5C, 0x85, 0x29, 0x4B,
+       0x14, 0xD8, 0xA7, 0xA1, 0xDD, 0x96, 0x4C, 0x5A, 0x19, 0xB1, 0xAF, 0xB4, 0x0E, 0x13, 0x47, 0x08,
+       0xE1, 0xD0, 0x48, 0x09, 0x16, 0x73, 0xE9, 0x23, 0xBB, 0xDE, 0xBF, 0x67, 0x6F, 0x7C, 0xA7, 0xA2,
+       0xE7, 0x5B, 0xF5, 0xC4, 0x86, 0xF0, 0xB0, 0x11, 0x79, 0x13, 0x2A, 0xB2, 0xED, 0xCA, 0x06, 0x4C,
+       0x37, 0xFB, 0xB5, 0xE6, 0xAA, 0x5C, 0x6D, 0x31, 0x0D, 0x95, 0xCD, 0x19, 0xEA, 0xEC, 0x26, 0x2E,
+       0x4F, 0xE6, 0x69, 0x0D, 0x0D, 0x4A, 0x36, 0xAA, 0xD5, 0x69, 0xF0, 0xF4, 0x83, 0x78, 0x6A, 0xB1,
+       0x35, 0x95, 0xCF, 0x19, 0xBD, 0xCD, 0x3C, 0xAA, 0x47, 0x7D, 0xBD, 0xFD, 0x5B, 0xAE, 0xF6, 0x43,
+       0x31, 0xEB, 0x5D, 0x05, 0x9F, 0xE4, 0x42, 0xF5, 0xBA, 0xC4, 0xAF, 0x2A, 0x7D, 0x0E, 0xA7, 0x9E,
+       0xE4, 0xD6, 0xAA, 0x53, 0x97, 0x2A, 0xB4, 0x1A, 0x06, 0xCB, 0xE7, 0x05, 0x3B, 0x62, 0xF1, 0x17,
+       0x3B, 0x1E, 0x62, 0xCC, 0xE9, 0xFA, 0x32, 0x4F, 0xCC, 0x32, 0x58, 0x89, 0x42, 0x52, 0x32, 0x34,
+       0x8A, 0xE7, 0x88, 0x22, 0x43, 0x40, 0x6E, 0x20, 0xFB, 0x72, 0xD0, 0xCE, 0xD1, 0xED, 0x74, 0x38,
+       0x12, 0xE7, 0x37, 0x3F, 0x4A, 0x5D, 0x12, 0x8D, 0x9F, 0x23, 0x94, 0x93, 0x93, 0x9C, 0xDF, 0xB3,
+       0x21, 0x4B, 0xBF, 0x33, 0x58, 0xBF, 0x94, 0x51, 0x7C, 0x7F, 0xD8, 0x47, 0x98, 0xC8, 0x73, 0x1E,
+       0x81, 0x37, 0x1C, 0x5A, 0x3A, 0x78, 0xC3, 0x99, 0xBE, 0x2D, 0x76, 0x9A, 0x9E, 0xD1, 0x22, 0x62,
+       0xF7, 0x09, 0x0E, 0xC6, 0xEF, 0xC5, 0x50, 0x10, 0xF5, 0x26, 0x84, 0xA3, 0xD6, 0x3A, 0x34, 0xEC,
+       0x97, 0xC8, 0xC0, 0x90, 0x2B, 0xF8, 0xBF, 0x84, 0x88, 0xE1, 0xEC, 0x85, 0x31, 0x9A, 0xBC, 0x1F,
+       0xBC, 0xAD, 0x79, 0x6F, 0xEB, 0x15, 0x77, 0xDB, 0x2C, 0xAD, 0x93, 0xE1, 0x8C, 0x22, 0x9B, 0xE5,
+       0x19, 0x20, 0xB6, 0xC3, 0x7D, 0xB2, 0x31, 0xE0, 0x9A, 0x85, 0xD6, 0xD7, 0xFD, 0x1C, 0xBA, 0x59,
+       0xFA, 0x0F, 0x69, 0x4B, 0x9B, 0x6B, 0x9E, 0x0C, 0x34, 0xC1, 0xF5, 0xFC, 0x5C, 0x60, 0x58, 0x4A,
+       0xBB, 0xB7, 0xE2, 0x41, 0x44, 0x85, 0x1A, 0x78, 0x58, 0xE3, 0x49, 0x06, 0x6D, 0x5F, 0xA4, 0x6A,
+       0x93, 0xC7, 0x85, 0x72, 0x19, 0xEB, 0x20, 0xCA, 0xF7, 0x44, 0x12, 0x53, 0xB8, 0x99, 0xCC, 0xB3,
+       0x03, 0x02, 0x36, 0xB0, 0x3E, 0xE4, 0xDB, 0x79, 0x9F, 0x39, 0xAA, 0x3E, 0xDF, 0x84, 0x64, 0xA9,
+       0x08, 0xBF, 0x52, 0x59, 0x54, 0xBD, 0x08, 0x63, 0x52, 0x88, 0x55, 0x45, 0x8C, 0x9A, 0x5A, 0x69,
+       0xAA, 0x88, 0xF1, 0x43, 0x0D, 0xE9, 0xD8, 0x08, 0x7B, 0xC9, 0xE2, 0xA3, 0x4C, 0x2D, 0xC3, 0xA9,
+       0x24, 0x7D, 0xC3, 0xDB, 0x2C, 0xE0, 0x0B, 0x72, 0x19, 0xA7, 0xCF, 0x64, 0x58, 0x44, 0x91, 0xD9,
+       0xA1, 0x39, 0x76, 0x29, 0x01, 0xC7, 0x1A, 0x77, 0x92, 0x66, 0x68, 0xF7, 0x7E, 0xCD, 0x67, 0x52,
+       0x56, 0x19, 0xD8, 0x6C, 0x92, 0x36, 0x33, 0x1A, 0xD5, 0xCC, 0x56, 0x7F, 0xA2, 0x76, 0x00, 0x29,
+       0xFD, 0x41, 0xF1, 0x6A, 0xA4, 0xA7, 0x56, 0x1D, 0x14, 0x37, 0xB6, 0x67, 0x42, 0x9E, 0xAA, 0x28,
+       0x31, 0xFB, 0x63, 0x82, 0x2D, 0x37, 0x29, 0xB8, 0xEC, 0xDE, 0xF4, 0x28, 0x15, 0x99, 0xF7, 0x5E,
+       0x26, 0xCF, 0x1A, 0x12, 0x9E, 0xFC, 0x1C, 0x44, 0x86, 0x3C, 0x80, 0x71, 0x46, 0x77, 0x9C, 0xB2,
+       0x53, 0x02, 0x66, 0x81, 0xAD, 0x35, 0x74, 0x59, 0xC8, 0xB3, 0xFE, 0xF0, 0xB2, 0x5A, 0x62, 0x25,
+       0x41, 0xF2, 0xCE, 0x69, 0xE3, 0xBD, 0x7B, 0xB5, 0x80, 0x0D, 0x0D, 0xF1, 0x5F, 0xDC, 0xB6, 0xC4,
+       0xE9, 0xEF, 0x24, 0x18, 0xAD, 0x1C, 0x74, 0x2A, 0x80, 0x66, 0x42, 0x75, 0x2A, 0xB0, 0xF3, 0x33,
+       0xD9, 0x0F, 0x96, 0x89, 0xC9, 0x43, 0xFD, 0x64, 0xE1, 0x92, 0x52, 0xBC, 0xF1, 0xFF, 0xAB, 0xE3,
+       0x53, 0x82, 0x55, 0x0A, 0x90, 0x17, 0xDF, 0x46, 0x3D, 0xFD, 0x34, 0xE2, 0xA4, 0xF7, 0x48, 0x59,
+       0x19, 0x83, 0xC9, 0x37, 0x65, 0xD0, 0xEB, 0x4C, 0x51, 0xE5, 0x47, 0x04, 0x28, 0x49, 0xB9, 0x38,
+       0x4C, 0xEF, 0xD0, 0x41, 0xFE, 0x0B, 0x0E, 0xCA, 0x39, 0x33, 0xE6, 0xDC, 0x74, 0xE8, 0x1E, 0x57,
+       0x6F, 0x00, 0xE4, 0xE7, 0xA9, 0x4F, 0xAE, 0x74, 0x7F, 0x87, 0x04, 0x8C, 0xCC, 0x29, 0x97, 0xED,
+       0xE6, 0x74, 0x07, 0xAF, 0x25, 0x9C, 0x91, 0x9D, 0xC6, 0xCD, 0x8F, 0xEA, 0x8D, 0xFE, 0xEB, 0xE1,
+       0x0E, 0x6D, 0xE6, 0x5E, 0xC2, 0x1A, 0xA3, 0x43, 0x90, 0xD5, 0x1E, 0xC1, 0xE8, 0x17, 0x81, 0x8C,
+       0xF6, 0xF7, 0xB8, 0xBC, 0x3F, 0x6E, 0x96, 0xC5, 0x19, 0x6A, 0x5F, 0xBA, 0xBF, 0xA2, 0xAE, 0x88,
+       0x21, 0x0E, 0xAE, 0xB7, 0x14, 0xAB, 0xCB, 0x02, 0xFB, 0x50, 0xEF, 0x80, 0x87, 0x32, 0x8C, 0x0C,
+       0x86, 0x1A, 0xC1, 0x79, 0xC6, 0xA5, 0x56, 0xA5, 0x66, 0xC6, 0xE2, 0x94, 0xCD, 0x82, 0x5B, 0xE4,
+       0x3D, 0x33, 0x04, 0x7B, 0x4D, 0x2F, 0xA5, 0x93, 0x8F, 0x4E, 0xF1, 0xDE, 0xD3, 0x9D, 0xCA, 0x89,
+       0x96, 0x74, 0x65, 0xC3, 0x71, 0xAA, 0xFC, 0xE0, 0x94, 0x8B, 0x30, 0x65, 0x20, 0x0C, 0x54, 0x07,
+       0xD2, 0x2F, 0x92, 0x47, 0xA3, 0x62, 0x39, 0xB6, 0xF4, 0x44, 0x55, 0xDD, 0x75, 0x52, 0x35, 0x4F,
+       0x70, 0x3B, 0xE7, 0x11, 0x28, 0xB7, 0x91, 0x36, 0x61, 0xFE, 0x57, 0x81, 0x4C, 0xB3, 0xCB, 0xEB,
+       0x99, 0x40, 0x90, 0xE4, 0xE7, 0xF5, 0x35, 0xD0, 0x15, 0x7B, 0x49, 0xAD, 0xA9, 0xB7, 0xAE, 0x09,
+       0x69, 0x14, 0x5C, 0x28, 0x29, 0x3C, 0xA6, 0x42, 0xE6, 0x53, 0xCF, 0xC5, 0xB9, 0x23, 0x36, 0x29,
+       0x84, 0x8B, 0x1B, 0x87, 0x74, 0x15, 0x8C, 0x68, 0x44, 0x7D, 0xF7, 0x81, 0x44, 0x52, 0xA5, 0x80,
+       0x2B, 0x54, 0x5B, 0x95, 0x91, 0x10, 0xD3, 0xAB, 0xED, 0x86, 0x8A, 0xC7, 0x81, 0xF3, 0xD9, 0x67,
+       0xFE, 0xC6, 0xA7, 0x88, 0x67, 0x98, 0xD8, 0xC3, 0x46, 0x9E, 0x4F, 0x87, 0x9B, 0xFE, 0x70, 0xD4,
+       0xCB, 0x3A, 0x16, 0x91, 0xBC, 0x09, 0xB1, 0x0A, 0x44, 0x0D, 0x68, 0xBE, 0x85, 0x1E, 0x4E, 0x4F,
+       0xAC, 0xBA, 0x24, 0xB1, 0x0D, 0x1C, 0x84, 0x04, 0x0E, 0xAD, 0x8C, 0x39, 0x3D, 0x01, 0x9B, 0x52,
+       0xA4, 0x11, 0x9B, 0xF4, 0xDF, 0xA7, 0x95, 0x69, 0xCF, 0x4F, 0x06, 0x42, 0xCF, 0xAF, 0xD7, 0xA8,
+       0xCC, 0x28, 0xD5, 0x9D, 0x10, 0xF1, 0x9E, 0x63, 0x6C, 0x82, 0x85, 0xD0, 0xB1, 0x0C, 0xDE, 0xB6,
+       0x38, 0xA1, 0x09, 0xC5, 0xCF, 0x2C, 0xB6, 0x6E, 0x22, 0x4C, 0xC8, 0x2A, 0x75, 0x4F, 0xCD, 0xDF,
+       0xED, 0xCD, 0x18, 0x45, 0x16, 0x97, 0xDF, 0xDA, 0x79, 0x91, 0xAF, 0x17, 0xF2, 0x57, 0xAE, 0x87,
+       0xDE, 0x6B, 0xBE, 0x8D, 0x3B, 0x89, 0x5A, 0xB4, 0xDD, 0x10, 0x08, 0x3D, 0xE8, 0x60, 0xA2, 0x33,
+       0x7C, 0x2A, 0x68, 0xC4, 0x9A, 0xED, 0x06, 0x6D, 0xD8, 0x71, 0x19, 0xC7, 0xEA, 0x5C, 0x32, 0xE9,
+       0x4B, 0x86, 0x14, 0xA8, 0xC2, 0xB2, 0x40, 0x79, 0xD5, 0xBB, 0x3A, 0x34, 0x8C, 0x8C, 0x30, 0x46,
+       0x86, 0xB8, 0x9D, 0x2B, 0x03, 0x1A, 0x77, 0xE3, 0xC4, 0xE8, 0x54, 0x21, 0x01, 0x89, 0x4E, 0x80,
+       0xDD, 0xD2, 0x25, 0xED, 0xB5, 0xD9, 0xCD, 0xD4, 0x49, 0x65, 0xCF, 0x2C, 0xE1, 0x50, 0xDC, 0xD8,
+       0x45, 0x9C, 0x85, 0x69, 0xEE, 0x07, 0x22, 0x0D, 0x35, 0xF1, 0x1D, 0xB8, 0x4D, 0xD8, 0x2C, 0xAD,
+       0x0F, 0x7C, 0xB0, 0x1A, 0x71, 0x80, 0x2C, 0x79, 0x07, 0x83, 0x68, 0x4A, 0x21, 0x5F, 0xC2, 0xE9,
+       0x0B, 0x9E, 0x44, 0x73, 0x21, 0x70, 0x96, 0x5C, 0xFA, 0xEC, 0xFD, 0x4D, 0x74, 0xA3, 0x5D, 0x21,
+       0xA6, 0x26, 0x1F, 0x58, 0xD5, 0x3B, 0x34, 0xF2, 0xAA, 0xD7, 0x97, 0xDA, 0xD4, 0x43, 0xDA, 0xA7,
+       0x48, 0xDD, 0x51, 0x8D, 0x85, 0x81, 0xB0, 0xA1, 0x06, 0xF4, 0x85, 0x60, 0x5D, 0x5D, 0x9A, 0xF3,
+       0x20, 0x89, 0x37, 0xDA, 0x66, 0x40, 0xA5, 0x84, 0xDF, 0x3E, 0x77, 0x0E, 0x6F, 0xFE, 0xC4, 0xA1,
+       0xE7, 0x24, 0xA0, 0x27, 0x50, 0x43, 0x70, 0x74, 0x05, 0x35, 0x34, 0xB2, 0xEF, 0xC5, 0x41, 0x46,
+       0x17, 0x95, 0x41, 0xDE, 0x1E, 0x00, 0x53, 0xB0, 0x58, 0x8C, 0xF4, 0xB0, 0xF0, 0x2F, 0x2E, 0x45,
+       0x78, 0x5A, 0x8D, 0xB7, 0x99, 0x0F, 0xE4, 0xF5, 0x64, 0x60, 0x28, 0x48, 0xF9, 0x11, 0xEA, 0xDD,
+       0xA4, 0xC1, 0x8D, 0x2B, 0x55, 0x13, 0x6D, 0x6D, 0x23, 0x6B, 0xA7, 0xE1, 0xF8, 0x6E, 0xC5, 0xFA,
+       0x7C, 0xE5, 0x9B, 0x41, 0x10, 0x44, 0xBB, 0xAE, 0x7D, 0xED, 0x62, 0xF8, 0x5D, 0x6F, 0x7E, 0x1F,
+       0x07, 0xC7, 0x20, 0x50, 0xA3, 0x2D, 0x55, 0x11, 0x78, 0x3C, 0x2B, 0x6C, 0x72, 0x13, 0x0F, 0xE7,
+       0x3F, 0xC7, 0x63, 0x9A, 0xB1, 0xC2, 0x44, 0x87, 0x19, 0xC0, 0xEA, 0x29, 0x71, 0xA1, 0xFB, 0x1D,
+       0x29, 0xD3, 0x69, 0x9D, 0xF1, 0x3B, 0x6B, 0x15, 0x97, 0x59, 0x73, 0x31, 0x19, 0x5D, 0x97, 0xBE,
+       0xB5, 0x03, 0x6F, 0xB2, 0xF0, 0x64, 0x10, 0x13, 0x4F, 0x35, 0x21, 0xCE, 0xCD, 0x7B, 0x65, 0x83,
+       0x2A, 0xF2, 0xC8, 0xA4, 0x05, 0x84, 0x4C, 0x62, 0xA5, 0xD8, 0x23, 0xB2, 0x28, 0xDC, 0x14, 0x91,
+       0x10, 0xAF, 0xF8, 0x52, 0xD3, 0x85, 0x07, 0xBE, 0x49, 0x9B, 0xE5, 0x02, 0xBF, 0x2D, 0xEC, 0xF7,
+       0xE1, 0xDC, 0x93, 0x7E, 0x50, 0x78, 0x6B, 0x13, 0xB1, 0xDB, 0x80, 0x26, 0xA8, 0xE9, 0x7D, 0x23,
+       0x12, 0xEF, 0xB4, 0xC3, 0xBE, 0x82, 0x0F, 0xBD, 0xD4, 0x49, 0x80, 0xEC, 0x64, 0x5D, 0xF8, 0xED,
+       0x2B, 0xAC, 0x28, 0x1F, 0xBE, 0x4B, 0xAF, 0x85, 0xEB, 0xB5, 0x24, 0x06, 0xCA, 0xF5, 0xD4, 0x5F,
+       0x89, 0x72, 0x9E, 0x98, 0x43, 0x72, 0x6D, 0x04, 0xCA, 0xE5, 0xDB, 0x4F, 0xB5, 0x5C, 0x43, 0xA9,
+       0xF9, 0xD7, 0xAB, 0xEB, 0x2A, 0x63, 0x7E, 0x0D, 0x63, 0x2D, 0xA8, 0xA4, 0x62, 0xDE, 0xD3, 0x35,
+       0x4F, 0xB9, 0x87, 0xB2, 0x9C, 0xB7, 0x48, 0xA4, 0x49, 0x87, 0xAD, 0xF2, 0xB9, 0x57, 0x27, 0xBC,
+       0x97, 0xBC, 0x35, 0xA5, 0xE4, 0x51, 0xA2, 0x8C, 0xF0, 0xCA, 0x82, 0x79, 0x47, 0xD2, 0x70, 0xD4,
+       0x64, 0x6B, 0x62, 0x6D, 0xBA, 0xA3, 0x4A, 0x99, 0x5B, 0xC1, 0x91, 0x5E, 0x0A, 0xFE, 0x6C, 0x1F,
+       0xD9, 0x0A, 0x8D, 0x8A, 0x09, 0xA1, 0x1A, 0x5C, 0xFD, 0x93, 0xE4, 0xB9, 0xDB, 0xB7, 0x0F, 0xC7,
+       0x2E, 0x03, 0x89, 0xC7, 0x74, 0x89, 0xD5, 0xD7, 0x1F, 0x7A, 0x62, 0xD8, 0x87, 0x9E, 0xF3, 0x2D,
+       0x4A, 0xC7, 0x72, 0x09, 0xCF, 0xB8, 0x45, 0x7A, 0x27, 0xF6, 0x57, 0x6B, 0xF2, 0xCE, 0xFA, 0x7B,
+       0xBF, 0xA0, 0xE4, 0xDC, 0x79, 0x48, 0x90, 0x2B, 0xA0, 0x39, 0x68, 0xB3, 0x4F, 0x79, 0x87, 0x1A,
+       0xB4, 0x8E, 0x12, 0xB7, 0x40, 0x18, 0x5C, 0x3F, 0x99, 0x1D, 0xF3, 0x41, 0x2C, 0xB8, 0xD5, 0x61,
+       0x6C, 0x39, 0x20, 0x15, 0xDC, 0xE6, 0xA1, 0x23, 0x41, 0xF2, 0xCE, 0x17, 0xE9, 0xE1, 0xD0, 0xEB,
+       0x04, 0x81, 0xC6, 0x60, 0xA9, 0xAD, 0x9B, 0xDD, 0x66, 0x3C, 0xE5, 0x70, 0xAA, 0x28, 0xA2, 0x8B,
+       0x2F, 0xF3, 0xB9, 0xB4, 0xC9, 0x8D, 0x00, 0x65, 0x65, 0x8E, 0x40, 0x5A, 0xB4, 0x6A, 0xB9, 0x48,
+       0x33, 0x79, 0x31, 0xCC, 0xA4, 0x0D, 0x8C, 0x38, 0x56, 0xE0, 0x16, 0x00, 0x40, 0x65, 0x2D, 0x84,
+       0xDE, 0x10, 0xE3, 0x43, 0x3B, 0x2C, 0x37, 0x5D, 0x38, 0x05, 0x26, 0x5D, 0x3C, 0xC7, 0x04, 0xE1,
+       0x0B, 0xC9, 0xA8, 0xC3, 0x14, 0xF8, 0x02, 0x50, 0x40, 0x86, 0xCA, 0x57, 0xB3, 0xED, 0x05, 0xD1,
+       0xC4, 0x8F, 0x6D, 0x1D, 0xD0, 0xD4, 0xBA, 0xAF, 0xC8, 0x6B, 0xE5, 0xBA, 0x63, 0xE5, 0x65, 0x52,
+       0x03, 0xF1, 0xE1, 0x52, 0xB8, 0xC1, 0x21, 0xB8, 0x9B, 0xA6, 0x56, 0xEE, 0xDA, 0x18, 0x05, 0xC8,
+       0x42, 0xAA, 0xB9, 0xC4, 0x08, 0x78, 0xD4, 0xFE, 0x48, 0xE4, 0xD7, 0x08, 0x39, 0x91, 0x7A, 0x21,
+       0x5B, 0x46, 0x0F, 0x9A, 0x3F, 0xC8, 0x5C, 0xF2, 0xAD, 0x40, 0xED, 0xEE, 0x29, 0xA3, 0x97, 0x0D,
+       0xEE, 0x89, 0x35, 0xE4, 0xBB, 0xCD, 0x9F, 0xEF, 0x39, 0x1D, 0x11, 0x6F, 0xDC, 0x56, 0x22, 0x4B,
+       0x0F, 0x6F, 0xA7, 0x19, 0xE5, 0xDD, 0xD0, 0x48, 0x10, 0xB2, 0xDA, 0xEB, 0x26, 0x0C, 0x8E, 0x56,
+       0x4B, 0x1F, 0x35, 0xD8, 0x0F, 0x79, 0x8D, 0xB6, 0x06, 0x49, 0x95, 0x7F, 0x12, 0xAA, 0x00, 0xBF,
+       0xB9, 0x40, 0xA4, 0x2B, 0xCB, 0x16, 0xC3, 0x85, 0xB2, 0x64, 0xF0, 0x59, 0x12, 0x94, 0xB0, 0xA9,
+       0x02, 0xDC, 0x31, 0x9A, 0xB8, 0xC4, 0xB2, 0x9B, 0x05, 0x86, 0xFF, 0xD7, 0x48, 0xB9, 0x7B, 0x3E,
+       0x85, 0xF5, 0x3C, 0xD9, 0x87, 0xCE, 0xDA, 0x97, 0xFE, 0x56, 0x52, 0x28, 0x23, 0x16, 0x88, 0xB4,
+       0xF5, 0xC9, 0xF4, 0xBA, 0x2B, 0x95, 0x61, 0x7A, 0xF2, 0xF7, 0x31, 0x95, 0xCD, 0xA0, 0x90, 0x8A,
+       0x3B, 0xBD, 0x71, 0x71, 0xD2, 0x19, 0x59, 0x7E, 0x82, 0x7A, 0x78, 0x17, 0xF3, 0x81, 0x7B, 0x72,
+       0x1F, 0x4C, 0xDD, 0xF7, 0x0A, 0x99, 0x4A, 0x3D, 0x35, 0xB4, 0x96, 0x35, 0xFB, 0xB1, 0xF6, 0x6E,
+       0x21, 0x2A, 0xB6, 0xEE, 0x4E, 0xDA, 0x6C, 0xA6, 0xDB, 0x2C, 0xBF, 0x09, 0xAA, 0xC0, 0x78, 0x9A,
+       0xB1, 0x23, 0x1A, 0xBC, 0xF6, 0x59, 0x06, 0xC6, 0xE3, 0x1A, 0x71, 0xD5, 0x0A, 0xF0, 0xC1, 0x4D,
+       0x8E, 0x12, 0x10, 0x0E, 0x21, 0xE0, 0xE2, 0x14, 0xB0, 0x65, 0x09, 0xC2, 0xE5, 0xDD, 0xFC, 0x43,
+       0x3E, 0x6C, 0xBF, 0x75, 0xAD, 0x93, 0xAE, 0x06, 0x2F, 0x3B, 0x7D, 0x8E, 0xE9, 0x1C, 0x74, 0x5A,
+       0xF2, 0x3C, 0xFF, 0x6A, 0x49, 0xCD, 0x2A, 0x9D, 0xBA, 0x40, 0xB3, 0x45, 0x6B, 0x93, 0xEA, 0xD1,
+       0xD7, 0xED, 0x2D, 0x81, 0x55, 0xE6, 0xC4, 0x1C, 0xD0, 0x63, 0xC5, 0x6B, 0x26, 0x1A, 0x67, 0xA7,
+       0x6E, 0x3B, 0x48, 0x4A, 0x28, 0xA8, 0x73, 0xE4, 0xC2, 0xAF, 0xD7, 0x9A, 0x16, 0x70, 0x63, 0x71,
+       0x7A, 0xB7, 0xE2, 0x25, 0x3F, 0x7D, 0x6D, 0x71, 0xFC, 0x7A, 0x33, 0x99, 0xFB, 0xEC, 0x0F, 0x5C,
+       0x63, 0xD4, 0xD2, 0x89, 0xCF, 0x05, 0xBF, 0xBB, 0x61, 0x01, 0xC0, 0xD1, 0xC0, 0xA9, 0x91, 0x24,
+       0x8E, 0xB9, 0x36, 0xDB, 0xD2, 0x34, 0x1D, 0x58, 0x94, 0xE8, 0xBA, 0x57, 0x1F, 0xB0, 0x75, 0x86,
+       0xD7, 0x06, 0xC5, 0xDA, 0x01, 0x3D, 0x26, 0x0E, 0x33, 0xE2, 0xDB, 0x24, 0x86, 0x2A, 0xD8, 0x7D,
+       0x36, 0x00, 0x6C, 0xB4, 0x02, 0x82, 0xA2, 0x7B, 0x92, 0x20, 0x26, 0xB7, 0x6B, 0x9A, 0x08, 0x40,
+       0xC0, 0x93, 0x8C, 0x50, 0x27, 0xA8, 0x73, 0xFB, 0xA9, 0x78, 0x4E, 0x77, 0x50, 0x2A, 0x52, 0xBB,
+       0xCE, 0x5B, 0xC2, 0x08, 0x75, 0x81, 0x97, 0xC0, 0xBF, 0x8E, 0x7E, 0x8F, 0x5A, 0xB1, 0xE5, 0xEC,
+       0x44, 0xEA, 0x5F, 0x77, 0x4D, 0x8D, 0x4B, 0x35, 0xCE, 0x9F, 0x70, 0xEB, 0xA5, 0x1D, 0xDD, 0xE5,
+       0xF6, 0x52, 0xE5, 0x51, 0x38, 0x0E, 0xB8, 0xA2, 0x8C, 0xE1, 0xE3, 0xAF, 0xE9, 0xAC, 0x46, 0x5F,
+       0xAF, 0x1F, 0x2C, 0x56, 0xC5, 0xA0, 0xB1, 0xEF, 0x80, 0x2F, 0x5E, 0xE4, 0xE8, 0x49, 0x57, 0x52,
+       0x27, 0xE6, 0x1B, 0x62, 0x52, 0xCD, 0x0B, 0x84, 0x7B, 0xD9, 0x8B, 0x0E, 0x28, 0x7A, 0x06, 0x01,
+       0x59, 0x56, 0xB1, 0x89, 0xFD, 0x94, 0x0F, 0x9E, 0x2F, 0x36, 0x9F, 0x9F, 0x55, 0xA1, 0xE1, 0xFC,
+       0x0F, 0x09, 0xD3, 0xE6, 0x73, 0xCC, 0x01, 0xF8, 0xA6, 0x5C, 0x25, 0xAF, 0x6A, 0x5F, 0x7F, 0x81,
+       0x51, 0x9D, 0x01, 0x8A, 0xB5, 0x9F, 0xF7, 0x81, 0x63, 0x23, 0x96, 0xEE, 0x88, 0x77, 0xD2, 0xD0,
+       0x8F, 0x74, 0xA2, 0x0B, 0x65, 0x64, 0x47, 0xFF, 0xB1, 0xA4, 0x1C, 0x27, 0x39, 0x85, 0x88, 0xD3,
+       0xCD, 0x7D, 0xEB, 0x1C, 0x14, 0xFC, 0xC2, 0x7E, 0x0F, 0x21, 0x53, 0x20, 0xB9, 0x01, 0xD6, 0xCB,
+       0xB0, 0x3B, 0xA5, 0x59, 0xAC, 0xF9, 0xEB, 0x71, 0x74, 0xF7, 0xA0, 0x72, 0xA4, 0xC9, 0x19, 0x86,
+       0x25, 0x71, 0x59, 0x16, 0x7F, 0x2A, 0xEC, 0xDB, 0x10, 0x36, 0xE4, 0xE5, 0xCD, 0x0A, 0x3F, 0x18,
+       0xFC, 0x28, 0xF5, 0xE0, 0x60, 0x0F, 0x18, 0x06, 0xEE, 0x8F, 0x28, 0x8C, 0x24, 0x22, 0x57, 0xCF,
+       0xDC, 0x35, 0x2B, 0xA9, 0xBB, 0x18, 0x2E, 0x19, 0xDE, 0x4A, 0xCF, 0xBF, 0x70, 0xDB, 0x55, 0x25,
+       0x73, 0xF7, 0x42, 0xFB, 0xEC, 0xA7, 0xCE, 0x47, 0xDF, 0x4A, 0x7F, 0x26, 0xBF, 0x5A, 0xDC, 0x97,
+       0xB4, 0x12, 0x47, 0x6A, 0x7C, 0xD5, 0xA8, 0x8E, 0x1C, 0x57, 0xE0, 0x8F, 0xCC, 0x6E, 0xEA, 0x99,
+       0x78, 0xC4, 0xAB, 0xAA, 0xA9, 0xC0, 0x83, 0x88, 0xCC, 0x64, 0x05, 0xD3, 0x9A, 0x2F, 0x5F, 0xDD,
+       0x06, 0xA7, 0x3B, 0x55, 0xA5, 0x9C, 0xB5, 0x25, 0x3E, 0x25, 0x68, 0x72, 0xD5, 0xF5, 0x76, 0x7F,
+       0x9B, 0xD2, 0x24, 0x22, 0xF1, 0xCB, 0x07, 0xC3, 0xE7, 0xAB, 0x8D, 0xBC, 0x26, 0x5A, 0x6F, 0x6C,
+       0x32, 0x50, 0xBB, 0x91, 0xC4, 0xA8, 0x65, 0xB4, 0xBE, 0xA4, 0x3A, 0xEC, 0x88, 0xEE, 0xEB, 0x69,
+       0x52, 0xFD, 0x7F, 0xA4, 0x51, 0x19, 0xF2, 0x1B, 0x52, 0x06, 0xF0, 0xC1, 0xB8, 0xF4, 0xE7, 0xD9,
+       0x2A, 0x7F, 0xCD, 0x7F, 0x6E, 0x5A, 0x44, 0xD7, 0x41, 0x86, 0xBE, 0xD2, 0x67, 0x05, 0x50, 0x83,
+       0x0B, 0x0D, 0xCE, 0xCD, 0xD6, 0xB7, 0x42, 0xD3, 0xD6, 0x69, 0x89, 0x68, 0xCB, 0xC4, 0x61, 0xA2,
+       0x67, 0x3C, 0x82, 0x79, 0x3B, 0x4D, 0x0F, 0xA8, 0x11, 0x57, 0x14, 0xC7, 0x10, 0xA6, 0x72, 0x95,
+       0x80, 0xEB, 0x23, 0x3F, 0x19, 0x26, 0x06, 0x7B, 0xBC, 0x68, 0x67, 0x9F, 0x2F, 0x57, 0x63, 0x82,
+       0xD2, 0x91, 0xE4, 0x2C, 0x8D, 0x7C, 0x5E, 0xDA, 0xEB, 0xD2, 0xAB, 0xB9, 0xE3, 0x3F, 0x82, 0x0E,
+       0x0E, 0x66, 0x56, 0x05, 0xDA, 0xB8, 0xDC, 0x2B, 0xB0, 0xD2, 0xF5, 0x47, 0xE1, 0x27, 0x12, 0xF2,
+       0xBF, 0x87, 0x3C, 0xC4, 0x84, 0xB2, 0xB6, 0x70, 0x63, 0xB6, 0xC3, 0x1A, 0x67, 0x26, 0xB4, 0xAC,
+       0x4C, 0xD8, 0x53, 0x1A, 0x47, 0x27, 0x9A, 0x0B, 0x29, 0x81, 0x7F, 0x60, 0x6B, 0x94, 0x95, 0x53,
+       0xAB, 0xF0, 0x04, 0x9F, 0x96, 0x15, 0x75, 0x9D, 0x6A, 0x1D, 0x46, 0xF7, 0x31, 0xB7, 0xD4, 0x55,
+       0xE0, 0xC1, 0x36, 0x63, 0xE5, 0xB3, 0xE5, 0x9A, 0xBA, 0xA2, 0x72, 0x2E, 0x13, 0xB5, 0xCB, 0x65,
+       0x78, 0xC4, 0x91, 0x86, 0x54, 0xCF, 0x80, 0xE8, 0xFC, 0xD4, 0x2A, 0xA5, 0x04, 0xE7, 0xFC, 0x7D,
+       0x35, 0xD8, 0x27, 0x8B, 0xEB, 0x94, 0xD6, 0x32, 0x9B, 0xC8, 0xA0, 0x3F, 0x17, 0x95, 0x1E, 0xF8,
+       0x3D, 0xDE, 0x0A, 0xBF, 0xCE, 0xEE, 0x48, 0x97, 0x32, 0x2F, 0x7D, 0xE2, 0x61, 0x99, 0x66, 0x04,
+       0x34, 0xB1, 0xB5, 0x9D, 0x9B, 0xB1, 0xF8, 0xCD, 0x52, 0x6E, 0x2F, 0xBD, 0xDC, 0x2B, 0x4A, 0x30,
+       0xE0, 0x83, 0xE8, 0x65, 0xDD, 0x02, 0xCF, 0x02, 0xC9, 0xE3, 0x59, 0x3D, 0x98, 0x7E, 0xC7, 0x5B,
+       0x59, 0x5A, 0x6E, 0x0F, 0xF4, 0x25, 0x4C, 0x23, 0xD7, 0x1E, 0xBE, 0xB9, 0x45, 0xCB, 0xF9, 0x65,
+       0xDE, 0xB3, 0x08, 0x50, 0x70, 0x8D, 0x3E, 0x87, 0x58, 0x52, 0x16, 0x2A, 0xFA, 0xBC, 0x97, 0x7D,
+       0xC2, 0xC7, 0xD6, 0x51, 0x22, 0xAA, 0xBE, 0xDC, 0x77, 0x74, 0x61, 0x42, 0xF2, 0xF1, 0x9A, 0x5C,
+       0x74, 0x34, 0xD5, 0x1A, 0x77, 0x17, 0xD3, 0x70, 0x97, 0xED, 0xF1, 0x75, 0x9F, 0x54, 0x65, 0x66,
+       0x4C, 0xAA, 0x11, 0xC2, 0x4B, 0xF4, 0x2F, 0x8A, 0x97, 0xCA, 0xA4, 0x36, 0x55, 0xC6, 0x22, 0x94,
+       0xFD, 0x7F, 0xB4, 0xC7, 0x18, 0xC3, 0x3C, 0x2C, 0xED, 0x15, 0x49, 0x0C, 0xB9, 0x6A, 0xF2, 0xF4,
+       0xE5, 0xA3, 0xDF, 0x16, 0x43, 0xB4, 0x24, 0x4C, 0xB8, 0x08, 0xCC, 0xA0, 0x35, 0x20, 0x5D, 0x8D,
+       0xEA, 0xC2, 0xE1, 0x66, 0xEC, 0x3F, 0x1E, 0x80, 0x86, 0x4F, 0xD1, 0x82, 0x45, 0xC0, 0x97, 0xCE,
+       0x38, 0x34, 0x40, 0x45, 0x70, 0x1D, 0x78, 0x56, 0x33, 0x0D, 0x11, 0x45, 0xEB, 0x94, 0x29, 0x0C,
+       0x5D, 0xC2, 0xFE, 0x5B, 0x30, 0x47, 0x04, 0xE0, 0xE4, 0x01, 0x09, 0x51, 0xB2, 0x31, 0x05, 0x10,
+       0x07, 0x73, 0xBC, 0x3E, 0x8C, 0x34, 0x65, 0x9B, 0x58, 0x6C, 0xE0, 0xF3, 0x3D, 0x2F, 0x5D, 0x81,
+       0x76, 0x95, 0x85, 0x4C, 0xB0, 0xD3, 0x03, 0x8F, 0x61, 0x49, 0x0F, 0x60, 0x23, 0x90, 0xF0, 0x2A,
+       0x85, 0xB1, 0x15, 0xD7, 0xB3, 0xBC, 0xBA, 0x31, 0xD2, 0x58, 0x5F, 0x63, 0x3F, 0x14, 0xFF, 0x6D,
+       0xC2, 0x0C, 0x1F, 0x62, 0x41, 0x9C, 0xFB, 0x2A, 0xB0, 0xBC, 0xF3, 0xFC, 0x2D, 0x0A, 0x36, 0x26,
+       0x45, 0x28, 0x73, 0xCD, 0x54, 0x41, 0x71, 0xE5, 0xC9, 0xCB, 0x40, 0x1B, 0x6F, 0x66, 0x46, 0xE4,
+       0x1A, 0xA8, 0x00, 0xC5, 0x23, 0x33, 0xAC, 0xAA, 0x5F, 0xA9, 0x8B, 0x73, 0x29, 0xF1, 0x32, 0xCE,
+       0xCF, 0x8F, 0xB6, 0x51, 0x6B, 0xA5, 0xEE, 0xA5, 0x3F, 0xC7, 0xA6, 0x1C, 0xD8, 0x75, 0x39, 0xDA,
+       0x46, 0xAB, 0xBC, 0x9C, 0x44, 0x82, 0x08, 0x7E, 0xE1, 0x61, 0x62, 0xC5, 0x5F, 0x9A, 0xB7, 0x26,
+       0xCD, 0x15, 0xAC, 0x1B, 0xC0, 0x1F, 0x1A, 0xCA, 0x9A, 0x14, 0x13, 0x68, 0xD1, 0x39, 0x54, 0x6F,
+       0x47, 0x3F, 0x79, 0xE2, 0x2E, 0x29, 0xCF, 0xAD, 0x94, 0x78, 0x21, 0xCD, 0x57, 0xEB, 0xB7, 0x3D,
+       0x7B, 0x29, 0xA1, 0x82, 0x03, 0x58, 0x2B, 0xEF, 0x7E, 0x5B, 0x09, 0x05, 0xA0, 0x31, 0xB8, 0x34,
+       0xBF, 0xBC, 0x20, 0x41, 0x51, 0x6F, 0x49, 0x4E, 0xC8, 0xA2, 0xCD, 0x31, 0xBB, 0xC4, 0xBE, 0x4F,
+       0x9F, 0xE4, 0xD1, 0xD5, 0x18, 0x58, 0x96, 0xDA, 0x7A, 0x03, 0x6B, 0xD1, 0xCA, 0x66, 0x0F, 0x3A,
+       0x61, 0x12, 0x6D, 0xC4, 0xC8, 0xD3, 0x02, 0xE6, 0x1B, 0x6A, 0xDB, 0xB3, 0x2C, 0xF0, 0xFB, 0xC2,
+       0xF8, 0x8F, 0xB3, 0x77, 0x8C, 0x0B, 0x2D, 0x3C, 0x69, 0x72, 0x05, 0x07, 0x37, 0x50, 0x8F, 0x5C,
+       0xCF, 0x18, 0xC8, 0xAC, 0x4B, 0x04, 0x95, 0xD6, 0xA6, 0xB5, 0x0E, 0x70, 0xD4, 0x1A, 0xA8, 0xB5,
+       0xE1, 0x2C, 0x62, 0x08, 0x68, 0x68, 0x23, 0xE9, 0x48, 0xED, 0xA7, 0x1A, 0x5B, 0x34, 0x0A, 0xE4,
+       0x44, 0x6B, 0x2B, 0x32, 0x6D, 0x9E, 0x86, 0x3C, 0xC2, 0xE8, 0xA3, 0x5A, 0xD0, 0x76, 0x1E, 0x62,
+       0x21, 0x6B, 0x57, 0x73, 0x21, 0x32, 0xB3, 0x42, 0xEA, 0x9A, 0x46, 0xB8, 0x83, 0xF6, 0x24, 0x50,
+       0x7D, 0x1D, 0xFE, 0x23, 0xEE, 0x0B, 0x54, 0xCB, 0x73, 0x7C, 0x14, 0x1D, 0xEA, 0xA6, 0xDF, 0xF6,
+       0xBF, 0xAA, 0xC5, 0xA7, 0xEC, 0xF6, 0x67, 0x4B, 0xFC, 0x89, 0x24, 0xDE, 0x3A, 0x15, 0x9E, 0xC9,
+       0xDF, 0x08, 0x7B, 0x4F, 0x81, 0x46, 0x47, 0x05, 0x75, 0xDD, 0x6F, 0xE2, 0xA6, 0x1A, 0x26, 0xE1,
+       0x72, 0x66, 0x63, 0x78, 0x58, 0x87, 0xFB, 0x65, 0x25, 0xA3, 0x24, 0x64, 0x23, 0x6D, 0xA1, 0xC6,
+       0x95, 0x78, 0x92, 0x7F, 0x1C, 0xAF, 0x45, 0x50, 0x80, 0x8A, 0x32, 0xE7, 0x0C, 0x03, 0xC1, 0xF9,
+       0xF6, 0xB6, 0xB3, 0xFD, 0x4D, 0x64, 0x32, 0xE4, 0x65, 0x8C, 0xDC, 0x30, 0x07, 0xBD, 0x4A, 0xEB,
+       0x05, 0x08, 0x04, 0xBB, 0xA4, 0xF1, 0x7A, 0x6B, 0xBA, 0x81, 0x4F, 0xB0, 0xFB, 0x3E, 0x10, 0x16,
+       0x32, 0x6A, 0x8E, 0x5E, 0x1B, 0xEC, 0x23, 0x7B, 0x47, 0xE9, 0x4A, 0xE6, 0xAC, 0x23, 0xE2, 0xF8,
+       0x50, 0x7C, 0x87, 0x89, 0xC4, 0xAD, 0x16, 0x50, 0xB6, 0x8A, 0x6E, 0xB0, 0xE2, 0x39, 0x97, 0xF5,
+       0x17, 0x2E, 0xEB, 0x88, 0x37, 0x93, 0x66, 0xD9, 0xA5, 0x49, 0xD2, 0x2B, 0x95, 0x27, 0x92, 0x0A,
+       0x83, 0x50, 0x61, 0x64, 0x11, 0x71, 0xE1, 0x47, 0xDC, 0x32, 0x5D, 0x85, 0x84, 0x64, 0x3E, 0x7A,
+       0xE7, 0x9C, 0x83, 0x20, 0x07, 0x93, 0xBB, 0xA8, 0x9C, 0xD2, 0xF3, 0xAD, 0x27, 0x1E, 0x07, 0x78,
+       0xB6, 0xD8, 0xBB, 0x22, 0xEC, 0xF9, 0x54, 0x36, 0xE6, 0xC4, 0x03, 0x1A, 0x09, 0x25, 0x60, 0xD8,
+       0x39, 0x1A, 0x34, 0x5C, 0x38, 0x2A, 0xAD, 0x55, 0x3C, 0x4F, 0x18, 0x85, 0x60, 0xF1, 0x18, 0x3A,
+       0xBB, 0x15, 0x54, 0x93, 0x5B, 0x4C, 0xD5, 0x15, 0x4B, 0x61, 0x7B, 0x52, 0xE6, 0x6B, 0xCB, 0x78,
+       0x2E, 0x01, 0x03, 0xCF, 0x9F, 0x7C, 0xCD, 0xF9, 0x31, 0xA4, 0xCC, 0xE0, 0xE0, 0x57, 0x30, 0x96,
+       0x02, 0xD1, 0xA1, 0x4A, 0xA6, 0x77, 0x32, 0x12, 0xFC, 0x4C, 0x40, 0x50, 0xBF, 0x78, 0x03, 0x53,
+       0x51, 0xF6, 0x09, 0xCA, 0xF2, 0x0B, 0x8B, 0x03, 0xDD, 0x49, 0x74, 0x7C, 0x00, 0x45, 0x5C, 0x46,
+       0x2D, 0x17, 0x3B, 0x9D, 0x89, 0xB9, 0x3C, 0x48, 0x47, 0xBC, 0x98, 0x37, 0x76, 0x13, 0x22, 0x00,
+       0x4F, 0x63, 0xB4, 0xA0, 0x7C, 0x3C, 0x5E, 0x64, 0xBB, 0xCB, 0xBF, 0xBC, 0x08, 0x50, 0x67, 0x5D,
+       0xAC, 0x34, 0xDE, 0xCF, 0xD4, 0x8B, 0xBD, 0x3C, 0x21, 0x2D, 0xC7, 0x74, 0x92, 0xCD, 0x4C, 0x61,
+       0x0F, 0x62, 0x20, 0xA8, 0xFB, 0x79, 0x83, 0x63, 0xE3, 0x00, 0xBE, 0x77, 0x2E, 0x77, 0x80, 0x4C,
+       0xB0, 0x85, 0x8B, 0x42, 0x92, 0x5D, 0xF1, 0x66, 0xAA, 0x3B, 0x1F, 0x45, 0x4B, 0xCE, 0x58, 0x49,
+       0x66, 0x38, 0xA6, 0x76, 0xF7, 0x41, 0x7F, 0x3E, 0x12, 0xD7, 0xF1, 0x9E, 0xB7, 0x11, 0xE2, 0x3C,
+       0xCB, 0xC9, 0x5A, 0x99, 0x28, 0x9E, 0x8B, 0x3E, 0xDA, 0xDC, 0x28, 0xDE, 0xD1, 0x52, 0x6F, 0x34,
+       0x1A, 0x10, 0xE1, 0xCD, 0xF9, 0xC0, 0x3F, 0x05, 0x28, 0x19, 0x30, 0x3E, 0xFF, 0x2B, 0xEF, 0x3C,
+       0x94, 0xF0, 0x26, 0x2E, 0x83, 0x76, 0x51, 0x8F, 0x6B, 0x11, 0x08, 0xB0, 0x72, 0x66, 0x8F, 0xD6,
+       0x57, 0x7A, 0x85, 0x1F, 0x12, 0xB6, 0x68, 0x4E, 0x4C, 0xDE, 0xA1, 0xED, 0x7D, 0x42, 0x7B, 0xEC,
+       0x34, 0x46, 0x1D, 0x36, 0x8C, 0x48, 0xF6, 0x01, 0x16, 0xBD, 0x7E, 0x6D, 0x62, 0x2B, 0x83, 0xD3,
+       0x18, 0x1F, 0x83, 0x66, 0x74, 0x2E, 0x6D, 0xB1, 0x28, 0xC0, 0x7F, 0x05, 0x97, 0x0D, 0xE8, 0x2F,
+       0xE4, 0x61, 0x9E, 0x78, 0xF4, 0xEA, 0x29, 0x60, 0x15, 0x64, 0x3A, 0x77, 0x92, 0x48, 0x36, 0xBA,
+       0x56, 0xDF, 0xB8, 0xCE, 0x71, 0x0D, 0x2D, 0x0B, 0x4C, 0x27, 0x7B, 0x7E, 0xD5, 0x06, 0xC2, 0x77,
+       0x28, 0x51, 0x61, 0xB5, 0xAB, 0xCC, 0x3E, 0x84, 0xB8, 0xB3, 0xD1, 0x26, 0x52, 0x7C, 0xDC, 0xEE,
+       0xDC, 0xE1, 0x59, 0x62, 0x83, 0xD7, 0xD6, 0xA7, 0x9B, 0xDA, 0x6E, 0x30, 0x76, 0x4D, 0xA3, 0x15,
+       0x22, 0x09, 0x14, 0xC0, 0x74, 0xF8, 0x01, 0x47, 0x47, 0x0C, 0x70, 0x1C, 0xCD, 0xC9, 0xDB, 0x29,
+       0x91, 0xBB, 0x7B, 0xD0, 0x2A, 0x79, 0xFF, 0xF9, 0x46, 0xA0, 0x15, 0x7D, 0x95, 0x64, 0xC6, 0x7C,
+       0xA4, 0xC8, 0xC0, 0xAB, 0x07, 0xF7, 0x00, 0x42, 0xEA, 0xCF, 0x3D, 0x6B, 0x39, 0xBE, 0x7F, 0x72,
+       0xCB, 0x78, 0x81, 0x15, 0x7E, 0x8C, 0xDF, 0xCF, 0x51, 0x0C, 0x45, 0xFD, 0x45, 0x6F, 0x2D, 0x63,
+       0xF1, 0x8B, 0x38, 0xD2, 0x8B, 0x87, 0x38, 0x28, 0x86, 0xE7, 0x38, 0x94, 0xAB, 0x9F, 0x8E, 0x6F,
+       0x0F, 0xF7, 0xB0, 0x53, 0x42, 0x1E, 0x1A, 0x82, 0xB5, 0x21, 0xA2, 0x1B, 0x7F, 0x33, 0x79, 0x2D,
+       0xD4, 0x8C, 0x34, 0x76, 0x37, 0x33, 0x92, 0x4F, 0xE3, 0x08, 0x01, 0x84, 0x1E, 0x45, 0x2A, 0xF4,
+       0x67, 0x76, 0x8D, 0x68, 0xC0, 0xB7, 0xF9, 0x24, 0x4A, 0x7A, 0x97, 0x2F, 0x4D, 0xA3, 0x94, 0xDF,
+       0x73, 0x4F, 0x61, 0xCF, 0x46, 0xF7, 0x81, 0x14, 0x7C, 0x37, 0x4A, 0x3D, 0xE0, 0x5B, 0x0F, 0x3C,
+       0xC5, 0x58, 0xA2, 0x3B, 0x8C, 0x16, 0xCD, 0x6D, 0xFC, 0xE5, 0xF6, 0xEE, 0x0C, 0xAB, 0xDA, 0x49,
+       0xDA, 0xC4, 0xBF, 0x2E, 0x26, 0x38, 0x3C, 0xDD, 0x56, 0xA6, 0x80, 0xFB, 0x18, 0x7E, 0xB9, 0x17,
+       0x63, 0x93, 0x9F, 0x34, 0xCF, 0x71, 0x5E, 0xD2, 0xEF, 0xB6, 0xF0, 0x72, 0x2D, 0xA4, 0xA7, 0x50,
+       0x3D, 0x9E, 0xE9, 0x1B, 0x89, 0x56, 0x9F, 0xFF, 0x11, 0x24, 0x6C, 0xC6, 0x14, 0xF2, 0x64, 0x53,
+       0x96, 0x60, 0x15, 0x2F, 0x01, 0x08, 0xB1, 0x97, 0xA0, 0x4C, 0x70, 0x91, 0x1A, 0x7F, 0x73, 0xE7,
+       0x9C, 0xE6, 0xDA, 0x1C, 0x14, 0x3F, 0xD6, 0x85, 0x71, 0xCE, 0xF8, 0xD5, 0x0E, 0x91, 0xCC, 0x0D,
+       0x58, 0x75, 0x6B, 0x8E, 0xF8, 0xD2, 0x81, 0xFE, 0xE1, 0x6E, 0xC8, 0x4F, 0x14, 0x91, 0x76, 0xEC,
+       0x19, 0xEC, 0xD6, 0xBD, 0x68, 0x54, 0x25, 0xD0, 0x58, 0x40, 0xBC, 0x28, 0xC9, 0x0D, 0xFE, 0x6E,
+       0x6C, 0x2D, 0xBA, 0xF2, 0x27, 0xCB, 0x5A, 0xC6, 0x8E, 0x85, 0xB0, 0x90, 0xC0, 0xC0, 0x63, 0xE1,
+       0x46, 0x17, 0xE6, 0xC6, 0xB6, 0xDA, 0x7E, 0x5B, 0x02, 0x7B, 0xC1, 0xE7, 0xE3, 0xAA, 0x1D, 0xA1,
+       0x0C, 0xD6, 0x41, 0x02, 0x71, 0x94, 0x5E, 0x87, 0xA1, 0x4E, 0x14, 0x92, 0xEC, 0xBF, 0x1F, 0x56,
+       0x0F, 0x8F, 0x95, 0x0D, 0xCA, 0x61, 0xEE, 0x9F, 0xEE, 0x04, 0x4F, 0xFE, 0x73, 0xD0, 0xB1, 0x4A,
+       0x55, 0x7C, 0x57, 0xD2, 0x23, 0xD9, 0x1D, 0x7C, 0x88, 0x06, 0xA8, 0x9A, 0xF1, 0x89, 0xB4, 0x36,
+       0xD6, 0x71, 0x83, 0x19, 0x08, 0xBA, 0x57, 0x97, 0x40, 0xF7, 0x2F, 0xBB, 0x5D, 0xD7, 0xAD, 0x4A,
+       0x93, 0x4F, 0x81, 0xDA, 0xEB, 0x2B, 0xA8, 0x56, 0x43, 0x4A, 0xA2, 0xAD, 0x1B, 0xC3, 0x5C, 0xA0,
+       0x0B, 0xE1, 0x50, 0x5C, 0xEE, 0x61, 0x3E, 0xEC, 0x38, 0x68, 0x1B, 0xDC, 0xEC, 0x8B, 0x55, 0xB9,
+       0x74, 0xD4, 0x8D, 0x97, 0x2E, 0x43, 0xD2, 0xF3, 0x4D, 0x38, 0xF9, 0x1B, 0xF2, 0x23, 0xC9, 0x93,
+       0x90, 0x1F, 0x86, 0xA7, 0xDC, 0x72, 0x67, 0x79, 0xAC, 0x4C, 0x07, 0x25, 0xA4, 0x83, 0x7E, 0x86,
+       0x29, 0xBF, 0x84, 0xFC, 0xB8, 0xC7, 0xD8, 0x7F, 0x85, 0x90, 0xD4, 0xE7, 0xA1, 0x9D, 0xBC, 0x53,
+       0x1E, 0x8F, 0x02, 0x3E, 0xC1, 0x6E, 0x93, 0x3D, 0x66, 0xF1, 0xD7, 0x8C, 0xE6, 0x9A, 0x46, 0xE9,
+       0x93, 0x3F, 0xFF, 0x21, 0x20, 0xBE, 0xB7, 0x5F, 0x01, 0xE5, 0x43, 0x9F, 0x5E, 0x22, 0x74, 0x9E,
+       0x59, 0xAF, 0xD0, 0x01, 0x76, 0x8D, 0x27, 0x16, 0x72, 0x53, 0xF1, 0x76, 0x96, 0x5D, 0x9C, 0xD6,
+       0x39, 0x26, 0xD4, 0x85, 0x30, 0xD7, 0x51, 0xD3, 0xB1, 0x6C, 0x3D, 0xC2, 0xD5, 0xFF, 0x82, 0x4B,
+       0x46, 0xAB, 0x03, 0x91, 0x63, 0x5C, 0xEB, 0x35, 0x07, 0x4B, 0x61, 0x19, 0x90, 0x1E, 0x3F, 0x62,
+       0x82, 0x80, 0xAE, 0xC1, 0xE5, 0xA9, 0x1A, 0x66, 0xF3, 0x56, 0xB0, 0x2E, 0xB8, 0x43, 0x81, 0xF5,
+       0xA4, 0xCA, 0xA0, 0x91, 0xFD, 0x65, 0x4B, 0x87, 0xB1, 0xC5, 0xF6, 0x03, 0xE0, 0x1D, 0x15, 0x16,
+       0x08, 0x6B, 0x8C, 0x3E, 0xFD, 0x43, 0x82, 0xB5, 0x01, 0x47, 0x66, 0x32, 0x33, 0x3E, 0x45, 0xD1,
+       0x79, 0xAF, 0x84, 0x80, 0xB7, 0xA1, 0xC4, 0x2E, 0x27, 0x21, 0x09, 0x08, 0x38, 0x1F, 0x26, 0xD4,
+       0xCC, 0x4E, 0x12, 0xE7, 0xD6, 0x59, 0xAE, 0x04, 0x29, 0x38, 0xA6, 0x69, 0x37, 0x32, 0x50, 0xB0,
+       0xBB, 0xB6, 0xB6, 0x7C, 0x71, 0x92, 0x8A, 0xFE, 0xAE, 0x1F, 0x10, 0x7C, 0xE3, 0xA8, 0x5F, 0xD3,
+       0xBF, 0x7D, 0xE3, 0xB2, 0x40, 0x44, 0x32, 0x9F, 0xD9, 0x62, 0xF0, 0xA4, 0x7A, 0x0B, 0x5D, 0x19,
+       0x0F, 0x01, 0x05, 0x99, 0xC7, 0xD1, 0x7E, 0xED, 0x1E, 0xF2, 0xA9, 0x80, 0xBC, 0xC7, 0x70, 0x81,
+       0x77, 0x1D, 0x1B, 0xAB, 0x4C, 0xCE, 0xE7, 0xF6, 0xD3, 0x72, 0x8F, 0xC4, 0x8E, 0x8F, 0x5D, 0x97,
+       0x99, 0xB0, 0xCA, 0xB3, 0x08, 0x38, 0x2A, 0x72, 0xB7, 0xFD, 0xC2, 0x09, 0x6E, 0x50, 0xF8, 0xBE,
+       0xA2, 0xA8, 0x88, 0x38, 0x53, 0xC7, 0xA5, 0x71, 0x12, 0x68, 0x3B, 0x49, 0x89, 0xFA, 0x98, 0x45,
+       0x61, 0xC1, 0x3C, 0x26, 0xC5, 0x54, 0x08, 0xD4, 0x00, 0xE8, 0xDC, 0x77, 0xF2, 0x02, 0x9A, 0xE6,
+       0x4E, 0xA6, 0x92, 0x96, 0xE1, 0x87, 0x99, 0x43, 0x87, 0xFF, 0x0C, 0xCF, 0xDD, 0x2C, 0xBB, 0x9E,
+       0xF8, 0x43, 0xE1, 0xD7, 0xAA, 0x7F, 0x19, 0xC2, 0xF1, 0x95, 0x64, 0x18, 0xCD, 0x19, 0xA3, 0x85,
+       0x81, 0x24, 0x7F, 0x64, 0x90, 0x24, 0xC6, 0x1F, 0x8E, 0x7B, 0x69, 0x93, 0x33, 0x95, 0xB3, 0x97,
+       0x9E, 0x27, 0xD3, 0xB5, 0x36, 0x6E, 0x4D, 0xBC, 0x11, 0xB3, 0x5D, 0x6C, 0xD7, 0x7A, 0x6F, 0x42,
+       0x8B, 0x4C, 0x6F, 0xCF, 0xC5, 0x68, 0x7F, 0xEF, 0x95, 0xFE, 0xE3, 0x46, 0x59, 0xB4, 0x22, 0x91,
+       0xD3, 0x5E, 0x55, 0xD9, 0x75, 0xE4, 0x23, 0x40, 0x4C, 0xB0, 0x9D, 0x6F, 0x0A, 0xBA, 0x76, 0x72,
+       0x8C, 0x86, 0xEE, 0xD5, 0xE9, 0x50, 0xA6, 0x82, 0x3B, 0x15, 0xFA, 0xA7, 0xCB, 0x0E, 0x96, 0xFF,
+       0xD3, 0x45, 0xFB, 0x75, 0x14, 0xC0, 0xFB, 0x23, 0xE6, 0x7E, 0x1F, 0xF7, 0x32, 0xDD, 0xE9, 0xEB,
+       0x62, 0x89, 0x69, 0xF8, 0x06, 0x4F, 0xCE, 0x98, 0x9E, 0x9E, 0xE5, 0x40, 0xE1, 0xE5, 0x5E, 0x60,
+       0x2A, 0xB2, 0xD3, 0xC8, 0xF9, 0x28, 0xF5, 0x32, 0x78, 0xC7, 0x8D, 0x2E, 0xD8, 0xA1, 0x82, 0xF3,
+       0xED, 0x0A, 0xFE, 0xEB, 0xAC, 0x6F, 0xFE, 0xB6, 0x1A, 0x29, 0xE7, 0x51, 0x4A, 0x3E, 0x03, 0xEF,
+       0x7B, 0x30, 0x49, 0x94, 0x0B, 0xC2, 0xE9, 0x1D, 0x6E, 0xE3, 0x6E, 0x07, 0xE7, 0xCA, 0xB3, 0xEE,
+       0x8F, 0x72, 0x78, 0xFC, 0x9B, 0xA0, 0xB8, 0x74, 0xCC, 0xC3, 0x04, 0x01, 0x00, 0xA5, 0xAC, 0x56,
+       0x59, 0xCE, 0x00, 0xAD, 0xFF, 0x32, 0xD2, 0x79, 0x5D, 0x81, 0x82, 0x3E, 0xDD, 0x33, 0x67, 0x37,
+       0x37, 0x50, 0x3B, 0xD7, 0x87, 0x6A, 0x54, 0x34, 0x9E, 0x7F, 0x2C, 0x0C, 0x0B, 0x02, 0xA3, 0xDD,
+       0xFD, 0x13, 0x87, 0x12, 0xBC, 0xC2, 0xAF, 0x19, 0xEB, 0xC0, 0x52, 0x49, 0xC4, 0x97, 0xBC, 0x7E,
+       0x2C, 0x51, 0x6D, 0x72, 0xB7, 0xD3, 0xA3, 0x48, 0x15, 0x8B, 0x75, 0x14, 0x9A, 0x90, 0xA9, 0xD4,
+       0xD4, 0x38, 0x00, 0xC0, 0x6B, 0x1B, 0x69, 0xCD, 0xF8, 0x9D, 0xC5, 0xC6, 0x45, 0x2D, 0xAE, 0x13,
+       0x93, 0x50, 0x24, 0xBB, 0x27, 0x21, 0x47, 0xA1, 0x41, 0xBB, 0x20, 0x7C, 0xDF, 0x1B, 0x32, 0x68,
+       0xE1, 0x4E, 0xC4, 0x04, 0x3F, 0x31, 0x0F, 0xC8, 0x10, 0x71, 0xD2, 0xCE, 0xAD, 0x1C, 0x19, 0x89,
+       0x7B, 0x09, 0xB1, 0x36, 0x69, 0x38, 0xDB, 0xFE, 0x52, 0x76, 0x57, 0xAA, 0x3D, 0x21, 0x44, 0x2A,
+       0x9F, 0x3A, 0xFD, 0xEB, 0x52, 0xBA, 0x08, 0x34, 0x66, 0x39, 0xE4, 0x8B, 0x97, 0x09, 0xDC, 0xA4,
+       0x4D, 0xE7, 0x15, 0xBB, 0x0A, 0xC8, 0xE8, 0x15, 0xDB, 0x96, 0x02, 0x1C, 0xA8, 0x06, 0xE4, 0xD1,
+       0x6D, 0x17, 0x1C, 0xCF, 0x2C, 0x19, 0x7A, 0x9C, 0x59, 0x34, 0xF9, 0x10, 0xBF, 0x88, 0xFF, 0x31,
+       0xB4, 0x7D, 0x59, 0x5D, 0x69, 0x06, 0x46, 0x60, 0x57, 0xA2, 0xEA, 0xFE, 0x2D, 0xBF, 0x25, 0x69,
+       0x7A, 0xA8, 0xB0, 0x46, 0x0A, 0x7D, 0x86, 0x81, 0xD6, 0x46, 0x0B, 0x2D, 0xB7, 0xD2, 0xEE, 0xD4,
+       0x57, 0x27, 0xD1, 0x6C, 0x9E, 0x46, 0xCB, 0xA1, 0x36, 0x18, 0x6D, 0xC2, 0x01, 0x8C, 0xC0, 0x81,
+       0x89, 0x85, 0xD6, 0xB9, 0x03, 0x6D, 0xCA, 0xE5, 0x5A, 0xE6, 0xBA, 0x15, 0x5E, 0xA6, 0x2F, 0x99,
+       0x6B, 0xA1, 0x7D, 0x44, 0x56, 0x90, 0x26, 0xB9, 0x53, 0x46, 0x4C, 0x5F, 0xF9, 0x43, 0x69, 0x2E,
+       0x41, 0x43, 0x12, 0x66, 0x77, 0xF3, 0x5E, 0x1A, 0x79, 0xAD, 0xE8, 0xB1, 0x14, 0x54, 0x37, 0x04,
+       0x27, 0x9E, 0xC8, 0x13, 0x10, 0x3F, 0x21, 0xE7, 0x97, 0x97, 0xA5, 0xBB, 0xC4, 0x0C, 0x5E, 0x85,
+       0x03, 0xEC, 0x23, 0x74, 0x32, 0xE8, 0x61, 0x93, 0x66, 0xCB, 0x98, 0x61, 0x8E, 0x5E, 0x7E, 0x4E,
+       0xE3, 0x3E, 0x9A, 0xC1, 0x4A, 0xAF, 0xBA, 0x93, 0xC2, 0x7E, 0x65, 0xFF, 0x94, 0x38, 0x1E, 0x74,
+       0x15, 0xA8, 0x8A, 0xE3, 0x44, 0x6B, 0x6F, 0x29, 0x0B, 0xF2, 0xAF, 0x9F, 0x31, 0x69, 0x7A, 0x0C,
+       0x65, 0x36, 0xEE, 0xF6, 0xD6, 0x5E, 0x2C, 0x8E, 0x5E, 0x03, 0x6C, 0xB4, 0xBB, 0xF2, 0xDB, 0xFF,
+       0xFA, 0x1F, 0x94, 0x1C, 0x7A, 0xF2, 0x23, 0x01, 0xB2, 0xF5, 0x53, 0xD6, 0xDB, 0xA4, 0x6A, 0x2B,
+       0x97, 0x77, 0x95, 0xB6, 0x37, 0x51, 0xFE, 0xF3, 0xAA, 0xE2, 0x0C, 0xF4, 0x19, 0x1F, 0x27, 0x37,
+       0x2B, 0x00, 0xB8, 0xC8, 0x18, 0xC8, 0x35, 0xAE, 0xE6, 0x65, 0xB1, 0x45, 0x9B, 0x24, 0xEE, 0xAF,
+       0xDF, 0x93, 0xD3, 0xDE, 0xBE, 0x29, 0xD6, 0x64, 0x90, 0xF7, 0x77, 0x47, 0x1E, 0x0B, 0xBE, 0x19,
+       0x19, 0x3E, 0x98, 0x2B, 0xBA, 0x78, 0x28, 0x20, 0x8F, 0xBA, 0xE0, 0x20, 0x96, 0x29, 0x9C, 0x59,
+       0x5A, 0x7A, 0x39, 0x19, 0x54, 0xF1, 0x9D, 0xC4, 0xE4, 0x6C, 0xE4, 0x9E, 0x6D, 0x8B, 0x7A, 0x4E,
+       0x4D, 0x88, 0xA3, 0x6D, 0x81, 0x13, 0x76, 0x49, 0x4C, 0xF1, 0x29, 0xD7, 0x51, 0x74, 0x09, 0x98,
+       0x73, 0xD6, 0xB1, 0xD0, 0x04, 0x5B, 0x26, 0xA7, 0xDF, 0x29, 0xB9, 0x1C, 0xDB, 0x92, 0x0B, 0x8C,
+       0x3D, 0x7F, 0xD8, 0x86, 0x17, 0x77, 0x4A, 0xBF, 0xDA, 0x2F, 0x42, 0x7C, 0x65, 0x31, 0x92, 0x93,
+       0xF2, 0x55, 0x96, 0x13, 0x8C, 0x52, 0x9C, 0x0E, 0x7D, 0x94, 0xAD, 0x80, 0x19, 0x21, 0x3B, 0x2B,
+       0x0E, 0x36, 0x7B, 0x67, 0x6B, 0xF9, 0xB8, 0x5B, 0x63, 0x34, 0x85, 0xB7, 0xF4, 0xEC, 0xBD, 0xC1,
+       0x74, 0xDC, 0xCB, 0x06, 0xEE, 0x95, 0x40, 0xF4, 0x20, 0x22, 0xBF, 0xBE, 0x9F, 0xD5, 0xF4, 0xFD,
+       0xBD, 0xC0, 0x37, 0x22, 0xDF, 0xDA, 0xDF, 0x2C, 0x35, 0xD2, 0xBA, 0xB4, 0x02, 0x39, 0x0B, 0x5B,
+       0xFB, 0xFA, 0x94, 0x55, 0x0D, 0x6C, 0x9A, 0x2B, 0xCB, 0xF1, 0x2C, 0x35, 0x15, 0x6C, 0x72, 0x85,
+       0x66, 0x9D, 0x3E, 0x0B, 0x64, 0x95, 0x6C, 0xF7, 0xB4, 0x0D, 0x4F, 0x9A, 0x71, 0xF1, 0x98, 0x95,
+       0xF6, 0x80, 0x41, 0x49, 0xE7, 0xDF, 0xC7, 0x64, 0x1A, 0xB2, 0x52, 0x81, 0x47, 0x3B, 0xF4, 0x2E,
+       0x2A, 0xAD, 0xD8, 0xBF, 0x78, 0x95, 0x2F, 0xE9, 0x69, 0xFB, 0xBC, 0x4A, 0x6C, 0x6E, 0xED, 0x3D,
+       0x96, 0xF1, 0x9A, 0x31, 0x5D, 0x26, 0xB4, 0x1D, 0xBA, 0x28, 0x55, 0x47, 0x35, 0xAB, 0xDC, 0x77,
+       0x68, 0x24, 0x8A, 0x04, 0xF0, 0x32, 0x4B, 0x62, 0xAB, 0xB8, 0x55, 0xA9, 0x14, 0x77, 0x09, 0xE2,
+       0xF8, 0x99, 0xCF, 0x65, 0x0A, 0xC2, 0xC9, 0x94, 0x6F, 0xCA, 0x16, 0xAD, 0xF8, 0x05, 0x9F, 0x87,
+       0x62, 0x5A, 0x17, 0xF8, 0x60, 0xBB, 0x6F, 0x84, 0x16, 0x02, 0xDD, 0x25, 0xD5, 0xD4, 0xE4, 0x4C,
+       0x22, 0x9A, 0x33, 0xC9, 0x44, 0xC5, 0x47, 0xF5, 0xBF, 0x7D, 0xA8, 0xCC, 0x5C, 0xA0, 0x66, 0x5F,
+       0x40, 0xA4, 0xBB, 0x85, 0x22, 0xBF, 0xB2, 0x28, 0x96, 0x5D, 0xF7, 0x50, 0x34, 0xF3, 0x52, 0xFE,
+       0x9E, 0xE7, 0x99, 0x37, 0xD7, 0x99, 0xBC, 0x4A, 0x40, 0x42, 0x0C, 0xAE, 0x11, 0x73, 0x85, 0xFC,
+       0x9A, 0x36, 0xF0, 0x68, 0xA5, 0x18, 0xA1, 0xEC, 0xE7, 0xC9, 0x18, 0x74, 0x25, 0xDC, 0x57, 0x4D,
+       0x17, 0x3F, 0x48, 0x83, 0x70, 0x54, 0x35, 0xD1, 0x70, 0x57, 0x91, 0x16, 0x79, 0x49, 0x31, 0x74,
+       0x0B, 0x79, 0x93, 0xDA, 0x77, 0x44, 0x3E, 0x79, 0xBA, 0xB2, 0x5A, 0x58, 0xAD, 0x74, 0x85, 0x41,
+       0x2C, 0xDA, 0xB7, 0x84, 0xA3, 0x80, 0x32, 0xB8, 0x84, 0xE2, 0x81, 0x35, 0x72, 0x46, 0x96, 0x95,
+       0x1E, 0x38, 0xEF, 0xE4, 0x3E, 0xA4, 0x77, 0x9C, 0x96, 0x53, 0x72, 0x94, 0x48, 0x29, 0xE5, 0xC6,
+       0xA3, 0xF5, 0x14, 0xB5, 0xB5, 0xDD, 0xF9, 0x41, 0xE8, 0x6A, 0xD7, 0xB4, 0xEB, 0x67, 0x56, 0x51,
+       0xA8, 0xC2, 0x10, 0x70, 0x2B, 0xB3, 0x43, 0x30, 0xA4, 0x1C, 0x54, 0x16, 0xCB, 0xFF, 0x6D, 0x17,
+       0xA6, 0x21, 0x2D, 0xFB, 0x30, 0x87, 0xFB, 0xB5, 0xAD, 0x60, 0xFA, 0x29, 0x26, 0xF7, 0xC4, 0xD2,
+       0x99, 0xF3, 0x89, 0x82, 0x95, 0x94, 0xA9, 0x3D, 0x49, 0x6A, 0x98, 0x0C, 0xAF, 0x3A, 0x02, 0x05,
+       0x34, 0xC2, 0x9F, 0x50, 0x9D, 0x9C, 0x3D, 0xD2, 0x8D, 0x59, 0xAD, 0xCA, 0xA6, 0x71, 0x26, 0x88,
+       0x1D, 0x0E, 0xA2, 0xBC, 0x72, 0xF8, 0x22, 0x74, 0x1E, 0x01, 0xEF, 0xAD, 0x0E, 0x05, 0xB0, 0xF2,
+       0x00, 0xC5, 0xE5, 0xD2, 0x6A, 0xBF, 0xBF, 0xB4, 0xE6, 0x07, 0xF7, 0xF6, 0xF2, 0xF8, 0x35, 0x2E,
+       0xD9, 0x34, 0x20, 0x25, 0x39, 0x47, 0xBC, 0x33, 0x9E, 0x6A, 0x56, 0x97, 0x68, 0x1D, 0x8E, 0xD5,
+       0x4D, 0x61, 0xC5, 0x07, 0x5B, 0x3E, 0xAC, 0xC2, 0xC8, 0xA3, 0x21, 0x18, 0xD6, 0x3B, 0xBE, 0x48,
+       0x89, 0x91, 0x4F, 0xF1, 0x8F, 0x84, 0x77, 0xDB, 0xD1, 0x53, 0x36, 0xF8, 0x01, 0x80, 0xBF, 0x90,
+       0x6D, 0xA1, 0x4F, 0x70, 0x34, 0xC4, 0xCA, 0x8A, 0x27, 0x09, 0xF8, 0x3D, 0x13, 0x55, 0x28, 0x9B,
+       0x23, 0x8F, 0x19, 0xF2, 0x39, 0xCC, 0x92, 0x64, 0xBA, 0x6A, 0x78, 0x31, 0x8C, 0x56, 0x7E, 0x3D,
+       0xA0, 0x4B, 0x52, 0x05, 0xB4, 0xCE, 0x04, 0xF2, 0xA7, 0x4C, 0xD0, 0x4D, 0x99, 0xB7, 0x6B, 0x20,
+       0x30, 0x16, 0x61, 0xB4, 0x39, 0xC1, 0xC0, 0x00, 0xD1, 0xB6, 0xC9, 0x67, 0x79, 0x1C, 0x0C, 0xAB,
+       0xDF, 0xD7, 0xEB, 0x12, 0xD3, 0xE8, 0xD6, 0x70, 0x88, 0xCB, 0xDF, 0x60, 0xC9, 0xCE, 0x81, 0x47,
+       0x8F, 0xB0, 0x78, 0x33, 0x78, 0x0F, 0x99, 0x90, 0xC6, 0x9A, 0x7C, 0xAB, 0x67, 0x29, 0x20, 0x88,
+       0x62, 0x26, 0x4D, 0x18, 0x8A, 0xE1, 0xDD, 0xC0, 0x3E, 0x50, 0xB1, 0xB9, 0x2F, 0x5E, 0x02, 0x83,
+       0xB6, 0x8C, 0x73, 0x96, 0xE1, 0x0E, 0xA2, 0x26, 0xCD, 0x98, 0x01, 0x90, 0xED, 0x1D, 0x28, 0x2E,
+       0x92, 0xF2, 0x40, 0xCC, 0x7C, 0x66, 0x25, 0xC5, 0x55, 0x01, 0x0B, 0x7E, 0x03, 0x5A, 0x94, 0x91,
+       0xD8, 0x18, 0x59, 0x8B, 0x05, 0x49, 0x30, 0xAE, 0x0D, 0xB0, 0xAB, 0xAA, 0x66, 0x90, 0xA4, 0x3E,
+       0xD0, 0x0E, 0xDC, 0xA0, 0x97, 0x10, 0xAD, 0xBE, 0xF2, 0xD7, 0xDD, 0x40, 0x27, 0x96, 0x83, 0xD7,
+       0x38, 0x7E, 0xD0, 0xFB, 0x53, 0xD0, 0x13, 0xAE, 0x61, 0xC8, 0xEB, 0x6F, 0x8C, 0x48, 0xEE, 0x50,
+       0x72, 0x6B, 0x56, 0x05, 0xD6, 0x3B, 0xBC, 0x55, 0xF0, 0x79, 0xF2, 0xD8, 0x4D, 0x11, 0x09, 0x8C,
+       0xC1, 0xD6, 0x54, 0xF9, 0xB2, 0xDE, 0xCE, 0x3A, 0x38, 0x08, 0xAB, 0xBF, 0xC9, 0xE1, 0x20, 0x62,
+       0x97, 0x9D, 0x51, 0x1F, 0xA7, 0x32, 0xB6, 0x55, 0xF4, 0xDB, 0x2E, 0x7B, 0x85, 0xB1, 0xFF, 0x04,
+       0xA7, 0xB6, 0x6F, 0xEA, 0x94, 0xF9, 0x87, 0xC9, 0x13, 0xEE, 0x68, 0x32, 0xD3, 0x68, 0x22, 0xBB,
+       0x24, 0xC5, 0x80, 0x20, 0x56, 0xCB, 0x07, 0xAB, 0x78, 0xD0, 0x42, 0x5C, 0x9B, 0x70, 0xF5, 0x01,
+       0xBF, 0x28, 0x94, 0xA6, 0x16, 0xB2, 0xE8, 0xF1, 0xF3, 0x68, 0x7B, 0x0A, 0xDA, 0xFF, 0x58, 0x94,
+       0x1D, 0x78, 0x3A, 0x19, 0x7B, 0x39, 0x54, 0xAA, 0xDA, 0x7D, 0x9E, 0x14, 0x3F, 0x9B, 0x82, 0x6E,
+       0x1B, 0xD3, 0xC3, 0xA7, 0x01, 0x9E, 0x22, 0x46, 0x0B, 0x99, 0x5A, 0x42, 0x29, 0xD3, 0xA2, 0xD6,
+       0x89, 0x7A, 0x45, 0xAD, 0x8A, 0x2E, 0x0A, 0xFA, 0x09, 0x7F, 0x22, 0x84, 0x6E, 0xBC, 0x7C, 0x7D,
+       0x32, 0x80, 0xB7, 0x06, 0x2C, 0x48, 0xF1, 0xA7, 0xEE, 0xF8, 0xC3, 0x83, 0x9C, 0xC1, 0x0E, 0xBB,
+       0x85, 0x27, 0x2F, 0xFE, 0x1B, 0xC6, 0x47, 0xEB, 0x85, 0xD8, 0x3B, 0x09, 0x3C, 0xBB, 0x1C, 0x11,
+       0x50, 0xA1, 0xE7, 0x16, 0x28, 0xA6, 0xDA, 0xE9, 0xF2, 0xAF, 0x26, 0x48, 0xC7, 0xC8, 0x75, 0x7B,
+       0x8A, 0xA6, 0xA3, 0xCC, 0x7B, 0xCA, 0x60, 0x8F, 0xCA, 0x2A, 0xFA, 0xB9, 0xB0, 0xCC, 0xBD, 0x20,
+       0x61, 0x67, 0x9D, 0x83, 0x6A, 0xB5, 0xFC, 0xE7, 0xA0, 0x52, 0x87, 0xB3, 0xFC, 0x7A, 0x2E, 0xC5,
+       0xDD, 0x04, 0xD3, 0x8B, 0x3C, 0x55, 0x7D, 0x10, 0xCF, 0xC6, 0x21, 0xCF, 0x7D, 0x9A, 0x7E, 0xDE,
+       0xB9, 0x04, 0x09, 0x27, 0xB7, 0x77, 0x23, 0xF1, 0x55, 0x92, 0x84, 0xA8, 0x7C, 0xA4, 0x6B, 0xE4,
+       0x53, 0x91, 0xD1, 0xC7, 0xED, 0xCA, 0xAB, 0x8E, 0x3A, 0xD8, 0x71, 0xEC, 0x32, 0x3F, 0x95, 0xBB,
+       0x01, 0xB9, 0xBF, 0x2B, 0xBC, 0x7F, 0xD3, 0x6E, 0xE0, 0x96, 0x2C, 0x47, 0xD1, 0x92, 0x5D, 0xAD,
+       0x35, 0x99, 0x72, 0x4D, 0x1B, 0x7B, 0x33, 0x4E, 0x21, 0x3E, 0x7A, 0x8C, 0x71, 0x62, 0x0E, 0x2A,
+       0x6E, 0xAD, 0xA6, 0xD6, 0xBB, 0x1E, 0x04, 0x58, 0x0E, 0x68, 0xCB, 0x4B, 0xF4, 0xD2, 0x90, 0xAD,
+       0x3E, 0x14, 0x13, 0xA2, 0xC0, 0x54, 0xDF, 0x46, 0x7E, 0x43, 0xDE, 0x23, 0x5A, 0x2A, 0x0E, 0xB0,
+       0x47, 0x18, 0x3C, 0x7C, 0xEE, 0xBE, 0xAE, 0xD0, 0x06, 0x2A, 0x8B, 0xCB, 0xCA, 0xDB, 0xAE, 0x43,
+       0x1F, 0x79, 0x4E, 0x79, 0xAD, 0x4D, 0x44, 0xBE, 0x99, 0xC3, 0x82, 0x97, 0x1C, 0x21, 0xF1, 0x25,
+       0xDE, 0x15, 0xEB, 0x1E, 0x20, 0xAF, 0x4E, 0x74, 0xD2, 0x9D, 0xB3, 0x62, 0x20, 0x62, 0xC5, 0xBA,
+       0x54, 0x8E, 0xCC, 0x51, 0x99, 0xEE, 0xAE, 0xFE, 0x2D, 0xD5, 0x5B, 0xE6, 0xD6, 0xBA, 0x45, 0x18,
+       0xDC, 0xB4, 0x73, 0x22, 0x3C, 0x5D, 0xF6, 0x90, 0x1E, 0xE8, 0x4F, 0x37, 0xBD, 0x04, 0x69, 0x85,
+       0xDB, 0xA8, 0x2A, 0x39, 0x95, 0x3B, 0x1C, 0x2E, 0xE2, 0x18, 0xE7, 0xAF, 0x4C, 0x7A, 0xED, 0xCD,
+       0xEC, 0x61, 0xE3, 0xFC, 0x94, 0xD8, 0xAA, 0x0A, 0xE0, 0xA0, 0x76, 0xFC, 0xFD, 0xF6, 0xDC, 0x1B,
+       0xBA, 0xE0, 0xE5, 0xD7, 0xE4, 0x34, 0xDE, 0x63, 0xCE, 0x85, 0xEC, 0x57, 0x1E, 0xFC, 0x71, 0x5C,
+       0xB0, 0x64, 0xE5, 0xA7, 0x21, 0x50, 0x69, 0x13, 0x27, 0x1D, 0xBE, 0x1E, 0x07, 0xF3, 0x49, 0xF1,
+       0xEE, 0xBA, 0x9A, 0xB8, 0x17, 0x6E, 0x95, 0x2F, 0x89, 0xD8, 0xB9, 0x87, 0x1A, 0xCE, 0x6D, 0xF6,
+       0xF2, 0xC1, 0xFB, 0x42, 0x6C, 0x1D, 0x2D, 0x5C, 0xE0, 0xA2, 0x69, 0x52, 0xF8, 0x2F, 0xD2, 0x75,
+       0xDC, 0x1A, 0xC4, 0xC3, 0x53, 0x8E, 0x30, 0x80, 0x97, 0xE9, 0xAD, 0xF1, 0xD5, 0x69, 0xB9, 0x3A,
+       0xD3, 0x63, 0x14, 0xBF, 0x93, 0x82, 0x10, 0x6E, 0x6F, 0x68, 0xE4, 0x16, 0x8E, 0x01, 0x1D, 0x0F,
+       0xB8, 0x05, 0xD4, 0xAF, 0x06, 0xB1, 0xBA, 0x4A, 0x2A, 0xC5, 0x8E, 0x51, 0x82, 0x49, 0x06, 0x06,
+       0xD4, 0xB9, 0x96, 0x6F, 0x3E, 0xAB, 0xAE, 0x2C, 0x2F, 0x65, 0x15, 0x13, 0xED, 0x3A, 0xAA, 0x2C,
+       0x38, 0x2D, 0x0B, 0x05, 0xF9, 0xFE, 0x78, 0x2D, 0x6A, 0xBC, 0xCF, 0xE3, 0xC6, 0x42, 0x87, 0xB9,
+       0x55, 0xF4, 0x38, 0x1E, 0x4B, 0x5E, 0x85, 0xBB, 0x00, 0xEE, 0xE1, 0x6E, 0xAE, 0x89, 0xA8, 0x5E,
+       0x56, 0x19, 0xE4, 0xB0, 0xFD, 0x47, 0xD3, 0xD1, 0x0B, 0xC1, 0x6A, 0xA8, 0x62, 0x01, 0x05, 0x27,
+       0x6A, 0xDB, 0x4E, 0xBF, 0xDE, 0xE2, 0xA8, 0x6F, 0x16, 0x20, 0xAC, 0xDD, 0x65, 0xA8, 0x60, 0x17,
+       0xB7, 0x49, 0xF1, 0xBA, 0x47, 0x80, 0x4A, 0xBA, 0xD5, 0xEE, 0xA3, 0x28, 0xDF, 0xC7, 0x69, 0x44,
+       0x7E, 0x41, 0xF6, 0xC4, 0x32, 0xE3, 0xD8, 0x8C, 0xA0, 0xF7, 0xD5, 0xC6, 0x09, 0xDB, 0xA9, 0x71,
+       0x08, 0x44, 0x77, 0x56, 0xE1, 0xBE, 0xB8, 0x84, 0x0D, 0xB8, 0xE6, 0xE5, 0x20, 0x01, 0x85, 0xA5,
+       0x9A, 0xCF, 0x5E, 0x5D, 0xEF, 0x49, 0x2F, 0x90, 0x44, 0xF2, 0x3A, 0x2A, 0xB6, 0xDA, 0xB0, 0xF0,
+       0x55, 0x35, 0x95, 0x41, 0x7C, 0xFF, 0xD5, 0xFD, 0xE3, 0x15, 0xD9, 0xEB, 0xCB, 0x4C, 0x8E, 0x30,
+       0x12, 0xCA, 0x58, 0xF5, 0xAE, 0x63, 0x1A, 0x5B, 0x68, 0x62, 0x80, 0x1B, 0x32, 0x11, 0xDB, 0xBE,
+       0x8D, 0x5C, 0x4B, 0xFE, 0x08, 0x56, 0x36, 0x6C, 0x19, 0xA6, 0x74, 0x43, 0xA8, 0x1F, 0x7A, 0x33,
+       0xE1, 0xDD, 0x49, 0x85, 0xEE, 0x8F, 0xDB, 0xD5, 0x53, 0x78, 0x8D, 0x00, 0x49, 0x48, 0xD1, 0x76,
+       0x26, 0x05, 0x9B, 0xA2, 0x97, 0x16, 0xD3, 0x11, 0xD6, 0x3F, 0x78, 0x9D, 0xE6, 0x73, 0x0E, 0x61,
+       0xCE, 0x90, 0x0E, 0xC6, 0xFD, 0xB1, 0x2E, 0xBD, 0x21, 0x6C, 0x7C, 0x8A, 0x8D, 0xD3, 0x27, 0xEA,
+       0xC5, 0x92, 0xC1, 0xA0, 0x71, 0x0F, 0x82, 0x75, 0xFA, 0xE4, 0x94, 0x17, 0x2A, 0x19, 0x20, 0x07,
+       0x4D, 0xD8, 0x5F, 0xF8, 0xED, 0xBD, 0x66, 0x92, 0xED, 0x5B, 0x98, 0x2B, 0xCC, 0x6B, 0x53, 0x6A,
+       0xD1, 0x51, 0x4C, 0x52, 0x33, 0x90, 0xFA, 0xB3, 0xB8, 0xAA, 0xBB, 0x15, 0xEA, 0xAB, 0x61, 0xD9,
+       0x72, 0x91, 0x1A, 0xAA, 0xFD, 0x5D, 0x3D, 0x50, 0xA7, 0xC5, 0x1F, 0x3A, 0x97, 0xD0, 0x52, 0xF6,
+       0x02, 0xF6, 0x52, 0x44, 0xDB, 0xB6, 0x82, 0xAB, 0x15, 0x40, 0xF2, 0xF2, 0x7D, 0x1E, 0x8D, 0xE4,
+       0xE3, 0xBB, 0x9E, 0x83, 0x22, 0xD5, 0x00, 0xB0, 0x10, 0x3D, 0xEE, 0x80, 0x3C, 0x0A, 0xA2, 0xB3,
+       0x6D, 0x6F, 0x79, 0xBB, 0x74, 0x65, 0x7F, 0x19, 0x66, 0x2F, 0xDA, 0xAD, 0xA4, 0x97, 0x2B, 0x15,
+       0x6D, 0x17, 0x6E, 0x50, 0x34, 0x6B, 0x76, 0x92, 0xE3, 0x0E, 0x72, 0xF8, 0x7A, 0xF9, 0x53, 0xFA,
+       0xD4, 0x92, 0x57, 0xE9, 0x66, 0xAF, 0xF7, 0xF4, 0xE1, 0x3D, 0xC2, 0xE0, 0x7B, 0x78, 0x8C, 0x50,
+       0xCC, 0x14, 0x0D, 0x06, 0x8B, 0x87, 0x3A, 0xF6, 0x5D, 0xBD, 0x15, 0x11, 0x77, 0xF9, 0xB4, 0x4A,
+       0x3D, 0x33, 0x2A, 0x4E, 0xBE, 0xC7, 0x54, 0xCF, 0x71, 0x20, 0x4C, 0xC1, 0xFE, 0xB0, 0x47, 0x1B,
+       0x2C, 0x1F, 0x39, 0x20, 0x9A, 0xC8, 0x56, 0xB4, 0xB7, 0x14, 0x59, 0xDD, 0x65, 0xDA, 0x08, 0x2C,
+       0xC4, 0x23, 0xCB, 0x86, 0xD6, 0x66, 0xF8, 0x39, 0x96, 0x92, 0x8A, 0xE9, 0xCF, 0x93, 0x11, 0xA4,
+       0x76, 0x5D, 0x0C, 0x0B, 0xAF, 0x2A, 0xDB, 0x1F, 0xBC, 0xDC, 0xCF, 0xE4, 0x72, 0x65, 0x02, 0xEF,
+       0x50, 0xAB, 0x5D, 0xEB, 0x3F, 0xB0, 0x33, 0x11, 0xA2, 0x47, 0x5A, 0xB7, 0x76, 0x7E, 0x16, 0x02,
+       0x15, 0x7F, 0x1E, 0x4A, 0x24, 0xA7, 0x48, 0x97, 0x9F, 0x89, 0x7F, 0xF7, 0xB4, 0x7F, 0x3C, 0x0E,
+       0x17, 0x9D, 0xE4, 0xE3, 0x03, 0x28, 0x4F, 0xDD, 0x37, 0x85, 0x52, 0x73, 0x74, 0x3E, 0xCD, 0x77,
+       0x4F, 0x69, 0x48, 0x72, 0x5B, 0x71, 0xA9, 0xB8, 0x5E, 0xDD, 0x0C, 0xF5, 0x36, 0xEF, 0xEA, 0xA7,
+       0x96, 0x84, 0x07, 0xD4, 0xB6, 0xC9, 0xFC, 0x2A, 0xD5, 0xD6, 0x7E, 0xE5, 0xB7, 0x1C, 0xAB, 0x88,
+       0xB4, 0x3A, 0xEC, 0x4C, 0xB1, 0xBD, 0x15, 0x06, 0xFA, 0xA9, 0x88, 0x2D, 0x1B, 0x23, 0x4E, 0x5F,
+       0x57, 0x52, 0xF4, 0x67, 0x8F, 0x4F, 0xD1, 0xF9, 0x45, 0xE0, 0xE9, 0xD1, 0x1E, 0xFA, 0x9A, 0xC3,
+       0xB9, 0x01, 0x1A, 0x92, 0xBE, 0xAC, 0xE7, 0x30, 0x7F, 0xC9, 0x5E, 0x8E, 0xEE, 0x81, 0x6B, 0xD3,
+       0x03, 0x25, 0x31, 0xDF, 0xBC, 0x09, 0x70, 0x78, 0xEE, 0xB2, 0xFA, 0x4C, 0xA7, 0x9B, 0xE9, 0xDD,
+       0x8F, 0xBD, 0xE8, 0x6D, 0x24, 0x6D, 0xDB, 0x38, 0x36, 0xEF, 0x6C, 0xFE, 0x78, 0xFE, 0x21, 0x52,
+       0x1F, 0xF1, 0x3A, 0x85, 0x0C, 0x84, 0x99, 0xFB, 0x1E, 0x9F, 0x06, 0xDE, 0xF6, 0x6D, 0x35, 0xB1,
+       0x51, 0x06, 0x48, 0xA3, 0xD6, 0xF2, 0x65, 0x6E, 0x15, 0x3C, 0x7F, 0x66, 0xCC, 0xC8, 0x81, 0xB5,
+       0xDF, 0x9F, 0x95, 0x18, 0x25, 0xB5, 0xBE, 0x28, 0x75, 0x76, 0x94, 0xC1, 0xA1, 0x68, 0xEB, 0xA1,
+       0xC7, 0xF5, 0xC0, 0x1A, 0x71, 0x99, 0xEF, 0x36, 0x70, 0x45, 0x9E, 0x40, 0xF2, 0x9D, 0xE8, 0x0D,
+       0x6A, 0xC4, 0x91, 0x62, 0x7B, 0x70, 0x76, 0x3D, 0x8C, 0xB3, 0x58, 0xB3, 0x1E, 0x45, 0x05, 0x85,
+       0x8C, 0xBD, 0xF9, 0xE5, 0x70, 0xCA, 0x76, 0x42, 0xDB, 0x9D, 0xCF, 0xA4, 0x6A, 0x17, 0x30, 0xAD,
+       0x86, 0x03, 0xF0, 0x3B, 0xF5, 0x68, 0xCD, 0x46, 0xED, 0x4A, 0xBD, 0x9B, 0xF7, 0x86, 0xED, 0xE2,
+       0xCB, 0x21, 0xA2, 0x8F, 0x9A, 0x47, 0xBB, 0x64, 0x7F, 0xB2, 0xA3, 0x52, 0x81, 0x59, 0xE9, 0x83,
+       0xF6, 0xE4, 0x80, 0xB2, 0x7C, 0xB3, 0x37, 0x9E, 0xE6, 0x2C, 0x1E, 0x4E, 0xE0, 0x72, 0xC8, 0x32,
+       0x76, 0xF7, 0xB3, 0x11, 0x75, 0x0A, 0x1B, 0xAC, 0xDE, 0x0E, 0x69, 0x1B, 0xF9, 0x8A, 0x76, 0x72,
+       0xE2, 0x19, 0x04, 0x2E, 0x1B, 0xC8, 0xB3, 0x6F, 0xB1, 0xB2, 0xE1, 0xA0, 0xA9, 0x3F, 0x90, 0x48,
+       0x9D, 0x45, 0xC8, 0x5A, 0x06, 0x0A, 0x3A, 0x87, 0xA2, 0xD3, 0xEB, 0x20, 0x53, 0x4B, 0x1B, 0x89,
+       0x1E, 0x8E, 0x6A, 0xCA, 0x09, 0x19, 0x83, 0x0E, 0x30, 0xE1, 0x03, 0x59, 0x77, 0x4A, 0xE0, 0xAC,
+       0xF3, 0xC0, 0x2D, 0x6E, 0x06, 0x59, 0x72, 0xB9, 0x53, 0x05, 0x70, 0xA9, 0xDC, 0xDC, 0x76, 0x8C,
+       0x17, 0x2B, 0xE6, 0x25, 0x92, 0xC8, 0x36, 0xFB, 0xB4, 0x6E, 0xA4, 0x10, 0x02, 0x90, 0x5E, 0xA8,
+       0x12, 0xAD, 0xF9, 0xDD, 0x27, 0xC0, 0x5E, 0x40, 0xAC, 0xB0, 0xA2, 0x09, 0x41, 0x9B, 0x5B, 0x1A,
+       0x85, 0x06, 0xA6, 0x63, 0x61, 0xCC, 0x3B, 0xAE, 0xB3, 0xD0, 0x54, 0xA0, 0xE6, 0x8E, 0xE8, 0x8A,
+       0x56, 0xFC, 0xBE, 0x40, 0x99, 0x33, 0x8F, 0x0F, 0x2C, 0xBF, 0x97, 0x96, 0xFD, 0x93, 0xF4, 0xDD,
+       0x2D, 0x28, 0x5B, 0x81, 0x2A, 0x7B, 0x4D, 0xA6, 0x9F, 0xF8, 0x63, 0xC2, 0xC1, 0xA9, 0x06, 0x3E,
+       0xF9, 0x8B, 0x0F, 0xE2, 0xCF, 0x13, 0x22, 0x49, 0x81, 0x36, 0xC2, 0x09, 0x62, 0x21, 0xBD, 0x21,
+       0x41, 0xE9, 0xE6, 0xD3, 0x75, 0x79, 0x36, 0x53, 0xD4, 0xD5, 0xA8, 0x17, 0xF8, 0x7B, 0xEF, 0x04,
+       0xBE, 0x41, 0x57, 0xEB, 0x16, 0xD7, 0x99, 0x83, 0xFE, 0xD1, 0xA7, 0xF2, 0xE6, 0x60, 0x00, 0x00,
+       0xCC, 0xD0, 0x30, 0x00, 0x03, 0x38, 0x14, 0xA9, 0xAD, 0x5A, 0x52, 0x62, 0x18, 0xAF, 0xA4, 0xC3,
+       0x09, 0xC0, 0xCE, 0x06, 0x5E, 0xE1, 0xA0, 0x9D, 0xF5, 0x73, 0x36, 0x20, 0xEA, 0x1D, 0xFD, 0x00,
+       0xA5, 0x02, 0xCB, 0x4C, 0x1A, 0xCB, 0x43, 0xB5, 0x89, 0xD7, 0x8E, 0x0A, 0x04, 0x9D, 0x4C, 0x9E,
+       0xBE, 0xBC, 0xC4, 0x07, 0x79, 0xCD, 0x71, 0xE8, 0xAA, 0x81, 0x35, 0xF2, 0x28, 0xAC, 0x10, 0x57,
+       0x19, 0xA5, 0xFE, 0xFC, 0x82, 0xF2, 0x0B, 0x48, 0x34, 0x89, 0xB3, 0xDE, 0x9D, 0xD0, 0x96, 0x9B,
+       0x77, 0xBD, 0xB7, 0xDE, 0xBA, 0x3F, 0x08, 0x02, 0x13, 0x3B, 0xAD, 0x9B, 0x1D, 0x64, 0xAD, 0xE9,
+       0x05, 0xCD, 0x11, 0x5F, 0xDC, 0xE7, 0xA3, 0xCA, 0x19, 0xD7, 0x1B, 0x9C, 0xCB, 0x20, 0x3A, 0xC3,
+       0xEB, 0xEF, 0x1A, 0xB4, 0x6B, 0xB9, 0x12, 0x65, 0xB4, 0x22, 0x85, 0x61, 0xD2, 0x61, 0x83, 0x23,
+       0x86, 0x9C, 0xB1, 0x45, 0xAD, 0x8F, 0x15, 0x2D, 0xCA, 0x0B, 0xDE, 0x15, 0xFE, 0x91, 0x03, 0x96,
+       0x8F, 0x35, 0xB7, 0x1A, 0xB8, 0xFC, 0xE4, 0x7F, 0x4C, 0xE9, 0x6C, 0xAE, 0x7E, 0x27, 0xED, 0x15,
+       0x9A, 0x47, 0x0C, 0xEE, 0x13, 0xC5, 0xCA, 0xF8, 0xDD, 0x3A, 0xC8, 0x44, 0xC4, 0xF7, 0x39, 0xEE,
+       0xEF, 0xBD, 0xAD, 0x52, 0x24, 0xFB, 0x43, 0xF4, 0x37, 0x3A, 0xD4, 0x2E, 0xF3, 0xCB, 0x80, 0xF4,
+       0xC2, 0x2A, 0x69, 0xA4, 0x98, 0x8F, 0x94, 0xF5, 0x59, 0x5F, 0x81, 0xCF, 0xE4, 0x10, 0x0A, 0x95,
+       0x7F, 0x50, 0x5B, 0x90, 0x86, 0x3F, 0xC9, 0xA5, 0x2C, 0x5D, 0x87, 0x77, 0xCE, 0xC9, 0x34, 0x0B,
+       0x46, 0xC5, 0xE7, 0xD7, 0x9F, 0x6C, 0xCE, 0x73, 0xE2, 0xEA, 0x70, 0x9E, 0xDF, 0x58, 0x2A, 0x10,
+       0xF7, 0x62, 0x86, 0x67, 0xC1, 0xDD, 0xAC, 0x6E, 0xD1, 0x2C, 0x14, 0x62, 0x58, 0xB9, 0xA3, 0x79,
+       0x17, 0xF5, 0xE2, 0xA3, 0x87, 0x2D, 0x6A, 0x19, 0xE1, 0xD3, 0xE6, 0x0A, 0x69, 0xB0, 0x10, 0x7A,
+       0x7F, 0xD4, 0xE9, 0x23, 0xB4, 0x6F, 0xD1, 0x09, 0x64, 0x6F, 0x61, 0x16, 0x3A, 0xB1, 0xB5, 0xFF,
+       0x30, 0xBD, 0xA9, 0x9C, 0xA1, 0x8E, 0xC3, 0x4E, 0x6C, 0xD2, 0x7C, 0x74, 0xA0, 0x61, 0xC4, 0x28,
+       0x14, 0x15, 0xA4, 0x45, 0xE9, 0x50, 0x31, 0x9C, 0x26, 0xD1, 0xC9, 0xFA, 0x93, 0xFE, 0x20, 0x28,
+       0x03, 0x00, 0x15, 0x50, 0x5A, 0xFA, 0xE0, 0x61, 0x0A, 0x4E, 0x58, 0xEF, 0x2E, 0xB5, 0xF4, 0x28,
+       0xE3, 0x74, 0x3B, 0x28, 0x3F, 0x43, 0x74, 0x60, 0x6C, 0x12, 0xE4, 0x40, 0x25, 0x0C, 0xDF, 0x1C,
+       0xB9, 0xD5, 0xF1, 0x38, 0xED, 0x2A, 0xB7, 0x7E, 0x11, 0x5C, 0x35, 0x63, 0xC0, 0x58, 0x52, 0x2A,
+       0xCA, 0xBD, 0x39, 0xBC, 0xDC, 0x37, 0xA0, 0xD9, 0x39, 0xC6, 0xA7, 0x0F, 0xAB, 0xC4, 0x69, 0xBF,
+       0x90, 0x14, 0x49, 0x98, 0x93, 0x21, 0x81, 0x2D, 0x6A, 0xCE, 0x93, 0xC4, 0xBA, 0x4D, 0x5B, 0x83,
+       0xC6, 0xB6, 0x5B, 0xD2, 0xEF, 0xF6, 0x71, 0xFA, 0xF5, 0x72, 0xE2, 0xF9, 0xCA, 0xD9, 0x1A, 0xC2,
+       0x54, 0x6F, 0xBE, 0x2C, 0x83, 0x49, 0xA6, 0x5B, 0xD9, 0xF0, 0x09, 0x59, 0x0E, 0x16, 0xB7, 0x3C,
+       0x8C, 0xBE, 0xCD, 0x3D, 0x1B, 0x9B, 0xB9, 0x30, 0x8C, 0xF5, 0xE2, 0x7D, 0x2F, 0xF0, 0x5E, 0x7B,
+       0x25, 0x96, 0xD4, 0xDB, 0x50, 0x85, 0x47, 0x4C, 0xA4, 0x25, 0x90, 0x8D, 0xE8, 0xEA, 0x56, 0x83,
+       0xDD, 0x16, 0x79, 0x9E, 0x12, 0x2B, 0x4D, 0x3A, 0x64, 0x06, 0x03, 0xE7, 0x9C, 0x73, 0x70, 0xB6,
+       0x3A, 0xE1, 0xDB, 0x8C, 0x9A, 0x6C, 0x35, 0x81, 0x04, 0x90, 0x0E, 0xAC, 0xBF, 0xF8, 0x0F, 0xFB,
+       0xC7, 0x2D, 0xAC, 0x60, 0xFB, 0xB8, 0xD0, 0x08, 0xE2, 0x0E, 0xCA, 0x93, 0x81, 0x82, 0xAD, 0x62,
+       0x5C, 0x48, 0x8D, 0x1F, 0x23, 0x60, 0x46, 0xC7, 0x38, 0x30, 0x4C, 0x8F, 0x15, 0x9C, 0x9C, 0x79,
+       0x11, 0x40, 0xCC, 0x7A, 0x9B, 0xB6, 0x96, 0xE1, 0x38, 0xD0, 0x57, 0xEF, 0x7C, 0xA6, 0x7D, 0xFE,
+       0x9F, 0xBA, 0x4B, 0xA6, 0xBF, 0x9A, 0x89, 0x6F, 0x20, 0x7C, 0x35, 0x98, 0x86, 0x02, 0x7E, 0x85,
+       0x8F, 0x81, 0x55, 0x65, 0x36, 0xA5, 0x3B, 0xF7, 0x30, 0x0C, 0x66, 0x14, 0x2C, 0x22, 0xC4, 0x6E,
+       0x9D, 0xE4, 0xD6, 0xFE, 0x23, 0x4B, 0x76, 0x7D, 0xBD, 0xDC, 0xE3, 0xCA, 0xD4, 0x73, 0x4C, 0xD1,
+       0x80, 0xD0, 0x81, 0x59, 0x44, 0x6C, 0x10, 0x93, 0x4F, 0x05, 0x78, 0x41, 0x8C, 0x24, 0x90, 0x5B,
+       0x0C, 0xF7, 0xC5, 0xD3, 0x2C, 0x02, 0xBA, 0xE1, 0x43, 0x48, 0x04, 0x61, 0x2F, 0xF9, 0xFB, 0xD1,
+       0x07, 0xDA, 0x57, 0x75, 0xA5, 0xCD, 0xF7, 0x36, 0x58, 0x3C, 0x35, 0x88, 0x4A, 0xB0, 0xF8, 0x80,
+       0xA1, 0x16, 0x9D, 0x53, 0x46, 0x18, 0x00, 0x67, 0xFE, 0xB2, 0x30, 0x37, 0x7E, 0xF3, 0x49, 0x0B,
+       0xAB, 0x4D, 0x86, 0xEA, 0xE4, 0x3C, 0x77, 0xAE, 0xCA, 0xC1, 0x5D, 0x59, 0xD1, 0xC0, 0x7A, 0x94,
+       0x81, 0x54, 0xC2, 0xAB, 0x0A, 0x02, 0xC3, 0xD5, 0xBA, 0x5C, 0xCE, 0x4E, 0x64, 0xA3, 0x77, 0x6B,
+       0xDC, 0xFE, 0x38, 0x0C, 0x0A, 0xBC, 0x1E, 0xB3, 0x64, 0x60, 0x33, 0x77, 0x0F, 0x58, 0xFC, 0xB3,
+       0xC0, 0x5D, 0xF9, 0x64, 0x45, 0xF4, 0x03, 0xE4, 0xFE, 0x24, 0x62, 0x34, 0x69, 0x57, 0x1D, 0xB9,
+       0x91, 0xC6, 0x0D, 0x9F, 0xE4, 0x88, 0x4E, 0xC1, 0xF1, 0x55, 0x5F, 0x0F, 0xDC, 0xC5, 0x7A, 0xFA,
+       0x06, 0x87, 0x36, 0x17, 0xB1, 0x67, 0x65, 0x63, 0xDA, 0xB9, 0x44, 0xE9, 0xD0, 0x71, 0x9C, 0x1F,
+       0xF4, 0xAA, 0x4D, 0xE3, 0x00, 0xB8, 0x3C, 0x3A, 0xFA, 0xAE, 0xFC, 0xB1, 0xB9, 0x6B, 0xC9, 0x74,
+       0xE3, 0xC2, 0x25, 0x97, 0x5B, 0x4D, 0x20, 0x2A, 0x69, 0x64, 0x4A, 0x15, 0xC6, 0x9F, 0xF7, 0x28,
+       0x32, 0xDE, 0x78, 0x4F, 0x30, 0x08, 0x40, 0xB1, 0x73, 0xE0, 0x51, 0xB6, 0x0D, 0xF0, 0xC7, 0xE7,
+       0xE6, 0x15, 0xBA, 0xD2, 0x2D, 0xF9, 0x1D, 0x0C, 0x50, 0xF9, 0x73, 0x60, 0x7C, 0xDB, 0x06, 0x79,
+       0x3B, 0x05, 0x54, 0x0F, 0xA0, 0xDD, 0x90, 0xDC, 0xCE, 0x17, 0x49, 0xF5, 0x07, 0xD7, 0xAD, 0x2A,
+       0x9D, 0x7E, 0x8F, 0x6A, 0x38, 0x50, 0xA6, 0x04, 0xCC, 0xB2, 0x40, 0xCF, 0x7E, 0xD1, 0xE0, 0xD0,
+       0x8D, 0x3B, 0xF2, 0x5A, 0xBA, 0xBA, 0xB8, 0x9D, 0xC4, 0xE4, 0x83, 0x53, 0x4C, 0x4B, 0xA2, 0x0A,
+       0x07, 0x1B, 0x46, 0xDE, 0x67, 0xA4, 0xE3, 0xD1, 0x18, 0x16, 0x84, 0x4E, 0x78, 0xF0, 0xDC, 0xB6,
+       0x55, 0x87, 0xE3, 0x76, 0x5E, 0x4A, 0xBE, 0xF6, 0xB9, 0x41, 0x5F, 0x82, 0xBB, 0xC8, 0x82, 0xCC,
+       0xAA, 0xFD, 0x1B, 0xA4, 0x82, 0x0E, 0x25, 0x3E, 0x44, 0x8F, 0x9D, 0x89, 0xDC, 0x9F, 0xEA, 0x9F,
+       0x6E, 0xE6, 0xB3, 0xE5, 0x72, 0x46, 0xBE, 0xB0, 0x7E, 0x00, 0xD8, 0x91, 0xB6, 0x31, 0x17, 0x7E,
+       0xFE, 0xD5, 0x25, 0x94, 0x25, 0xA6, 0xAA, 0x46, 0x4B, 0x91, 0xAA, 0x74, 0x3B, 0x67, 0x72, 0xA1,
+       0x92, 0xA8, 0x8D, 0x5C, 0xD4, 0x29, 0xBF, 0x8D, 0xFB, 0x41, 0x0C, 0x4B, 0xCE, 0x44, 0x23, 0xF7,
+       0x73, 0xE9, 0x1E, 0x40, 0x7B, 0xFC, 0x42, 0x31, 0x1C, 0xA7, 0x48, 0x93, 0x94, 0x81, 0xA3, 0x0C,
+       0x6B, 0xE2, 0x60, 0x41, 0xE0, 0x88, 0x79, 0xD4, 0x69, 0x44, 0xDF, 0x5C, 0x5F, 0xBB, 0x40, 0x26,
+       0x65, 0x10, 0x3B, 0xC5, 0x14, 0x72, 0x16, 0xD1, 0x06, 0x4F, 0x17, 0xCD, 0x70, 0x85, 0xD9, 0xEB,
+       0x3D, 0x64, 0xAA, 0xF0, 0xDB, 0xA0, 0x5A, 0xD6, 0x8C, 0xA3, 0x97, 0xC9, 0xA5, 0x29, 0xB1, 0x0F,
+       0x6C, 0x93, 0x2D, 0x82, 0x3A, 0xB0, 0x41, 0x05, 0xF2, 0xF7, 0x5C, 0x3D, 0x44, 0x16, 0x5C, 0xAB,
+       0xFC, 0xE1, 0x9E, 0x64, 0x89, 0xC5, 0x6E, 0x8B, 0x5B, 0xE0, 0x5F, 0x88, 0xFC, 0x5D, 0x14, 0x9E,
+       0x35, 0x81, 0xCA, 0x01, 0xD4, 0x98, 0x8A, 0xB1, 0x71, 0x00, 0xF7, 0x27, 0xC6, 0x8C, 0x6D, 0x33,
+       0x0D, 0x0C, 0x24, 0xA2, 0x9E, 0xC5, 0x9F, 0x02, 0xE0, 0x2A, 0x32, 0xD0, 0xDB, 0x80, 0x28, 0xE1,
+       0xA1, 0xC6, 0xD0, 0xC0, 0x10, 0x81, 0x2A, 0x03, 0xE9, 0xC0, 0xF5, 0xD7, 0xDF, 0x2F, 0xB7, 0xCE,
+       0x2C, 0xCF, 0x09, 0x72, 0x1E, 0x35, 0x3F, 0xB5, 0xAD, 0x7B, 0xAB, 0x89, 0x84, 0xE2, 0x83, 0x24,
+       0x2C, 0xDB, 0x5D, 0x1D, 0x1B, 0x77, 0x05, 0x0A, 0xFE, 0x08, 0x06, 0x8A, 0x87, 0x55, 0x9E, 0xBC,
+       0xD6, 0x08, 0x71, 0xCC, 0x05, 0xD1, 0x6E, 0x6D, 0x9F, 0x8B, 0xEE, 0x29, 0x59, 0x81, 0x73, 0x0B,
+       0xC1, 0xFA, 0x4C, 0xCE, 0x30, 0x78, 0xCF, 0xE2, 0xD9, 0xFB, 0x19, 0xC4, 0x4D, 0x3D, 0x11, 0x71,
+       0x84, 0xC9, 0x73, 0x4B, 0x4B, 0x17, 0x91, 0x7F, 0xDE, 0x6F, 0x00, 0x2E, 0x25, 0x09, 0x87, 0xD6,
+       0xDF, 0x62, 0x15, 0x58, 0xF4, 0xAF, 0x8B, 0xBB, 0x0D, 0xDD, 0xA7, 0x50, 0xE3, 0x56, 0xED, 0x48,
+       0xA1, 0x2A, 0x5C, 0x5F, 0x90, 0x0E, 0x2D, 0xF4, 0xED, 0xF1, 0x8D, 0x08, 0xBC, 0x69, 0xFE, 0x59,
+       0xB3, 0x04, 0x7A, 0x7E, 0xEC, 0xEC, 0xFF, 0xD3, 0x58, 0x33, 0x45, 0x06, 0x93, 0x58, 0x48, 0x10,
+       0x0F, 0x7A, 0xC6, 0x59, 0xE4, 0x04, 0xE9, 0x17, 0x49, 0x58, 0xF5, 0x71, 0xBA, 0x96, 0x34, 0x46,
+       0xB1, 0x6E, 0x11, 0xF4, 0xF4, 0xFB, 0xDF, 0xC7, 0x60, 0x8C, 0x21, 0xC5, 0x77, 0x68, 0x2F, 0x96,
+       0xEA, 0x75, 0x9A, 0xFC, 0x27, 0xD7, 0xEC, 0xC7, 0x78, 0x15, 0xD7, 0x31, 0xEF, 0x31, 0x8F, 0x82,
+       0x02, 0x41, 0x64, 0x11, 0xE3, 0x0A, 0xA1, 0xB7, 0x7B, 0x27, 0x2C, 0x1F, 0x0E, 0x9F, 0x1F, 0x07,
+       0xF0, 0xEC, 0x9B, 0xDF, 0x75, 0x0D, 0xF6, 0x79, 0x79, 0x73, 0xDB, 0xBD, 0x70, 0xE2, 0x8B, 0xC2,
+       0x20, 0xE4, 0x89, 0xAE, 0x4F, 0x41, 0x89, 0x5D, 0x8A, 0x34, 0x8D, 0xEB, 0x54, 0x92, 0xE5, 0x02,
+       0x53, 0x86, 0xBD, 0x4A, 0x56, 0xC1, 0x9E, 0xCE, 0x74, 0x82, 0xA8, 0x98, 0x7B, 0xD0, 0x96, 0x17,
+       0x2B, 0x08, 0xAA, 0xE1, 0x05, 0x6D, 0x4B, 0xBB, 0x94, 0x39, 0xE4, 0x1A, 0x30, 0xA4, 0x44, 0x7B,
+       0x15, 0xEB, 0x0F, 0x4A, 0x49, 0xC9, 0xCC, 0x32, 0xFA, 0xF2, 0x8C, 0x5A, 0x45, 0xF5, 0x70, 0xC2,
+       0x70, 0x00, 0x79, 0x71, 0x3C, 0xF9, 0xE0, 0x32, 0xCA, 0x8E, 0x6A, 0x3B, 0x0F, 0x21, 0x59, 0x32,
+       0x6F, 0x81, 0x6C, 0x7C, 0xAB, 0x5B, 0xE3, 0x6D, 0x59, 0x35, 0xAC, 0x6D, 0xE4, 0xB4, 0x4A, 0xD7,
+       0xB3, 0x14, 0xD8, 0xA0, 0x4E, 0xBF, 0x05, 0xFE, 0x36, 0xF2, 0x25, 0xA5, 0xCB, 0x9E, 0xFF, 0xA3,
+       0xA9, 0xF2, 0x1C, 0xE7, 0x56, 0x27, 0x45, 0xFE, 0xF9, 0x29, 0xDD, 0x6B, 0xC2, 0x13, 0xC9, 0x55,
+       0x30, 0x40, 0x38, 0xFD, 0x56, 0x84, 0xAC, 0xA9, 0x95, 0xDB, 0xAA, 0x92, 0x67, 0x5A, 0x26, 0x07,
+       0xD2, 0x44, 0xED, 0x2B, 0xF4, 0x34, 0xE2, 0x6E, 0x17, 0x0F, 0x53, 0xB0, 0xD4, 0x28, 0x4E, 0x37,
+       0xB7, 0xB8, 0x6F, 0x82, 0xB3, 0x5F, 0x38, 0xB3, 0x15, 0x59, 0x76, 0xE4, 0x81, 0xDC, 0x52, 0xB3,
+       0xF4, 0xED, 0x5F, 0xF6, 0x17, 0x08, 0x64, 0x12, 0x41, 0xB8, 0xAF, 0x72, 0xC1, 0x31, 0xEF, 0x75,
+       0x02, 0xA2, 0x70, 0x9E, 0x60, 0x7A, 0x5A, 0xD8, 0xB0, 0xB9, 0xA4, 0xA8, 0x0F, 0x8E, 0x61, 0x09,
+       0x42, 0xA3, 0x11, 0x10, 0x46, 0x62, 0x2B, 0x8B, 0x5E, 0x27, 0x05, 0xC6, 0x8C, 0x9D, 0x49, 0x91,
+       0x26, 0x06, 0x67, 0xEF, 0x6C, 0xDA, 0x78, 0x64, 0x1A, 0x74, 0xBA, 0xC4, 0x95, 0x50, 0xFE, 0xE0,
+       0x61, 0xBA, 0xF1, 0x05, 0xFD, 0x39, 0x88, 0xDD, 0x11, 0x40, 0xAD, 0xA2, 0xC7, 0x49, 0xEA, 0x4C,
+       0xE3, 0xF3, 0x65, 0xF9, 0xB1, 0x57, 0x37, 0x3B, 0x05, 0x20, 0xD8, 0xD7, 0x75, 0x61, 0x65, 0x71,
+       0x5C, 0xB3, 0x24, 0xF1, 0x90, 0x92, 0x44, 0x00, 0x93, 0xC4, 0x16, 0x04, 0x66, 0x88, 0x30, 0x10,
+       0xAC, 0xEA, 0x9D, 0x20, 0x06, 0xB7, 0x12, 0x3B, 0xA6, 0x2C, 0x3F, 0x0C, 0x30, 0xE9, 0xA7, 0x69,
+       0xD6, 0xF7, 0xEE, 0x27, 0xA9, 0x20, 0xFF, 0xD6, 0x2D, 0x3F, 0x0D, 0xD6, 0xEC, 0xDE, 0x1C, 0xA0,
+       0x70, 0xFA, 0x7A, 0x75, 0x19, 0xA6, 0x83, 0x85, 0xC3, 0x6B, 0x6E, 0xF7, 0x30, 0xA6, 0x54, 0x32,
+       0x0A, 0xC7, 0xC1, 0x0E, 0x2C, 0xD2, 0x17, 0xB3, 0x97, 0xCE, 0x0C, 0x37, 0xDD, 0x91, 0xFF, 0xE8,
+       0x83, 0x51, 0x94, 0xD6, 0x65, 0x69, 0x1B, 0xD4, 0x44, 0x09, 0x25, 0x99, 0xFB, 0x9D, 0x78, 0xD5,
+       0x8D, 0x3D, 0xB7, 0xBD, 0x07, 0x23, 0xB1, 0xDF, 0xB1, 0xFF, 0x86, 0x29, 0xA1, 0xF4, 0x8D, 0x6C,
+       0xBF, 0xE3, 0xA6, 0x25, 0x2A, 0xCE, 0xD8, 0xE5, 0x79, 0x81, 0xEE, 0x98, 0x9E, 0xCE, 0x0A, 0xE7,
+       0x53, 0x12, 0xD0, 0x92, 0x0F, 0xA6, 0xF8, 0xCF, 0xEA, 0x4D, 0x8C, 0x7B, 0x18, 0xA7, 0x53, 0xED,
+       0x63, 0xB2, 0x5B, 0x2D, 0x9E, 0x65, 0x5C, 0x0A, 0x7C, 0x7B, 0xB9, 0x8E, 0xD0, 0x73, 0x5F, 0x29,
+       0xDC, 0xD5, 0xFB, 0x12, 0xE7, 0x18, 0xDD, 0x33, 0x74, 0x4C, 0x95, 0x2A, 0xDB, 0xA0, 0xE2, 0xC6,
+       0x2B, 0x6A, 0xBF, 0xE1, 0x84, 0xA3, 0x24, 0xE0, 0xF4, 0x33, 0x75, 0x4B, 0xA9, 0x82, 0xBD, 0xCF,
+       0xD7, 0x12, 0xF6, 0x0F, 0x10, 0x1E, 0xF5, 0x64, 0xDE, 0xA3, 0x2C, 0x6D, 0x10, 0xCA, 0x4B, 0x1C,
+       0x9F, 0x1C, 0x41, 0xE5, 0xCF, 0x47, 0x40, 0x20, 0xA6, 0x94, 0xA7, 0x36, 0xDD, 0x60, 0xE6, 0x47,
+       0xFC, 0x86, 0xA6, 0x0C, 0x79, 0x66, 0x8D, 0x4D, 0xBA, 0x15, 0x17, 0xF3, 0x96, 0x44, 0x76, 0x6E,
+       0x5A, 0x61, 0xC8, 0x5A, 0x5C, 0x25, 0x4A, 0xEC, 0x1D, 0xCE, 0x3F, 0x2F, 0x8D, 0x4D, 0xC2, 0xB2,
+       0x62, 0xE4, 0xD7, 0xF8, 0x41, 0x4B, 0x43, 0xAB, 0x1A, 0x22, 0x4E, 0xB3, 0xBC, 0xAA, 0xCE, 0x99,
+       0x0B, 0x8D, 0x11, 0x19, 0x12, 0x9D, 0x0E, 0xBE, 0x2C, 0x94, 0x3F, 0xB1, 0xBE, 0x7E, 0xD2, 0xE1,
+       0xC9, 0xBE, 0x33, 0x3D, 0xCB, 0xCD, 0x56, 0xCD, 0xB8, 0xB4, 0x5C, 0xD4, 0xA0, 0x3B, 0x7C, 0x3C,
+       0x2C, 0x8B, 0x8E, 0x43, 0x3C, 0x15, 0x9E, 0xF4, 0xF2, 0xB6, 0x26, 0xA1, 0xB7, 0xBE, 0xC9, 0x7F,
+       0x43, 0x8A, 0xFA, 0x0E, 0x2F, 0x49, 0x7C, 0xCF, 0x2E, 0x98, 0x5E, 0x76, 0x71, 0xC6, 0x1A, 0x2D,
+       0xA8, 0xDB, 0x57, 0x96, 0x10, 0xFE, 0xD5, 0x0C, 0xBB, 0x15, 0x5D, 0x04, 0x0B, 0x79, 0x5D, 0x3E,
+       0x6B, 0xC5, 0x1A, 0xD9, 0x0B, 0xAD, 0x0C, 0x3D, 0x3E, 0x7E, 0x57, 0x98, 0xDE, 0x23, 0x36, 0x5F,
+       0x92, 0xBA, 0x31, 0x28, 0xE8, 0x3B, 0xBE, 0x7F, 0x6A, 0xA6, 0x16, 0x2C, 0x55, 0x2A, 0xBC, 0x2E,
+       0x5D, 0xF4, 0xCB, 0x7B, 0x21, 0x71, 0x77, 0x15, 0xEF, 0xAC, 0xE4, 0x28, 0x3F, 0x75, 0x81, 0xD5,
+       0x88, 0xF0, 0x37, 0x78, 0xBD, 0xB3, 0x26, 0x26, 0x64, 0x91, 0x2A, 0x8D, 0x20, 0xFE, 0x20, 0xA7,
+       0x23, 0xB6, 0xA4, 0xFA, 0xA7, 0x09, 0x41, 0xB2, 0x66, 0x2F, 0x9D, 0xE4, 0xFD, 0x29, 0x69, 0x45,
+       0x03, 0x0C, 0x86, 0x3E, 0x3A, 0x95, 0x93, 0x97, 0x31, 0x4C, 0x39, 0x61, 0xB2, 0xDF, 0x01, 0xDB,
+       0x79, 0xA6, 0x64, 0xC9, 0x59, 0x7D, 0x92, 0x02, 0x46, 0x76, 0x58, 0x17, 0x44, 0xC3, 0x8C, 0x68,
+       0x5B, 0xD3, 0x1E, 0x7A, 0x0F, 0x48, 0x7D, 0x03, 0xF5, 0x96, 0x27, 0xB3, 0xC0, 0x61, 0x20, 0x12,
+       0xDC, 0x97, 0x9F, 0xEC, 0x7B, 0xA6, 0x39, 0x10, 0x44, 0x8B, 0x61, 0xE5, 0xF5, 0xDE, 0x53, 0x53,
+       0x33, 0x92, 0xBF, 0x22, 0x72, 0x28, 0x54, 0x4B, 0x92, 0x38, 0xA3, 0x5F, 0x08, 0x0C, 0xB6, 0x8D,
+       0xF3, 0x14, 0x87, 0xCF, 0xB6, 0xF9, 0x5D, 0x8D, 0x47, 0x21, 0xB5, 0xA5, 0x6F, 0x9C, 0x82, 0xED,
+       0xC7, 0x7B, 0xAD, 0xCD, 0x7D, 0xE3, 0x68, 0xD8, 0x7B, 0xA4, 0x8D, 0x27, 0xB5, 0x16, 0x3B, 0xA0,
+       0x78, 0x43, 0x81, 0xEF, 0xB7, 0x42, 0xA2, 0xFC, 0xBB, 0x47, 0x0A, 0x75, 0xB6, 0xE5, 0x16, 0x6D,
+       0xD5, 0x45, 0x41, 0x0B, 0x66, 0x82, 0xBB, 0x8C, 0xBA, 0x90, 0xCA, 0x0B, 0x25, 0x0A, 0x8C, 0xA7,
+       0x62, 0x05, 0x03, 0x3B, 0xD3, 0xBF, 0xF3, 0x54, 0x94, 0x0F, 0x3A, 0x50, 0x0D, 0xEF, 0x70, 0x23,
+       0xF6, 0x23, 0x27, 0xE3, 0xD7, 0xA1, 0xAC, 0x40, 0xE4, 0x3F, 0xCD, 0x0E, 0x27, 0xCA, 0x2D, 0xE0,
+       0x47, 0x16, 0x78, 0xDE, 0xA9, 0x07, 0x1D, 0x2D, 0x89, 0xC3, 0xE7, 0x0C, 0x4B, 0x6C, 0x10, 0x5D,
+       0xDF, 0x37, 0x63, 0xE7, 0xB5, 0x06, 0xEC, 0x03, 0x6E, 0x02, 0x80, 0x24, 0x69, 0xDA, 0x20, 0xD7,
+       0x7D, 0x4C, 0x49, 0xF6, 0x14, 0x21, 0x63, 0xC9, 0x60, 0x50, 0x35, 0x83, 0x9D, 0xFC, 0x71, 0x37,
+       0xCF, 0x06, 0xF6, 0x98, 0x4A, 0x9D, 0xF7, 0x3E, 0xB5, 0xFD, 0x6E, 0x0E, 0x0E, 0xC8, 0x92, 0xC3,
+       0x6B, 0x59, 0x89, 0x65, 0x9A, 0x70, 0x0A, 0x03, 0x14, 0xB0, 0xB4, 0xA0, 0x6D, 0x90, 0x6E, 0x90,
+       0xC9, 0x37, 0x7B, 0x62, 0x13, 0x34, 0x9F, 0x77, 0x4E, 0x39, 0xCE, 0xAC, 0xCA, 0x10, 0xAD, 0xAA,
+       0x3D, 0xBD, 0x0F, 0x4A, 0xC0, 0xF6, 0x52, 0x6A, 0x4C, 0xC1, 0x60, 0x07, 0x2E, 0xFE, 0xBD, 0xAE,
+       0x86, 0x75, 0x9C, 0xFB, 0xDE, 0x8A, 0x96, 0x4F, 0x67, 0xCC, 0x3B, 0x9A, 0x77, 0xE8, 0x90, 0x04,
+       0x97, 0xE0, 0x20, 0x43, 0x96, 0x07, 0xB9, 0xD9, 0x56, 0x8F, 0xBB, 0x9C, 0x48, 0xBA, 0xA3, 0x44,
+       0x36, 0xC7, 0x6F, 0x25, 0x76, 0x10, 0x66, 0x17, 0x50, 0x49, 0x10, 0xBD, 0xB4, 0xE1, 0x92, 0x81,
+       0xE6, 0x74, 0x20, 0x1D, 0x50, 0xD3, 0x31, 0x9B, 0xD6, 0x48, 0x16, 0x20, 0xB4, 0x3E, 0x95, 0x8D,
+       0x72, 0xE9, 0x6D, 0xC7, 0x15, 0x3E, 0x42, 0xA4, 0xF8, 0x75, 0xC5, 0xD0, 0x2C, 0x13, 0x9F, 0x4A,
+       0x3E, 0x4C, 0x19, 0xAC, 0x14, 0x9A, 0x66, 0xF0, 0x66, 0x6B, 0x41, 0x7F, 0xA5, 0x44, 0x1D, 0x96,
+       0x03, 0x85, 0x0C, 0xCE, 0x49, 0x80, 0xDC, 0x8F, 0x0F, 0xE3, 0x32, 0x9C, 0x57, 0xE3, 0x2E, 0x21,
+       0xC5, 0x35, 0xFA, 0x28, 0x44, 0x7B, 0x8B, 0x99, 0x0F, 0x2D, 0x9F, 0xB2, 0x68, 0xB7, 0x33, 0xAA,
+       0xAB, 0xED, 0x3E, 0xA4, 0x46, 0xD5, 0xDB, 0x30, 0x4A, 0x46, 0xDD, 0x7B, 0x46, 0x02, 0xBB, 0x55,
+       0x21, 0xA3, 0x33, 0xDB, 0x8B, 0xCA, 0xE7, 0x1C, 0x27, 0x75, 0x17, 0xB3, 0xE2, 0x4F, 0x56, 0x08,
+       0x0D, 0xC5, 0x2F, 0xEC, 0x0E, 0x15, 0xEB, 0x79, 0x21, 0xD2, 0xA1, 0x5F, 0x67, 0xDB, 0xED, 0x05,
+       0x3C, 0x3E, 0x51, 0x09, 0x17, 0xAE, 0x66, 0x59, 0x7D, 0xA2, 0xDF, 0xE8, 0x80, 0x98, 0x5F, 0x89,
+       0x48, 0x6E, 0xDF, 0x64, 0xE1, 0x04, 0xA2, 0xF2, 0x3E, 0xF5, 0x93, 0x23, 0x56, 0xDB, 0x0A, 0x1E,
+       0x59, 0x68, 0x19, 0x6F, 0x77, 0xD3, 0x55, 0xCC, 0x6D, 0xB1, 0x89, 0x14, 0x53, 0x14, 0xD8, 0x49,
+       0x22, 0xA1, 0xEC, 0x3D, 0x10, 0x5D, 0x2B, 0xA6, 0x79, 0xA0, 0x76, 0x2D, 0xC6, 0x7C, 0x61, 0x06,
+       0x34, 0xDD, 0x44, 0xB2, 0x15, 0x4D, 0xD6, 0x6A, 0x89, 0x4B, 0xA6, 0x82, 0x94, 0x4A, 0x55, 0xB2,
+       0x2F, 0x1F, 0x92, 0xC7, 0xAB, 0xAE, 0xB6, 0xF9, 0xAE, 0xD9, 0xE2, 0x36, 0x3A, 0x9A, 0xC7, 0x31,
+       0xDC, 0xFC, 0xE5, 0x07, 0x24, 0xCD, 0x12, 0xC2, 0x51, 0xF3, 0x6E, 0x8E, 0x61, 0x39, 0xAC, 0x4D,
+       0xCB, 0xD0, 0x49, 0xF6, 0x6F, 0xE6, 0xCF, 0xC0, 0x32, 0xE7, 0xE6, 0x8C, 0xB5, 0x86, 0x7E, 0xCC,
+       0x97, 0x8F, 0xA8, 0xB8, 0xE4, 0x59, 0xD4, 0x6D, 0xA8, 0xAC, 0x11, 0x16, 0xFD, 0x6C, 0x69, 0xBF,
+       0xC3, 0x81, 0x11, 0x11, 0x43, 0xF6, 0x15, 0x22, 0x42, 0x53, 0xC8, 0x09, 0x8E, 0x9A, 0x2D, 0x32,
+       0x3A, 0x95, 0xBD, 0x0F, 0x4B, 0xB3, 0xD5, 0x85, 0xF6, 0x07, 0xCA, 0xEA, 0xFA, 0xA0, 0x35, 0x64,
+       0x3F, 0x2F, 0x1E, 0xEF, 0xDB, 0xB1, 0xA3, 0xCE, 0x2A, 0x6C, 0x71, 0x90, 0xAE, 0x7D, 0x0F, 0x19,
+       0x39, 0x88, 0x36, 0x7C, 0xE0, 0xF8, 0xB1, 0xE7, 0xF5, 0xF7, 0xAE, 0xB6, 0xCB, 0xF5, 0x8F, 0xD8,
+       0x58, 0x7B, 0x93, 0x6D, 0x07, 0x66, 0x22, 0x6C, 0x31, 0xA6, 0x44, 0x53, 0xED, 0x85, 0x5B, 0x22,
+       0x09, 0x86, 0x3D, 0xCF, 0xA8, 0x70, 0xAA, 0xA0, 0xC0, 0x4B, 0x55, 0x40, 0xED, 0xE8, 0x2F, 0x37,
+       0xF0, 0x8E, 0xCC, 0x20, 0x59, 0x1F, 0x48, 0xAA, 0xC4, 0x7C, 0x9F, 0xB4, 0xF3, 0xB0, 0xDD, 0x09,
+       0xD7, 0xBC, 0x24, 0x61, 0xAD, 0x5A, 0x3A, 0x71, 0xD4, 0xCB, 0xBD, 0x46, 0x10, 0xB9, 0xE3, 0x53,
+       0x6E, 0x86, 0x79, 0x2F, 0xFB, 0x92, 0xD1, 0x5C, 0xF6, 0x05, 0x59, 0x0F, 0x0F, 0x6F, 0x3D, 0x40,
+       0xB8, 0xD3, 0x7E, 0x87, 0xEF, 0x69, 0x21, 0x93, 0xA0, 0x08, 0xC1, 0x36, 0xE8, 0x65, 0xA1, 0x09,
+       0xB6, 0x76, 0x5A, 0xA6, 0xED, 0x64, 0x51, 0xC3, 0x12, 0xD2, 0x91, 0x57, 0x47, 0x5D, 0xE7, 0x21,
+       0x8A, 0x4E, 0x56, 0x11, 0x20, 0x78, 0xE9, 0x99, 0x0B, 0xA0, 0x7A, 0xCB, 0xE8, 0xAC, 0x91, 0xE6,
+       0xCA, 0x60, 0x2A, 0x4B, 0x05, 0xD0, 0xCB, 0x7A, 0xAC, 0xB8, 0x19, 0x7D, 0xDA, 0xB2, 0x7F, 0x28,
+       0x9F, 0x91, 0xC3, 0xF6, 0xFB, 0x36, 0x25, 0x88, 0x2C, 0xC1, 0x6B, 0x7A, 0x03, 0xA5, 0x07, 0x64,
+       0xFA, 0xBD, 0x4C, 0x65, 0x69, 0x49, 0x00, 0x4C, 0x92, 0xB4, 0xAB, 0xEF, 0xA6, 0xB0, 0x39, 0x28,
+       0xEA, 0xCF, 0x2F, 0x1F, 0xBC, 0xEE, 0x29, 0xF9, 0x06, 0x49, 0xB5, 0x23, 0x77, 0x55, 0x64, 0x02,
+       0x33, 0x6A, 0x1C, 0xF6, 0xE8, 0x05, 0x2A, 0xF0, 0x94, 0xD8, 0xFC, 0x4A, 0xD2, 0x4E, 0x76, 0x08,
+       0x99, 0xE5, 0x01, 0x6E, 0xFF, 0x49, 0x31, 0x98, 0xBD, 0xAE, 0x9D, 0x05, 0x54, 0x37, 0xC6, 0x0B,
+       0x4B, 0x9C, 0x9C, 0x6F, 0x5C, 0x38, 0xE4, 0x76, 0xD2, 0xEF, 0xD9, 0x9F, 0xE6, 0xFA, 0x90, 0xD7,
+       0x21, 0xC6, 0xB0, 0x9B, 0x13, 0xD7, 0xB8, 0xA2, 0xEC, 0x09, 0x67, 0xB7, 0x3A, 0x2F, 0x83, 0x87,
+       0x36, 0x3C, 0xC2, 0xC0, 0x1F, 0xF1, 0xE8, 0x8E, 0x46, 0x62, 0xD9, 0x8A, 0x41, 0x92, 0x16, 0xAD,
+       0xCB, 0xD6, 0xAC, 0xA8, 0x4D, 0xCB, 0x39, 0x30, 0x81, 0x3A, 0x14, 0x12, 0x45, 0x75, 0xC3, 0xAA,
+       0xAB, 0x01, 0x06, 0x6D, 0xC7, 0x42, 0x1F, 0xF9, 0x04, 0x88, 0x90, 0x5A, 0x98, 0x35, 0xDE, 0xC4,
+       0xC6, 0x8D, 0x08, 0x56, 0x4A, 0x2E, 0xE3, 0x78, 0x46, 0x47, 0x07, 0x4E, 0x40, 0xD1, 0x8F, 0x5A,
+       0x67, 0xAD, 0xF2, 0x5F, 0xF0, 0x0A, 0x8E, 0x71, 0xBF, 0x0A, 0x00, 0xFB, 0xC5, 0xC8, 0x90, 0x7B,
+       0x4F, 0xF4, 0xCC, 0x6F, 0xE5, 0xAE, 0x30, 0x56, 0x9B, 0xEF, 0x7E, 0x48, 0x21, 0x2B, 0x97, 0x65,
+       0xCE, 0xAB, 0x98, 0x6D, 0x89, 0xF9, 0x35, 0x39, 0x37, 0xE3, 0x89, 0x67, 0x53, 0x1F, 0x1C, 0xE4,
+       0x9F, 0xD0, 0x3B, 0xAE, 0xFB, 0x63, 0x29, 0xCA, 0xE9, 0x58, 0x02, 0xE3, 0x4A, 0xA7, 0x2D, 0x99,
+       0x06, 0x03, 0x3B, 0x9A, 0x2A, 0x13, 0xE9, 0x27, 0xA7, 0xD7, 0x06, 0x8A, 0x49, 0x7A, 0xD3, 0x64,
+       0xC1, 0xF4, 0x69, 0xA0, 0xC0, 0x14, 0xC4, 0x56, 0x89, 0x31, 0xD0, 0xDC, 0xF3, 0xB2, 0xB3, 0x51,
+       0xF5, 0x38, 0x47, 0x47, 0x90, 0xC2, 0x2F, 0xFF, 0x80, 0x43, 0x35, 0x96, 0x2B, 0xE3, 0x50, 0x55,
+       0x2D, 0x11, 0xCB, 0xF4, 0x93, 0x10, 0xD5, 0x3A, 0x5B, 0x82, 0x58, 0x10, 0xC1, 0x17, 0x31, 0xDE,
+       0x96, 0x7B, 0xCA, 0xE4, 0x90, 0x89, 0x74, 0x97, 0x91, 0xA2, 0x2F, 0x01, 0xE0, 0xCC, 0x73, 0x0F,
+       0xB1, 0x76, 0x56, 0x5F, 0x2B, 0xDE, 0x7C, 0x29, 0xD3, 0x51, 0x42, 0xA3, 0x7C, 0x16, 0xB6, 0x6B,
+       0x4A, 0x06, 0x7B, 0xDD, 0xF0, 0x3B, 0x8B, 0x6A, 0x55, 0x0C, 0x2B, 0xF2, 0x61, 0x41, 0xB4, 0x37,
+       0xA2, 0xB4, 0x4E, 0x01, 0xD3, 0x09, 0x44, 0xD0, 0xE3, 0x88, 0x6E, 0x6F, 0xF3, 0x22, 0x6E, 0xF7,
+       0x59, 0xC9, 0xE4, 0xA6, 0x97, 0x51, 0x33, 0x16, 0x53, 0xA0, 0xE9, 0xD5, 0x6E, 0x97, 0xAE, 0x5B,
+       0x02, 0x11, 0x2B, 0x5F, 0xE3, 0x93, 0xAA, 0x09, 0x56, 0x09, 0x17, 0xFE, 0xE9, 0x93, 0x1A, 0x46,
+       0x45, 0xBD, 0xBD, 0x75, 0xD6, 0x60, 0xE9, 0x5A, 0xA9, 0x7E, 0x91, 0xD1, 0x7C, 0xDB, 0xF1, 0x32,
+       0x6F, 0x79, 0x26, 0xBC, 0xE3, 0x79, 0xB0, 0x2D, 0xCE, 0xBE, 0x08, 0xD5, 0xFD, 0x52, 0xD5, 0xD5,
+       0xAC, 0x86, 0x70, 0xBC, 0x17, 0xB3, 0xF0, 0x4F, 0x6A, 0x94, 0xF2, 0x20, 0xDD, 0xCB, 0x2F, 0xAF,
+       0x1D, 0xA7, 0x24, 0xFE, 0x3A, 0x98, 0x07, 0x68, 0xBE, 0xE1, 0x6F, 0x01, 0x78, 0xF1, 0x26, 0x3E,
+       0xFC, 0x75, 0xBC, 0xA1, 0x05, 0xE7, 0x70, 0xAA, 0xFC, 0x7C, 0x8C, 0x29, 0x6B, 0x20, 0x30, 0x65,
+       0xBF, 0x34, 0x30, 0xA7, 0xFE, 0x2F, 0x51, 0x2E, 0x11, 0x99, 0xF9, 0xD5, 0xDA, 0xF4, 0x1D, 0x74,
+       0xEF, 0x50, 0x7E, 0x3D, 0xEE, 0xD6, 0xDA, 0x44, 0xDD, 0x83, 0x3F, 0x9C, 0x2F, 0xE8, 0x7E, 0x28,
+       0x65, 0x4E, 0x9C, 0xEF, 0x6C, 0xAA, 0xE0, 0x0C, 0x33, 0x33, 0xDB, 0x65, 0x19, 0x18, 0xC5, 0x91,
+       0xA3, 0x9F, 0x02, 0x1D, 0x0D, 0xDA, 0x44, 0x8A, 0x1D, 0xF5, 0x61, 0x41, 0x55, 0x11, 0x75, 0x06,
+       0x3C, 0x79, 0x45, 0xDE, 0xDC, 0x75, 0x24, 0xC6, 0x92, 0x16, 0xFE, 0x7C, 0x0C, 0x1B, 0x0A, 0x62,
+       0x9E, 0x5E, 0x0A, 0x30, 0xF4, 0x1A, 0x2C, 0x45, 0xEF, 0xE4, 0x10, 0xB6, 0x0C, 0xC2, 0x8B, 0x73,
+       0xDE, 0x4E, 0x37, 0x6C, 0xAB, 0xBA, 0x70, 0x76, 0x30, 0x26, 0x11, 0x92, 0x8C, 0x80, 0x6C, 0x1C,
+       0x3F, 0xBF, 0x7D, 0xD4, 0x63, 0x70, 0x0C, 0x9B, 0xEF, 0xF2, 0x75, 0x34, 0x67, 0x81, 0x77, 0x8F,
+       0xF9, 0x2F, 0x9E, 0x9F, 0xA6, 0x3B, 0x9C, 0x1E, 0x42, 0x9A, 0xCB, 0x3F, 0xA7, 0xF1, 0xBF, 0xF1,
+       0x39, 0xB4, 0x0A, 0x6D, 0x73, 0xC9, 0x01, 0x6E, 0xAE, 0x17, 0x95, 0x5A, 0xC0, 0x25, 0xA1, 0xB1,
+       0x4D, 0xF1, 0xA4, 0x42, 0xAC, 0x92, 0xE6, 0x84, 0xD4, 0xAF, 0x14, 0x44, 0x2E, 0x2F, 0xA5, 0x34,
+       0x24, 0x61, 0x0A, 0x22, 0x07, 0x60, 0x7B, 0xE6, 0x4B, 0xF6, 0xB2, 0x7C, 0x24, 0x86, 0x2E, 0x86,
+       0xCF, 0xC1, 0x13, 0xB6, 0xC9, 0x9F, 0xD6, 0x19, 0x57, 0x3F, 0x2A, 0x4A, 0x54, 0x68, 0xDE, 0x16,
+       0x5D, 0xED, 0x35, 0x99, 0x6C, 0xFC, 0xED, 0x31, 0xE2, 0xD7, 0x8E, 0x2E, 0x3C, 0x35, 0xA2, 0xEA,
+       0xEE, 0x7B, 0xEE, 0x33, 0x62, 0x37, 0x8D, 0xE8, 0x12, 0x9A, 0x05, 0x17, 0xCC, 0xDC, 0x38, 0xFF,
+       0x41, 0x6A, 0xC6, 0x67, 0x80, 0x76, 0x98, 0x57, 0x06, 0x4B, 0x31, 0x8F, 0x9C, 0x1A, 0x90, 0x3D,
+       0x3F, 0xD8, 0x10, 0x2A, 0xC5, 0xF9, 0xC6, 0x0C, 0x16, 0x9A, 0x5A, 0xCD, 0x41, 0xB3, 0x1A, 0x75,
+       0x26, 0x7B, 0x5D, 0x18, 0xAA, 0xB9, 0x1E, 0x98, 0xEC, 0x3C, 0xE0, 0xCA, 0x13, 0xAE, 0x0B, 0x6C,
+       0x6E, 0x09, 0x9C, 0x2D, 0xF0, 0xCC, 0x2E, 0x88, 0x2E, 0xDC, 0xA5, 0xB6, 0x4F, 0x14, 0x9A, 0x11,
+       0x95, 0x3B, 0xB3, 0x0B, 0xA1, 0x62, 0x84, 0x67, 0xE2, 0x50, 0x90, 0x5A, 0x75, 0xFA, 0x2F, 0x35,
+       0x39, 0xF0, 0xBB, 0x34, 0x89, 0xF5, 0x6A, 0xBC, 0x01, 0x76, 0xFF, 0xCF, 0xE3, 0xF7, 0xA2, 0x71,
+       0xCE, 0xD8, 0x58, 0xC7, 0xBB, 0x6F, 0x08, 0xE3, 0xB4, 0x44, 0x5C, 0x95, 0x4D, 0xF5, 0x84, 0x35,
+       0x39, 0x14, 0x1F, 0x8E, 0xD7, 0x52, 0x57, 0x1E, 0xE9, 0x1D, 0x2D, 0x27, 0x82, 0xCC, 0x07, 0xF2,
+       0xE7, 0xA1, 0xCA, 0xB7, 0xF3, 0xED, 0x30, 0x9D, 0xC3, 0x8C, 0x30, 0x09, 0x50, 0x51, 0xAF, 0xE1,
+       0x50, 0xC4, 0x57, 0x31, 0xC3, 0x88, 0xC4, 0x7A, 0xAF, 0xBB, 0x97, 0x89, 0xB5, 0xED, 0x42, 0xC9,
+       0xDF, 0xB4, 0x2A, 0x12, 0x4C, 0x73, 0x0B, 0x23, 0xC8, 0xF7, 0x09, 0x6F, 0x81, 0xE7, 0x12, 0x7C,
+       0xD8, 0xD7, 0x6F, 0x84, 0x5B, 0xBC, 0xFF, 0x0D, 0xCD, 0x3D, 0x29, 0x0F, 0x03, 0xB3, 0x29, 0x28,
+       0x83, 0x7B, 0x78, 0xD1, 0x3B, 0x15, 0x38, 0x6F, 0xC1, 0x29, 0xF5, 0x0E, 0x04, 0x88, 0xCC, 0xB2,
+       0x6C, 0x4A, 0xF1, 0x51, 0x5E, 0x11, 0x39, 0x80, 0x26, 0xCF, 0xC4, 0x07, 0x2E, 0x20, 0x40, 0xB1,
+       0xE9, 0x9D, 0xD5, 0xED, 0x99, 0xC6, 0x6D, 0xCE, 0xBE, 0x0D, 0x28, 0x17, 0xCA, 0x1B, 0x13, 0xFA,
+       0xC2, 0x66, 0xD2, 0x4D, 0xF6, 0x1B, 0x9F, 0x0F, 0xAB, 0x24, 0x3C, 0x31, 0x04, 0xA2, 0x91, 0x38,
+       0x19, 0x6E, 0x58, 0x72, 0x20, 0x90, 0xE0, 0x54, 0x4C, 0xCB, 0x3E, 0x6F, 0xBC, 0x09, 0x26, 0x72,
+       0x20, 0x83, 0xF2, 0x46, 0xD4, 0xED, 0x52, 0x3D, 0x5B, 0xE4, 0x27, 0xD4, 0xDB, 0x83, 0xE6, 0x4A,
+       0x0E, 0x6D, 0x33, 0x12, 0x89, 0xE3, 0x8B, 0x57, 0xDF, 0xBB, 0x84, 0xEE, 0x44, 0x6F, 0xD1, 0x44,
+       0x5C, 0x30, 0x49, 0x13, 0x3E, 0xDE, 0xFE, 0x87, 0xAD, 0x73, 0x73, 0xF8, 0xE6, 0x0C, 0x0C, 0xBC,
+       0xA9, 0x18, 0x33, 0x97, 0x4D, 0xF5, 0x53, 0xAF, 0x93, 0xEA, 0xF4, 0x01, 0x39, 0x18, 0x59, 0xB3,
+       0x8F, 0xE5, 0x0D, 0xEB, 0x4A, 0xD3, 0xF3, 0xE8, 0x79, 0xB8, 0xAD, 0x16, 0xC3, 0x5A, 0x24, 0xF2,
+       0x8B, 0xB1, 0x52, 0x51, 0x33, 0xBD, 0xA1, 0x00, 0xBA, 0x78, 0x48, 0x7E, 0xD1, 0xC3, 0xD6, 0x3A,
+       0x62, 0x44, 0xC9, 0x6A, 0x26, 0xA9, 0x65, 0x1E, 0xC8, 0x27, 0xE4, 0xD9, 0x9E, 0x78, 0xEC, 0xC7,
+       0x20, 0xC0, 0x2D, 0x8F, 0xF6, 0x04, 0x8B, 0x0A, 0x51, 0x73, 0xF3, 0x5E, 0xF2, 0x09, 0xDF, 0x39,
+       0xBE, 0x62, 0x80, 0x7D, 0x55, 0xDC, 0xD6, 0x3F, 0xA6, 0x78, 0x69, 0xDB, 0xC4, 0x48, 0x20, 0x2F,
+       0x37, 0xCB, 0xC4, 0xDE, 0xEB, 0xB8, 0x6B, 0xD3, 0x73, 0x87, 0xA2, 0x94, 0xF8, 0x7B, 0x98, 0x2A,
+       0x63, 0xFA, 0xBE, 0x4B, 0x72, 0x3E, 0xC2, 0x3B, 0x59, 0x34, 0xBD, 0xF5, 0x0C, 0xBF, 0x5B, 0x9C,
+       0x64, 0xE3, 0xF8, 0x93, 0x94, 0x9F, 0x63, 0x0A, 0xDF, 0x5A, 0xAF, 0xEE, 0x3F, 0xC2, 0x2D, 0x08,
+       0xA9, 0x41, 0xAD, 0x67, 0x42, 0xEC, 0x42, 0x91, 0xE2, 0xE5, 0x2D, 0xA9, 0x1D, 0x8D, 0x20, 0xB7,
+       0x36, 0x89, 0x6B, 0xC9, 0xDB, 0x83, 0xE3, 0x37, 0x7F, 0xDC, 0x5A, 0x61, 0x8A, 0x1E, 0x31, 0xFE,
+       0x1F, 0x77, 0x43, 0x8C, 0xD9, 0x8C, 0x46, 0x5C, 0x7A, 0x0C, 0xFB, 0x17, 0x35, 0x39, 0xD0, 0xA1,
+       0xED, 0xF8, 0x10, 0xCB, 0x0D, 0x2C, 0x7C, 0xCA, 0x89, 0x29, 0xB8, 0x3E, 0x85, 0x68, 0x44, 0x9F,
+       0xE8, 0x2D, 0x35, 0x7D, 0x77, 0x2F, 0x11, 0xB1, 0xB2, 0x62, 0xAA, 0xF1, 0x9D, 0xB3, 0x14, 0x1A,
+       0x90, 0xD0, 0xAF, 0x88, 0xB2, 0xBC, 0x26, 0x83, 0xAF, 0x4D, 0xC4, 0xB2, 0xAD, 0xEA, 0x48, 0xFD,
+       0xDF, 0xE7, 0xF7, 0x83, 0x31, 0x81, 0x74, 0xD9, 0x20, 0x06, 0x30, 0x87, 0x36, 0x6C, 0xC4, 0x9D,
+       0xA9, 0x31, 0x60, 0x01, 0xD3, 0x9E, 0xEE, 0xD3, 0x28, 0x39, 0xEA, 0xD1, 0x16, 0xBB, 0x90, 0x1B,
+       0x59, 0x26, 0x8D, 0xAF, 0xAC, 0x00, 0xEE, 0xBD, 0x1D, 0x62, 0x9E, 0xC5, 0x7E, 0x26, 0x5B, 0xBE,
+       0x7A, 0x7A, 0x64, 0x75, 0xC2, 0x0B, 0x11, 0xDA, 0x3C, 0x1D, 0x9A, 0x42, 0xFD, 0x64, 0x6C, 0x04,
+       0x96, 0x57, 0x8B, 0x62, 0x26, 0x02, 0xAD, 0x33, 0xE5, 0x35, 0x9F, 0x39, 0xDF, 0xF0, 0xEC, 0x04,
+       0x65, 0x4D, 0xA7, 0xE9, 0x78, 0xDC, 0xEB, 0x2C, 0xA9, 0xC1, 0x82, 0x3E, 0x30, 0x83, 0x99, 0x17,
+       0x74, 0x67, 0x92, 0xCE, 0x90, 0x24, 0x7A, 0x50, 0xF0, 0x90, 0xD5, 0x09, 0x82, 0x49, 0x70, 0x19,
+       0xEF, 0x20, 0xFA, 0x2E, 0x9E, 0x60, 0xC1, 0x01, 0x04, 0x0E, 0x4C, 0x82, 0x9E, 0xA5, 0x81, 0x3C,
+       0x78, 0x05, 0x08, 0x87, 0xDB, 0x84, 0xDD, 0x92, 0x63, 0xFA, 0xEF, 0x92, 0x8E, 0xCE, 0xB9, 0x65,
+       0xED, 0xB7, 0x29, 0x30, 0xF5, 0x5F, 0xFA, 0xA8, 0x46, 0xDA, 0xF3, 0xFC, 0x78, 0x06, 0x19, 0x9A,
+       0xC5, 0xDC, 0x8B, 0xD2, 0x8F, 0x3F, 0xA2, 0x9D, 0xE4, 0x02, 0xD9, 0x36, 0xA9, 0xBC, 0x73, 0x95,
+       0xC6, 0xA8, 0x43, 0x7B, 0x65, 0x46, 0xDB, 0xBD, 0x5C, 0x93, 0xE6, 0xD1, 0x3C, 0xF5, 0xC8, 0x35,
+       0x2B, 0xB3, 0x90, 0x37, 0x07, 0xEE, 0x48, 0x42, 0x63, 0x10, 0x27, 0xE9, 0xF6, 0xD5, 0x3D, 0xB4,
+       0x44, 0x01, 0xC7, 0xAF, 0x07, 0xD5, 0x39, 0x07, 0xC9, 0x8F, 0x13, 0x37, 0x42, 0xBF, 0xCF, 0xC8,
+       0xA1, 0x50, 0xDB, 0x45, 0x39, 0x3D, 0x4D, 0xD0, 0x0B, 0x66, 0xA3, 0x10, 0x8F, 0xB8, 0x74, 0x01,
+       0x47, 0x3B, 0x2E, 0xE4, 0x93, 0xF3, 0x7C, 0xD6, 0x96, 0x34, 0xE2, 0x5D, 0x2C, 0xC2, 0x57, 0x15,
+       0x85, 0x3A, 0xC4, 0xBB, 0xB6, 0x7F, 0xD8, 0xBD, 0x08, 0x7C, 0x8F, 0xB8, 0x90, 0xB4, 0xBE, 0x69,
+       0xC8, 0xFE, 0x03, 0xAA, 0xBA, 0x3A, 0x35, 0xC8, 0x23, 0xC1, 0xE2, 0xDE, 0xA0, 0xD1, 0x1F, 0xBE,
+       0x6D, 0xDF, 0xFD, 0xD3, 0x9F, 0x87, 0xF5, 0xA8, 0x72, 0x1C, 0x68, 0xA9, 0xD3, 0x11, 0x3E, 0x05,
+       0xBF, 0x7B, 0x00, 0x1F, 0x65, 0xB3, 0x1E, 0x8E, 0xFC, 0x66, 0x47, 0xFB, 0x64, 0x29, 0x43, 0x05,
+       0x76, 0x9A, 0xA1, 0xF9, 0xB4, 0x6C, 0x86, 0xBC, 0x76, 0xA6, 0x3B, 0x42, 0xD5, 0x7D, 0x2F, 0x93,
+       0xF6, 0xE8, 0xEF, 0x32, 0xEC, 0x61, 0x62, 0xD1, 0xA3, 0xA1, 0xF5, 0xAD, 0xBF, 0x55, 0x92, 0x42,
+       0xD9, 0xF3, 0x37, 0x88, 0xFA, 0xD2, 0x9B, 0x54, 0xF1, 0xE3, 0x43, 0xEF, 0x18, 0x29, 0xA6, 0xA9,
+       0xB9, 0x74, 0x9A, 0xD7, 0x77, 0x38, 0xE3, 0x36, 0x3D, 0xF5, 0x11, 0x22, 0x52, 0xBB, 0x4E, 0xBF,
+       0xC1, 0xF9, 0xF4, 0x48, 0x73, 0x32, 0x1D, 0x3E, 0x1D, 0x70, 0x7C, 0x63, 0xF1, 0xB7, 0x0B, 0xAB,
+       0x1B, 0x7C, 0x22, 0x8E, 0x9C, 0xA4, 0x9B, 0x28, 0xF6, 0xD7, 0x02, 0xD1, 0x25, 0x9F, 0x4F, 0x20,
+       0x77, 0xB1, 0xE1, 0x40, 0x63, 0x30, 0x3E, 0xC1, 0x6D, 0x85, 0x3A, 0x25, 0xFC, 0x65, 0xE4, 0xE4,
+       0xAA, 0x70, 0x8B, 0xB2, 0xC5, 0xEB, 0xC9, 0xAF, 0x86, 0x39, 0x2C, 0x70, 0x3A, 0x74, 0x96, 0x32,
+       0xDD, 0x6B, 0x37, 0x26, 0x6F, 0x63, 0x2A, 0xEB, 0xD1, 0x2F, 0xF6, 0x25, 0x3B, 0xFA, 0x8B, 0x9F,
+       0x32, 0x9C, 0xD3, 0x40, 0x76, 0x86, 0x4D, 0x99, 0x4D, 0x9C, 0x57, 0xF7, 0x0F, 0x99, 0xF9, 0x45,
+       0x43, 0x31, 0x50, 0x39, 0x50, 0x84, 0x55, 0xD3, 0x9B, 0x03, 0x11, 0x36, 0xE1, 0x59, 0x51, 0xDF,
+       0x6F, 0xFA, 0x19, 0x07, 0x59, 0x1F, 0x40, 0xB1, 0x7C, 0x85, 0x60, 0xC4, 0x15, 0xDB, 0x12, 0xB6,
+       0x2A, 0x31, 0x6E, 0x9D, 0x28, 0x74, 0xAE, 0xF6, 0x85, 0xCA, 0x34, 0x07, 0x6F, 0x90, 0xBF, 0xAC,
+       0xF0, 0xDC, 0xF1, 0x14, 0x65, 0x7E, 0x6D, 0x60, 0xC8, 0xEA, 0x8C, 0xC7, 0xB1, 0x52, 0x42, 0xD0,
+       0x0C, 0x88, 0xC2, 0x14, 0xF8, 0xD3, 0x08, 0x51, 0xBB, 0x19, 0x4A, 0x56, 0x77, 0x37, 0x7E, 0x8C,
+       0xE0, 0xB2, 0x90, 0x26, 0x95, 0xCD, 0x4B, 0x05, 0xA9, 0x42, 0xF4, 0x62, 0x11, 0x04, 0x4A, 0x76,
+       0x6F, 0x9D, 0x04, 0x37, 0x35, 0xCB, 0xC2, 0x29, 0xB6, 0x5D, 0xE4, 0x2D, 0x09, 0xD3, 0x94, 0x21,
+       0x4A, 0xEA, 0xFB, 0x1F, 0x21, 0xBF, 0x41, 0x36, 0xB6, 0x3F, 0x03, 0x8C, 0x2D, 0x33, 0x3B, 0x67,
+       0x31, 0x67, 0xC8, 0x83, 0x08, 0xD2, 0x33, 0x3E, 0x36, 0xA2, 0x8B, 0x5A, 0xA2, 0x11, 0xF0, 0xDB,
+       0xBD, 0x19, 0x8F, 0x40, 0x3C, 0x73, 0x52, 0x76, 0x98, 0xFD, 0xB4, 0xE3, 0x61, 0xFD, 0x89, 0xE7,
+       0x18, 0xC4, 0xA2, 0x67, 0x41, 0x55, 0x00, 0x1A, 0x34, 0x48, 0xE5, 0x8A, 0x34, 0x1C, 0xBF, 0xD0,
+       0x7F, 0x42, 0x0C, 0x61, 0x3F, 0x05, 0x77, 0x4C, 0xA8, 0xBB, 0x11, 0xF6, 0x9F, 0xAA, 0x18, 0x6A,
+       0x9A, 0xC0, 0x31, 0xAE, 0xBA, 0x27, 0xFC, 0xDF, 0x21, 0x71, 0x03, 0xF2, 0xD3, 0x54, 0x39, 0x84,
+       0x22, 0xC5, 0x35, 0x48, 0x49, 0x07, 0x84, 0x8A, 0xA1, 0x49, 0x34, 0x4B, 0xFD, 0x75, 0x3B, 0x41,
+       0x0B, 0xD3, 0xEE, 0x62, 0x1B, 0x88, 0xAD, 0x2F, 0x7B, 0xED, 0x7D, 0x8F, 0xB9, 0x6B, 0xF3, 0x37,
+       0xDF, 0x87, 0x0D, 0x88, 0xF0, 0xE8, 0x1E, 0x64, 0xF5, 0xB6, 0x09, 0x93, 0x7B, 0xBC, 0x58, 0xE8,
+       0x21, 0x4E, 0x32, 0xE5, 0xC2, 0x04, 0x3C, 0x64, 0x9C, 0x16, 0x6D, 0x3A, 0xD6, 0x5C, 0xDE, 0x85,
+       0x39, 0x25, 0x1B, 0x1C, 0xDD, 0x67, 0x95, 0xA9, 0xAA, 0x68, 0x35, 0x62, 0x61, 0xE5, 0xED, 0x8C,
+       0x62, 0xFA, 0xA3, 0xB7, 0x81, 0x9B, 0x41, 0xAF, 0x43, 0xDC, 0x14, 0xF5, 0x71, 0x93, 0xA6, 0x04,
+       0x2D, 0x97, 0xD1, 0x34, 0x7D, 0x10, 0x18, 0xDC, 0x34, 0x8B, 0xBC, 0x50, 0xC3, 0x25, 0x8E, 0x96,
+       0x97, 0x7B, 0x7B, 0x7D, 0xCA, 0x62, 0xD1, 0xFF, 0x19, 0xD8, 0xF3, 0x8F, 0xC3, 0x60, 0xC9, 0x22,
+       0xE9, 0x70, 0x27, 0x70, 0x34, 0xE5, 0xD7, 0x0E, 0x00, 0x5E, 0x86, 0x83, 0x58, 0x8F, 0x5C, 0x98,
+       0x6B, 0xB8, 0xAA, 0x68, 0x89, 0x26, 0x82, 0xD5, 0x67, 0x81, 0xAD, 0x45, 0x5D, 0x72, 0xBA, 0x11,
+       0x86, 0xB7, 0x12, 0x68, 0xD1, 0xC6, 0xFC, 0xDD, 0x2A, 0xEA, 0xF8, 0x13, 0x16, 0x00, 0x3C, 0x21,
+       0xCB, 0x1D, 0x46, 0x31, 0xC4, 0xC3, 0xFF, 0x04, 0xDB, 0xF4, 0x0C, 0xF9, 0xAC, 0x75, 0x52, 0x22,
+       0x07, 0xC4, 0xD4, 0xC1, 0xAB, 0xF3, 0x10, 0x0C, 0x67, 0x5F, 0x21, 0x31, 0xB9, 0x8A, 0x52, 0x22,
+       0x12, 0x34, 0x80, 0x8D, 0x3F, 0x5B, 0xE3, 0x32, 0x28, 0x28, 0xBE, 0x26, 0xC7, 0xEF, 0x8A, 0x71,
+       0xD6, 0xCA, 0x71, 0x2C, 0x9F, 0x9E, 0xA3, 0xAA, 0xB5, 0xD4, 0x6B, 0xA5, 0x0A, 0xD7, 0x25, 0x92,
+       0x81, 0x10, 0xB3, 0xC0, 0x7A, 0xC1, 0xDC, 0x2C, 0x1F, 0xAC, 0x96, 0xD9, 0x32, 0xCF, 0x69, 0xAC,
+       0x3B, 0xBF, 0xE4, 0xA2, 0xF7, 0xDD, 0xD7, 0xFC, 0x1E, 0x7C, 0x47, 0x6D, 0xFE, 0x17, 0x40, 0x1C,
+       0x4A, 0xEB, 0x8D, 0x2C, 0x03, 0xFE, 0x56, 0x37, 0x89, 0xE4, 0x59, 0x99, 0x5D, 0x7C, 0x20, 0x6A,
+       0x57, 0xCD, 0x66, 0xD9, 0xF8, 0x33, 0x42, 0x1E, 0xE4, 0x0F, 0xBA, 0x32, 0xFB, 0x67, 0xA4, 0x79,
+       0x43, 0xAA, 0xFB, 0xB3, 0x20, 0xA4, 0xC1, 0xCE, 0x48, 0x03, 0xB0, 0x1E, 0x4A, 0x26, 0x47, 0x81,
+       0x90, 0x70, 0x69, 0x0E, 0x3E, 0x75, 0x89, 0x1B, 0xBC, 0x57, 0x09, 0xE8, 0x78, 0xE8, 0xDB, 0xAB,
+       0x43, 0xE2, 0xC4, 0xAB, 0xBF, 0xDA, 0x50, 0x45, 0x6E, 0x4D, 0x5E, 0xE7, 0xE4, 0x4B, 0x12, 0xBF,
+       0x9A, 0x36, 0xF3, 0xCF, 0x75, 0xBF, 0x7A, 0x2A, 0xD5, 0xC6, 0x92, 0xCB, 0xCE, 0x49, 0xD7, 0xF3,
+       0x35, 0xE4, 0x26, 0x70, 0x0D, 0x98, 0x0A, 0x46, 0x53, 0xCC, 0xB3, 0xFE, 0x48, 0xA8, 0xB8, 0x5E,
+       0x1C, 0x1F, 0x29, 0xBF, 0xF5, 0x46, 0x36, 0xF9, 0xF5, 0xDA, 0x4D, 0xF4, 0x3E, 0x4B, 0x7A, 0x39,
+       0xA1, 0xA6, 0x17, 0x23, 0x21, 0xB9, 0x98, 0xFB, 0x19, 0x61, 0x30, 0x86, 0xE4, 0xC1, 0x4A, 0x95,
+       0x70, 0x4A, 0x34, 0x73, 0x60, 0x4C, 0xAA, 0xEC, 0x16, 0xE9, 0x0B, 0xA8, 0xA3, 0x43, 0xD1, 0xC5,
+       0x3C, 0xB6, 0xEB, 0xA1, 0x2A, 0xFC, 0x75, 0xDE, 0x1B, 0x08, 0x1A, 0x32, 0xE7, 0x6B, 0xFD, 0xFC,
+       0x64, 0x0E, 0xCC, 0x67, 0x7F, 0x98, 0xFD, 0xCE, 0xF1, 0xE2, 0x80, 0xF3, 0xCC, 0xAC, 0x07, 0x08,
+       0x88, 0x0D, 0x73, 0xE7, 0x7E, 0xF8, 0xB8, 0x9F, 0xF5, 0xFB, 0x3F, 0x02, 0x72, 0xBA, 0x2D, 0x60,
+       0xEF, 0x8C, 0xAC, 0x75, 0x26, 0xE5, 0xA6, 0xA8, 0xA9, 0xC8, 0x85, 0x28, 0xC4, 0x8D, 0x5C, 0x9A,
+       0xF9, 0xC6, 0x48, 0x3F, 0x4A, 0x83, 0x5E, 0xD0, 0xFC, 0x62, 0x58, 0x6A, 0x7C, 0x26, 0x2F, 0xB4,
+       0x2D, 0x23, 0xD5, 0xBC, 0x4F, 0x18, 0x39, 0xF6, 0xEB, 0x34, 0xED, 0xF7, 0xDD, 0x47, 0xC4, 0x3B,
+       0x32, 0x53, 0xE6, 0x72, 0x1F, 0xE6, 0x04, 0x3A, 0x58, 0x95, 0x7E, 0x0E, 0x53, 0x66, 0xB9, 0x85,
+       0x25, 0x96, 0xB2, 0xDE, 0xEC, 0x60, 0xF3, 0x64, 0x1D, 0xFC, 0xB6, 0xAB, 0x48, 0x48, 0xB7, 0xEA,
+       0xA9, 0x29, 0x05, 0xDC, 0xB3, 0x75, 0xFB, 0xB9, 0x45, 0x3F, 0x75, 0xE5, 0x9A, 0xCE, 0x7A, 0xBD,
+       0x1A, 0x17, 0x14, 0xAA, 0xBA, 0x94, 0xDA, 0xA9, 0x7D, 0x32, 0xEB, 0x99, 0x8F, 0xE8, 0x1C, 0xCB,
+       0xE4, 0x03, 0x35, 0x80, 0xCF, 0xA5, 0xD4, 0x42, 0xD9, 0x37, 0xCB, 0x1C, 0xE5, 0x13, 0x5E, 0x21,
+       0x9E, 0x91, 0x04, 0xF4, 0xB4, 0x7D, 0x28, 0xC7, 0xF4, 0x1A, 0x75, 0x43, 0x07, 0x4E, 0xD5, 0x59,
+       0x3B, 0x1C, 0x65, 0x71, 0x23, 0x31, 0x9A, 0x82, 0x43, 0x14, 0x1D, 0x22, 0xE5, 0x08, 0xAF, 0xD3,
+       0xCB, 0xFB, 0x5A, 0x48, 0xC8, 0xF0, 0xB6, 0xBE, 0xAB, 0x70, 0x6E, 0x8F, 0x3B, 0x7B, 0xB4, 0xE7,
+       0x4A, 0x80, 0x8E, 0x96, 0x65, 0x90, 0x0E, 0x49, 0xDC, 0x07, 0x49, 0xCF, 0x2C, 0xE1, 0xE7, 0x25,
+       0xCD, 0xE9, 0x2D, 0xC9, 0x7D, 0xF4, 0x16, 0x27, 0x88, 0x24, 0x51, 0x97, 0x52, 0x66, 0xE8, 0x77,
+       0xD2, 0x2C, 0xFF, 0x5A, 0xB8, 0x57, 0xEE, 0xA6, 0x94, 0x36, 0xD0, 0x35, 0x35, 0x9B, 0x14, 0xA3,
+       0x6E, 0xE8, 0x5E, 0x05, 0xBD, 0xD3, 0x1D, 0x76, 0xE4, 0xA7, 0x62, 0x6E, 0x50, 0x8E, 0xED, 0xB5,
+       0x38, 0x15, 0x42, 0x48, 0xC3, 0x4C, 0x73, 0x9B, 0xE8, 0xD7, 0xF5, 0x7F, 0xB0, 0xF4, 0x13, 0x98,
+       0x7A, 0x8D, 0xBE, 0x82, 0x0C, 0x5E, 0x28, 0xAF, 0x1D, 0x4F, 0x34, 0x1F, 0x66, 0xE1, 0x54, 0x78,
+       0xDC, 0xA8, 0x48, 0x4A, 0xF7, 0xC5, 0x34, 0x8A, 0x03, 0x5B, 0xE5, 0x16, 0xB8, 0x13, 0x60, 0x62,
+       0x74, 0x27, 0xEB, 0xE3, 0x1D, 0xC1, 0x0D, 0x36, 0xFD, 0xB6, 0xE8, 0xDC, 0xB3, 0xEB, 0xDA, 0x37,
+       0xD9, 0x6C, 0xDC, 0xE4, 0xA3, 0x28, 0xCF, 0x66, 0xF6, 0xB1, 0xC4, 0x62, 0x6F, 0xD8, 0x00, 0xBB,
+       0x7D, 0xA1, 0xEA, 0xCE, 0x88, 0x8F, 0xE6, 0x91, 0x15, 0x0F, 0x02, 0xAC, 0x87, 0x14, 0xA8, 0x3C,
+       0x71, 0x14, 0x8E, 0xCB, 0x0D, 0x65, 0x48, 0xA2, 0xCB, 0x67, 0xBE, 0xA5, 0x4D, 0x0B, 0x44, 0xCE,
+       0x57, 0xB0, 0xCA, 0x79, 0x3B, 0xA8, 0x4E, 0x4F, 0x95, 0xBD, 0xF0, 0xD0, 0x44, 0xCC, 0xD9, 0x0E,
+       0x1C, 0x8D, 0xE2, 0x4B, 0xC4, 0x38, 0x58, 0xA1, 0x8D, 0x52, 0xA8, 0xF9, 0x28, 0xEE, 0x52, 0x33,
+       0xE7, 0x9A, 0x32, 0x29, 0x0F, 0x7B, 0x41, 0x47, 0x6D, 0x14, 0x4D, 0xA3, 0x93, 0xEC, 0x3E, 0xBA,
+       0xE8, 0x7C, 0xFC, 0x38, 0x07, 0x22, 0x8C, 0x7B, 0x6E, 0x6E, 0xAB, 0x34, 0x40, 0xC7, 0xBD, 0x47,
+       0x48, 0x43, 0x01, 0x73, 0x60, 0xC9, 0xA4, 0x46, 0xF9, 0x5C, 0xC5, 0xD2, 0xF0, 0x03, 0xF6, 0x13,
+       0x8D, 0x2A, 0x6D, 0xB1, 0xEF, 0x0B, 0x6F, 0x93, 0x25, 0x7C, 0xA8, 0xA7, 0xDF, 0xFA, 0x5C, 0x15,
+       0xD1, 0x99, 0x95, 0x7E, 0x34, 0x6E, 0xB7, 0x2B, 0xAB, 0xC2, 0xDC, 0xDD, 0xE6, 0xB2, 0x83, 0x1A,
+       0xAE, 0x3C, 0x75, 0x1C, 0xEF, 0xB7, 0xB5, 0x29, 0xEA, 0x5C, 0x92, 0xB2, 0xB5, 0x7B, 0x6E, 0xE4,
+       0xCF, 0x12, 0x34, 0xD1, 0xDF, 0xA0, 0x30, 0x7E, 0xF6, 0xA1, 0xF8, 0xE2, 0x4F, 0x23, 0xF8, 0xC4,
+       0xA5, 0x71, 0x80, 0xE7, 0x7F, 0xBB, 0x1C, 0x9D, 0xFF, 0x5D, 0x8D, 0xDC, 0xC6, 0x49, 0x7D, 0xC8,
+       0x13, 0xA2, 0x86, 0x7A, 0x61, 0xBB, 0xD3, 0xF7, 0xCA, 0xAC, 0xAF, 0xB6, 0x17, 0x79, 0xF9, 0xE6,
+       0x96, 0x72, 0xFB, 0xB8, 0x83, 0x4C, 0xF9, 0x44, 0xB9, 0xF0, 0xD8, 0xF1, 0x5E, 0xA8, 0xD3, 0xC6,
+       0xEF, 0xD8, 0x40, 0x63, 0xF9, 0xAC, 0x68, 0x2F, 0x17, 0xCA, 0x71, 0x8A, 0xF1, 0x4A, 0x69, 0xBA,
+       0x34, 0x6A, 0xA5, 0x4B, 0xBE, 0x4F, 0x16, 0x60, 0x25, 0xFF, 0xAC, 0xA3, 0x76, 0xB2, 0x07, 0x19,
+       0x86, 0x97, 0xAE, 0x37, 0x62, 0x79, 0x39, 0x8F, 0x3C, 0xEF, 0xB8, 0xFB, 0x64, 0xC9, 0x50, 0xF6,
+       0x38, 0x57, 0x7A, 0x1A, 0x0E, 0x97, 0x60, 0x49, 0x13, 0x22, 0x21, 0x15, 0xC4, 0x14, 0x42, 0x0D,
+       0xFC, 0x00, 0x92, 0x89, 0xAA, 0xBD, 0x00, 0x5D, 0xF0, 0x0C, 0xC2, 0x32, 0xD9, 0xCD, 0x9D, 0x31,
+       0x4B, 0xF0, 0x94, 0x3A, 0xD2, 0x3C, 0xBF, 0x92, 0xC3, 0x79, 0xAC, 0x19, 0xB9, 0x18, 0x9A, 0x58,
+       0x4C, 0xAD, 0x1A, 0x84, 0x85, 0x21, 0x6F, 0x02, 0x1F, 0xB4, 0x2D, 0x38, 0x39, 0xFE, 0xAD, 0xD5,
+       0x6C, 0xB5, 0x4F, 0xE3, 0x9A, 0xD9, 0x08, 0x10, 0x7C, 0x7D, 0xE2, 0xD9, 0x78, 0xF4, 0x28, 0x57,
+       0x99, 0xC8, 0x06, 0xE0, 0x58, 0x54, 0x85, 0x9A, 0xA1, 0x87, 0x4E, 0x02, 0xA7, 0x4F, 0x64, 0xDA,
+       0x5A, 0x73, 0xFC, 0x6C, 0xB2, 0xF8, 0x6F, 0xA6, 0xFC, 0x67, 0xE1, 0x64, 0xB2, 0xA2, 0xDB, 0x41,
+       0x1B, 0xEA, 0x21, 0xE4, 0x4A, 0x24, 0x11, 0xB6, 0xB1, 0xF3, 0x51, 0x6E, 0x81, 0xF8, 0x42, 0xA9,
+       0xC2, 0xF6, 0x37, 0x3E, 0xB6, 0xDC, 0xAB, 0x15, 0x2F, 0x7E, 0x23, 0x72, 0xFE, 0x8A, 0xD7, 0x8C,
+       0xDF, 0x11, 0xB8, 0xA0, 0xAF, 0x57, 0x28, 0xE6, 0xF8, 0x79, 0x89, 0x94, 0x36, 0x15, 0xD9, 0x08,
+       0x7B, 0xFB, 0xDA, 0x1C, 0x88, 0xAC, 0x2A, 0xDA, 0xE4, 0xE2, 0x14, 0x51, 0x1C, 0x3F, 0x79, 0xDE,
+       0xD9, 0x02, 0x51, 0xEE, 0xE0, 0x80, 0x4C, 0xCE, 0x6D, 0xD0, 0xDB, 0x58, 0x77, 0x72, 0x42, 0x91,
+       0x08, 0x13, 0x7A, 0x69, 0xFD, 0xDA, 0x9E, 0x97, 0xEF, 0x9C, 0xA4, 0x76, 0x18, 0x21, 0x9B, 0x1E,
+       0xCA, 0xAC, 0xBD, 0x69, 0xBE, 0xE2, 0x00, 0xD7, 0x77, 0xCC, 0x3D, 0x5C, 0xED, 0xB7, 0x35, 0x3D,
+       0x42, 0x57, 0xED, 0xC7, 0x3D, 0xB7, 0xC3, 0xC0, 0x0B, 0x0E, 0x12, 0xC0, 0xEA, 0x26, 0xB0, 0xB6,
+       0x31, 0x3B, 0xAD, 0x0A, 0xDD, 0x1E, 0xE7, 0xFB, 0x33, 0x6C, 0x6F, 0x7A, 0x45, 0xCC, 0x1D, 0x37,
+       0x88, 0x47, 0x7F, 0x67, 0xFA, 0x81, 0x02, 0x98, 0xD4, 0x54, 0x11, 0xFD, 0x9A, 0x5E, 0x46, 0x28,
+       0xF6, 0xE5, 0xF3, 0x8A, 0x9B, 0x8B, 0xCB, 0x65, 0x03, 0x43, 0xDB, 0xD9, 0xD5, 0x60, 0xDF, 0x1C,
+       0xFC, 0x30, 0x44, 0xDB, 0x9B, 0xE8, 0x86, 0x45, 0xB7, 0x69, 0x18, 0x21, 0x14, 0xE7, 0xD2, 0x7E,
+       0xF8, 0x24, 0x0D, 0x4A, 0x73, 0xF7, 0xCE, 0x59, 0x41, 0x46, 0xC4, 0x89, 0xF8, 0x0D, 0xCE, 0xC8,
+       0x5E, 0x9D, 0x18, 0x3A, 0x57, 0xE0, 0x08, 0x07, 0x55, 0x79, 0x1A, 0xEB, 0x25, 0x0C, 0xB3, 0x97,
+       0x96, 0xA4, 0x6D, 0x74, 0x31, 0xEA, 0xD3, 0x44, 0xB3, 0x11, 0x9A, 0x31, 0xCB, 0xA6, 0xB4, 0x8A,
+       0x3B, 0x6F, 0xFB, 0xE6, 0x50, 0xA8, 0xB3, 0x7D, 0xC6, 0x5C, 0xEB, 0xA5, 0xFA, 0x49, 0x3F, 0xD4,
+       0x86, 0x34, 0x30, 0x6B, 0x92, 0xBA, 0x26, 0x66, 0xD2, 0x5A, 0xC9, 0xA8, 0xAC, 0x9D, 0x06, 0x76,
+       0x69, 0x0C, 0x3D, 0x8D, 0x87, 0xB1, 0xEA, 0xC9, 0x69, 0xB2, 0x41, 0xA4, 0xA7, 0xDA, 0xE7, 0x69,
+       0x17, 0x53, 0xB7, 0x7A, 0x6F, 0xF5, 0xDA, 0x59, 0x67, 0xB5, 0xC0, 0xD4, 0x5F, 0x28, 0x3A, 0x31,
+       0x20, 0x38, 0xFD, 0xB6, 0xFE, 0x5A, 0x2A, 0xB0, 0x2B, 0x45, 0x1C, 0x8A, 0xAC, 0x92, 0x1B, 0x5D,
+       0xB8, 0x14, 0x95, 0xAE, 0xD7, 0xBB, 0xB9, 0xCE, 0xDE, 0xFD, 0xB8, 0xB0, 0x50, 0xD0, 0x64, 0xCE,
+       0x75, 0x2E, 0x4E, 0x51, 0x28, 0x8F, 0xEB, 0xF7, 0xEC, 0x70, 0x75, 0x60, 0x0F, 0x72, 0xD3, 0x16,
+       0x9B, 0x90, 0x02, 0x8B, 0xC9, 0xBA, 0x29, 0x99, 0x2B, 0xB4, 0xD9, 0xAE, 0xCD, 0x0B, 0xC1, 0xD6,
+       0xA3, 0x3E, 0x96, 0x8C, 0x3F, 0x58, 0x4C, 0xED, 0xB2, 0x89, 0x14, 0x51, 0xCB, 0xA4, 0x75, 0x26,
+       0x49, 0xA8, 0x4F, 0xA8, 0xFB, 0xA4, 0x7C, 0x5E, 0x06, 0xA5, 0xF5, 0x64, 0x02, 0x15, 0x39, 0x20,
+       0xA9, 0x98, 0x8E, 0x5E, 0xB5, 0xF4, 0x9F, 0xF9, 0xE5, 0x5C, 0x27, 0xB2, 0xA8, 0x7E, 0xA7, 0xA9,
+       0xE0, 0x20, 0xCA, 0x9C, 0xC9, 0x96, 0x61, 0x2F, 0xC3, 0x65, 0x46, 0x93, 0x83, 0xF3, 0x84, 0x1C,
+       0xF4, 0xE9, 0xA2, 0xC3, 0xC3, 0x31, 0xC7, 0x29, 0xDB, 0xB6, 0x59, 0xB0, 0xE0, 0xEE, 0xD0, 0x7C,
+       0x51, 0x67, 0xA5, 0x43, 0xA4, 0xE4, 0x26, 0x1A, 0xB2, 0x0A, 0xFE, 0x5D, 0x70, 0x91, 0x29, 0x64,
+       0x4D, 0xD3, 0x6D, 0x53, 0x9B, 0xC6, 0xE8, 0xB9, 0xF2, 0xE8, 0x7C, 0x50, 0x0D, 0x74, 0x88, 0x0C,
+       0x6B, 0x33, 0xE3, 0x66, 0x48, 0x01, 0xE0, 0x70, 0x18, 0x37, 0xD9, 0x73, 0x29, 0x6B, 0x95, 0x42,
+       0x20, 0x3D, 0xE7, 0x81, 0xB4, 0xF9, 0x39, 0xEF, 0xD2, 0xD6, 0xD4, 0xBE, 0xBC, 0x2B, 0x38, 0x52,
+       0x50, 0x82, 0xA5, 0x0D, 0x53, 0x3E, 0x2A, 0x82, 0xF6, 0xB8, 0x0A, 0x78, 0x28, 0x41, 0x16, 0x8B,
+       0x38, 0x1A, 0xDC, 0x6F, 0x91, 0x61, 0x5A, 0x59, 0x3D, 0xB0, 0xB1, 0x91, 0x27, 0x7F, 0xAD, 0x4F,
+       0xD4, 0x71, 0x3A, 0xD0, 0xD6, 0x6A, 0xAA, 0x81, 0xEA, 0x50, 0x80, 0xA2, 0xEE, 0xAA, 0x4C, 0xD4,
+       0x8B, 0xB1, 0x40, 0x9D, 0xAF, 0x7F, 0x62, 0x07, 0xFC, 0xD9, 0xC5, 0x52, 0x29, 0x1C, 0x6F, 0x8E,
+       0x9A, 0x85, 0x75, 0x2A, 0x0F, 0x2C, 0xD7, 0x17, 0x82, 0x47, 0xCC, 0x7C, 0x0C, 0xBD, 0x68, 0x44,
+       0xD5, 0x4E, 0xF6, 0x49, 0xB4, 0xCB, 0xF2, 0xC8, 0xF1, 0x2E, 0xB1, 0xB1, 0x95, 0x58, 0xAF, 0x20,
+       0x05, 0x09, 0xA3, 0x53, 0x93, 0xD7, 0x79, 0xDC, 0x7E, 0xD5, 0x47, 0x68, 0x2C, 0x20, 0x6F, 0xCC,
+       0x22, 0x8C, 0xC1, 0x9C, 0x6E, 0xE4, 0xB9, 0xB1, 0xE8, 0xA6, 0x94, 0x6A, 0x84, 0xC8, 0x1B, 0x83,
+       0x92, 0x2B, 0x15, 0xEA, 0xF0, 0xCE, 0x6A, 0x8B, 0x30, 0x3C, 0x01, 0x52, 0xFC, 0x3E, 0x58, 0xBD,
+       0x0A, 0xAD, 0xCC, 0x98, 0xFB, 0x0B, 0x36, 0xB6, 0xAB, 0x0C, 0x62, 0x46, 0x45, 0x8B, 0xC2, 0x4C,
+       0xF3, 0x5B, 0xDF, 0x2C, 0xD1, 0xBC, 0xD4, 0x46, 0xD4, 0x22, 0xE3, 0xE1, 0x71, 0xE3, 0xAE, 0x0D,
+       0x0C, 0x89, 0xB9, 0x75, 0x84, 0xE3, 0xDF, 0x3E, 0x4E, 0xE0, 0xA7, 0x1A, 0x0A, 0x4A, 0x3C, 0x6C,
+       0x62, 0x0A, 0xBC, 0x0B, 0x22, 0xBE, 0xB2, 0x9F, 0x1E, 0x5F, 0x39, 0x63, 0x10, 0xDC, 0x58, 0xE3,
+       0x06, 0xAA, 0xCC, 0x18, 0x25, 0xB9, 0x34, 0xC6, 0x66, 0x74, 0x7C, 0xFC, 0xED, 0xA2, 0x5F, 0x07,
+       0x8A, 0x4E, 0x62, 0x3B, 0xCD, 0x66, 0xBD, 0x7E, 0x9E, 0x45, 0x5B, 0xF8, 0x30, 0xDA, 0x20, 0xD7,
+       0xA7, 0xE9, 0x8A, 0xE1, 0xF1, 0x13, 0xFD, 0x3B, 0xE2, 0x8A, 0xFF, 0xEF, 0x67, 0xFA, 0xD1, 0x99,
+       0xA2, 0x44, 0x3D, 0x24, 0x31, 0xE8, 0x59, 0x57, 0x99, 0x47, 0xE3, 0x60, 0xAA, 0xF8, 0x15, 0x0F,
+       0x77, 0x45, 0x3A, 0x91, 0x29, 0xFA, 0xA3, 0xEB, 0xB9, 0xB6, 0x64, 0xD6, 0x51, 0xE4, 0xD2, 0xF4,
+       0xEF, 0x93, 0x14, 0x6A, 0xC0, 0x41, 0xFB, 0x78, 0x03, 0x8E, 0x3A, 0xCA, 0x1B, 0xFB, 0xA3, 0x78,
+       0x94, 0x81, 0xAC, 0x56, 0xCC, 0x54, 0x15, 0x46, 0xF4, 0x64, 0xA6, 0x9E, 0xCA, 0x43, 0x2D, 0x91,
+       0x8F, 0x1F, 0xCF, 0x97, 0xF1, 0xA9, 0x72, 0x63, 0xCC, 0x35, 0x28, 0x51, 0x08, 0x5D, 0x72, 0xEB,
+       0x63, 0xF4, 0x21, 0xC5, 0x5C, 0x1D, 0x58, 0x4C, 0x83, 0x22, 0xAD, 0x27, 0xFF, 0x6E, 0x6B, 0x5B,
+       0xB8, 0x82, 0xFB, 0xDF, 0x4F, 0x5A, 0x12, 0x6F, 0xF0, 0x3B, 0xF5, 0x7F, 0x82, 0x4D, 0x8E, 0xB7,
+       0x6A, 0xC4, 0x0A, 0x3A, 0xA1, 0x09, 0x33, 0x65, 0xAA, 0x59, 0x82, 0xC8, 0xC9, 0x70, 0x2E, 0xF9,
+       0x8B, 0x89, 0x2F, 0xAC, 0xB0, 0xFE, 0x29, 0xA2, 0xA7, 0x5D, 0x66, 0xE1, 0x08, 0xE2, 0xE9, 0x8F,
+       0x94, 0x37, 0x5A, 0x4F, 0x2D, 0x4F, 0x06, 0x2C, 0x4C, 0x62, 0x4C, 0x09, 0x54, 0x0F, 0x4C, 0xEB,
+       0x69, 0x13, 0x39, 0xD0, 0xA6, 0x8B, 0x7E, 0xA4, 0xEB, 0x48, 0x2C, 0xAF, 0xA2, 0x74, 0x9D, 0x80,
+       0x6E, 0x48, 0xF6, 0x07, 0xFD, 0x48, 0xBC, 0x55, 0xB8, 0x2B, 0xAC, 0xA0, 0x64, 0x00, 0xC5, 0xDE,
+       0xC9, 0x35, 0x34, 0x98, 0x88, 0xF6, 0x3B, 0xC0, 0x95, 0xC9, 0x77, 0x08, 0x5A, 0xC3, 0x3D, 0x39,
+       0x1D, 0x60, 0x24, 0x79, 0x99, 0x27, 0xAA, 0x41, 0xF1, 0xDA, 0xA1, 0xD5, 0xF0, 0x5E, 0xD1, 0x04,
+       0xD7, 0xD1, 0xBA, 0x71, 0x10, 0x55, 0x9C, 0xF9, 0x61, 0xA9, 0x53, 0x23, 0x67, 0x2E, 0x4D, 0x89,
+       0x2B, 0x7F, 0x07, 0x4A, 0x6A, 0x8A, 0x2D, 0xE4, 0x9D, 0xA3, 0x20, 0x0A, 0x1F, 0x6A, 0x1C, 0xB4,
+       0xCD, 0x11, 0x7A, 0x60, 0xEB, 0x71, 0xDE, 0x89, 0xFC, 0xEB, 0xBD, 0x33, 0x50, 0xA2, 0x3D, 0x32,
+       0x6B, 0xC7, 0x37, 0x1B, 0x0D, 0x76, 0x6A, 0xE6, 0xD7, 0xB9, 0xB3, 0x69, 0x27, 0x14, 0xCD, 0xB3,
+       0x73, 0xEE, 0x6F, 0x85, 0xE2, 0xCB, 0x3E, 0x5A, 0xF9, 0x05, 0xD3, 0x0A, 0x9A, 0x84, 0x97, 0xB5,
+       0x73, 0x39, 0x89, 0xB4, 0x10, 0x73, 0xAD, 0x34, 0x94, 0x86, 0x56, 0x6C, 0x22, 0x2C, 0x9D, 0xA1,
+       0xBC, 0xED, 0x83, 0x29, 0x20, 0x44, 0xE1, 0xCD, 0xAD, 0xDC, 0x00, 0x61, 0xD6, 0xDF, 0xF3, 0x45,
+       0xBA, 0x29, 0x97, 0x29, 0xA8, 0xAD, 0xCF, 0x76, 0x7A, 0x60, 0x17, 0x75, 0xED, 0xFE, 0x5F, 0xA2,
+       0xC2, 0x2D, 0x7B, 0xA9, 0x22, 0xE9, 0x3B, 0xBE, 0x4F, 0xAB, 0x7C, 0x23, 0xBD, 0xAB, 0x8A, 0x37,
+       0x4F, 0x82, 0xFB, 0x7F, 0xE6, 0x28, 0x1E, 0x46, 0x6F, 0xAF, 0x30, 0x58, 0x3A, 0x2A, 0x0C, 0xFC,
+       0xCD, 0x87, 0x6C, 0x07, 0xB7, 0x3A, 0xEC, 0x75, 0x5A, 0x50, 0x6F, 0x7B, 0x59, 0x23, 0xAD, 0xB8,
+       0xD3, 0xD1, 0xF2, 0x88, 0x89, 0xBD, 0x2F, 0xA5, 0x00, 0x79, 0x21, 0x00, 0x39, 0x39, 0x7B, 0x5A,
+       0xA0, 0x36, 0x6B, 0x2A, 0x41, 0xD8, 0x93, 0x8F, 0xFD, 0xA2, 0xCA, 0xF3, 0xCD, 0xEA, 0x37, 0xF4,
+       0xC9, 0x63, 0x50, 0xD6, 0x43, 0x4C, 0xDC, 0x10, 0x96, 0x20, 0xC2, 0xE4, 0xE9, 0x62, 0x51, 0x51,
+       0xE3, 0x5E, 0x0E, 0x57, 0x4B, 0xA9, 0xA5, 0x43, 0xCB, 0xE6, 0xE8, 0xAC, 0x8E, 0xB0, 0xDA, 0x68,
+       0x46, 0xDC, 0xC8, 0x02, 0xE1, 0x1A, 0x9A, 0xFB, 0x5D, 0x5E, 0x84, 0x28, 0xAC, 0xFD, 0xB9, 0x21,
+       0x0B, 0xD0, 0x14, 0x3C, 0x80, 0x67, 0xF6, 0x51, 0x3E, 0xC7, 0x1B, 0xB7, 0xFC, 0x08, 0xA3, 0x7E,
+       0xB6, 0x80, 0x52, 0xE9, 0x0D, 0x4B, 0x84, 0x21, 0xA7, 0x6B, 0x69, 0x0D, 0x0E, 0x62, 0xDB, 0xEC,
+       0xB8, 0x4A, 0x54, 0x43, 0xE3, 0xC6, 0x42, 0x58, 0x3A, 0xDD, 0x0B, 0x94, 0x7E, 0xC0, 0xAC, 0xD9,
+       0x51, 0xB5, 0xD9, 0xA3, 0x02, 0x64, 0x6D, 0xA8, 0xAA, 0xA1, 0x38, 0x07, 0x4E, 0x93, 0xAA, 0xC6,
+       0xD8, 0x87, 0x63, 0x14, 0xA6, 0xE4, 0x07, 0xC9, 0xE7, 0x37, 0x8F, 0xC8, 0x7D, 0xCD, 0x90, 0xD1,
+       0xCF, 0x64, 0x04, 0x0B, 0xF2, 0x74, 0x7A, 0x8D, 0x3C, 0xB2, 0x39, 0x8B, 0x37, 0x76, 0x8F, 0x0F,
+       0x99, 0x01, 0xAF, 0xE3, 0xB8, 0x27, 0xA8, 0xA9, 0xB4, 0xB6, 0x10, 0x71, 0xA6, 0x2D, 0x69, 0xD5,
+       0xD7, 0x10, 0x72, 0xB3, 0x8F, 0xBB, 0x67, 0xA8, 0x98, 0x12, 0x33, 0x5D, 0x89, 0x4C, 0xE7, 0x30,
+       0xA6, 0xF6, 0x1D, 0x19, 0x1F, 0x8D, 0x0E, 0xF4, 0xA1, 0xAA, 0x32, 0x0A, 0x75, 0x48, 0x7A, 0x99,
+       0xA8, 0x4D, 0xF5, 0xBA, 0xB8, 0x82, 0x0C, 0xDA, 0xB0, 0x91, 0x7C, 0x4E, 0x3D, 0x57, 0x82, 0x3F,
+       0x86, 0xEC, 0xAF, 0x72, 0x16, 0x6C, 0x00, 0xA0, 0xCC, 0x31, 0x1A, 0x1B, 0x4E, 0x29, 0xA5, 0xF4,
+       0x60, 0x46, 0x35, 0xC6, 0xE6, 0x80, 0xA0, 0xB4, 0x39, 0xB5, 0x74, 0x9B, 0x64, 0x48, 0xBA, 0x3C,
+       0x9C, 0x24, 0xEC, 0x2D, 0x9E, 0xEC, 0x0D, 0xC9, 0x8B, 0x68, 0x58, 0xA7, 0x28, 0x79, 0x7C, 0xC5,
+       0x23, 0x99, 0xF1, 0x3B, 0xA9, 0x39, 0xD0, 0xF7, 0x48, 0x4F, 0x94, 0x81, 0x8A, 0x8E, 0x65, 0x71,
+       0x30, 0xCF, 0xD9, 0x04, 0x05, 0xE8, 0xFD, 0x85, 0x5F, 0x9C, 0xC7, 0xAC, 0x6C, 0x3A, 0x35, 0xCA,
+       0xA3, 0xDA, 0x69, 0x29, 0x1C, 0xC7, 0xD8, 0x98, 0x42, 0x64, 0x74, 0x40, 0x2A, 0x9D, 0xBB, 0x30,
+       0xCC, 0xEC, 0x99, 0xFF, 0x4F, 0xF8, 0x5E, 0xFA, 0x0C, 0x0D, 0x95, 0x8D, 0x53, 0xB9, 0x41, 0x26,
+       0xB9, 0xFB, 0x42, 0xAA, 0xC7, 0x7C, 0xCD, 0x73, 0x8F, 0xA2, 0x1E, 0x0F, 0xC6, 0xCD, 0x25, 0x36,
+       0x48, 0x5B, 0x97, 0x69, 0x6D, 0x53, 0xF4, 0x37, 0x12, 0xA2, 0x4C, 0x59, 0xBF, 0x02, 0xEA, 0xC5,
+       0xB4, 0x26, 0x67, 0xFF, 0xFB, 0x57, 0xA8, 0x4D, 0x94, 0x6E, 0xA6, 0x44, 0x50, 0xCF, 0x3E, 0x85,
+       0x63, 0x47, 0xE4, 0x91, 0x72, 0xED, 0x77, 0xDC, 0xC8, 0x0F, 0x65, 0x36, 0x4E, 0xF1, 0xEC, 0x83,
+       0x84, 0xEF, 0xA9, 0xBD, 0x1A, 0x67, 0x4B, 0x95, 0x7A, 0x3A, 0x51, 0x52, 0xDB, 0x2A, 0x3E, 0x4B,
+       0x88, 0x92, 0x47, 0x92, 0x83, 0xFA, 0xE4, 0xA4, 0xA1, 0xB9, 0x1D, 0xB3, 0xB5, 0xF4, 0xA2, 0x93,
+       0x56, 0x25, 0xA7, 0xF6, 0xEC, 0x86, 0x80, 0x5F, 0x6E, 0xAF, 0x2B, 0xC4, 0xE9, 0x1F, 0xA7, 0xE3,
+       0x6B, 0x96, 0xF0, 0x87, 0x86, 0xB5, 0x34, 0xD2, 0xB8, 0xF0, 0xA2, 0x72, 0x0E, 0x3C, 0xFC, 0x3F,
+       0x3A, 0x2F, 0x4D, 0x2A, 0xFA, 0x2A, 0x17, 0x0C, 0xC6, 0x9A, 0x88, 0x3C, 0x3C, 0x8D, 0x36, 0xA0,
+       0x0C, 0x5D, 0xDB, 0x50, 0x5C, 0xEE, 0x45, 0x47, 0xD0, 0x3E, 0x82, 0x64, 0x8D, 0x6B, 0x17, 0xE7,
+       0xEC, 0xAB, 0xF2, 0xC2, 0xB0, 0x11, 0xEE, 0x25, 0x76, 0xDE, 0x0B, 0xAC, 0x18, 0x90, 0xFF, 0xAA,
+       0x91, 0x27, 0xA8, 0xA6, 0x2B, 0x99, 0xDF, 0x9D, 0xE1, 0x7C, 0x3A, 0xF8, 0xF7, 0xB7, 0x85, 0x89,
+       0x99, 0xD4, 0x8C, 0x70, 0x64, 0xED, 0x06, 0xC9, 0x76, 0xE6, 0x3D, 0x6E, 0xC0, 0xC8, 0x11, 0xF0,
+       0x91, 0x84, 0x4D, 0x20, 0xCB, 0x02, 0x41, 0x76, 0x06, 0xAD, 0xE2, 0xC6, 0xCC, 0x4F, 0xCE, 0x2F,
+       0xA4, 0x8B, 0x33, 0x71, 0x2D, 0xC9, 0x07, 0x2D, 0x5B, 0x9A, 0x55, 0xB9, 0xC0, 0x9C, 0x63, 0xDA,
+       0x56, 0x57, 0x49, 0xBA, 0x74, 0xBB, 0xFE, 0x8E, 0xC9, 0xB2, 0x1E, 0xCE, 0xB5, 0xA3, 0x7A, 0x6D,
+       0xBD, 0x28, 0x30, 0x4D, 0xD3, 0x91, 0x6F, 0x47, 0x7C, 0xD1, 0x61, 0xF8, 0xA6, 0xC5, 0x9F, 0x0B,
+       0x13, 0xCD, 0xD5, 0x05, 0x81, 0xFC, 0x95, 0xEE, 0xD3, 0x3C, 0x0D, 0x19, 0x45, 0x4E, 0x0C, 0x31,
+       0x6E, 0xBE, 0x7E, 0xB9, 0x4B, 0x2F, 0xA4, 0x4D, 0xBA, 0x94, 0x59, 0x7C, 0x5B, 0xDC, 0xC1, 0x3D,
+       0x8B, 0x3A, 0x80, 0x00, 0x00, 0x3D, 0x94, 0x47, 0xA6, 0x0D, 0x95, 0xF7, 0xCD, 0xE4, 0xCF, 0x16,
+       0x11, 0x19, 0x4C, 0x3E, 0x35, 0x85, 0x95, 0x1A, 0xC8, 0x3D, 0x15, 0x5D, 0xA6, 0x7F, 0x46, 0x06,
+       0x30, 0xAE, 0x61, 0x80, 0x27, 0xAB, 0xD8, 0xF4, 0x03, 0xD8, 0xD5, 0xA3, 0x6C, 0x2A, 0x0F, 0x15,
+       0x25, 0x3F, 0xA8, 0xCE, 0xA9, 0x53, 0xF8, 0x6B, 0x4E, 0x4B, 0xE1, 0x08, 0xD1, 0xB0, 0x34, 0xB8,
+       0x8D, 0xA1, 0xF1, 0x31, 0xFA, 0x03, 0x33, 0xBD, 0x35, 0xDF, 0x52, 0xE8, 0x9E, 0x77, 0xB0, 0x48,
+       0xEB, 0xD5, 0xF0, 0x59, 0x62, 0x3D, 0x14, 0x5C, 0xF2, 0x59, 0xD0, 0xC0, 0xDA, 0x4F, 0x29, 0x3F,
+       0x42, 0x38, 0x06, 0xB3, 0x78, 0xBB, 0xCC, 0xD9, 0x37, 0x7F, 0x83, 0x4E, 0xEE, 0x7A, 0xB8, 0x34,
+       0x55, 0x51, 0xBE, 0xFB, 0x74, 0x10, 0xEC, 0x7F, 0x33, 0x17, 0xDD, 0xF1, 0x8C, 0xF3, 0xFE, 0xA7,
+       0x49, 0x8A, 0x81, 0xF2, 0x08, 0x9D, 0xDC, 0x47, 0x9E, 0xDB, 0xAD, 0xD3, 0x45, 0x3B, 0xDC, 0x7D,
+       0x2F, 0x5A, 0xAE, 0xB2, 0xAA, 0x90, 0x86, 0x24, 0x8A, 0xAA, 0x63, 0x8D, 0x24, 0x41, 0xFC, 0xA8,
+       0x8C, 0xF1, 0xF1, 0x11, 0x5A, 0xCA, 0x82, 0x6E, 0xCF, 0x9B, 0x2D, 0x2D, 0x15, 0xA3, 0x29, 0xE4,
+       0xBA, 0x25, 0xD8, 0x0C, 0x3F, 0x38, 0xCC, 0x8A, 0xBF, 0x43, 0xD8, 0x8B, 0x31, 0xFC, 0xFB, 0x57,
+       0xA1, 0xD9, 0x56, 0xEE, 0x1F, 0xE7, 0xD3, 0x77, 0xFB, 0xB9, 0x1C, 0xBC, 0x4A, 0x31, 0x88, 0xE1,
+       0x29, 0x51, 0xA4, 0x5A, 0x15, 0xF2, 0x66, 0xF0, 0x76, 0xA4, 0x77, 0xAA, 0x7E, 0x4D, 0xD4, 0xB7,
+       0x2C, 0x82, 0x37, 0xE7, 0xA0, 0x79, 0x4E, 0xBB, 0x4B, 0x75, 0x25, 0x7C, 0x30, 0x56, 0xC8, 0xA4,
+       0xDF, 0xF8, 0x29, 0x3C, 0xD1, 0x91, 0x72, 0x88, 0xB0, 0xFB, 0x24, 0xE2, 0x82, 0xCF, 0x6A, 0x0F,
+       0x1A, 0x79, 0xC6, 0x46, 0x0B, 0x1F, 0xA8, 0x88, 0x95, 0xD1, 0xB2, 0xD0, 0xE0, 0x5D, 0xE6, 0x42,
+       0xB4, 0x22, 0x63, 0x13, 0x17, 0xFC, 0xBE, 0xA7, 0xFF, 0xC9, 0x1D, 0xAC, 0x11, 0x89, 0xA2, 0xD5,
+       0x67, 0xC3, 0x61, 0xF8, 0x8C, 0x09, 0x88, 0xF6, 0x1E, 0x2A, 0x65, 0x92, 0x6A, 0x1A, 0x1B, 0x48,
+       0xA9, 0x12, 0x4A, 0xF6, 0xFE, 0x38, 0xFC, 0xAA, 0x99, 0x26, 0x5E, 0x21, 0xDC, 0xEE, 0x5D, 0x13,
+       0xE1, 0x93, 0xA8, 0xD3, 0x3D, 0x98, 0x2A, 0x8D, 0x04, 0xAF, 0x5F, 0x76, 0xED, 0xE6, 0x8C, 0x93,
+       0x42, 0xED, 0x26, 0x8E, 0x4A, 0x8E, 0xFF, 0xB6, 0xED, 0x71, 0xFF, 0x7F, 0x2F, 0xD3, 0x82, 0x25,
+       0x34, 0xC9, 0x78, 0xC1, 0x6E, 0x71, 0xDC, 0x8E, 0xD7, 0xFB, 0xFB, 0x90, 0x53, 0x75, 0x93, 0x1E,
+       0x21, 0x66, 0x96, 0x6F, 0x1A, 0xC8, 0x6C, 0x4E, 0x1A, 0xA4, 0x8A, 0xEB, 0x64, 0xC1, 0x21, 0xEF,
+       0xA6, 0x10, 0x06, 0x1E, 0x3B, 0x88, 0x5B, 0x47, 0x4B, 0x9E, 0xCE, 0xB0, 0xA3, 0xAC, 0x49, 0xD4,
+       0xAA, 0x43, 0xF0, 0xC5, 0xB4, 0x24, 0x29, 0xC0, 0xFB, 0xB4, 0x03, 0xD2, 0x79, 0x54, 0x90, 0x02,
+       0xCE, 0xB8, 0x10, 0x6B, 0xC0, 0xEE, 0x6E, 0x43, 0xC6, 0x1B, 0x61, 0xB5, 0x64, 0xC3, 0x12, 0x05,
+       0xD4, 0xE7, 0x74, 0x8B, 0x1B, 0x1F, 0x8C, 0x13, 0xC7, 0x3F, 0x64, 0x50, 0x7A, 0xA3, 0x07, 0x57,
+       0xFC, 0x11, 0x79, 0x13, 0x5C, 0xC8, 0xC0, 0x41, 0xEA, 0x75, 0xFA, 0x0C, 0x3E, 0x90, 0x7A, 0x36,
+       0xB8, 0x6B, 0x9D, 0x37, 0xED, 0x7F, 0xE1, 0x4F, 0x12, 0xCD, 0x87, 0x15, 0x69, 0x5E, 0x3E, 0x94,
+       0x94, 0xB2, 0xFC, 0x72, 0x0D, 0x04, 0x57, 0xDA, 0x31, 0xD9, 0x3E, 0xEA, 0xD7, 0xA0, 0x6C, 0xB7,
+       0xBC, 0x8A, 0xD3, 0x08, 0x7D, 0x12, 0x00, 0x5C, 0x40, 0x66, 0x13, 0x57, 0x6D, 0x41, 0xCD, 0x9E,
+       0x8F, 0x39, 0x1F, 0xD1, 0x7E, 0xD2, 0xA3, 0x43, 0x83, 0x48, 0x26, 0x73, 0xA2, 0x80, 0x4E, 0xED,
+       0x38, 0xB4, 0x93, 0xE7, 0x19, 0x24, 0xAA, 0x75, 0xF4, 0x4E, 0x48, 0xDB, 0x59, 0x1F, 0x76, 0x32,
+       0xF5, 0xF7, 0x9F, 0xB9, 0x44, 0xE2, 0x74, 0x8F, 0xDB, 0xA6, 0x0A, 0x61, 0xC3, 0x2D, 0x5D, 0x6A,
+       0x47, 0xDC, 0x23, 0xE1, 0x02, 0x0D, 0x77, 0xAF, 0x25, 0xD8, 0xB8, 0x7C, 0x10, 0xBE, 0xB3, 0x54,
+       0x4C, 0xFE, 0x0D, 0x4A, 0xCE, 0x21, 0x19, 0x43, 0x14, 0xE1, 0x13, 0x28, 0x5D, 0x96, 0xCC, 0xF9,
+       0xF3, 0x02, 0xEA, 0xE7, 0xA1, 0xAE, 0xA7, 0x40, 0x6D, 0x7B, 0x0E, 0xA8, 0x43, 0x05, 0xC7, 0x47,
+       0x97, 0xE8, 0x0C, 0xEC, 0xBD, 0x2F, 0x92, 0xE1, 0x9A, 0x88, 0x65, 0x54, 0xF5, 0x1D, 0xF3, 0xE2,
+       0x1D, 0x2D, 0x15, 0xD3, 0x9E, 0xFF, 0x37, 0x4D, 0x87, 0x8C, 0x1C, 0x0B, 0x1F, 0xFF, 0xE7, 0xB5,
+       0xA0, 0xF1, 0x86, 0x7A, 0x01, 0x67, 0xAB, 0x98, 0xE7, 0xC1, 0x40, 0x06, 0x83, 0x43, 0x5C, 0x0D,
+       0x50, 0xFF, 0xA7, 0xF1, 0xA7, 0x20, 0xDD, 0xFC, 0xDE, 0x33, 0x38, 0x18, 0x87, 0x02, 0x2D, 0x5F,
+       0x13, 0xE3, 0xFF, 0x25, 0xE7, 0xF4, 0xD1, 0xF1, 0x98, 0x3C, 0x22, 0x10, 0x2C, 0x4C, 0x66, 0xA8,
+       0xDC, 0x5D, 0xBC, 0xE6, 0xE4, 0xCB, 0x84, 0x77, 0x0E, 0x4A, 0xBE, 0xC9, 0xD5, 0x91, 0xEC, 0xA2,
+       0x15, 0x51, 0xC6, 0xEC, 0x67, 0x1A, 0x21, 0x7F, 0x1D, 0x47, 0xB3, 0x45, 0x3B, 0xB6, 0x3A, 0x81,
+       0x37, 0xA2, 0xC2, 0x31, 0xC0, 0xC3, 0xD3, 0xF0, 0x00, 0x2B, 0x61, 0xB9, 0x6A, 0xD5, 0xBB, 0x96,
+       0xF3, 0x08, 0x4B, 0xCC, 0xE7, 0x9B, 0x2C, 0xAA, 0x21, 0x9B, 0xC7, 0x63, 0xF6, 0x24, 0x33, 0x0A,
+       0xFD, 0xE0, 0x1E, 0x50, 0xAC, 0x86, 0xF6, 0x35, 0xFE, 0xC2, 0x3F, 0x4A, 0x85, 0xB7, 0x3C, 0xAF,
+       0xF5, 0xAF, 0xD4, 0x0B, 0xEE, 0x44, 0x69, 0x44, 0xFA, 0x7F, 0x44, 0x46, 0x84, 0x4F, 0xB1, 0xAA,
+       0x0A, 0xCA, 0xBA, 0x00, 0xC6, 0x51, 0x29, 0x64, 0x31, 0x7E, 0xFF, 0xCA, 0x5F, 0x26, 0xFC, 0x86,
+       0xA9, 0xF4, 0xDB, 0x50, 0x19, 0x52, 0xBD, 0xDA, 0xDA, 0x36, 0x6E, 0x79, 0xBA, 0x21, 0xC6, 0x16,
+       0x8A, 0xBC, 0xAC, 0x9E, 0x3F, 0x55, 0x96, 0x6D, 0x8B, 0xD6, 0xDC, 0x48, 0xF0, 0x1A, 0x43, 0x8A,
+       0x29, 0x71, 0x25, 0x39, 0x11, 0xD3, 0x0E, 0x68, 0x7A, 0x87, 0x28, 0x5B, 0xB4, 0x70, 0x46, 0x29,
+       0xCD, 0x1F, 0x8E, 0x38, 0xAA, 0xDB, 0xD4, 0xFC, 0x99, 0xDB, 0x8A, 0x40, 0xFC, 0x70, 0xD5, 0xEE,
+       0x27, 0xD7, 0x35, 0x86, 0xA1, 0x06, 0xA3, 0x63, 0x33, 0x38, 0x94, 0x63, 0xBD, 0x34, 0xD4, 0x55,
+       0x32, 0x5A, 0x97, 0x24, 0x72, 0x64, 0x60, 0xD9, 0x2A, 0x97, 0x8D, 0xC4, 0x19, 0x1C, 0xAD, 0x13,
+       0xF8, 0xC1, 0xD4, 0x94, 0x4A, 0x0F, 0x9B, 0x63, 0x5F, 0x59, 0x67, 0x88, 0x48, 0x8D, 0xD3, 0x92,
+       0xE1, 0xE3, 0x47, 0x2F, 0x4B, 0xE6, 0xCE, 0x4E, 0x87, 0x30, 0xCB, 0x4C, 0xFB, 0x49, 0x54, 0x1A,
+       0x59, 0x2D, 0x18, 0x59, 0xB3, 0xAE, 0xD5, 0xFD, 0xB9, 0x8F, 0x03, 0x36, 0x14, 0x0E, 0x39, 0xAE,
+       0x92, 0x9C, 0x04, 0x16, 0xFD, 0x52, 0x20, 0x2F, 0xC8, 0xEA, 0xCF, 0x7D, 0xC7, 0x3A, 0xF8, 0x6D,
+       0x86, 0xA3, 0x2A, 0x0F, 0x5E, 0xB6, 0xDA, 0x6C, 0xED, 0xF2, 0x79, 0x32, 0xD7, 0x3C, 0x77, 0x9B,
+       0x90, 0xA3, 0x7E, 0x1D, 0x30, 0xDE, 0xD5, 0xEE, 0xA0, 0x96, 0xD5, 0xE4, 0x92, 0xEA, 0x09, 0x3A,
+       0x62, 0x00, 0xFC, 0x72, 0x67, 0xDA, 0x60, 0x36, 0x80, 0x38, 0xE6, 0x85, 0xE2, 0x50, 0x0F, 0x49,
+       0x60, 0x4A, 0x5F, 0xC4, 0x25, 0xFB, 0x48, 0xBB, 0xB9, 0x50, 0x71, 0x34, 0xA1, 0x37, 0x6D, 0x7C,
+       0x50, 0x71, 0x20, 0x35, 0x60, 0x42, 0x33, 0xFB, 0x81, 0xCA, 0xAD, 0x95, 0x36, 0x5A, 0x8E, 0x08,
+       0x8B, 0x93, 0x86, 0xC3, 0x9B, 0x28, 0xFD, 0xFB, 0xF7, 0xEF, 0x3E, 0x19, 0xE6, 0x93, 0x29, 0xF9,
+       0x2D, 0xA6, 0x69, 0x95, 0xCE, 0x25, 0x4A, 0xAA, 0x32, 0x69, 0xD1, 0xF4, 0x64, 0x16, 0x12, 0x6A,
+       0x0C, 0xF7, 0x82, 0xEC, 0x61, 0xEC, 0x3A, 0x0D, 0x8A, 0x16, 0xF4, 0x27, 0x6E, 0x5B, 0xDE, 0xB9,
+       0xDD, 0x4F, 0x81, 0x50, 0x03, 0x1C, 0x6F, 0x7A, 0x52, 0xFA, 0xC7, 0x6B, 0x3D, 0x32, 0x23, 0xD5,
+       0xE8, 0xF0, 0x15, 0x6B, 0xB5, 0x55, 0xF1, 0x06, 0xFE, 0x85, 0xA5, 0x42, 0x10, 0x10, 0x5C, 0x1C,
+       0xDC, 0x98, 0x01, 0x95, 0x49, 0x96, 0x57, 0xFA, 0xE0, 0x32, 0x59, 0xFE, 0x1C, 0x05, 0xB0, 0x3F,
+       0x01, 0xFD, 0x86, 0xD6, 0xD3, 0xFE, 0x1B, 0x3A, 0x42, 0x85, 0x4F, 0xB8, 0xB3, 0x5E, 0x11, 0x29,
+       0xF9, 0xEB, 0x04, 0x8E, 0x5C, 0xDC, 0x70, 0x37, 0x18, 0xF9, 0x00, 0x1F, 0xB7, 0xC4, 0x16, 0x46,
+       0xC1, 0x39, 0xC9, 0xD6, 0x13, 0x66, 0xF9, 0xBB, 0xB5, 0xC1, 0x9D, 0xB5, 0x66, 0xBA, 0x52, 0x2A,
+       0xA1, 0xEC, 0x3F, 0x1E, 0x92, 0xDC, 0x0C, 0x91, 0x4D, 0xED, 0xE4, 0x51, 0xB0, 0xF8, 0x92, 0x55,
+       0xD1, 0x86, 0xD6, 0x4D, 0xCC, 0x9E, 0x05, 0x28, 0x97, 0xAC, 0x92, 0x4F, 0x46, 0xCE, 0xE9, 0x17,
+       0x50, 0x4F, 0x3B, 0x51, 0x09, 0xDC, 0x80, 0x8A, 0xFD, 0xDF, 0x56, 0x66, 0xB4, 0xAF, 0xDC, 0x40,
+       0xB8, 0x29, 0x8D, 0xE2, 0xF9, 0x92, 0x18, 0x1D, 0xBC, 0x9E, 0x25, 0xB1, 0x30, 0x94, 0xDB, 0x0B,
+       0x5B, 0x8E, 0x4B, 0x68, 0xC1, 0xE7, 0x2E, 0x94, 0x08, 0xD4, 0x9A, 0x2F, 0x39, 0xCE, 0x69, 0xAB,
+       0x50, 0x5E, 0x5D, 0x45, 0x8D, 0x14, 0xAE, 0x5D, 0xB7, 0x8A, 0xCA, 0xE1, 0xDF, 0xF6, 0x01, 0xE7,
+       0x2B, 0xB4, 0x18, 0xB8, 0xA3, 0xF0, 0xD5, 0x4F, 0xD4, 0xF4, 0x0C, 0x96, 0x5D, 0x3D, 0x9F, 0xEE,
+       0x73, 0x12, 0x48, 0xFB, 0xE9, 0xAC, 0x33, 0xDA, 0xD9, 0xA5, 0x1E, 0x2E, 0xEB, 0xDD, 0xEE, 0x0A,
+       0x8A, 0x55, 0xD6, 0x80, 0x63, 0x74, 0x6C, 0x44, 0x7B, 0xF6, 0x44, 0x4D, 0x17, 0x2B, 0x67, 0x37,
+       0xD2, 0xC7, 0x8A, 0xEB, 0xCB, 0x11, 0x80, 0xF3, 0xFB, 0xBA, 0x46, 0x14, 0xD9, 0x82, 0xE8, 0x1C,
+       0x95, 0x28, 0x6B, 0xFF, 0x26, 0xF7, 0x85, 0xD8, 0x82, 0x2A, 0x46, 0x4F, 0x0C, 0xA1, 0x9D, 0xB6,
+       0xAA, 0x61, 0xAD, 0x71, 0x1F, 0xF3, 0x4C, 0xDE, 0xE0, 0xE1, 0xAB, 0xCF, 0x97, 0xA9, 0xE0, 0x62,
+       0xDC, 0xBD, 0xDE, 0xAD, 0xF3, 0x37, 0x4F, 0x61, 0xAB, 0xB1, 0x85, 0xFD, 0xCE, 0x42, 0x67, 0xAF,
+       0x3C, 0x5B, 0xED, 0x71, 0x35, 0xA5, 0x4C, 0x3C, 0x2B, 0x98, 0x18, 0x69, 0xA7, 0x24, 0xBE, 0x25,
+       0xFB, 0x6C, 0x88, 0x6A, 0x6D, 0xA4, 0x72, 0x7E, 0xF8, 0x1E, 0x88, 0xA4, 0x20, 0x84, 0x0B, 0x2B,
+       0x9C, 0xB0, 0x48, 0x66, 0x82, 0x18, 0xEA, 0x98, 0x49, 0x51, 0x1A, 0xEE, 0x12, 0x17, 0x30, 0xC8,
+       0x5A, 0xB8, 0xE3, 0x90, 0x36, 0x35, 0x4D, 0xC1, 0xA1, 0x60, 0x22, 0xE5, 0xC3, 0x07, 0xB8, 0x36,
+       0x24, 0x3C, 0x2C, 0x76, 0x2A, 0x60, 0xDC, 0xF5, 0x42, 0xD4, 0x02, 0x3F, 0xCA, 0xCA, 0xA7, 0x86,
+       0xD3, 0x7A, 0x38, 0x51, 0x32, 0xA0, 0x0E, 0x7E, 0x22, 0xFC, 0xDB, 0xDD, 0xF8, 0x52, 0x36, 0xDE,
+       0xCD, 0x84, 0x30, 0x83, 0xC1, 0x84, 0xDF, 0xDE, 0xEF, 0xF9, 0x99, 0xF6, 0xBC, 0x38, 0x18, 0x15,
+       0x99, 0xAD, 0x46, 0x90, 0xD4, 0xFA, 0xEF, 0x8B, 0x63, 0x57, 0x37, 0x12, 0x6C, 0x39, 0x2D, 0xAA,
+       0xD5, 0x25, 0x44, 0x51, 0x30, 0xA5, 0xE2, 0x38, 0x21, 0x20, 0x39, 0x31, 0xC3, 0x8D, 0x8C, 0x7F,
+       0x54, 0xD1, 0x00, 0x2C, 0x19, 0x70, 0x97, 0xB1, 0xEF, 0x17, 0x1E, 0xED, 0x6E, 0x99, 0xF6, 0xE9,
+       0xCC, 0xED, 0x92, 0xC2, 0x45, 0xBB, 0xF5, 0x72, 0x87, 0x65, 0x21, 0xA3, 0x46, 0xBB, 0x43, 0x78,
+       0x11, 0x9F, 0xAD, 0x6E, 0xDD, 0xD1, 0xF8, 0x1E, 0x18, 0xA1, 0xB2, 0x80, 0xB8, 0x52, 0x52, 0xBE,
+       0xD9, 0xE8, 0xD8, 0xE9, 0xA4, 0x02, 0x24, 0x2F, 0x01, 0x8B, 0x4E, 0x71, 0xC7, 0x27, 0xE8, 0x2B,
+       0xD9, 0x71, 0xE5, 0xE4, 0x36, 0x4B, 0x17, 0xBC, 0x55, 0x02, 0xA2, 0x82, 0xCE, 0xD4, 0x33, 0x71,
+       0xA2, 0x1F, 0x9F, 0xA9, 0x7F, 0x73, 0x5F, 0x31, 0xC5, 0xBA, 0xB0, 0x31, 0x9A, 0xA5, 0x8F, 0x9E,
+       0x81, 0x69, 0xA6, 0x26, 0x32, 0x58, 0xB9, 0x6A, 0x8D, 0xF1, 0xCE, 0xC3, 0x97, 0xE2, 0xEC, 0x0A,
+       0x27, 0x21, 0x9C, 0xC6, 0xCD, 0xC2, 0x62, 0xC0, 0x78, 0xB1, 0xDD, 0xCC, 0xD1, 0x19, 0x53, 0x05,
+       0x5B, 0x96, 0x62, 0xBB, 0xF8, 0x55, 0x38, 0x71, 0x6D, 0x34, 0x0A, 0x4C, 0x35, 0xA6, 0xBE, 0x91,
+       0xEE, 0xFF, 0x4F, 0x81, 0x11, 0xEE, 0x61, 0xA8, 0xDD, 0x0A, 0x8A, 0x31, 0xEC, 0xF5, 0x4C, 0x70,
+       0x01, 0x02, 0x01, 0x10, 0x60, 0xF8, 0xB4, 0x2F, 0x74, 0x48, 0xF8, 0xF6, 0x34, 0xE3, 0xC8, 0xEB,
+       0x34, 0x5E, 0x4B, 0x44, 0x03, 0x68, 0xE6, 0x6D, 0x56, 0x5D, 0x70, 0x94, 0x57, 0x05, 0x62, 0x43,
+       0x22, 0x5A, 0xD5, 0x5C, 0xC6, 0x04, 0xAD, 0xCF, 0x2A, 0x2D, 0x56, 0x9D, 0x86, 0x38, 0x57, 0xA5,
+       0x30, 0xDD, 0x4A, 0x41, 0x2B, 0x1A, 0xB2, 0x3D, 0x4C, 0x4A, 0xF3, 0x5C, 0xD0, 0x5C, 0xF2, 0xF7,
+       0x1E, 0xE9, 0x18, 0x63, 0x73, 0xF7, 0x69, 0xE8, 0xDD, 0x80, 0xF5, 0x3C, 0x3D, 0xC6, 0x24, 0xCA,
+       0xC9, 0x7E, 0x80, 0xBB, 0xDF, 0x17, 0x38, 0x61, 0x37, 0xE2, 0x93, 0xDC, 0x6F, 0x78, 0x7A, 0x63,
+       0x0C, 0x93, 0xDC, 0x21, 0xE1, 0xE9, 0x56, 0xA3, 0xE4, 0x81, 0x82, 0x81, 0x69, 0x86, 0x8E, 0xF2,
+       0x37, 0xD3, 0xC3, 0x1D, 0x5F, 0x12, 0x46, 0xAC, 0x9B, 0x76, 0xDD, 0xBF, 0x16, 0xA1, 0xD8, 0x0D,
+       0xE4, 0x45, 0x13, 0x87, 0xAA, 0xAF, 0x5F, 0x88, 0xF6, 0xAE, 0x2D, 0xC4, 0x46, 0x2B, 0xE3, 0x91,
+       0x28, 0x2E, 0x17, 0xAE, 0xB8, 0x3C, 0xB0, 0xCA, 0xA0, 0x4D, 0x85, 0x81, 0xB6, 0x2D, 0x81, 0x04,
+       0x8D, 0x13, 0xA9, 0xE4, 0xF1, 0x56, 0xDE, 0x86, 0x24, 0x52, 0x6B, 0x23, 0xD6, 0xC1, 0xD6, 0xA5,
+       0xD5, 0x13, 0x42, 0xDF, 0x14, 0x3D, 0x20, 0xEF, 0x18, 0x57, 0xAC, 0xCF, 0x88, 0x28, 0x3F, 0xE2,
+       0x40, 0x45, 0xA2, 0xAC, 0x05, 0xCC, 0x37, 0x6D, 0x09, 0x54, 0xA6, 0x75, 0x67, 0x99, 0xBA, 0xFF,
+       0x0E, 0x47, 0xB8, 0xC1, 0x3D, 0x4E, 0xFE, 0x0F, 0x4F, 0xEB, 0x48, 0xD1, 0x07, 0x0E, 0xD7, 0xA6,
+       0x8F, 0xD1, 0x74, 0x67, 0xA4, 0x35, 0xC8, 0x83, 0x91, 0x5A, 0x47, 0xA7, 0x06, 0xF8, 0xB8, 0x3D,
+       0x48, 0x19, 0xF5, 0x32, 0x0E, 0x22, 0xA5, 0xB4, 0x31, 0x20, 0x79, 0x30, 0x19, 0x17, 0x75, 0x50,
+       0x7B, 0x3B, 0x12, 0x9C, 0xB1, 0xC5, 0xE8, 0xBC, 0x38, 0xCF, 0x5D, 0x65, 0x26, 0x1C, 0x00, 0xE7,
+       0xA1, 0xED, 0x74, 0x6D, 0x08, 0x8F, 0xF6, 0xC5, 0x9E, 0x29, 0x7D, 0xF5, 0x19, 0xC2, 0x48, 0x1C,
+       0xE8, 0x2E, 0x6E, 0xC2, 0x2B, 0xE1, 0x98, 0x88, 0xB6, 0x95, 0xF4, 0xA5, 0x3E, 0xFD, 0x1A, 0x97,
+       0xFB, 0xAA, 0xB2, 0x7D, 0x3F, 0x16, 0x07, 0x00, 0x44, 0xD1, 0x8D, 0x67, 0x89, 0x4D, 0x5B, 0x1E,
+       0x51, 0xFF, 0x1B, 0x46, 0x31, 0x05, 0xFC, 0x73, 0x39, 0x0B, 0xB1, 0x39, 0x70, 0x7E, 0x1A, 0x80,
+       0x99, 0x9C, 0x36, 0x00, 0x6D, 0xDD, 0xDE, 0x9A, 0xDB, 0x1C, 0x52, 0x32, 0xDA, 0x62, 0x79, 0xFF,
+       0x4A, 0x68, 0xDE, 0x16, 0xC2, 0x83, 0x4E, 0xBC, 0xDA, 0x0F, 0xAB, 0x98, 0xDB, 0xA1, 0x92, 0x96,
+       0x57, 0x66, 0x5B, 0x39, 0x96, 0x30, 0x1C, 0xE6, 0x56, 0xB7, 0x34, 0xE8, 0xA1, 0xBF, 0xD1, 0xB0,
+       0xDC, 0xCB, 0x5E, 0x09, 0x88, 0xF8, 0x34, 0x2D, 0xEF, 0xC3, 0x67, 0x3C, 0x4F, 0x69, 0x85, 0x97,
+       0xDE, 0x03, 0x36, 0xC8, 0xE7, 0x42, 0x8C, 0x03, 0xFA, 0x31, 0x84, 0x95, 0x25, 0xC2, 0x46, 0xA7,
+       0x3F, 0xC1, 0x90, 0xEF, 0x85, 0x48, 0x0C, 0xE4, 0xA8, 0x8A, 0x8F, 0x0E, 0x0A, 0x9E, 0x28, 0xCD,
+       0x71, 0x3D, 0x57, 0x5F, 0x46, 0xBF, 0x12, 0xEB, 0x18, 0x72, 0x4E, 0x4F, 0x62, 0xAE, 0xFE, 0x4C,
+       0xD6, 0xD7, 0x6C, 0x22, 0x00, 0xBE, 0x21, 0xBD, 0xFF, 0x49, 0xDE, 0x3F, 0x6B, 0xBF, 0x8F, 0x02,
+       0xF1, 0x63, 0xF0, 0xB4, 0x86, 0x30, 0x0A, 0xF6, 0x94, 0xD9, 0x11, 0xF8, 0xB1, 0x7A, 0x8C, 0x51,
+       0x8D, 0x67, 0x4B, 0xE7, 0xCC, 0xC2, 0x06, 0x04, 0xD5, 0x28, 0xD7, 0xCA, 0xF2, 0x0E, 0x87, 0xC0,
+       0x71, 0x47, 0x8D, 0x4F, 0xEC, 0x90, 0x23, 0x8C, 0x82, 0x95, 0xAE, 0xAF, 0x32, 0x05, 0x29, 0x32,
+       0x22, 0x59, 0x3C, 0x39, 0xC7, 0x50, 0x30, 0x0F, 0x6B, 0x0E, 0x44, 0x34, 0xD9, 0xB2, 0xF3, 0xE3,
+       0x53, 0x10, 0x32, 0x0B, 0x6E, 0xF5, 0x58, 0xE7, 0x2E, 0x1A, 0xD5, 0xDB, 0x14, 0x92, 0xAC, 0xF9,
+       0x20, 0xC5, 0xE5, 0x91, 0xC5, 0xF2, 0x92, 0x51, 0x19, 0x0D, 0x82, 0xCE, 0xAC, 0xA6, 0x39, 0x6B,
+       0x3C, 0xD0, 0x4D, 0x0A, 0x7E, 0xEB, 0x8C, 0x59, 0xCB, 0x9C, 0x1D, 0x47, 0x9D, 0x68, 0x7D, 0x44,
+       0xED, 0xD4, 0x07, 0x24, 0x3B, 0x37, 0x3E, 0x38, 0xA9, 0x35, 0xFE, 0x8D, 0x3F, 0xDD, 0xDF, 0x86,
+       0xB1, 0xEB, 0xDC, 0xAC, 0x10, 0xA7, 0xBF, 0x78, 0x0A, 0xA0, 0x20, 0x32, 0x0D, 0x45, 0xE0, 0xC2,
+       0xF7, 0x96, 0xB2, 0x8A, 0x4C, 0xB0, 0x93, 0x1C, 0x19, 0x91, 0xA7, 0xD6, 0x80, 0x45, 0xE5, 0x39,
+       0x54, 0xDB, 0x89, 0xBC, 0xD8, 0xD9, 0xBD, 0x16, 0xC9, 0x0F, 0x02, 0xAA, 0x50, 0x0D, 0xDD, 0x74,
+       0xE7, 0xEF, 0x99, 0x8F, 0x0E, 0x42, 0xAF, 0x86, 0xF0, 0x48, 0x7F, 0xB2, 0x54, 0xC6, 0xDD, 0x45,
+       0x40, 0x98, 0x15, 0xEA, 0xB0, 0xBA, 0x29, 0x68, 0x3E, 0x76, 0x43, 0x52, 0x18, 0x47, 0x86, 0xC6,
+       0xB0, 0x62, 0x2E, 0x8E, 0x42, 0xB0, 0x68, 0x5A, 0xE2, 0xD9, 0x8E, 0x95, 0x0A, 0xEE, 0x7A, 0xFA,
+       0x5B, 0x5B, 0x00, 0xE8, 0x5E, 0x97, 0xEC, 0x9B, 0xC3, 0xB1, 0xFD, 0x3A, 0xC3, 0x19, 0x64, 0xF2,
+       0x69, 0x28, 0x2C, 0x34, 0x48, 0x34, 0xF6, 0x0A, 0x9B, 0x7E, 0x5B, 0x3A, 0x49, 0x91, 0x25, 0xDE,
+       0x5A, 0x02, 0xBC, 0x34, 0x7F, 0x32, 0x65, 0x55, 0x6E, 0x76, 0x4D, 0x61, 0xD6, 0xE9, 0xA7, 0xBC,
+       0x80, 0x85, 0x97, 0xA5, 0xA9, 0x07, 0x5C, 0xB8, 0xAD, 0x5C, 0x2D, 0xD7, 0x1F, 0xAA, 0x72, 0x95,
+       0xB7, 0x4F, 0x88, 0xA5, 0xAD, 0x85, 0xAF, 0x32, 0x4E, 0x8E, 0xFF, 0x76, 0x37, 0x05, 0x96, 0xEA,
+       0xCB, 0x82, 0xFC, 0xAD, 0x18, 0xA0, 0x37, 0x87, 0x20, 0xFF, 0x42, 0xCD, 0x9F, 0x9A, 0x08, 0x56,
+       0x22, 0xE5, 0xF6, 0x2E, 0x9F, 0x4B, 0xF8, 0x29, 0x07, 0xD4, 0x16, 0xD6, 0x5B, 0xF0, 0xF8, 0xE7,
+       0x91, 0x1D, 0x2A, 0x51, 0xDC, 0x17, 0x73, 0xBA, 0x0B, 0xB8, 0xFD, 0x60, 0xF4, 0xB2, 0x53, 0x33,
+       0xD7, 0x17, 0xDC, 0x30, 0x45, 0x74, 0xBB, 0xCB, 0xED, 0x00, 0x0A, 0x6C, 0xBF, 0x18, 0xEE, 0x28,
+       0xB0, 0x16, 0x71, 0x8B, 0x8B, 0x6D, 0xEE, 0x0C, 0xC0, 0xF7, 0x3E, 0x4E, 0x92, 0xD8, 0x10, 0x89,
+       0x22, 0x5B, 0x07, 0xD0, 0xB6, 0xE2, 0x11, 0x4D, 0xBE, 0x27, 0xF6, 0x0A, 0x6C, 0xE3, 0x50, 0xA6,
+       0x40, 0xBA, 0xDC, 0x56, 0x50, 0x5B, 0x30, 0x47, 0x45, 0x1F, 0x6C, 0xF6, 0xC1, 0xB4, 0xC8, 0xB9,
+       0xC2, 0xFD, 0x95, 0x2D, 0x2A, 0x73, 0x28, 0xAB, 0x23, 0x37, 0xB2, 0xE1, 0xC2, 0x86, 0xED, 0x70,
+       0x8A, 0xE3, 0xF1, 0x4D, 0x99, 0x8C, 0x71, 0xFB, 0xD7, 0x3D, 0x4B, 0x54, 0x89, 0x7D, 0x00, 0xB0,
+       0x66, 0x82, 0xA2, 0xEC, 0x1D, 0x67, 0x65, 0x2C, 0xD2, 0x2B, 0xF9, 0xA7, 0x26, 0x04, 0x9E, 0x49,
+       0xC8, 0x1D, 0xF7, 0x34, 0x90, 0x0D, 0x4D, 0x9F, 0xCA, 0xB0, 0x0D, 0x0E, 0x3B, 0x2E, 0x11, 0x61,
+       0xE7, 0x5F, 0x73, 0x3E, 0x92, 0x6C, 0xB5, 0x86, 0xE3, 0xDC, 0x4F, 0x52, 0xFC, 0x8C, 0x6E, 0x97,
+       0xD0, 0x75, 0xB1, 0xE6, 0x91, 0xF5, 0xD3, 0x10, 0x61, 0x0F, 0x2D, 0x12, 0xAC, 0x9C, 0x6A, 0x31,
+       0xC9, 0x49, 0xA8, 0xC2, 0x2E, 0x52, 0xC3, 0x29, 0xA5, 0xC6, 0x64, 0x54, 0x52, 0x76, 0x16, 0xEE,
+       0x4E, 0xD0, 0x67, 0x0D, 0x32, 0xEE, 0x52, 0x1E, 0xF6, 0x46, 0x16, 0x89, 0x54, 0xD7, 0x8A, 0x0A,
+       0x3F, 0x98, 0x94, 0x9B, 0xAF, 0xFF, 0x06, 0xA7, 0x7F, 0x31, 0xF5, 0x55, 0x6F, 0xE9, 0x92, 0xF6,
+       0xA0, 0x10, 0x9B, 0xCD, 0xD2, 0x9B, 0xF7, 0xF4, 0x70, 0xAF, 0xC7, 0x56, 0xB0, 0xE1, 0x54, 0xC6,
+       0x62, 0x1E, 0x24, 0x42, 0x78, 0xC5, 0xF1, 0x67, 0x13, 0x81, 0x0B, 0x41, 0xA3, 0x10, 0x8B, 0x34,
+       0xD5, 0x60, 0xC2, 0xC4, 0xA2, 0x7A, 0xB8, 0x81, 0x04, 0x90, 0x32, 0x85, 0x9A, 0x01, 0xCA, 0x79,
+       0xC5, 0x79, 0xA3, 0x6F, 0xFD, 0x5D, 0xF5, 0xBB, 0x20, 0x86, 0xDB, 0xB2, 0x14, 0x32, 0x24, 0x7E,
+       0xEB, 0xEE, 0xF7, 0x05, 0x1B, 0xB4, 0x37, 0x18, 0x8D, 0xCF, 0x25, 0xC4, 0x0B, 0x68, 0xCB, 0xF9,
+       0xC7, 0xD8, 0x73, 0xFF, 0xF9, 0x7A, 0x99, 0x24, 0xC5, 0x1C, 0x0F, 0xEA, 0x84, 0xEC, 0x05, 0x1B,
+       0xAB, 0x71, 0x50, 0xDA, 0xF4, 0x20, 0x1E, 0x01, 0xCD, 0x21, 0x87, 0x50, 0x76, 0xEA, 0x13, 0xA0,
+       0x21, 0x6D, 0xA1, 0xD7, 0xE3, 0x09, 0x36, 0x73, 0xF0, 0xA3, 0xA1, 0x21, 0xAE, 0x73, 0x12, 0xB9,
+       0xC6, 0x11, 0xF4, 0x5B, 0xCB, 0x25, 0x64, 0x59, 0xF3, 0x6F, 0xE7, 0x60, 0x2D, 0xCC, 0x04, 0xBD,
+       0x92, 0xB0, 0xFA, 0x63, 0x3C, 0x66, 0xA8, 0xC4, 0x91, 0x96, 0x41, 0x19, 0x58, 0x8F, 0xF1, 0xC1,
+       0x01, 0x2F, 0x70, 0x93, 0x68, 0xC7, 0xFB, 0x23, 0xED, 0x70, 0x39, 0xE0, 0x7D, 0x36, 0xE7, 0xE5,
+       0x4B, 0x00, 0xD4, 0xC7, 0xE5, 0x81, 0xA4, 0xFC, 0x9F, 0x89, 0xD6, 0x9C, 0xC1, 0xA1, 0x24, 0x88,
+       0x59, 0x93, 0xAC, 0xBC, 0xF7, 0x54, 0xD1, 0x9F, 0xE5, 0x19, 0xF9, 0x8C, 0xE6, 0xE6, 0x4E, 0xD5,
+       0x3F, 0xF3, 0xD7, 0xEE, 0xF8, 0x84, 0x8D, 0x2D, 0x41, 0x0F, 0xBE, 0x8F, 0xC0, 0xB2, 0x6F, 0x89,
+       0xDE, 0xDA, 0x23, 0xE7, 0x1F, 0x35, 0x71, 0x52, 0x76, 0xAF, 0x3A, 0x8B, 0x49, 0xCD, 0xDD, 0x4C,
+       0x8B, 0xAD, 0xB5, 0x7A, 0xA4, 0x01, 0x8C, 0x79, 0x15, 0xA9, 0x0D, 0x0A, 0xE8, 0x02, 0x29, 0x81,
+       0x47, 0xF2, 0xF1, 0x6F, 0x26, 0xC2, 0xBC, 0xB4, 0x97, 0xEC, 0xCD, 0x3F, 0xF1, 0x2F, 0x3A, 0x35,
+       0xD1, 0xA5, 0x41, 0xC5, 0xC9, 0x6B, 0xAE, 0x29, 0x92, 0xAE, 0x84, 0xD6, 0xCF, 0x16, 0x80, 0xD3,
+       0xBC, 0x1B, 0xE0, 0x19, 0x4C, 0x15, 0x54, 0x4E, 0x13, 0x68, 0x07, 0xF2, 0xB2, 0xA7, 0x22, 0x64,
+       0xAB, 0x2B, 0xEC, 0x93, 0x51, 0xB3, 0xF8, 0x58, 0x76, 0x66, 0xD3, 0xE7, 0x40, 0xAF, 0x09, 0x6E,
+       0xE1, 0x14, 0xC7, 0xAE, 0xCB, 0x20, 0xA5, 0xF0, 0x44, 0x05, 0x4B, 0x3E, 0x4F, 0xA0, 0x6A, 0x19,
+       0x35, 0x89, 0xE0, 0x72, 0x64, 0x5C, 0x38, 0xC6, 0xA0, 0xA4, 0x36, 0x5F, 0xDA, 0xD0, 0xE5, 0xC1,
+       0xFA, 0xAF, 0xF7, 0x6D, 0x94, 0x80, 0xFA, 0x19, 0xEE, 0xFF, 0xC8, 0x2D, 0x3A, 0x21, 0x1A, 0xDD,
+       0x69, 0x3E, 0x36, 0xC4, 0x7A, 0x56, 0x8E, 0xE9, 0x7F, 0x23, 0x46, 0x66, 0xA1, 0xCF, 0xCE, 0x24,
+       0xB8, 0x6C, 0xCC, 0x3F, 0xF8, 0x47, 0x4A, 0x7C, 0x4D, 0x1A, 0x42, 0x4B, 0x75, 0x7F, 0x2E, 0x09,
+       0x57, 0x1D, 0x3D, 0xE5, 0x2D, 0x03, 0x9E, 0x47, 0xC6, 0xB8, 0x1C, 0x99, 0xDC, 0x2E, 0xC7, 0x41,
+       0x1B, 0x6B, 0xBB, 0x49, 0x75, 0xA0, 0xB5, 0x67, 0x83, 0x9A, 0xA3, 0xA7, 0xF4, 0x6F, 0x54, 0x5C,
+       0xD8, 0xE8, 0x1D, 0xAA, 0xE4, 0x52, 0x4F, 0x0A, 0x61, 0x48, 0x2C, 0x4A, 0x53, 0x64, 0x62, 0x96,
+       0x0A, 0xC0, 0x70, 0xAF, 0x67, 0xC2, 0x0A, 0x63, 0x10, 0x80, 0x68, 0x3D, 0xFC, 0xA2, 0xD0, 0x05,
+       0x8C, 0xEE, 0x10, 0xFA, 0xC6, 0x72, 0x99, 0x40, 0x86, 0xFD, 0x3D, 0x84, 0x20, 0xD2, 0x38, 0xBD,
+       0xAC, 0x6E, 0x65, 0x23, 0x23, 0x35, 0x5D, 0xC5, 0x72, 0x01, 0xDC, 0xF9, 0xB8, 0xC0, 0x91, 0x57,
+       0xE8, 0x50, 0xD1, 0x44, 0xE7, 0xD8, 0x4D, 0x1F, 0xDC, 0xDF, 0x10, 0x4D, 0xE7, 0xF4, 0x63, 0x4B,
+       0x80, 0xEC, 0x7D, 0xCE, 0xF3, 0xBC, 0xBC, 0x26, 0xFB, 0x82, 0xC2, 0x7F, 0xCC, 0x41, 0x23, 0x04,
+       0x0F, 0xC1, 0xFB, 0xF5, 0xBD, 0x49, 0xCD, 0xF5, 0xA5, 0x1E, 0x05, 0xDE, 0x65, 0x6B, 0x7D, 0xFE,
+       0x2E, 0x3A, 0x93, 0x6B, 0x52, 0x19, 0xE5, 0xF3, 0x87, 0x47, 0x44, 0xE1, 0xF4, 0xB3, 0xAB, 0x0D,
+       0xA1, 0xD6, 0x8B, 0xE9, 0x3C, 0x17, 0x88, 0x01, 0xBE, 0xC8, 0x24, 0x3D, 0x52, 0xD2, 0x1F, 0xF2,
+       0x50, 0xE2, 0x93, 0x23, 0xC1, 0xBF, 0x1A, 0x84, 0x98, 0x81, 0xF2, 0x31, 0x4E, 0xBD, 0xA8, 0x70,
+       0x8B, 0x3B, 0xB8, 0x6D, 0x2C, 0x57, 0x0A, 0xEE, 0x2C, 0xBE, 0xED, 0xC0, 0xF7, 0x0F, 0xEF, 0xBA,
+       0xB5, 0x7B, 0xD0, 0x2F, 0xE2, 0x46, 0x1A, 0x0A, 0xC4, 0x97, 0xB3, 0xB9, 0xF7, 0xEC, 0x76, 0xF8,
+       0x8C, 0x60, 0x4C, 0xA6, 0xA4, 0xCC, 0xE5, 0x42, 0x51, 0x9C, 0x3A, 0xBD, 0xCC, 0x22, 0xCF, 0x63,
+       0xAE, 0xF1, 0x57, 0xCA, 0x7A, 0x93, 0xAD, 0x6D, 0x8F, 0x64, 0x4A, 0x53, 0x95, 0x55, 0x62, 0x19,
+       0x12, 0x92, 0x3C, 0x92, 0x59, 0x47, 0xA2, 0x51, 0x79, 0xFC, 0x00, 0x54, 0x43, 0xE3, 0x71, 0x48,
+       0x4C, 0x4F, 0x62, 0x70, 0x80, 0xE5, 0x78, 0x36, 0x32, 0xE8, 0xD6, 0x0A, 0x49, 0xDB, 0x27, 0x93,
+       0xDC, 0xF7, 0x6B, 0x71, 0x4A, 0xCF, 0x45, 0x8C, 0x56, 0xE3, 0xB3, 0x8F, 0x46, 0x2F, 0xC8, 0xBD,
+       0xB6, 0xC0, 0xEB, 0x08, 0xF5, 0x0E, 0x26, 0x68, 0x36, 0x95, 0x4E, 0x24, 0x16, 0xA0, 0x2B, 0x99,
+       0x9A, 0x97, 0x59, 0x89, 0xE9, 0x9A, 0x3D, 0xEA, 0x2D, 0x42, 0xA2, 0x8A, 0xFF, 0xAF, 0xC4, 0x6D,
+       0xAB, 0xA5, 0xBF, 0x5D, 0xB9, 0x09, 0x17, 0x07, 0xCC, 0xE6, 0x6C, 0xD1, 0x8A, 0x33, 0xAF, 0x0F,
+       0x23, 0x49, 0x90, 0xD7, 0x90, 0xC1, 0x72, 0x3D, 0x19, 0x0A, 0x10, 0x7E, 0xBA, 0xF2, 0x30, 0x36,
+       0x14, 0xE1, 0xB1, 0x12, 0x7E, 0xB6, 0x3C, 0x64, 0x5F, 0x1A, 0x37, 0x12, 0xE4, 0x52, 0x28, 0x17,
+       0x5D, 0xF2, 0x38, 0x91, 0x4E, 0x1C, 0xAC, 0xD6, 0x76, 0xDA, 0xBA, 0xCA, 0xCA, 0xDC, 0x3B, 0xD2,
+       0x92, 0xFD, 0x57, 0xB1, 0x67, 0xF4, 0xE1, 0x21, 0x6F, 0xB2, 0x6D, 0x99, 0xF3, 0x41, 0x9B, 0xB3,
+       0xCC, 0x52, 0x3D, 0xDB, 0x54, 0xA7, 0xF3, 0x69, 0xCC, 0xD9, 0x39, 0x3F, 0x7F, 0x51, 0xB7, 0xAF,
+       0x24, 0x7B, 0x14, 0x79, 0xB3, 0x4F, 0xDD, 0xD4, 0x5B, 0x2D, 0x8B, 0xE2, 0xB4, 0x07, 0x96, 0x22,
+       0xE4, 0x78, 0x16, 0xC2, 0x45, 0x41, 0x58, 0x29, 0x16, 0x44, 0x87, 0x66, 0x62, 0x3B, 0xED, 0xF8,
+       0xC9, 0x39, 0xF8, 0xE6, 0x59, 0x3E, 0xA4, 0x82, 0x21, 0x79, 0x06, 0x79, 0xF1, 0xDD, 0x0B, 0xB1,
+       0x02, 0xA0, 0x22, 0xF1, 0xF8, 0x97, 0xB0, 0x86, 0x22, 0xAA, 0x4B, 0xF3, 0x82, 0x0D, 0x55, 0xEF,
+       0xD4, 0x5F, 0x5B, 0xBF, 0x0F, 0x4C, 0x5C, 0x46, 0x20, 0xC9, 0xD9, 0xDB, 0x15, 0x6F, 0x8A, 0x57,
+       0xD3, 0xED, 0x0D, 0x18, 0x5C, 0x90, 0x20, 0x35, 0x29, 0x96, 0xBD, 0x20, 0x54, 0xA9, 0x4F, 0x77,
+       0xBB, 0x77, 0xB7, 0x2A, 0xA0, 0xDF, 0x2B, 0xB3, 0x1A, 0x42, 0x91, 0x66, 0x8F, 0x3A, 0x44, 0x9A,
+       0xC4, 0x29, 0x68, 0x0D, 0x33, 0xE1, 0xA9, 0x53, 0xA9, 0x2E, 0x41, 0xA0, 0x94, 0xD0, 0x6B, 0x49,
+       0x60, 0x48, 0x82, 0x13, 0xC1, 0x8D, 0x7C, 0xBC, 0xF8, 0x87, 0xD7, 0xEE, 0x68, 0x8C, 0x2E, 0x54,
+       0x02, 0xB1, 0x0A, 0x15, 0x20, 0x71, 0x03, 0x94, 0x03, 0x00, 0x92, 0x7B, 0x43, 0xF7, 0xEC, 0x06,
+       0xA9, 0x7A, 0xB0, 0xCC, 0xF3, 0x2B, 0x25, 0xD7, 0xC3, 0x67, 0x8F, 0x12, 0xAE, 0xCF, 0x63, 0x0C,
+       0x42, 0x72, 0x24, 0x63, 0x10, 0x17, 0xC7, 0x4A, 0xFD, 0x14, 0x35, 0xBC, 0xF1, 0x3E, 0x3E, 0x1E,
+       0x3F, 0x6A, 0x45, 0xEA, 0x3D, 0x5A, 0xC4, 0xFD, 0x0A, 0xD9, 0x7C, 0x47, 0xE3, 0x7C, 0x2B, 0x6D,
+       0xFF, 0xBA, 0x68, 0x5E, 0xD5, 0x30, 0xF5, 0x38, 0x57, 0x58, 0xC7, 0x2F, 0x14, 0x6B, 0xDE, 0x7E,
+       0xF6, 0x6C, 0x9B, 0x5C, 0xFC, 0x44, 0xF0, 0xEC, 0x73, 0xB9, 0x15, 0x9E, 0x6E, 0xE9, 0xC4, 0xC8,
+       0xDA, 0xBA, 0x52, 0x72, 0x95, 0xD9, 0x47, 0x86, 0xE7, 0x79, 0x0E, 0x57, 0x8E, 0x11, 0xBC, 0xB5,
+       0x9A, 0xA0, 0x29, 0xD2, 0x4F, 0xEE, 0x32, 0xAD, 0xBB, 0x8E, 0xE4, 0x66, 0x66, 0x51, 0x67, 0xBE,
+       0x85, 0xFA, 0x0B, 0x4C, 0x77, 0x0B, 0x49, 0x24, 0xCA, 0x95, 0xF1, 0x6C, 0x60, 0x26, 0x0C, 0xD4,
+       0x1A, 0x56, 0x21, 0x39, 0xA4, 0x51, 0x7F, 0x91, 0x19, 0xB5, 0xE5, 0xF8, 0x92, 0x90, 0x5D, 0xB6,
+       0xCD, 0x8D, 0xCF, 0x33, 0x4A, 0xAB, 0x75, 0x2A, 0xA0, 0x1F, 0x3B, 0x66, 0x1D, 0x00, 0x01, 0x15,
+       0x7C, 0x71, 0xAC, 0x71, 0x88, 0xBA, 0xA8, 0xCE, 0x04, 0xB6, 0xE3, 0xE1, 0xC2, 0x57, 0x10, 0xEA,
+       0xCD, 0xAB, 0x67, 0x3F, 0x5E, 0xBB, 0x92, 0xAF, 0x5D, 0xD7, 0xDF, 0x6A, 0x1D, 0x5F, 0x44, 0x7B,
+       0x35, 0xB8, 0xBC, 0xC6, 0x19, 0x22, 0x61, 0xAE, 0x8A, 0x93, 0xFC, 0x4F, 0x66, 0x9E, 0x38, 0xDA,
+       0x09, 0xE8, 0xC8, 0xBA, 0x93, 0x88, 0x5E, 0x55, 0x68, 0xA7, 0x4E, 0x89, 0xF3, 0xE5, 0x1C, 0x23,
+       0x0D, 0x92, 0x58, 0xAE, 0x17, 0x64, 0x08, 0x85, 0x62, 0xE8, 0xFC, 0xE2, 0x56, 0x4C, 0x57, 0x48,
+       0x49, 0x1A, 0xA9, 0x1A, 0x7B, 0x34, 0xBF, 0x5F, 0x89, 0x81, 0x53, 0x8B, 0x14, 0x99, 0xBC, 0xA1,
+       0x2F, 0x6B, 0xE7, 0xE5, 0x1A, 0x3F, 0xA9, 0x53, 0x57, 0x96, 0x96, 0xC6, 0x78, 0xF7, 0x44, 0x0C,
+       0x4B, 0x54, 0x38, 0xB9, 0x71, 0xFB, 0x9F, 0x48, 0xD6, 0x3C, 0x6D, 0xBD, 0xE6, 0x2A, 0x11, 0xA4,
+       0x49, 0x83, 0x8D, 0xE0, 0x14, 0xBD, 0x01, 0x69, 0xB7, 0xF0, 0x38, 0x4D, 0xE9, 0xBE, 0xC1, 0x26,
+       0xA6, 0x97, 0x39, 0x45, 0x0E, 0x9F, 0x81, 0x1A, 0xCD, 0x61, 0xF6, 0x77, 0xCA, 0xA1, 0x9B, 0x86,
+       0x74, 0x93, 0x4D, 0xC5, 0x34, 0xD5, 0x55, 0x35, 0xCC, 0xD4, 0x97, 0xEA, 0xF0, 0x65, 0xB4, 0x4B,
+       0x46, 0xFE, 0x58, 0xED, 0x97, 0x3F, 0xE4, 0xD4, 0xF4, 0xF4, 0x29, 0x22, 0x66, 0xD6, 0xCA, 0x28,
+       0xDC, 0xE0, 0x93, 0x9E, 0x31, 0x0D, 0xDC, 0x95, 0x0D, 0x5A, 0x77, 0x18, 0x0D, 0x2E, 0x60, 0xE1,
+       0x6F, 0xEE, 0x67, 0xC2, 0xFB, 0x50, 0x01, 0xC5, 0x1A, 0x1A, 0x6C, 0x50, 0x19, 0xF8, 0xCE, 0xE2,
+       0xA3, 0x9B, 0x9B, 0xFC, 0x7C, 0x88, 0xE2, 0x7A, 0x38, 0xF8, 0xB1, 0xC5, 0x12, 0x90, 0x5C, 0x1C,
+       0x21, 0xEC, 0x41, 0x57, 0xDB, 0x8A, 0x4D, 0x8A, 0x5B, 0xCA, 0x2C, 0x23, 0x7B, 0x6B, 0xBF, 0x2B,
+       0xBF, 0x3D, 0x57, 0x5A, 0x63, 0x1F, 0x9C, 0xFC, 0x4C, 0x51, 0xB2, 0x20, 0x52, 0xB6, 0x0F, 0xC9,
+       0xAE, 0x01, 0xF0, 0x2F, 0xE1, 0xD6, 0x3F, 0x67, 0x7E, 0x1A, 0x05, 0x04, 0xAE, 0xBC, 0x13, 0xB2,
+       0xFA, 0x36, 0x42, 0x69, 0xAF, 0xB8, 0x7F, 0xBF, 0xEE, 0x14, 0xA8, 0x41, 0x7C, 0x60, 0xEB, 0xA9,
+       0xA9, 0x30, 0x9C, 0x17, 0x68, 0xFA, 0x3B, 0x54, 0x71, 0xDC, 0x4F, 0xE9, 0x5E, 0xEF, 0xC8, 0x02,
+       0xDB, 0x00, 0x7F, 0x6F, 0x49, 0x63, 0x16, 0x3F, 0x3A, 0xE3, 0xD5, 0x36, 0x09, 0x31, 0x70, 0xA2,
+       0x2F, 0x40, 0x26, 0x90, 0x94, 0x21, 0x62, 0xAA, 0x6A, 0xDE, 0x15, 0x92, 0x5A, 0x28, 0xEC, 0x7C,
+       0x76, 0xF3, 0x76, 0x9F, 0x6A, 0xDE, 0x6C, 0x5D, 0xD1, 0x66, 0x74, 0xE3, 0xA5, 0xCA, 0x87, 0xAD,
+       0x9B, 0x5F, 0x41, 0xB9, 0x5F, 0xDB, 0xE3, 0x56, 0x93, 0x9C, 0xB6, 0x5B, 0xBF, 0x07, 0x48, 0xFA,
+       0xE2, 0xC1, 0x84, 0xB9, 0x99, 0x46, 0xE0, 0x43, 0x1B, 0x23, 0x14, 0xA6, 0x6F, 0x88, 0xEC, 0xA4,
+       0x9C, 0xBA, 0x5D, 0x45, 0xE9, 0x11, 0x5B, 0x51, 0xFB, 0xB1, 0x1E, 0xE5, 0x46, 0x3E, 0x20, 0x67,
+       0x72, 0xF0, 0x1E, 0x61, 0xEB, 0x24, 0x01, 0x20, 0xFE, 0x4B, 0xA2, 0x47, 0xF3, 0x14, 0x4F, 0x8D,
+       0x4C, 0x67, 0x7D, 0x12, 0xD7, 0x5F, 0xBB, 0xED, 0x14, 0x66, 0xC7, 0x3C, 0x97, 0x80, 0x77, 0xA9,
+       0x0D, 0xC3, 0x71, 0x33, 0xEE, 0x6C, 0x71, 0x80, 0xA4, 0x87, 0xA5, 0x81, 0xB3, 0x6C, 0x57, 0x7D,
+       0x63, 0xAA, 0xD1, 0x9F, 0x33, 0x51, 0x29, 0x75, 0x06, 0xF6, 0xFE, 0xB9, 0x06, 0x97, 0xCF, 0x44,
+       0xD7, 0x33, 0x21, 0x44, 0xF3, 0xA8, 0x81, 0x9F, 0x7E, 0x8D, 0xF0, 0x36, 0xCE, 0x40, 0xDA, 0x76,
+       0x99, 0xEF, 0xFB, 0xED, 0xEF, 0xF3, 0x59, 0x6A, 0xA7, 0x67, 0xFA, 0xE1, 0xF5, 0x6C, 0x25, 0x63,
+       0x95, 0xD0, 0x07, 0x92, 0x62, 0x1F, 0x09, 0x56, 0x87, 0x8A, 0x21, 0xDD, 0x13, 0x72, 0x36, 0x3F,
+       0xC9, 0x45, 0x29, 0x77, 0x44, 0x49, 0x7F, 0x3F, 0x8F, 0x95, 0x55, 0x98, 0x9D, 0x03, 0x8F, 0x7B,
+       0x91, 0x66, 0x0E, 0x9E, 0x17, 0x25, 0x94, 0x1C, 0x56, 0xBF, 0x78, 0x5D, 0x22, 0xC2, 0x5A, 0x8F,
+       0x0D, 0x5E, 0x5B, 0x05, 0xE1, 0xCF, 0x07, 0x44, 0x09, 0x00, 0x8A, 0xBE, 0xEF, 0x1F, 0xCE, 0x3E,
+       0x9A, 0x1E, 0xA5, 0xD1, 0x0C, 0x24, 0x52, 0xDE, 0x7E, 0x71, 0x4F, 0x1E, 0x93, 0x25, 0xAE, 0x03,
+       0x59, 0x74, 0x6C, 0xD7, 0x68, 0xB4, 0x9F, 0x67, 0x28, 0x40, 0x54, 0xA3, 0x5E, 0xDE, 0x27, 0xFD,
+       0x97, 0xED, 0x48, 0xBB, 0x73, 0x93, 0x0B, 0x6B, 0x1A, 0x4E, 0x51, 0x3F, 0x5F, 0x59, 0x42, 0xD6,
+       0x6C, 0xDF, 0x03, 0xE7, 0x90, 0x70, 0x9B, 0x77, 0xE4, 0xB1, 0xEF, 0xA8, 0x5A, 0x10, 0x92, 0xE5,
+       0x92, 0x6A, 0x03, 0x6D, 0x38, 0x19, 0xA4, 0xD7, 0xED, 0xA6, 0x92, 0x90, 0xB0, 0x00, 0x5A, 0x63,
+       0xFB, 0x7F, 0x5A, 0xA2, 0x27, 0xC6, 0xE9, 0xA8, 0x51, 0x18, 0xFA, 0x70, 0x73, 0x32, 0xA6, 0xAE,
+       0x3F, 0xE5, 0x5C, 0x36, 0xB1, 0xEA, 0xA6, 0xFC, 0xDD, 0xBA, 0x0F, 0x52, 0xD2, 0x56, 0xC4, 0x49,
+       0xD0, 0xCB, 0xCE, 0x27, 0x87, 0xE9, 0x0B, 0x4C, 0x21, 0x0E, 0x88, 0x18, 0x9A, 0x4C, 0x65, 0x4D,
+       0x12, 0x23, 0x45, 0xD6, 0x2D, 0xB4, 0x87, 0x20, 0x47, 0xE2, 0xFD, 0x9B, 0x42, 0xFB, 0x70, 0x17,
+       0x3E, 0x30, 0xB1, 0x47, 0xD6, 0x85, 0x67, 0xAE, 0xF1, 0x33, 0xF2, 0x8F, 0xD0, 0xB0, 0xA3, 0xAC,
+       0xB1, 0xFA, 0x57, 0xFE, 0x60, 0x3C, 0x40, 0xFC, 0x0A, 0x3B, 0xEE, 0x2E, 0xA8, 0xDB, 0xC0, 0x88,
+       0x0F, 0x1C, 0xEF, 0xF9, 0x2A, 0x3A, 0x4A, 0x4C, 0x08, 0x6F, 0x29, 0x15, 0x11, 0x74, 0xB6, 0x9C,
+       0xF5, 0xD4, 0x79, 0x38, 0x59, 0xE6, 0xFA, 0x4A, 0x68, 0xED, 0x22, 0xB2, 0xFC, 0x92, 0x87, 0xC6,
+       0x81, 0xA8, 0x5B, 0x5E, 0x33, 0x5F, 0xD7, 0x70, 0xC1, 0xF7, 0xA7, 0xFF, 0x7D, 0xBA, 0xFF, 0x2E,
+       0x60, 0x55, 0x76, 0xA9, 0x0B, 0xBB, 0x9D, 0xFC, 0xF7, 0x42, 0x97, 0xAC, 0xB6, 0x74, 0x1A, 0xF2,
+       0xBE, 0x27, 0xE2, 0xD4, 0x5D, 0x29, 0x59, 0xFB, 0xEE, 0xAB, 0xFB, 0x49, 0xC5, 0xDE, 0x1C, 0x25,
+       0x98, 0x32, 0x16, 0x90, 0x0A, 0x6C, 0xCF, 0x5C, 0xD7, 0x08, 0x82, 0x1C, 0x71, 0x33, 0x60, 0x8F,
+       0x30, 0xF8, 0x98, 0xF2, 0x9A, 0x12, 0x87, 0xB7, 0xA5, 0x8D, 0xC5, 0x83, 0xAC, 0x20, 0x50, 0x2D,
+       0xC3, 0x11, 0x6D, 0x63, 0x06, 0xDF, 0xB0, 0xA1, 0xE2, 0x09, 0x41, 0x92, 0x93, 0x0C, 0x92, 0xBB,
+       0xD7, 0xAA, 0x26, 0x3D, 0x89, 0x71, 0x58, 0x72, 0x47, 0x77, 0x2C, 0x4C, 0x08, 0xD5, 0x05, 0x1C,
+       0x6D, 0x6D, 0xBE, 0x76, 0x5C, 0x90, 0x9A, 0x8E, 0xD4, 0xC5, 0xC9, 0xCE, 0x59, 0x0A, 0x64, 0x51,
+       0xA2, 0x45, 0xB5, 0x0B, 0xEA, 0x63, 0xD6, 0x6D, 0xB5, 0xBD, 0x44, 0xFA, 0x68, 0x16, 0xB0, 0x99,
+       0x59, 0xE4, 0x29, 0xB3, 0x53, 0x57, 0x1D, 0xC5, 0x4D, 0x77, 0x3C, 0xFD, 0x3D, 0xFA, 0xC9, 0x1A,
+       0x8E, 0x69, 0x90, 0xE7, 0xE6, 0xB9, 0xCE, 0x94, 0xF1, 0x5C, 0xBD, 0xA8, 0x62, 0xFF, 0x2D, 0x71,
+       0x67, 0x1C, 0x24, 0x58, 0xAD, 0xC5, 0xAE, 0xA1, 0xD2, 0x80, 0xEC, 0xF9, 0x44, 0x4B, 0xF1, 0x12,
+       0x02, 0xE7, 0x59, 0x0F, 0x26, 0x20, 0x51, 0x96, 0xDC, 0x39, 0xF1, 0x5D, 0x2B, 0xC5, 0xB2, 0x3F,
+       0xD5, 0x4B, 0x8B, 0x51, 0x70, 0x07, 0xFE, 0xFD, 0xD8, 0x15, 0x4F, 0xE8, 0xA0, 0x29, 0x3A, 0xB7,
+       0xB1, 0xBA, 0xE8, 0xF8, 0xFD, 0x98, 0x40, 0x38, 0x3B, 0x23, 0x5E, 0xDB, 0xA5, 0x3A, 0x58, 0x8A,
+       0x32, 0x9A, 0xA8, 0xF1, 0xE2, 0x50, 0x7B, 0x54, 0x49, 0xAC, 0x9C, 0x60, 0x24, 0xC8, 0x7E, 0xA0,
+       0x79, 0x8F, 0x02, 0x81, 0xAD, 0xDB, 0x5F, 0x71, 0xEA, 0xB3, 0x53, 0xCD, 0xDB, 0x0E, 0x69, 0x68,
+       0x74, 0x49, 0x4E, 0x00, 0x9F, 0x02, 0xCE, 0x03, 0x6F, 0xCA, 0x4A, 0x31, 0xFA, 0xAE, 0xB7, 0xAF,
+       0xB4, 0x5E, 0x4D, 0x35, 0x91, 0x20, 0xA0, 0xAD, 0x93, 0xE1, 0x9C, 0x88, 0x7E, 0x05, 0xAB, 0xFF,
+       0x91, 0x16, 0x87, 0xB9, 0x0E, 0x6D, 0xC5, 0x85, 0x7C, 0xF8, 0xE1, 0x05, 0xF9, 0x35, 0x83, 0x9F,
+       0xFA, 0x6D, 0xB1, 0x3D, 0x4E, 0x1F, 0xEF, 0xBD, 0xA6, 0x06, 0x14, 0xE4, 0xD5, 0xBD, 0x82, 0x61,
+       0x13, 0x00, 0x94, 0x5E, 0x74, 0xFD, 0x44, 0xD9, 0x5F, 0xA7, 0xC9, 0x2A, 0xE1, 0xAF, 0x78, 0x44,
+       0x67, 0x68, 0x15, 0x96, 0xDD, 0x46, 0x92, 0x18, 0xC5, 0x02, 0xC6, 0xEB, 0x8E, 0xC0, 0x4E, 0x62,
+       0xE8, 0x2C, 0xD8, 0xA2, 0xFB, 0x54, 0x65, 0x1E, 0xF0, 0x2E, 0x2C, 0x2D, 0x78, 0xA3, 0x43, 0x22,
+       0xD8, 0x30, 0xE9, 0x50, 0x23, 0x12, 0xDD, 0x50, 0x62, 0x0E, 0xF9, 0x58, 0x8C, 0xCB, 0xBA, 0x31,
+       0x1B, 0x47, 0xB5, 0x60, 0xF3, 0x57, 0x47, 0x26, 0xA5, 0xD2, 0x47, 0x76, 0x4E, 0x84, 0xC8, 0xB6,
+       0xA2, 0x08, 0x15, 0x11, 0x82, 0x8C, 0xA2, 0xE8, 0xBC, 0x98, 0x4D, 0x56, 0x87, 0x65, 0xB1, 0x31,
+       0x8A, 0x06, 0x16, 0xD3, 0xD4, 0x05, 0xC5, 0xF6, 0xEE, 0xA2, 0x90, 0xC8, 0x11, 0xA8, 0x5B, 0x72,
+       0x0F, 0xAE, 0x2B, 0x65, 0x66, 0x52, 0x12, 0x55, 0x2A, 0xB9, 0x99, 0x5B, 0x1C, 0xD4, 0x6D, 0x6A,
+       0x6E, 0x25, 0x57, 0x9B, 0x47, 0x41, 0x7F, 0x0E, 0xB3, 0x6B, 0xC0, 0x0B, 0x52, 0xE5, 0xED, 0xE9,
+       0x2B, 0x44, 0x35, 0x3D, 0xE5, 0xD1, 0x73, 0x12, 0x20, 0x2B, 0xCA, 0x62, 0x14, 0x99, 0xD6, 0x7D,
+       0x22, 0x4B, 0x63, 0xA9, 0xEB, 0x67, 0x2F, 0x89, 0xFA, 0x15, 0x1E, 0x43, 0xFA, 0x6C, 0xEA, 0x64,
+       0x45, 0x36, 0xAA, 0x80, 0xFE, 0x6D, 0xD5, 0xC1, 0x20, 0x31, 0x03, 0x0C, 0xFF, 0xAE, 0x13, 0x92,
+       0x94, 0x0F, 0xCE, 0x1C, 0x07, 0x90, 0x88, 0x70, 0x6D, 0xD2, 0xF8, 0xC5, 0x86, 0x7A, 0x31, 0x69,
+       0xF1, 0x90, 0x55, 0x48, 0x33, 0x57, 0x47, 0x21, 0x5E, 0x28, 0x1C, 0x3B, 0xE8, 0xE7, 0xDA, 0x34,
+       0x09, 0xA0, 0x71, 0xB6, 0x97, 0x78, 0x1E, 0x0E, 0x3B, 0xAA, 0x39, 0xC4, 0x49, 0x85, 0xEB, 0x12,
+       0xB8, 0xDE, 0xC9, 0xC1, 0x66, 0x60, 0x30, 0xE6, 0x85, 0xCD, 0x4F, 0x8C, 0xC2, 0x38, 0xB6, 0x19,
+       0x6D, 0x3D, 0x64, 0x58, 0xD0, 0x57, 0xAD, 0xF2, 0xC9, 0x65, 0x70, 0x9C, 0x09, 0x98, 0xDB, 0xFD,
+       0x29, 0xAC, 0xB2, 0x1E, 0x6B, 0xB9, 0x4E, 0x3A, 0xF1, 0x20, 0xBC, 0x04, 0x63, 0x3D, 0x2B, 0xAC,
+       0x53, 0x7B, 0x89, 0x01, 0x13, 0xB5, 0xEC, 0x42, 0xF7, 0x2C, 0x27, 0xDA, 0x2D, 0xC2, 0xA7, 0x07,
+       0x84, 0xF4, 0x3A, 0x06, 0x5E, 0xEE, 0x0A, 0x0A, 0x4F, 0xA5, 0xAA, 0x42, 0x04, 0xED, 0x28, 0x67,
+       0x9B, 0x04, 0x95, 0x00, 0xEB, 0x53, 0x3F, 0xB5, 0xD3, 0x56, 0xCF, 0x0C, 0xAE, 0x95, 0x21, 0x1C,
+       0xE4, 0x77, 0x8C, 0xF0, 0x59, 0x23, 0x3D, 0xE3, 0xE1, 0xA2, 0x8B, 0xEA, 0x0B, 0x5D, 0x8D, 0x64,
+       0xF7, 0x7A, 0x6B, 0x6D, 0xCD, 0xB8, 0xBA, 0x63, 0x5D, 0x13, 0x30, 0x8D, 0x56, 0xFF, 0x53, 0xAA,
+       0x96, 0x2F, 0x74, 0xA4, 0x36, 0x68, 0xF8, 0x3E, 0xC8, 0x79, 0x98, 0xA7, 0xF0, 0x4D, 0x33, 0xF8,
+       0xC7, 0x20, 0xED, 0x42, 0x4E, 0xDA, 0x90, 0x58, 0xE7, 0xDB, 0x5A, 0x67, 0xD2, 0x0F, 0x0F, 0xB4,
+       0xD5, 0x9F, 0x37, 0x36, 0xE6, 0xAB, 0x4E, 0x3D, 0xFA, 0x79, 0x4A, 0xB4, 0xE3, 0xD1, 0xBB, 0x2B,
+       0xD5, 0x84, 0x6B, 0x48, 0x4C, 0xBC, 0xB7, 0xF6, 0xDB, 0xF7, 0x2D, 0x51, 0x45, 0xE4, 0x66, 0x43,
+       0x60, 0xB7, 0x28, 0x3F, 0x51, 0x23, 0xB7, 0x14, 0x6D, 0xD5, 0xC0, 0x7E, 0x52, 0xB6, 0x8C, 0xE1,
+       0xD8, 0xAF, 0x6F, 0xE9, 0xF3, 0xF7, 0xBC, 0x95, 0x18, 0x5A, 0x24, 0x7C, 0xE5, 0x6F, 0x99, 0x63,
+       0x7B, 0xD7, 0xE7, 0x94, 0x42, 0xEE, 0xD8, 0x7D, 0xED, 0xEF, 0x6C, 0xE5, 0x4D, 0x35, 0xC7, 0xFF,
+       0x20, 0xE8, 0x89, 0x71, 0xC3, 0xC9, 0xA6, 0x65, 0x7F, 0x36, 0x90, 0xA5, 0xE8, 0x37, 0x85, 0xA4,
+       0x4A, 0x0E, 0x14, 0x30, 0x1C, 0x7B, 0x96, 0x38, 0x43, 0xB3, 0xE0, 0x2F, 0xEB, 0x47, 0x58, 0xC0,
+       0x57, 0x21, 0x24, 0xCE, 0x7A, 0x32, 0x58, 0xA6, 0xE7, 0xC8, 0xCF, 0xE0, 0x01, 0xB6, 0x6F, 0xDB,
+       0x51, 0x47, 0xB8, 0x6E, 0x8C, 0x59, 0xB6, 0xFB, 0x2B, 0x61, 0xA9, 0x4B, 0xA0, 0x61, 0xF5, 0x7C,
+       0x7E, 0xA1, 0x3A, 0x0A, 0xC6, 0x39, 0xF3, 0x39, 0xF1, 0xB4, 0x30, 0x5F, 0xCB, 0x72, 0xA9, 0x38,
+       0xF2, 0xE2, 0x6B, 0xEE, 0xFD, 0xDB, 0x0A, 0x00, 0x01, 0xA6, 0x1F, 0x76, 0x6C, 0x80, 0x8B, 0xEF,
+       0x11, 0xB5, 0xB5, 0xE9, 0x8E, 0x08, 0xDA, 0x25, 0x52, 0xDF, 0x31, 0xB1, 0x2C, 0x1B, 0x87, 0x04,
+       0x69, 0x90, 0x3A, 0x75, 0x1D, 0xDD, 0x09, 0x09, 0x7D, 0x0A, 0x55, 0x16, 0x0E, 0xA4, 0x10, 0x84,
+       0xFC, 0x3D, 0xA8, 0x58, 0x44, 0x09, 0x62, 0xA1, 0x96, 0x92, 0xDC, 0x77, 0xC7, 0x87, 0x50, 0x18,
+       0x99, 0x3C, 0x70, 0x07, 0xA8, 0xD1, 0x8E, 0x65, 0x41, 0xD3, 0x37, 0x10, 0x91, 0x73, 0xD0, 0x43,
+       0x56, 0xAF, 0xB4, 0x29, 0x16, 0x3F, 0xF9, 0x64, 0x41, 0x0C, 0x98, 0xF8, 0x01, 0x89, 0xC5, 0xC3,
+       0x66, 0x38, 0xA0, 0x42, 0x7D, 0x12, 0x56, 0x01, 0x6B, 0x5F, 0x37, 0x37, 0xE4, 0xE0, 0x48, 0xB5,
+       0xB1, 0x79, 0x23, 0xBC, 0x7C, 0xC6, 0x42, 0x90, 0x25, 0xDD, 0xF7, 0x55, 0xA6, 0xAC, 0x7F, 0xEF,
+       0x6A, 0x0D, 0x09, 0x30, 0x23, 0x4C, 0xC5, 0x39, 0xED, 0xC3, 0x81, 0xA1, 0x68, 0xB6, 0xEA, 0x98,
+       0xE2, 0xA2, 0x72, 0x16, 0x71, 0xCD, 0xC5, 0x20, 0xC6, 0xDC, 0x18, 0xFB, 0x23, 0x35, 0x04, 0xDA,
+       0x96, 0xE8, 0x57, 0xCE, 0xA9, 0xD6, 0xB0, 0xFD, 0x9C, 0x58, 0xCE, 0x4B, 0xE2, 0x82, 0x88, 0x82,
+       0xAD, 0xDD, 0xAB, 0x29, 0x88, 0x52, 0x0E, 0xC3, 0xFC, 0xCB, 0x83, 0x93, 0x78, 0x23, 0xCF, 0x97,
+       0x5F, 0x49, 0x12, 0x92, 0x7B, 0x6B, 0xEA, 0x44, 0x8E, 0x70, 0x81, 0xB6, 0x5A, 0x39, 0x4C, 0xAE,
+       0x81, 0x69, 0x45, 0x4C, 0x6D, 0xAE, 0x4C, 0x69, 0x3B, 0x6B, 0x18, 0x8C, 0x2A, 0x66, 0x88, 0xFE,
+       0xB2, 0x9A, 0xF7, 0x84, 0x68, 0x0C, 0xCC, 0x7C, 0x3D, 0x4A, 0x8F, 0x74, 0x84, 0x36, 0x8E, 0xDC,
+       0xF3, 0xBC, 0x11, 0x59, 0x3B, 0x56, 0xCF, 0x49, 0x11, 0xEC, 0x70, 0x59, 0x7D, 0xFC, 0x96, 0x0F,
+       0x67, 0xFD, 0x90, 0x95, 0x40, 0x96, 0x7F, 0x29, 0x7C, 0xD2, 0x68, 0xC5, 0x33, 0x20, 0xA2, 0xF4,
+       0x6C, 0x12, 0x2D, 0xC9, 0xD5, 0xAE, 0x10, 0x9A, 0x73, 0x0A, 0xDD, 0x7F, 0x59, 0x60, 0x37, 0x36,
+       0x26, 0x0E, 0x80, 0xF8, 0x4C, 0xCD, 0xF2, 0xEB, 0xAA, 0x44, 0x91, 0x22, 0xAF, 0xBD, 0x8E, 0x8B,
+       0xE4, 0x09, 0xD0, 0x88, 0x18, 0x69, 0x62, 0xAD, 0x29, 0xAB, 0x93, 0x9C, 0x9B, 0xD7, 0x84, 0x67,
+       0x03, 0x78, 0x00, 0x9C, 0x48, 0x25, 0xB5, 0x1A, 0x91, 0x47, 0x77, 0xFE, 0x6D, 0x1D, 0xAB, 0x3A,
+       0x7D, 0xA4, 0x8C, 0x4D, 0xA1, 0xF4, 0x52, 0xAA, 0xB1, 0x70, 0x7A, 0x91, 0xA0, 0x22, 0xCC, 0x93,
+       0x25, 0x0C, 0xC8, 0x8D, 0xD0, 0x89, 0x50, 0x6F, 0x6A, 0x86, 0x60, 0x6E, 0xD0, 0xFC, 0x6E, 0x57,
+       0xB2, 0x71, 0xA1, 0x3B, 0x70, 0x70, 0x4B, 0x4C, 0xE9, 0xC0, 0x50, 0xC8, 0x58, 0x63, 0xAE, 0xEA,
+       0xEF, 0x00, 0xBD, 0xA7, 0x42, 0x5C, 0xB9, 0x4A, 0xDD, 0x3C, 0x9B, 0x0C, 0xCF, 0x1B, 0xC3, 0x3E,
+       0x8F, 0xAD, 0xE8, 0x0F, 0x75, 0x4E, 0x2C, 0xAE, 0x1F, 0x3B, 0xB6, 0x3E, 0xDD, 0x59, 0xB6, 0x80,
+       0xCE, 0x95, 0x86, 0x5A, 0xA8, 0x08, 0x95, 0x69, 0x23, 0xA8, 0x1C, 0x73, 0xBC, 0xFE, 0x2A, 0x38,
+       0xA0, 0xC2, 0x81, 0x88, 0xC3, 0x09, 0xB2, 0xA4, 0xBD, 0x16, 0xD8, 0x81, 0x43, 0x5E, 0x92, 0x7D,
+       0x08, 0xBF, 0x96, 0xD3, 0xDB, 0xDC, 0xB2, 0x5D, 0x3A, 0xA5, 0xCD, 0x47, 0x7E, 0xFA, 0xDA, 0x88,
+       0xED, 0xB8, 0x0E, 0x0E, 0x76, 0x19, 0x42, 0xA6, 0x55, 0x20, 0xF1, 0x1A, 0x17, 0x5A, 0x41, 0x1A,
+       0x38, 0x03, 0x70, 0x85, 0xBF, 0x0F, 0x71, 0xAE, 0x1B, 0x2F, 0xCD, 0xDB, 0x0C, 0xAE, 0xA8, 0x30,
+       0xB5, 0x9B, 0xA1, 0xEE, 0x45, 0xD2, 0x08, 0x3D, 0x3B, 0x75, 0x34, 0xFD, 0x81, 0xA5, 0x34, 0x87,
+       0x27, 0x43, 0x95, 0x08, 0x7B, 0xE5, 0xFF, 0x73, 0xC7, 0x0A, 0x1A, 0x7B, 0x09, 0x9C, 0x4A, 0xDF,
+       0x21, 0xBE, 0x38, 0xD3, 0x74, 0x80, 0x55, 0xA6, 0x28, 0xA2, 0x00, 0x5C, 0x04, 0x8E, 0xEE, 0x2F,
+       0x16, 0x30, 0xBD, 0xD6, 0xB0, 0x57, 0x68, 0xD3, 0x4B, 0x2D, 0x24, 0x60, 0x67, 0x32, 0x13, 0x10,
+       0x5D, 0xCF, 0x09, 0x3F, 0x15, 0x48, 0xA9, 0x99, 0x9B, 0x6C, 0x02, 0xD9, 0xA6, 0x4B, 0xFA, 0xFD,
+       0xCD, 0x44, 0x0A, 0x60, 0x70, 0xAE, 0xEE, 0x07, 0xC4, 0xB4, 0xA7, 0xD0, 0x0C, 0x29, 0x15, 0x80,
+       0x87, 0x62, 0x02, 0xF4, 0x79, 0x15, 0xF8, 0xA1, 0xF9, 0x78, 0x98, 0x11, 0x72, 0x09, 0xF6, 0x5A,
+       0x0D, 0xA4, 0x38, 0x90, 0x87, 0x17, 0xC6, 0xD8, 0x96, 0xA0, 0x1E, 0x20, 0x96, 0x58, 0xAA, 0x1E,
+       0x7E, 0xF9, 0x6C, 0x75, 0x95, 0x32, 0xD1, 0x82, 0x67, 0x1E, 0x51, 0xD2, 0x52, 0xA9, 0x2E, 0x35,
+       0xD8, 0x59, 0x1E, 0x4A, 0xBA, 0x71, 0x21, 0xA3, 0xA9, 0x95, 0x3C, 0xE8, 0x71, 0x4E, 0xA4, 0x84,
+       0x1B, 0x27, 0xD4, 0xFB, 0xFF, 0xFB, 0x16, 0x5C, 0xB4, 0xCF, 0x2B, 0x8F, 0x7C, 0x1C, 0x69, 0xE7,
+       0x3F, 0x98, 0x05, 0x34, 0xDA, 0x73, 0x84, 0x00, 0x91, 0x52, 0x7C, 0xB9, 0x03, 0x9D, 0xEA, 0x10,
+       0x6D, 0x16, 0xD0, 0x57, 0x69, 0xD2, 0x18, 0xCA, 0x80, 0x05, 0x89, 0x8E, 0x93, 0xD6, 0x28, 0x1A,
+       0xEF, 0xB8, 0xA5, 0x66, 0xBC, 0x46, 0x83, 0xBC, 0x15, 0x2B, 0x99, 0xD8, 0xB5, 0x9E, 0x38, 0x93,
+       0x4D, 0x18, 0xEB, 0x63, 0x15, 0x6F, 0xFB, 0x24, 0xF9, 0x5C, 0xDD, 0xE9, 0x7B, 0xE1, 0x91, 0x4B,
+       0xFB, 0x2D, 0xAC, 0xF2, 0x3A, 0x09, 0x52, 0xDA, 0x54, 0x0E, 0xBC, 0x12, 0x5C, 0x11, 0xFF, 0xE1,
+       0x27, 0x96, 0x96, 0x0C, 0x10, 0x7B, 0xC2, 0xCC, 0x48, 0x7C, 0xC9, 0xE8, 0x4C, 0xD0, 0x0E, 0xDA,
+       0x3E, 0x57, 0x99, 0x5B, 0x4F, 0x76, 0xAF, 0x8D, 0x8E, 0x9E, 0xB7, 0x94, 0x6A, 0xD1, 0xCB, 0x34,
+       0xFC, 0x41, 0x90, 0x5E, 0x68, 0x8E, 0x21, 0x44, 0x8F, 0x69, 0x5B, 0xAD, 0xB6, 0x9E, 0xBE, 0x9C,
+       0x51, 0x5D, 0xE5, 0xA2, 0x8E, 0x75, 0x25, 0xFC, 0x27, 0x21, 0x14, 0x9B, 0xAC, 0xB8, 0x48, 0x2B,
+       0x99, 0xAE, 0x8D, 0x17, 0x6D, 0x66, 0xEB, 0x08, 0x37, 0x61, 0x46, 0x47, 0x3C, 0x52, 0xCD, 0x94,
+       0xEB, 0x58, 0x94, 0xC8, 0xFE, 0xE0, 0xF4, 0xD4, 0xFB, 0xB7, 0x88, 0x83, 0x62, 0xB4, 0xB9, 0x9F,
+       0x17, 0x88, 0x94, 0xAA, 0x64, 0x6E, 0x5E, 0xA2, 0xFC, 0x01, 0xD6, 0xB0, 0xDE, 0xE3, 0xCF, 0xBA,
+       0xB2, 0xFB, 0x93, 0x39, 0x13, 0xE4, 0x79, 0x9E, 0x2D, 0x7C, 0x68, 0xC8, 0x0B, 0x95, 0xA6, 0x5F,
+       0x6D, 0x93, 0x43, 0xAF, 0xFF, 0xD2, 0x2A, 0xA2, 0x1C, 0x22, 0x4C, 0x4B, 0xAF, 0x60, 0x37, 0x3D,
+       0xE1, 0xE7, 0xD9, 0x18, 0x6A, 0x6C, 0x75, 0x31, 0xF1, 0x83, 0x67, 0x42, 0x76, 0x94, 0xC9, 0x33,
+       0x1C, 0xD0, 0x09, 0x70, 0xE2, 0x92, 0x59, 0x5F, 0xC1, 0x55, 0x13, 0xB6, 0x09, 0xA4, 0x81, 0xFA,
+       0xE2, 0x4C, 0x90, 0xE7, 0x29, 0x92, 0x3A, 0x2A, 0xE1, 0x07, 0x9A, 0xE0, 0x34, 0x79, 0x64, 0xED,
+       0x1B, 0x65, 0xF6, 0x15, 0x33, 0x20, 0xED, 0xB2, 0x8D, 0x4D, 0xF9, 0x6E, 0x16, 0x14, 0xF7, 0x4A,
+       0x87, 0xCF, 0xF8, 0x61, 0x37, 0xC8, 0x48, 0x03, 0xF3, 0x75, 0x9C, 0xA0, 0xC0, 0x75, 0x61, 0x7F,
+       0xD7, 0x64, 0x76, 0x16, 0x61, 0xD3, 0xF2, 0x46, 0xE9, 0x4F, 0x31, 0xA2, 0xFF, 0x12, 0xEB, 0xAC,
+       0x86, 0x47, 0x2A, 0xBE, 0x27, 0x2E, 0x4E, 0x71, 0xA0, 0xA5, 0x73, 0xBC, 0x9A, 0x24, 0x98, 0x13,
+       0xCC, 0x32, 0x52, 0xCB, 0x19, 0xCF, 0x3A, 0xEA, 0xBE, 0x82, 0x5C, 0x4C, 0xF4, 0x30, 0x81, 0x42,
+       0x63, 0xC0, 0x1C, 0x27, 0xDE, 0x56, 0x64, 0x9D, 0xDE, 0xDE, 0x58, 0x0F, 0xC0, 0x20, 0xA0, 0x1C,
+       0xB9, 0x71, 0x37, 0x38, 0x88, 0xB2, 0x62, 0xCA, 0x80, 0x54, 0x72, 0x64, 0x86, 0x59, 0x5F, 0xD4,
+       0x1E, 0x58, 0xF4, 0x09, 0x68, 0x1A, 0x78, 0xFC, 0x94, 0xEF, 0x44, 0x65, 0x2F, 0x42, 0xDC, 0x36,
+       0xDF, 0xBA, 0xD0, 0x8B, 0xD6, 0xCB, 0x70, 0xCB, 0x60, 0xB4, 0x9B, 0xBA, 0x2B, 0xF1, 0x14, 0x85,
+       0x70, 0xFB, 0x6D, 0x5E, 0x02, 0xE4, 0x5B, 0x2F, 0xEA, 0xAC, 0x3A, 0x2D, 0x44, 0xCC, 0x58, 0x33,
+       0x26, 0xEA, 0xFF, 0x0B, 0x0F, 0x06, 0x2D, 0xB1, 0x14, 0x4A, 0x4D, 0x32, 0xDF, 0x40, 0x75, 0x0D,
+       0x17, 0x08, 0xE1, 0x7E, 0x6F, 0xE3, 0xAC, 0xED, 0x01, 0x2D, 0xF1, 0x67, 0xE8, 0x33, 0x2C, 0x98,
+       0x60, 0xDA, 0x19, 0xE1, 0x3F, 0xBC, 0xE1, 0x72, 0xFC, 0xC6, 0x13, 0xB5, 0x66, 0x24, 0x55, 0x5E,
+       0x37, 0x7F, 0xDA, 0x19, 0x7E, 0xD3, 0x3A, 0xF9, 0x7F, 0x0A, 0x37, 0x90, 0x34, 0xB8, 0x59, 0x74,
+       0x55, 0xC6, 0xCD, 0xDC, 0xD0, 0xB1, 0x8A, 0x98, 0x2A, 0xC1, 0xFD, 0xA9, 0xC1, 0xA7, 0x76, 0xC8,
+       0xE6, 0x5D, 0xCD, 0x70, 0xC1, 0xBA, 0x4A, 0xD3, 0x19, 0x02, 0x2C, 0xA9, 0xB4, 0xFD, 0x63, 0x6C,
+       0x3D, 0xCD, 0x88, 0x08, 0xE3, 0xF9, 0x45, 0x89, 0x90, 0xCE, 0xC6, 0x67, 0xFD, 0x54, 0x23, 0x5A,
+       0x78, 0x30, 0x5B, 0x56, 0xEC, 0x2F, 0x8F, 0x9A, 0xD8, 0xC5, 0x5D, 0xDB, 0x4C, 0x44, 0x5F, 0x43,
+       0x3B, 0xF9, 0xA3, 0xAF, 0x53, 0x36, 0x95, 0x04, 0xFD, 0x19, 0x6B, 0x1C, 0x51, 0x01, 0x94, 0x8E,
+       0x98, 0x74, 0x7E, 0x5A, 0x8D, 0x05, 0xFA, 0xC3, 0x51, 0xD5, 0x8D, 0xCB, 0xE9, 0x79, 0x53, 0x89,
+       0x7D, 0x37, 0x79, 0xB8, 0xB2, 0xE9, 0xBB, 0x58, 0x58, 0x9B, 0x86, 0x98, 0x3B, 0xA9, 0xED, 0x3B,
+       0x3C, 0x39, 0x17, 0x9B, 0x43, 0x09, 0x6C, 0x84, 0x9A, 0xAA, 0x46, 0x2C, 0x2F, 0xA7, 0x8A, 0x93,
+       0x97, 0xFB, 0x0D, 0x9B, 0x16, 0x61, 0xFE, 0xA1, 0xDB, 0xDE, 0xF8, 0xC5, 0x75, 0x9E, 0x68, 0x05,
+       0x5E, 0xAE, 0x22, 0x91, 0x7B, 0x2B, 0x74, 0xAC, 0xAC, 0xC9, 0xBF, 0x11, 0x0C, 0xCD, 0xCB, 0x17,
+       0xA5, 0x85, 0x44, 0xA4, 0xB6, 0x99, 0xB8, 0x00, 0x94, 0x18, 0xF2, 0x8A, 0x80, 0xF5, 0xFC, 0xAB,
+       0x19, 0x87, 0x4E, 0xE9, 0x37, 0xD1, 0x48, 0x81, 0x70, 0x8A, 0x91, 0x0B, 0xEB, 0x07, 0x7C, 0x4A,
+       0xF0, 0xA6, 0x58, 0x8A, 0x0E, 0x82, 0xBD, 0x64, 0x2D, 0x14, 0xF8, 0x11, 0x67, 0x2F, 0x9F, 0x4B,
+       0xE4, 0x65, 0xB2, 0xAE, 0x71, 0xBD, 0xAF, 0x48, 0x67, 0xD5, 0x28, 0x1F, 0x1B, 0x7E, 0x1A, 0x11,
+       0xBD, 0x89, 0x8D, 0x22, 0x07, 0xAD, 0xD6, 0x08, 0xC7, 0x37, 0xE9, 0xFB, 0xB5, 0xE1, 0x89, 0x62,
+       0x45, 0x1C, 0xB6, 0xEA, 0x44, 0x73, 0x3A, 0x15, 0x1C, 0xF5, 0xBD, 0x7F, 0xF8, 0xAA, 0x02, 0x3E,
+       0x36, 0x5E, 0x57, 0xDA, 0x06, 0x8F, 0x97, 0x61, 0x92, 0x0D, 0x8A, 0x7E, 0x24, 0xA0, 0x0F, 0xE8,
+       0x7C, 0xFD, 0xA7, 0x27, 0x9C, 0xDD, 0xE1, 0xE8, 0xF5, 0x04, 0x7D, 0xD3, 0x7A, 0xD2, 0x58, 0x80,
+       0xF0, 0x37, 0xE6, 0x44, 0x00, 0xB0, 0x6D, 0x06, 0xB8, 0xCF, 0xAD, 0x3B, 0x2D, 0x47, 0xB0, 0x93,
+       0x30, 0x70, 0x0E, 0x54, 0x37, 0x47, 0x05, 0xC1, 0xDF, 0x49, 0x90, 0x5A, 0xA1, 0x98, 0x92, 0x23,
+       0x76, 0xAA, 0x08, 0x79, 0x20, 0x87, 0xCD, 0xC3, 0x1E, 0x33, 0xF6, 0x38, 0x7C, 0x01, 0xAB, 0x06,
+       0x4A, 0x0A, 0x0B, 0xED, 0x05, 0x4A, 0x01, 0x33, 0x95, 0x04, 0x17, 0x4D, 0xE5, 0xD5, 0x1C, 0x36,
+       0xFC, 0x8D, 0x6A, 0x5A, 0x3F, 0xB6, 0x56, 0xC6, 0xDB, 0x8E, 0xD5, 0xB5, 0x27, 0xAD, 0x6C, 0x7E,
+       0x1F, 0xB5, 0x90, 0xBA, 0xE9, 0xAB, 0x64, 0xD9, 0x77, 0x07, 0xE3, 0xFC, 0x9E, 0x96, 0xB4, 0x1A,
+       0xC8, 0xD4, 0xFE, 0x79, 0x7E, 0x8D, 0xDB, 0x07, 0xB4, 0x73, 0xC5, 0x48, 0xCD, 0x7C, 0x17, 0xD3,
+       0x67, 0xCC, 0x34, 0x42, 0xE9, 0x34, 0x67, 0x9A, 0xAE, 0xA2, 0x43, 0x80, 0x0E, 0xA8, 0x8D, 0x1C,
+       0xAB, 0x91, 0x2A, 0xEC, 0xBD, 0x21, 0x89, 0x5E, 0xF6, 0x6D, 0xF9, 0x6A, 0xE5, 0x2E, 0xFD, 0xAE,
+       0xFF, 0x6E, 0xC8, 0x5F, 0xFB, 0x1B, 0x46, 0x96, 0x9A, 0x91, 0x8B, 0x44, 0xC7, 0x7D, 0xD2, 0xF5,
+       0x13, 0xF8, 0x88, 0xF1, 0x96, 0xCF, 0x97, 0x89, 0x7F, 0xE9, 0x26, 0xE4, 0x1E, 0xA8, 0x75, 0x73,
+       0x8B, 0x83, 0x68, 0x80, 0x4B, 0xF6, 0x44, 0xE9, 0x78, 0x33, 0x8A, 0xA1, 0x8F, 0x0B, 0x3D, 0x78,
+       0xC0, 0xCC, 0xF2, 0xA2, 0x28, 0xDE, 0x0C, 0x92, 0x61, 0x05, 0x6B, 0xC0, 0xB1, 0x2B, 0xC6, 0x41,
+       0xF4, 0x11, 0x99, 0x86, 0x90, 0x4A, 0xD3, 0x63, 0x28, 0xEC, 0xF5, 0x5C, 0x80, 0x0B, 0x8E, 0xF9,
+       0xAB, 0x9C, 0xF6, 0xC3, 0xCA, 0x2F, 0xB2, 0xF2, 0x74, 0x86, 0x2E, 0x0E, 0x4F, 0xE3, 0x0D, 0xBE,
+       0xFA, 0x1D, 0x2D, 0x83, 0x99, 0x36, 0x00, 0xCC, 0x25, 0xC0, 0xB4, 0xAF, 0xEA, 0x21, 0x0E, 0x55,
+       0x42, 0x3F, 0x75, 0x2E, 0x6D, 0xA2, 0x64, 0x8B, 0x59, 0x11, 0xC5, 0xDC, 0x24, 0xBE, 0x5C, 0x94,
+       0x78, 0xD2, 0xD1, 0xC9, 0x15, 0x56, 0xEE, 0xEE, 0x5D, 0xA2, 0x23, 0x9E, 0xFF, 0x99, 0x04, 0x9D,
+       0x2F, 0x29, 0x5B, 0xCF, 0xAA, 0x2E, 0xB4, 0x4C, 0x05, 0xFC, 0xAA, 0xBA, 0x64, 0xAD, 0x40, 0xD2,
+       0x2B, 0xEF, 0xEB, 0xF0, 0x09, 0x21, 0x60, 0xE6, 0x1D, 0x44, 0xFD, 0x4D, 0x07, 0xA5, 0xE0, 0x94,
+       0xBE, 0xA1, 0xB7, 0xB2, 0x48, 0x96, 0xBD, 0x79, 0x4D, 0x0A, 0x18, 0xF3, 0x0A, 0xBE, 0x58, 0x3F,
+       0x17, 0x23, 0x03, 0xC1, 0x6F, 0x9C, 0xD7, 0x40, 0x96, 0x77, 0x9A, 0x71, 0x56, 0xA4, 0x6A, 0x1A,
+       0x93, 0xA1, 0xB6, 0xDF, 0xAB, 0xBE, 0xD7, 0x01, 0x38, 0xF4, 0xFD, 0x99, 0x14, 0x3D, 0x3D, 0x2E,
+       0x5A, 0x9D, 0x6C, 0x02, 0x3C, 0xDF, 0xF1, 0xE7, 0x8D, 0x14, 0x5D, 0x8D, 0xBC, 0x56, 0xE0, 0x45,
+       0x92, 0xFA, 0xFD, 0xC0, 0x70, 0x0B, 0xA8, 0x4B, 0xF4, 0xAB, 0x8C, 0x2B, 0xD0, 0x2E, 0x9F, 0xBD,
+       0x7F, 0xFF, 0x72, 0x2A, 0x25, 0x47, 0x5C, 0x6A, 0x63, 0x89, 0xC6, 0x8C, 0xA1, 0x99, 0x6D, 0x72,
+       0x24, 0xA6, 0xFA, 0x28, 0x85, 0xEA, 0xAE, 0x13, 0x6A, 0xFE, 0xDD, 0xA1, 0x20, 0x52, 0x2E, 0x43,
+       0x2F, 0x5C, 0xE4, 0x66, 0x57, 0x78, 0x55, 0xD7, 0x70, 0xA8, 0x17, 0x6B, 0x60, 0xB6, 0x87, 0x02,
+       0xC6, 0xC2, 0x4F, 0xE7, 0x32, 0x15, 0xEF, 0xC1, 0xCC, 0x50, 0xB6, 0x1F, 0x96, 0x87, 0xA2, 0x2A,
+       0x85, 0x4C, 0x63, 0x02, 0x5A, 0x63, 0xD0, 0x12, 0xAA, 0x74, 0x5A, 0xC1, 0xDD, 0x86, 0xC4, 0x27,
+       0x58, 0xE9, 0x53, 0xDE, 0x47, 0x64, 0xE4, 0x27, 0x5F, 0xB5, 0x70, 0xE3, 0x15, 0xEB, 0xDD, 0xDA,
+       0x09, 0xD6, 0xE2, 0xBB, 0x8D, 0x70, 0xBB, 0x8A, 0xAD, 0xAD, 0x1B, 0xCF, 0xA7, 0x1B, 0xC3, 0xCF,
+       0x98, 0x3C, 0x46, 0xBC, 0x2F, 0xE9, 0x88, 0x35, 0xC1, 0xE1, 0xB8, 0x08, 0xF1, 0x8B, 0xD0, 0x0F,
+       0x2B, 0x5E, 0xAC, 0x43, 0x17, 0x62, 0x43, 0x5D, 0x8C, 0x97, 0xEB, 0x72, 0x0D, 0xCA, 0x13, 0xB7,
+       0x90, 0xDD, 0x8F, 0x97, 0xF9, 0x11, 0xB9, 0xE4, 0xD2, 0xEF, 0x35, 0xE4, 0x60, 0x65, 0xDF, 0x82,
+       0x7A, 0x52, 0xCF, 0x07, 0xB1, 0xCA, 0x33, 0xA5, 0x2A, 0x03, 0xA8, 0x9C, 0xEE, 0x27, 0xE3, 0x94,
+       0x97, 0xD0, 0x49, 0xD3, 0x25, 0xEC, 0xC0, 0x11, 0x24, 0xFD, 0x36, 0xAE, 0x51, 0x53, 0x56, 0x61,
+       0x2B, 0xA7, 0x4D, 0x7B, 0xD4, 0x70, 0x73, 0x61, 0xCD, 0x48, 0xA2, 0x74, 0xBD, 0x13, 0x54, 0x34,
+       0xEA, 0x10, 0x0E, 0x3D, 0xC0, 0x02, 0xBB, 0x18, 0x70, 0x8D, 0x27, 0x58, 0xCE, 0xE2, 0x48, 0x95,
+       0xE0, 0xA6, 0xFC, 0x2E, 0xE3, 0x14, 0x5D, 0x05, 0xCF, 0x31, 0xCE, 0x6B, 0xC8, 0x34, 0x32, 0x47,
+       0xC5, 0x9C, 0xEF, 0x21, 0x50, 0x78, 0x47, 0xA6, 0xB1, 0x58, 0x37, 0x39, 0xAA, 0x6A, 0x0A, 0x7C,
+       0x63, 0xCB, 0x22, 0x72, 0xB9, 0x87, 0xAA, 0x67, 0x7B, 0x30, 0xEB, 0x65, 0x62, 0xE2, 0x23, 0x08,
+       0xB1, 0xF7, 0x38, 0x84, 0x6E, 0xEB, 0x6D, 0x60, 0x58, 0x94, 0x1F, 0xF3, 0xA9, 0x6E, 0x63, 0xD1,
+       0x1F, 0xC0, 0xC2, 0x0B, 0xDA, 0xB0, 0xB0, 0x4F, 0x92, 0x6F, 0xE9, 0x34, 0xBA, 0xC8, 0x13, 0xC4,
+       0xDF, 0x5B, 0x3B, 0x54, 0xF1, 0xD9, 0xEA, 0x6B, 0x9F, 0x12, 0x0D, 0xC1, 0xCD, 0x32, 0x50, 0x59,
+       0x7E, 0x73, 0xE4, 0xB0, 0x3B, 0x64, 0xF3, 0x11, 0xD2, 0x7F, 0x0E, 0x78, 0xE9, 0x99, 0xFC, 0xDD,
+       0x22, 0x43, 0xE1, 0x11, 0xA4, 0x4D, 0x11, 0x39, 0x44, 0x0A, 0x8D, 0x08, 0x32, 0x76, 0xF2, 0xF8,
+       0xAB, 0x4B, 0x65, 0x79, 0x51, 0x38, 0xBB, 0x90, 0x51, 0xF4, 0xBC, 0x8A, 0x26, 0x1E, 0x12, 0x1F,
+       0x7D, 0x9E, 0x54, 0x20, 0x31, 0x9A, 0x2E, 0x2F, 0x70, 0xA9, 0xF4, 0x88, 0x94, 0x1D, 0x6F, 0x9B,
+       0x76, 0x28, 0x42, 0xB9, 0x0D, 0x37, 0x5C, 0xA2, 0xF7, 0xA7, 0xB7, 0xD8, 0x5B, 0xF3, 0x92, 0x2E,
+       0x32, 0xF4, 0xAB, 0x24, 0xE3, 0x93, 0xE8, 0xBC, 0xFF, 0xB6, 0x66, 0x6F, 0x53, 0x2C, 0x8F, 0xC5,
+       0x1E, 0x5C, 0x8E, 0x41, 0xA9, 0x8B, 0x68, 0xD1, 0xB6, 0xD1, 0x5F, 0x28, 0xB5, 0x05, 0x6A, 0x40,
+       0x4C, 0xCA, 0x7D, 0x7E, 0x7E, 0xCB, 0xD2, 0xA5, 0x78, 0x18, 0xCD, 0x90, 0x38, 0xF2, 0x09, 0x0A,
+       0x36, 0x49, 0x98, 0x86, 0x9C, 0x2E, 0x80, 0x6A, 0x61, 0x26, 0xFD, 0xCE, 0x78, 0x90, 0x23, 0x4C,
+       0xB6, 0x64, 0xCA, 0x22, 0xBA, 0xE9, 0xAC, 0x5C, 0x3C, 0x09, 0x23, 0x99, 0x9C, 0x01, 0xF0, 0xA3,
+       0x06, 0xE1, 0x65, 0x8B, 0x50, 0x27, 0x2F, 0x1C, 0x25, 0xA5, 0x7E, 0xD1, 0xBC, 0x06, 0xDB, 0x04,
+       0xFF, 0x87, 0x66, 0xD1, 0xA8, 0x98, 0xB9, 0xAC, 0x98, 0xB9, 0xF8, 0x4F, 0x8F, 0x31, 0x21, 0xE0,
+       0x3E, 0xB2, 0x17, 0xA0, 0x24, 0xCB, 0x8E, 0xD2, 0x87, 0xED, 0x09, 0xD6, 0x44, 0x12, 0xCF, 0xA8,
+       0x31, 0xB6, 0x47, 0xE3, 0x2C, 0x2E, 0x91, 0x1A, 0x75, 0x3B, 0x25, 0x23, 0x45, 0x15, 0x6C, 0xB3,
+       0x98, 0xFC, 0x83, 0x52, 0xED, 0x29, 0x87, 0xD2, 0x13, 0x30, 0x55, 0x67, 0x5C, 0xD8, 0xC9, 0x41,
+       0x36, 0xAA, 0x2C, 0x19, 0xD8, 0x9B, 0x74, 0xEA, 0xC1, 0x4D, 0x3A, 0x79, 0xC5, 0x8E, 0x26, 0x90,
+       0x01, 0x1D, 0x29, 0x6C, 0x3A, 0xDF, 0xB0, 0xAB, 0xDA, 0x4C, 0xBE, 0x6D, 0xF1, 0x9C, 0xC5, 0xD6,
+       0x81, 0xA8, 0x41, 0xD4, 0xB0, 0x94, 0x53, 0xA4, 0x2A, 0x7E, 0x2B, 0xF3, 0xD4, 0xEF, 0x49, 0xFC,
+       0x5C, 0x06, 0xF2, 0x7B, 0x69, 0x09, 0xF1, 0xD9, 0x15, 0x25, 0x6B, 0x76, 0x05, 0xAD, 0x25, 0xFA,
+       0xA6, 0x07, 0x35, 0xA9, 0xC9, 0xD4, 0x32, 0x7C, 0xDF, 0x92, 0x68, 0xFB, 0x93, 0x18, 0x4F, 0xB9,
+       0x20, 0x4A, 0x85, 0x62, 0x13, 0x44, 0x5B, 0x3E, 0x8C, 0xFE, 0x95, 0x8E, 0x7F, 0xE7, 0xE5, 0xEE,
+       0xF9, 0x84, 0x83, 0x1B, 0x38, 0xEB, 0x6E, 0x10, 0x68, 0xC0, 0x3C, 0x71, 0xFA, 0xFD, 0x96, 0x2A,
+       0xEE, 0x44, 0x49, 0x31, 0x9F, 0x50, 0x60, 0x1A, 0x29, 0xE5, 0xBD, 0x5D, 0x8C, 0x54, 0xAD, 0x82,
+       0x14, 0x4A, 0xE0, 0x6E, 0x6D, 0x63, 0xEB, 0xC1, 0xD0, 0xA8, 0x76, 0xE6, 0x9E, 0x2B, 0x36, 0xDC,
+       0x16, 0x3F, 0xA7, 0xCD, 0x72, 0x9E, 0x29, 0xE9, 0x1D, 0x78, 0x3D, 0x51, 0x6C, 0xDF, 0xA6, 0x1E,
+       0x09, 0x63, 0x58, 0x14, 0x9B, 0xBD, 0xDB, 0xD8, 0xFF, 0x97, 0xEB, 0xD7, 0x78, 0xED, 0x28, 0xD8,
+       0xFB, 0xE3, 0xE0, 0x19, 0xF2, 0x0E, 0x2F, 0xB1, 0xDA, 0xC8, 0xEE, 0xCC, 0xCD, 0xCC, 0xD9, 0xBC,
+       0xF9, 0xCF, 0xBD, 0x66, 0x67, 0x20, 0xB3, 0xCC, 0x58, 0xDD, 0x95, 0x2F, 0x4A, 0xFF, 0xE2, 0x24,
+       0xC8, 0x76, 0xBB, 0xC5, 0x18, 0x2D, 0x85, 0xF3, 0x7C, 0x79, 0x7A, 0x7A, 0x8A, 0x46, 0x37, 0x0A,
+       0xE6, 0x45, 0x1B, 0xBB, 0xCA, 0xC4, 0x40, 0x29, 0xD0, 0x21, 0xC1, 0xB6, 0x41, 0xF3, 0xB3, 0x3B,
+       0x19, 0xD5, 0xA3, 0x6D, 0x1A, 0xD9, 0xCA, 0x5C, 0xB6, 0x7D, 0xC5, 0x2E, 0xB5, 0x07, 0x9A, 0x08,
+       0xF1, 0x38, 0x76, 0x0C, 0x22, 0xF5, 0xDF, 0xFC, 0x26, 0xEC, 0xBB, 0xE3, 0x6B, 0x40, 0xA0, 0xE0,
+       0xCA, 0x19, 0x67, 0xC1, 0xE2, 0x79, 0x0A, 0x18, 0x98, 0x8C, 0x43, 0x91, 0x0D, 0x41, 0x40, 0x72,
+       0x61, 0x21, 0xCA, 0x77, 0x96, 0x5B, 0x4E, 0xDB, 0xC4, 0xDD, 0x53, 0x5A, 0x9E, 0x49, 0x07, 0x28,
+       0x37, 0xEC, 0x7B, 0x8A, 0xF3, 0x0B, 0xBD, 0xA3, 0x9F, 0x3F, 0x56, 0x74, 0xD7, 0x1F, 0xC9, 0x3C,
+       0x60, 0x8D, 0x20, 0xA1, 0x76, 0x9B, 0xC0, 0x49, 0xAD, 0x2E, 0x3B, 0xD0, 0x7B, 0x40, 0x18, 0x0D,
+       0x59, 0x2F, 0xD1, 0x94, 0x30, 0x0A, 0x7B, 0xE4, 0x14, 0x35, 0xFE, 0x00, 0xBE, 0x13, 0xE3, 0xF3,
+       0x45, 0x4E, 0x95, 0x34, 0x88, 0xAF, 0x84, 0x57, 0xC8, 0x74, 0x1B, 0x7B, 0xE2, 0xF4, 0x97, 0x85,
+       0x5C, 0x1C, 0x43, 0x39, 0x36, 0x46, 0x82, 0xEB, 0x02, 0xD6, 0x86, 0xF4, 0x38, 0xA0, 0x0E, 0x6F,
+       0x89, 0x87, 0x0B, 0xAD, 0x7E, 0xAE, 0x02, 0xF1, 0x76, 0x3C, 0x3D, 0xF3, 0x90, 0xA3, 0x6A, 0x3C,
+       0x06, 0x84, 0xAB, 0x4C, 0x21, 0xB3, 0x97, 0x66, 0xEF, 0xF7, 0x2A, 0x9B, 0x9E, 0x28, 0x8F, 0x79,
+       0xCB, 0x07, 0x95, 0x1F, 0x48, 0xD8, 0x04, 0xCE, 0x89, 0x52, 0xBA, 0x56, 0xA0, 0x1F, 0xCF, 0x09,
+       0x33, 0x30, 0xF9, 0x23, 0x68, 0xEB, 0xDA, 0x2B, 0x91, 0x1B, 0xA4, 0x24, 0x0B, 0xE5, 0x78, 0xB7,
+       0x85, 0x22, 0x84, 0xD1, 0x8B, 0x14, 0xC3, 0x73, 0x77, 0x51, 0x4E, 0x13, 0x6E, 0x10, 0x07, 0x8A,
+       0x95, 0x20, 0xE9, 0x3F, 0xE6, 0xA2, 0xB6, 0x9A, 0xC6, 0x13, 0xEC, 0x68, 0xAA, 0xC6, 0xC2, 0xAF,
+       0xAF, 0x0E, 0xE7, 0xFC, 0xA3, 0x8B, 0x1F, 0xCD, 0xB8, 0xB3, 0xA5, 0x03, 0x59, 0x92, 0x8B, 0x76,
+       0x21, 0xD7, 0x41, 0xF3, 0x4E, 0xCB, 0xE7, 0x1A, 0xCB, 0x61, 0x40, 0xBB, 0x2F, 0xDF, 0x9F, 0xB4,
+       0x99, 0xB3, 0x52, 0x49, 0xCF, 0xAC, 0xCB, 0xFD, 0xE8, 0xD7, 0x32, 0x62, 0x6F, 0xF6, 0x00, 0x51,
+       0x66, 0xCD, 0x7D, 0xE7, 0x4C, 0xF9, 0x5A, 0x95, 0x0F, 0x9C, 0x5C, 0x24, 0xC1, 0x98, 0xE0, 0xCD,
+       0x10, 0x08, 0x72, 0xFF, 0xC1, 0xF0, 0x50, 0xD9, 0x80, 0xC1, 0x79, 0xED, 0x9F, 0x9C, 0x48, 0xC8,
+       0x26, 0xDB, 0x51, 0x05, 0x0E, 0x04, 0x58, 0x53, 0xE0, 0x37, 0xA8, 0x26, 0xEC, 0x0A, 0xAB, 0x12,
+       0xBC, 0xC0, 0x29, 0xC9, 0x24, 0x71, 0xE8, 0x84, 0xFF, 0x6B, 0x58, 0x3A, 0xA0, 0xA5, 0x15, 0xC9,
+       0x6F, 0xD0, 0x25, 0x15, 0x35, 0x99, 0xDD, 0xE8, 0x0E, 0xD7, 0xFF, 0x6D, 0x91, 0xD6, 0x5D, 0xEB,
+       0x3F, 0x28, 0xB8, 0x90, 0x4A, 0x72, 0xD3, 0x40, 0x17, 0x38, 0xAB, 0x63, 0x92, 0xF9, 0x78, 0x97,
+       0x04, 0x56, 0xB4, 0xDA, 0x85, 0x5B, 0x50, 0x09, 0x25, 0x95, 0xE1, 0x2B, 0x97, 0x9F, 0x93, 0x70,
+       0xA7, 0xC5, 0x9B, 0xE9, 0x55, 0x84, 0x46, 0x48, 0xE0, 0xAD, 0x07, 0xA3, 0x3E, 0xD9, 0xD8, 0x24,
+       0x51, 0x6B, 0xB3, 0xED, 0xEF, 0x68, 0x14, 0xCE, 0xA8, 0x26, 0x97, 0x47, 0x50, 0x15, 0x60, 0x13,
+       0x1B, 0x2D, 0x15, 0xF5, 0x96, 0x25, 0x51, 0xB3, 0x1A, 0xB3, 0x01, 0x67, 0x89, 0x3F, 0xA7, 0xD0,
+       0xD0, 0xD6, 0xF6, 0xB5, 0xB6, 0xA9, 0x3E, 0x66, 0xF0, 0xBD, 0xD2, 0x1A, 0x41, 0x4B, 0x06, 0x14,
+       0xCA, 0x92, 0x8F, 0xFC, 0x89, 0x6A, 0x7D, 0xEE, 0xB5, 0xD2, 0x19, 0x3B, 0x40, 0x51, 0xB7, 0x8F,
+       0xBE, 0xE8, 0xC5, 0xC4, 0x7F, 0x6C, 0x54, 0xBB, 0x8E, 0xDB, 0xFE, 0x00, 0xF1, 0x11, 0x5A, 0x05,
+       0x27, 0x7D, 0xB8, 0xE2, 0xA7, 0xC2, 0x03, 0xA9, 0x10, 0x7E, 0x63, 0x0F, 0x7D, 0xB6, 0x5B, 0x42,
+       0x0E, 0x23, 0x80, 0xE0, 0xA2, 0xAA, 0x93, 0xDC, 0x0E, 0xAF, 0x49, 0xF1, 0x0B, 0xF9, 0x2B, 0x23,
+       0x35, 0xDF, 0x61, 0xA2, 0x7C, 0xF6, 0x72, 0x2B, 0x19, 0xAD, 0x65, 0x38, 0xDE, 0xC8, 0xD1, 0x32,
+       0x39, 0x0B, 0x0C, 0x9C, 0xDC, 0xE4, 0x06, 0xFC, 0xEC, 0xEA, 0x74, 0x48, 0x39, 0x0B, 0x76, 0x8E,
+       0x98, 0x44, 0x74, 0xD2, 0xDA, 0x3F, 0x38, 0x7E, 0x2B, 0xA9, 0x4F, 0x45, 0x4E, 0x88, 0x9C, 0xAF,
+       0xF2, 0x22, 0x94, 0x43, 0x22, 0xC5, 0xC0, 0xAE, 0x04, 0xD5, 0xE4, 0xD2, 0xD1, 0x83, 0xA7, 0xEB,
+       0xFA, 0x6C, 0xB7, 0xFB, 0xFC, 0xA1, 0xA4, 0x18, 0x1F, 0xB0, 0xF4, 0xF4, 0x38, 0xD6, 0x57, 0x2A,
+       0x4C, 0x77, 0xAA, 0x4B, 0xA7, 0x4F, 0xA8, 0x63, 0x26, 0x47, 0x14, 0x85, 0x5C, 0x16, 0xA4, 0x43,
+       0xDA, 0xCD, 0x73, 0x46, 0x99, 0x56, 0x6C, 0xF0, 0xD7, 0x2B, 0xCB, 0x2A, 0x38, 0x2A, 0x02, 0xA1,
+       0xD0, 0x90, 0x37, 0x6F, 0x6B, 0xD7, 0xDF, 0xCA, 0xA7, 0x32, 0xDF, 0x61, 0x5E, 0xDD, 0x7C, 0x05,
+       0x16, 0x10, 0x8C, 0x36, 0xDB, 0xC4, 0x44, 0x60, 0xD5, 0xF7, 0xF8, 0x90, 0x0F, 0x87, 0xE1, 0xBE,
+       0x6C, 0x0C, 0xF2, 0x72, 0xEE, 0xFD, 0x2B, 0xDD, 0xE5, 0xD2, 0x22, 0x58, 0x32, 0x49, 0x1F, 0xB0,
+       0xAF, 0x52, 0x2C, 0xC0, 0x12, 0xA9, 0x6F, 0xF7, 0xF7, 0x3C, 0x9B, 0x03, 0xFA, 0x66, 0x28, 0xE3,
+       0x6A, 0xC4, 0xDC, 0x04, 0x51, 0xFA, 0x6F, 0x10, 0x63, 0xBE, 0x95, 0xD7, 0xC1, 0x76, 0x59, 0xAC,
+       0xA3, 0x78, 0x85, 0x6B, 0x6A, 0x03, 0x9F, 0x74, 0x0F, 0x0F, 0x94, 0x0B, 0xAD, 0x4B, 0xEB, 0x69,
+       0x9D, 0x26, 0x7A, 0xE9, 0x3D, 0x48, 0xF4, 0x49, 0x19, 0xBC, 0x3D, 0xAB, 0x95, 0xDC, 0xAF, 0x67,
+       0x22, 0xD7, 0x52, 0x2D, 0xBD, 0xB6, 0x8B, 0x86, 0x39, 0x34, 0xDC, 0x26, 0x1A, 0x7D, 0xF1, 0x70,
+       0x1C, 0x23, 0x94, 0xF0, 0x8A, 0x4A, 0xDB, 0x79, 0x9B, 0x9F, 0x1B, 0x7E, 0xB7, 0xF4, 0x8E, 0x5C,
+       0x7F, 0xC0, 0x9D, 0x85, 0x61, 0x51, 0x48, 0x4E, 0x79, 0xAD, 0x4A, 0xC6, 0xF4, 0x4E, 0xBF, 0xCB,
+       0xBF, 0xB4, 0x46, 0x83, 0x1A, 0x4E, 0xA8, 0x21, 0x22, 0x2F, 0xEA, 0x7C, 0x49, 0xE1, 0xC9, 0x2B,
+       0x58, 0xAF, 0xF7, 0x60, 0x54, 0xC8, 0x82, 0x24, 0xD8, 0xBE, 0xE7, 0x9E, 0xF5, 0x69, 0x70, 0xE5,
+       0xDB, 0xD3, 0xF3, 0x34, 0xDF, 0x3F, 0x88, 0x4B, 0x60, 0x46, 0x8B, 0x84, 0xEC, 0x23, 0x66, 0x73,
+       0x2D, 0xDD, 0xB9, 0x13, 0x75, 0xDD, 0x56, 0x10, 0x3A, 0x38, 0x4F, 0xE3, 0x94, 0x4C, 0xD1, 0x0C,
+       0x3C, 0xF2, 0x1D, 0xF9, 0x7F, 0xC2, 0x26, 0x9E, 0xE3, 0xD2, 0xD9, 0xBE, 0x8B, 0xCB, 0x53, 0xE7,
+       0x5A, 0x4C, 0x01, 0x13, 0x42, 0x60, 0xC7, 0x04, 0x37, 0x70, 0x04, 0x3E, 0x2B, 0x82, 0x43, 0x8C,
+       0xCC, 0x97, 0xF4, 0x65, 0x35, 0xFB, 0x08, 0x11, 0xD9, 0x0B, 0x09, 0x67, 0x45, 0x23, 0xAA, 0xCC,
+       0x3D, 0x07, 0x26, 0x64, 0xE3, 0x44, 0xEA, 0x3C, 0x2D, 0xBE, 0xE4, 0x49, 0xB9, 0x3B, 0x94, 0xDE,
+       0x3B, 0x19, 0x90, 0x3D, 0x30, 0x81, 0x25, 0xB8, 0xE4, 0x1E, 0x74, 0xED, 0xF1, 0xB5, 0x40, 0x6C,
+       0x2B, 0x8E, 0x02, 0xDF, 0xB1, 0x4B, 0xA9, 0xE0, 0x48, 0x97, 0x24, 0xE5, 0x55, 0xAE, 0x36, 0x35,
+       0xB4, 0x5D, 0x55, 0xA7, 0x7C, 0x6E, 0xB8, 0x53, 0x91, 0xA4, 0xBB, 0x47, 0x49, 0x03, 0xD3, 0x00,
+       0xF0, 0x26, 0x7E, 0x52, 0x69, 0x4B, 0xE2, 0x2C, 0xF8, 0x06, 0x0D, 0x3A, 0xEE, 0xA6, 0xBD, 0x0F,
+       0x1F, 0xA2, 0xBE, 0x1D, 0xDE, 0x82, 0x36, 0xA5, 0x1A, 0xFD, 0x81, 0x48, 0xC1, 0x91, 0xEB, 0x69,
+       0x53, 0x08, 0x9B, 0xBB, 0x0C, 0x2B, 0xE5, 0x04, 0x7A, 0x6A, 0xE3, 0xA2, 0x24, 0x69, 0x4E, 0xA5,
+       0xDE, 0x7C, 0xB4, 0x3D, 0x85, 0x7D, 0x78, 0x28, 0xEC, 0x99, 0xF4, 0x7E, 0x53, 0xEE, 0x8A, 0x3E,
+       0x69, 0xAD, 0xA1, 0x2D, 0xCF, 0x9F, 0x2C, 0xF1, 0x57, 0xA9, 0x73, 0xA4, 0x76, 0x92, 0xBC, 0xBA,
+       0x14, 0xA2, 0x7A, 0x97, 0x7E, 0x91, 0x49, 0xAB, 0x33, 0x8F, 0xA3, 0x9C, 0x67, 0xCA, 0xA9, 0xB1,
+       0x17, 0xE8, 0xBC, 0x33, 0x59, 0x17, 0x1D, 0x20, 0xDC, 0xE5, 0xA9, 0xA7, 0x3F, 0x95, 0x74, 0xB4,
+       0x0C, 0xBB, 0x0E, 0xDB, 0x5F, 0x5F, 0x7D, 0x78, 0x25, 0xFB, 0x55, 0x46, 0x39, 0x5D, 0x0B, 0x69,
+       0x1A, 0x35, 0xEF, 0xAA, 0x8A, 0x4C, 0x4E, 0x5B, 0x5F, 0x09, 0x09, 0xA1, 0x87, 0x79, 0x9B, 0x45,
+       0xEF, 0x1E, 0xA5, 0x65, 0x63, 0x86, 0x8B, 0x48, 0x53, 0x8D, 0xE7, 0x64, 0xEC, 0x51, 0x6F, 0x04,
+       0xDF, 0x90, 0x5B, 0x18, 0x43, 0x03, 0x35, 0x9D, 0x5B, 0xFC, 0x97, 0x19, 0xB6, 0x52, 0x78, 0xD4,
+       0x8E, 0xF0, 0x18, 0xCD, 0x03, 0x32, 0xDF, 0x99, 0x52, 0xD2, 0x81, 0x3D, 0xC1, 0xC7, 0x00, 0xCA,
+       0x1A, 0xB7, 0xA8, 0x34, 0x4B, 0x3F, 0x28, 0x86, 0x4C, 0x53, 0xC6, 0x08, 0xEE, 0x26, 0x96, 0xB4,
+       0x4D, 0xC9, 0x39, 0xA3, 0x8F, 0xC8, 0x99, 0x06, 0x7B, 0xDF, 0x2D, 0x45, 0xAF, 0xCB, 0x82, 0xA4,
+       0xCF, 0xB0, 0x38, 0xBF, 0x79, 0x3A, 0x04, 0x79, 0x26, 0x19, 0xAC, 0xD4, 0x49, 0x30, 0x8B, 0xD0,
+       0xC3, 0x3B, 0x72, 0xB2, 0xCE, 0x5D, 0x46, 0x16, 0x0B, 0x8B, 0xCD, 0x90, 0x96, 0x40, 0x5D, 0x1D,
+       0x12, 0x38, 0x0D, 0xBB, 0x0B, 0x88, 0x37, 0x0B, 0x8B, 0xD9, 0x1F, 0x7B, 0x88, 0x65, 0xD9, 0xED,
+       0x19, 0x66, 0x34, 0xE9, 0x9C, 0xDF, 0x17, 0xF9, 0x37, 0xB1, 0x52, 0xA8, 0x98, 0x7B, 0xE8, 0x76,
+       0xB7, 0x56, 0x5E, 0x62, 0xB6, 0x78, 0xFF, 0x99, 0xE9, 0x5A, 0x5A, 0xE4, 0x73, 0xF4, 0x70, 0x97,
+       0x8A, 0xB7, 0xF3, 0x63, 0x22, 0x7C, 0x07, 0xB5, 0xE5, 0x6F, 0xEB, 0xFC, 0x2B, 0x5D, 0xBC, 0xCE,
+       0x3C, 0x01, 0xF8, 0x08, 0x3D, 0xFE, 0x32, 0x29, 0x65, 0x1E, 0xBB, 0xE2, 0xAB, 0xDA, 0x73, 0xAA,
+       0xB4, 0x20, 0xCA, 0x17, 0x95, 0xC9, 0xFE, 0x08, 0x86, 0x6C, 0xC8, 0x32, 0x77, 0x26, 0x3A, 0x26,
+       0xD5, 0xB9, 0x36, 0xBC, 0xF9, 0x81, 0x7F, 0xD7, 0xB0, 0x66, 0x12, 0x4C, 0xB4, 0xCA, 0x44, 0x08,
+       0xC9, 0x24, 0xDE, 0x87, 0x7F, 0x7A, 0x61, 0xE4, 0x1A, 0x45, 0xB8, 0xF3, 0x90, 0x28, 0xBE, 0xD7,
+       0x36, 0xF8, 0x17, 0x5B, 0xA3, 0x32, 0xFF, 0xCF, 0x37, 0x7F, 0x1A, 0x54, 0x74, 0x63, 0xF6, 0xC1,
+       0xA7, 0x09, 0xC7, 0x08, 0xB6, 0x75, 0x16, 0x09, 0xED, 0x9A, 0xBF, 0x17, 0x58, 0x21, 0x88, 0x27,
+       0xD5, 0xC3, 0x8D, 0x9B, 0x81, 0x4C, 0x28, 0x5C, 0x34, 0x89, 0xC5, 0x80, 0x0B, 0x40, 0xA2, 0xA5,
+       0x90, 0x1C, 0x4D, 0x1A, 0xF7, 0x72, 0x25, 0x3E, 0x47, 0x21, 0x0D, 0xDC, 0xE2, 0xDE, 0xCC, 0x45,
+       0x3D, 0x64, 0xB3, 0x2B, 0xF4, 0xF6, 0x51, 0x78, 0x3C, 0x6A, 0xF3, 0x6F, 0xFF, 0x7F, 0xB0, 0x76,
+       0x21, 0x42, 0x87, 0x47, 0x32, 0xD6, 0x0C, 0x7D, 0x65, 0x9F, 0xE3, 0x08, 0x2A, 0x49, 0xE6, 0x67,
+       0x9E, 0x7B, 0x76, 0x14, 0x50, 0x9D, 0xD7, 0x1E, 0xB8, 0xF3, 0x88, 0xE6, 0x75, 0x86, 0x07, 0x1E,
+       0xA7, 0x2D, 0x6C, 0x20, 0xE8, 0x49, 0x25, 0x07, 0x28, 0x0C, 0xF8, 0xFA, 0x62, 0x6F, 0x38, 0xCC,
+       0xA5, 0x44, 0x73, 0x4E, 0xF4, 0x7B, 0xE3, 0x1A, 0x7C, 0x99, 0x3B, 0xA0, 0xC2, 0x98, 0xD3, 0xEC,
+       0xCE, 0x10, 0x75, 0x12, 0x2C, 0x70, 0x24, 0xBC, 0xE7, 0xF5, 0x83, 0x96, 0xC2, 0x51, 0xDC, 0xA9,
+       0x97, 0x2F, 0x32, 0xD8, 0xF3, 0x0B, 0x03, 0x1C, 0x93, 0x44, 0xC4, 0xEB, 0x21, 0xB3, 0xB0, 0x9A,
+       0x64, 0x94, 0x04, 0xAD, 0xCE, 0x91, 0x44, 0x04, 0xE4, 0xE6, 0xB2, 0xE1, 0xBC, 0x75, 0xB2, 0xC2,
+       0x6B, 0x46, 0xD1, 0xEE, 0x88, 0x80, 0xE8, 0x2C, 0x2D, 0x10, 0x95, 0x9A, 0x03, 0x30, 0xDF, 0x51,
+       0x74, 0x94, 0xDA, 0x67, 0x1F, 0xB5, 0x95, 0x23, 0x16, 0xC0, 0x46, 0x57, 0xF1, 0x37, 0xBC, 0xE2,
+       0x99, 0x2C, 0xA0, 0xFC, 0xEA, 0x24, 0x5B, 0xEE, 0x5E, 0x2A, 0x2B, 0xF3, 0xA2, 0x0A, 0x94, 0x27,
+       0xF4, 0x7D, 0x4D, 0x83, 0xCA, 0xCE, 0xAA, 0xE0, 0xA9, 0xDB, 0x9C, 0xF8, 0xFF, 0x25, 0xBD, 0x62,
+       0xD8, 0x99, 0xA7, 0x26, 0x36, 0x75, 0x62, 0x99, 0x77, 0x83, 0x49, 0x02, 0x3B, 0xC7, 0x5F, 0x37,
+       0x64, 0x48, 0xCF, 0x9A, 0x16, 0x0E, 0xBC, 0xCA, 0x0A, 0xF4, 0x0E, 0xDA, 0x5D, 0xFB, 0xDB, 0xE7,
+       0xBF, 0x51, 0x6E, 0x8B, 0x37, 0xCB, 0x4F, 0x0C, 0x73, 0x36, 0xC8, 0x0F, 0x2A, 0x70, 0x79, 0xFA,
+       0x77, 0xB1, 0x5D, 0xBB, 0xC7, 0x52, 0x39, 0x7C, 0x50, 0x73, 0x5F, 0x8F, 0xB5, 0x28, 0xEC, 0x48,
+       0x26, 0x14, 0xF0, 0x41, 0xD1, 0x32, 0x6C, 0x1D, 0x44, 0xA1, 0xF0, 0xEF, 0xE8, 0x69, 0xA4, 0x1E,
+       0x00, 0x45, 0xF8, 0x52, 0xA5, 0x31, 0x5D, 0xD3, 0x55, 0x6C, 0xCA, 0xB0, 0x51, 0x0E, 0x69, 0xA1,
+       0x47, 0x12, 0xC3, 0xFD, 0x9D, 0x99, 0x45, 0x2B, 0x95, 0x8E, 0x79, 0x51, 0x1D, 0x86, 0x5D, 0x06,
+       0x37, 0xCC, 0x19, 0xD3, 0xB2, 0xD4, 0x7A, 0x1E, 0x1E, 0xD1, 0x30, 0x40, 0x6D, 0x9B, 0x08, 0x77,
+       0xE5, 0xB3, 0x48, 0xFA, 0x1B, 0x8A, 0x4D, 0x26, 0x8F, 0x9E, 0x50, 0x78, 0xE2, 0x4D, 0x3A, 0x3E,
+       0x86, 0x27, 0x50, 0x05, 0x27, 0x05, 0x29, 0x83, 0x72, 0x46, 0x58, 0x34, 0x24, 0xDA, 0x11, 0x33,
+       0xA6, 0x4F, 0x10, 0xF3, 0xF3, 0xAB, 0x00, 0x27, 0x1F, 0x02, 0x71, 0x8B, 0xC9, 0x68, 0x9B, 0x12,
+       0xDE, 0x24, 0x4F, 0x85, 0x8D, 0xD3, 0xB3, 0xFC, 0xF4, 0xA4, 0x53, 0xD0, 0x2F, 0x57, 0x07, 0xEC,
+       0x28, 0xD7, 0x2E, 0x07, 0xCD, 0xEF, 0xDC, 0x6F, 0xC2, 0xA8, 0x48, 0x52, 0x15, 0xFA, 0x57, 0x26,
+       0xA8, 0xA3, 0x30, 0x10, 0xE1, 0x4D, 0xD2, 0x33, 0xCF, 0x0B, 0xF8, 0x73, 0x36, 0xE6, 0xE4, 0x6A,
+       0xED, 0x1C, 0xCD, 0xCB, 0xD1, 0xC8, 0x36, 0x3E, 0x68, 0xE7, 0xF4, 0xD2, 0xFE, 0xE6, 0x4C, 0x5B,
+       0xED, 0xE8, 0x85, 0xA3, 0x0D, 0x1C, 0xB3, 0xBC, 0x6A, 0x2B, 0x8B, 0x59, 0xD3, 0x32, 0x49, 0xE2,
+       0x22, 0x08, 0x8B, 0x22, 0xB2, 0x6D, 0x9B, 0x9A, 0xA2, 0x2F, 0xA2, 0xE1, 0x54, 0x73, 0xDD, 0x9C,
+       0xED, 0x58, 0xD8, 0x5C, 0xFD, 0x7B, 0x55, 0xFC, 0x0B, 0xC6, 0x23, 0x7D, 0x80, 0x77, 0x11, 0x2A,
+       0xCA, 0x2D, 0x93, 0x90, 0x3D, 0xEB, 0xF3, 0xDE, 0xCD, 0xF0, 0x3A, 0x37, 0x6F, 0x19, 0xA4, 0x0E,
+       0x37, 0x54, 0x17, 0x51, 0xCE, 0x0A, 0x53, 0x48, 0xFD, 0x29, 0x6F, 0x97, 0x5E, 0xD7, 0x65, 0x58,
+       0x8D, 0xAB, 0x38, 0x68, 0xD3, 0x10, 0xE2, 0x19, 0xAA, 0x91, 0x79, 0xB4, 0xD7, 0x0C, 0x6D, 0x29,
+       0xA2, 0xA9, 0x64, 0x36, 0x08, 0x19, 0x5D, 0xB2, 0x5F, 0x5D, 0x01, 0x24, 0x5E, 0xFD, 0x59, 0x7D,
+       0x92, 0x29, 0xBB, 0xFE, 0xC5, 0xEA, 0x29, 0x90, 0x6B, 0x59, 0x6D, 0x1C, 0x53, 0xE4, 0xA0, 0x9D,
+       0xD2, 0x2C, 0x83, 0xBA, 0x2F, 0xC4, 0xAE, 0x30, 0x65, 0xEC, 0xB4, 0x7F, 0x3E, 0x3E, 0xA4, 0x22,
+       0x92, 0xA2, 0xF2, 0xA9, 0xEF, 0x9B, 0xB4, 0x1D, 0x76, 0xF9, 0xA1, 0x92, 0x99, 0xA9, 0xED, 0x2D,
+       0x77, 0x0D, 0xAA, 0x1A, 0xEB, 0x5A, 0x65, 0x6F, 0x09, 0x76, 0x6A, 0x9A, 0x52, 0x32, 0x8D, 0x7F,
+       0x09, 0x1F, 0x2B, 0x82, 0xA2, 0x7F, 0xF7, 0xF6, 0x90, 0xD6, 0xF2, 0x49, 0x21, 0x47, 0xF9, 0x99,
+       0x25, 0xCB, 0x00, 0x8A, 0x6A, 0xBC, 0x4D, 0x3B, 0xB8, 0x0E, 0x68, 0x22, 0x70, 0x67, 0x23, 0x23,
+       0x82, 0xAE, 0xCB, 0xCD, 0x6E, 0x2B, 0xDA, 0x78, 0x8A, 0x9B, 0x66, 0x9D, 0x2B, 0x81, 0x8A, 0xCC,
+       0x0D, 0x25, 0x26, 0x1E, 0xA4, 0xF7, 0xF5, 0xB0, 0xB0, 0xD3, 0x9F, 0xA5, 0x5F, 0x4C, 0xB8, 0xBC,
+       0xAA, 0x25, 0xAF, 0xC5, 0x92, 0xE9, 0x76, 0x0F, 0x64, 0x1D, 0x34, 0x51, 0xAC, 0x2D, 0x52, 0x04,
+       0x49, 0xFA, 0xB2, 0xD5, 0x1E, 0x2E, 0x2B, 0x9E, 0xF3, 0xB6, 0xB7, 0x23, 0xC9, 0xFB, 0xC8, 0x93,
+       0x65, 0xAF, 0xCF, 0x17, 0xBA, 0x6B, 0x99, 0x5C, 0xB4, 0xC3, 0xD8, 0x74, 0x8D, 0x3B, 0xF1, 0xEB,
+       0x14, 0x15, 0x8A, 0x05, 0xCD, 0x09, 0x75, 0xF8, 0x70, 0x05, 0xE7, 0xEF, 0xA3, 0x7D, 0xCC, 0xDC,
+       0x56, 0x84, 0xB0, 0x45, 0xED, 0x6D, 0xF1, 0xCB, 0x5F, 0x4B, 0x3F, 0x2F, 0x20, 0x8B, 0xC3, 0x52,
+       0xB1, 0x77, 0xF8, 0xEC, 0x4E, 0x51, 0xD2, 0xAD, 0x87, 0x54, 0xE3, 0xF1, 0xC5, 0xCA, 0x43, 0x34,
+       0xEB, 0x9F, 0x4F, 0x20, 0x14, 0x7F, 0xF9, 0x36, 0x05, 0x9C, 0xBB, 0x2B, 0xE1, 0x1B, 0x01, 0x2C,
+       0x8F, 0xEB, 0x08, 0x16, 0x64, 0x15, 0x8F, 0x70, 0xDF, 0xEE, 0x56, 0xCB, 0x6D, 0x75, 0x51, 0x4D,
+       0x6F, 0xF6, 0xE4, 0x0D, 0x56, 0x31, 0xAB, 0xCF, 0xD5, 0x27, 0xC6, 0x2B, 0x80, 0xE0, 0x5C, 0xFD,
+       0xFB, 0x76, 0x7F, 0x8B, 0x73, 0x78, 0x50, 0x4C, 0xE2, 0x4E, 0x4F, 0xF4, 0x32, 0x72, 0x97, 0xBB,
+       0x07, 0x01, 0x63, 0x1E, 0x7E, 0xFD, 0xDA, 0xA6, 0x99, 0x00, 0x0E, 0x32, 0x8D, 0x66, 0xCE, 0xF6,
+       0x6B, 0x18, 0xF0, 0x08, 0xDE, 0x37, 0x33, 0x4A, 0x89, 0x7D, 0x17, 0x96, 0xB0, 0xB6, 0x59, 0x37,
+       0x2A, 0xAF, 0xF0, 0x72, 0x81, 0xA9, 0x49, 0xEB, 0x40, 0xF4, 0x96, 0x85, 0x6A, 0x71, 0xAC, 0x38,
+       0xDD, 0x25, 0xFA, 0xF8, 0x70, 0xDE, 0x0A, 0xA5, 0x48, 0x98, 0xB0, 0x7D, 0x78, 0x7A, 0x4D, 0xFD,
+       0xC4, 0x09, 0x8F, 0x7C, 0xAF, 0x39, 0x0F, 0xEA, 0xEA, 0xA8, 0x13, 0xD9, 0x80, 0x53, 0x58, 0x0B,
+       0x2B, 0x53, 0x27, 0x55, 0x27, 0xCE, 0xBC, 0x5F, 0x2F, 0x46, 0xC6, 0x0D, 0xBA, 0xE4, 0x1F, 0x1E,
+       0x49, 0x67, 0x69, 0x2D, 0xDA, 0xB5, 0x29, 0xB0, 0x80, 0xAA, 0xF2, 0x2E, 0xE7, 0xE7, 0x3D, 0x62,
+       0x44, 0x21, 0xB5, 0xD8, 0xF6, 0xA8, 0x88, 0x4D, 0x93, 0x0D, 0x4D, 0x51, 0xC3, 0xA9, 0x42, 0x6D,
+       0x25, 0x52, 0xBA, 0x0E, 0x71, 0x66, 0xAA, 0xED, 0xF2, 0xAF, 0xDC, 0xFC, 0xDB, 0xEF, 0xC4, 0x01,
+       0x51, 0x44, 0xF8, 0x90, 0x62, 0x32, 0x70, 0xB2, 0x85, 0x08, 0x05, 0x5E, 0x27, 0xE3, 0x6C, 0xD7,
+       0x6B, 0x02, 0x40, 0x78, 0x33, 0x22, 0xD2, 0x1A, 0xCA, 0xFA, 0x28, 0x89, 0x9B, 0x61, 0xD5, 0x97,
+       0x78, 0xEA, 0xEC, 0x05, 0x91, 0x03, 0xB5, 0xE8, 0x1E, 0x3D, 0xC3, 0xEF, 0xEA, 0xBF, 0x1E, 0x0E,
+       0x38, 0x0B, 0xAA, 0x18, 0x81, 0xBF, 0x0C, 0x95, 0x4A, 0xBD, 0x0E, 0xF0, 0xE5, 0x72, 0xAE, 0xE8,
+       0x3A, 0x7F, 0x0E, 0x5D, 0x0E, 0x45, 0x46, 0xB3, 0xCB, 0xCE, 0xF3, 0x8D, 0x8E, 0x3B, 0x77, 0xA8,
+       0x0F, 0x1E, 0x9E, 0xB9, 0x5C, 0xD4, 0xE6, 0x4F, 0xCC, 0xFB, 0x07, 0x04, 0xE2, 0xEF, 0xC4, 0xBB,
+       0x65, 0x87, 0x8C, 0xFA, 0x54, 0x25, 0x17, 0xC6, 0xF0, 0x96, 0xC6, 0x9E, 0x08, 0xE3, 0x71, 0xD6,
+       0xD5, 0x2B, 0xB0, 0x92, 0x10, 0x6F, 0x1D, 0xF6, 0xB4, 0x6E, 0xFC, 0x5E, 0x3C, 0x8F, 0x49, 0x7C,
+       0xD2, 0xA7, 0x52, 0xCC, 0xAA, 0xDE, 0xDF, 0x1B, 0x2B, 0x85, 0x29, 0x76, 0xC0, 0x04, 0xAC, 0xF1,
+       0xD2, 0x13, 0x60, 0x6F, 0xE7, 0x1D, 0xAE, 0xE8, 0xA4, 0x1E, 0xA1, 0xC1, 0x24, 0x9B, 0xD4, 0xC3,
+       0x7C, 0xFC, 0x64, 0x14, 0x80, 0xE6, 0x57, 0x0D, 0x3A, 0x93, 0x57, 0xBF, 0xC4, 0x24, 0x2B, 0xCE,
+       0xDC, 0x2E, 0xD6, 0xDE, 0x80, 0x90, 0x8B, 0xB0, 0x6D, 0xF2, 0xDF, 0x65, 0x34, 0x7C, 0xCC, 0xF4,
+       0x43, 0xBE, 0x37, 0x84, 0xBB, 0x98, 0x8A, 0x9D, 0x29, 0x03, 0x01, 0xDB, 0x90, 0x8C, 0x0D, 0x8A,
+       0x20, 0xDC, 0x28, 0x1E, 0x3B, 0x14, 0x30, 0xD7, 0xFB, 0x65, 0x2A, 0x63, 0x69, 0x01, 0xCE, 0xA7,
+       0xA7, 0x09, 0xDB, 0x25, 0xD2, 0x4F, 0x37, 0x21, 0x1F, 0x8A, 0x1D, 0x7F, 0x10, 0xC0, 0x01, 0x44,
+       0x28, 0x18, 0x43, 0x99, 0x11, 0x0F, 0x49, 0x21, 0x1A, 0x5A, 0x39, 0x76, 0x6A, 0x33, 0xBB, 0x4F,
+       0x2E, 0x16, 0xE2, 0xF9, 0x36, 0x59, 0xB4, 0xA7, 0x17, 0x6B, 0x47, 0xF1, 0x52, 0x6B, 0x4B, 0xF0,
+       0x2D, 0x79, 0x83, 0x73, 0x13, 0x65, 0xF0, 0x15, 0x43, 0xA3, 0xCD, 0xD7, 0xE8, 0xB5, 0x7B, 0x42,
+       0xFA, 0xB4, 0xFF, 0xCF, 0x87, 0xB5, 0x3E, 0x3D, 0xE2, 0xDD, 0x69, 0x0F, 0xA2, 0xD3, 0xC9, 0x13,
+       0xD2, 0xBC, 0xB0, 0x98, 0xE4, 0xBD, 0x3D, 0x89, 0xE3, 0x10, 0xB3, 0xB3, 0x6F, 0x6B, 0x94, 0xF3,
+       0x5A, 0x2E, 0xB4, 0x9A, 0x1E, 0x01, 0x6C, 0x73, 0xC9, 0xF3, 0x18, 0x4A, 0xC4, 0x9C, 0xC9, 0x93,
+       0xE2, 0x52, 0x6F, 0xD5, 0x54, 0x49, 0x52, 0xA6, 0xD2, 0xF7, 0x07, 0x88, 0xBC, 0xCD, 0x9E, 0x6E,
+       0x7B, 0x91, 0x26, 0x25, 0x81, 0x36, 0x5A, 0x56, 0xCF, 0x53, 0xCC, 0x67, 0xA7, 0xEB, 0x35, 0x4A,
+       0x65, 0x5D, 0x95, 0xF2, 0xCE, 0x96, 0x07, 0x4D, 0xF0, 0x90, 0xE6, 0x04, 0x07, 0x0D, 0xAC, 0x76,
+       0xA6, 0x41, 0xC7, 0xD7, 0xD4, 0x58, 0xD9, 0x37, 0xD7, 0x8A, 0x6D, 0x12, 0x9F, 0xAC, 0x08, 0x49,
+       0x97, 0x63, 0x46, 0x1D, 0x93, 0xD0, 0x04, 0xF9, 0xA1, 0x21, 0xE0, 0x71, 0x4F, 0x70, 0xD5, 0xF4,
+       0xB5, 0xD1, 0x64, 0x8F, 0xAE, 0x3B, 0x81, 0x85, 0x55, 0x42, 0x02, 0x4B, 0x83, 0x2A, 0xAE, 0xE0,
+       0x11, 0x7B, 0xF1, 0x9E, 0x39, 0x7E, 0x26, 0x1D, 0x77, 0x5B, 0x6B, 0x27, 0x64, 0x8F, 0x47, 0x74,
+       0x95, 0x6A, 0xF9, 0xDC, 0xA2, 0x5C, 0xDB, 0x31, 0xC6, 0xD8, 0x04, 0xDE, 0x3D, 0x00, 0x2D, 0xDF,
+       0xCD, 0xF8, 0x9A, 0x4C, 0xEE, 0xF5, 0x43, 0xA4, 0xD9, 0x20, 0x75, 0x74, 0xA0, 0xDF, 0x85, 0x10,
+       0xEA, 0xF4, 0xF9, 0x52, 0x4C, 0xF8, 0xC0, 0xD1, 0xA4, 0xA1, 0x52, 0x97, 0xA7, 0x9C, 0x79, 0x10,
+       0x4D, 0x56, 0x36, 0x50, 0xF4, 0xB0, 0xC9, 0xA2, 0x9A, 0xF4, 0xC1, 0x69, 0x3F, 0xA0, 0x5A, 0x90,
+       0xBA, 0xA2, 0x97, 0xBD, 0x66, 0x6C, 0x08, 0x53, 0x54, 0xF4, 0xB6, 0x79, 0x67, 0x7A, 0x30, 0xC0,
+       0xB1, 0x1D, 0x9D, 0x14, 0xBA, 0x73, 0x49, 0xC3, 0xE0, 0xD9, 0xD4, 0x01, 0xBB, 0x19, 0x44, 0x51,
+       0xFB, 0xAE, 0x29, 0xB9, 0x9C, 0x67, 0x65, 0x4A, 0xE2, 0x60, 0x9F, 0xEF, 0x34, 0x05, 0x0F, 0xA5,
+       0x7B, 0x65, 0xE4, 0x6F, 0x9F, 0xB2, 0x0D, 0x83, 0xF0, 0x89, 0xAC, 0x31, 0xAB, 0x4A, 0x6C, 0xEA,
+       0x3C, 0xD3, 0xFF, 0x40, 0x5B, 0xBB, 0xE7, 0x6B, 0x44, 0xE8, 0xFF, 0xAE, 0x6A, 0x1D, 0xFB, 0x6E,
+       0xC0, 0x28, 0x04, 0x8F, 0x85, 0xA6, 0x48, 0x4F, 0x81, 0xFB, 0x79, 0x21, 0x3F, 0xB9, 0x4E, 0x30,
+       0xEE, 0xFE, 0x65, 0x19, 0xC0, 0x6F, 0x84, 0xA2, 0xEB, 0xAB, 0xE0, 0xCA, 0x1D, 0x18, 0x09, 0x7B,
+       0x92, 0x8E, 0xFB, 0x5C, 0x08, 0x8A, 0x36, 0xFF, 0x97, 0x58, 0x10, 0x37, 0x83, 0x88, 0xCE, 0xD9,
+       0xF7, 0x59, 0x49, 0x5B, 0x53, 0xF3, 0xC8, 0xAF, 0xEA, 0x9A, 0x48, 0x63, 0xC8, 0xD6, 0xB9, 0x45,
+       0x70, 0x50, 0x10, 0x1D, 0x5A, 0x67, 0x4B, 0xFA, 0xB7, 0xA9, 0x47, 0xC3, 0x97, 0x6A, 0xC6, 0xE7,
+       0x06, 0x86, 0x22, 0xC9, 0xE2, 0x27, 0x99, 0x84, 0x19, 0x08, 0xBE, 0x24, 0x9C, 0xEF, 0xA5, 0x35,
+       0x2C, 0xBA, 0x3C, 0xA5, 0xA3, 0x7C, 0xAC, 0xB3, 0xAF, 0x04, 0xCC, 0x45, 0x0F, 0xEE, 0x26, 0xF3,
+       0x55, 0x27, 0x1F, 0x73, 0x1F, 0xD3, 0x5E, 0x55, 0x90, 0xFF, 0xE7, 0x77, 0x0C, 0x8F, 0x90, 0xB1,
+       0x24, 0x22, 0x5C, 0x07, 0xE8, 0xDB, 0xEE, 0x60, 0x77, 0x1F, 0xB3, 0x5D, 0x84, 0x44, 0xEF, 0xC3,
+       0x99, 0xD1, 0x56, 0x44, 0xCE, 0xE4, 0x0E, 0xB8, 0xAE, 0x46, 0x47, 0xE7, 0xFA, 0x79, 0x96, 0x2C,
+       0x63, 0x5D, 0x7E, 0x86, 0xD6, 0x0F, 0x97, 0xB2, 0x6C, 0xC5, 0xFA, 0x8A, 0xC1, 0xF8, 0x65, 0xD3,
+       0xA0, 0x83, 0xC1, 0xDD, 0x8D, 0xE2, 0x6F, 0xF6, 0xC3, 0xA4, 0x73, 0x27, 0xDE, 0x6F, 0x4E, 0x04,
+       0xDB, 0x18, 0xC9, 0x1D, 0x56, 0xC5, 0x31, 0xAA, 0xC5, 0x10, 0x8D, 0xEE, 0x79, 0xC9, 0x6D, 0x79,
+       0x05, 0x83, 0x30, 0x71, 0x08, 0x46, 0xA1, 0x3E, 0xF7, 0xEB, 0x20, 0x0C, 0xA4, 0x79, 0x7C, 0x0E,
+       0x12, 0x62, 0x15, 0x5D, 0x18, 0x37, 0xB4, 0x7D, 0xF3, 0x6F, 0x2A, 0x83, 0xC7, 0x26, 0xB1, 0x03,
+       0xD1, 0x52, 0x30, 0x1F, 0x0E, 0x69, 0x96, 0x44, 0x16, 0xC4, 0x4B, 0x07, 0x5B, 0xE3, 0xC6, 0x58,
+       0xFC, 0xB9, 0xAB, 0x64, 0x1C, 0x3C, 0x56, 0x79, 0x63, 0xBF, 0xCF, 0x5F, 0x43, 0x10, 0x49, 0xEA,
+       0x96, 0x67, 0xA0, 0xBD, 0x8A, 0xFA, 0xE1, 0xB9, 0xEF, 0xF3, 0x2C, 0x27, 0x0C, 0xFC, 0xEE, 0x4E,
+       0x86, 0xD7, 0xD4, 0x8C, 0x1E, 0xD5, 0x21, 0x7B, 0x58, 0xB2, 0x1C, 0xC9, 0x38, 0x59, 0xD1, 0x34,
+       0x5A, 0x88, 0x75, 0xE5, 0x95, 0x7E, 0x22, 0xA5, 0x25, 0x75, 0xB6, 0xDC, 0xC1, 0xF7, 0x22, 0x38,
+       0x75, 0x19, 0xBD, 0xE2, 0xF3, 0x45, 0xBF, 0x6F, 0x09, 0x44, 0xD4, 0x1F, 0xDF, 0x6C, 0x7C, 0x5A,
+       0x5A, 0xA2, 0x9D, 0x58, 0xB5, 0x6E, 0xA3, 0x95, 0xC4, 0x98, 0x4B, 0xF2, 0x14, 0x78, 0xD8, 0x92,
+       0xC8, 0x6A, 0xDF, 0x8F, 0xC1, 0xC8, 0xB3, 0x6B, 0xC4, 0x23, 0x61, 0xC3, 0x2D, 0xAB, 0x42, 0x27,
+       0x00, 0xFC, 0x5F, 0xD5, 0x41, 0x6F, 0x05, 0xD0, 0x84, 0xA1, 0x78, 0xE4, 0x14, 0x32, 0x3A, 0x17,
+       0xCA, 0x34, 0xAF, 0x2C, 0x09, 0x25, 0xB6, 0x85, 0x5D, 0xCE, 0xF7, 0x90, 0x50, 0x50, 0x00, 0x6C,
+       0xE1, 0xAA, 0x35, 0x23, 0xC3, 0xAE, 0x51, 0xC1, 0xD4, 0x35, 0x79, 0xF2, 0xE2, 0xAA, 0x46, 0xE5,
+       0x9F, 0xF0, 0xDE, 0xE4, 0x88, 0xB8, 0x61, 0x0B, 0x6A, 0x48, 0x22, 0x40, 0x11, 0x48, 0x5C, 0x80,
+       0xF6, 0xBD, 0x59, 0xB5, 0x27, 0x0E, 0x61, 0x29, 0x1E, 0xAB, 0xD3, 0x15, 0x27, 0x37, 0x19, 0x93,
+       0x9E, 0x85, 0x6B, 0xFB, 0xB2, 0x06, 0x3F, 0x0A, 0xE2, 0xED, 0x28, 0x60, 0x20, 0x35, 0x82, 0xFB,
+       0x54, 0xA1, 0xD1, 0x4D, 0xBC, 0xC4, 0x67, 0x5B, 0x2A, 0x4E, 0x71, 0xF4, 0x18, 0x2D, 0xCD, 0x8A,
+       0x8E, 0xE4, 0x7E, 0x41, 0xCA, 0xA1, 0xC1, 0x03, 0x3C, 0x40, 0x49, 0xEB, 0x74, 0xEA, 0xFC, 0x08,
+       0x30, 0x99, 0x9E, 0x7D, 0x30, 0x11, 0x7F, 0xA2, 0x67, 0x67, 0xB4, 0xCE, 0x7B, 0x65, 0xF5, 0xF8,
+       0xC7, 0xBF, 0x24, 0xFF, 0x88, 0x48, 0xE9, 0xCD, 0xFB, 0xF1, 0x2D, 0xBA, 0xB1, 0xC0, 0x50, 0x5D,
+       0x0B, 0xE5, 0x23, 0xDC, 0x43, 0x52, 0x64, 0x76, 0xDB, 0xC4, 0x74, 0xD9, 0x80, 0xDA, 0x72, 0x45,
+       0x08, 0xCC, 0x80, 0xA3, 0x8C, 0xD5, 0x99, 0x64, 0x51, 0x5A, 0xFE, 0x02, 0xA9, 0xBB, 0x8C, 0xF5,
+       0x0B, 0xC6, 0x88, 0x76, 0xD5, 0x07, 0x6E, 0x63, 0x3C, 0xDC, 0x59, 0x2C, 0x05, 0xC6, 0xAE, 0x7D,
+       0x5B, 0xC2, 0xF5, 0x4D, 0x16, 0x74, 0x47, 0xCD, 0x05, 0xB8, 0xC8, 0x31, 0x94, 0x4C, 0x8E, 0xB8,
+       0x50, 0xCD, 0xE8, 0x2C, 0x7B, 0x52, 0x60, 0xF7, 0x89, 0xF9, 0xC3, 0x25, 0x52, 0x94, 0x17, 0x23,
+       0xC9, 0x07, 0xA4, 0x7F, 0xBA, 0x15, 0xB8, 0x20, 0x39, 0xAA, 0x6E, 0xF9, 0xF7, 0x1F, 0xCD, 0x8C,
+       0xF6, 0xA3, 0xF9, 0x34, 0x02, 0xDB, 0xC6, 0x10, 0x7A, 0x28, 0x33, 0x09, 0x5E, 0x65, 0x68, 0x08,
+       0xF2, 0xC2, 0x84, 0xCD, 0x72, 0xA1, 0x69, 0xB5, 0xA2, 0x37, 0x70, 0xC6, 0xA8, 0x32, 0x1F, 0x71,
+       0x8C, 0xCD, 0x30, 0x1A, 0xDD, 0x58, 0x7D, 0x39, 0x09, 0x92, 0xDD, 0x20, 0x14, 0x03, 0x00, 0xA8,
+       0xCF, 0xF0, 0x90, 0x0C, 0x85, 0x30, 0xC3, 0xB0, 0xDE, 0xF5, 0xF5, 0xE1, 0x69, 0x73, 0x40, 0xF3,
+       0xE1, 0xF5, 0x7C, 0x32, 0xDE, 0x8D, 0xD3, 0x9D, 0x3F, 0xD0, 0xCD, 0xF5, 0xEE, 0xAB, 0x52, 0xB1,
+       0x91, 0x02, 0x08, 0xF1, 0x36, 0xFF, 0x4F, 0x89, 0xB1, 0x99, 0x2F, 0x5A, 0x28, 0x1B, 0x90, 0x86,
+       0x06, 0x30, 0x72, 0x3D, 0x18, 0xAA, 0x6F, 0x35, 0x1E, 0x9E, 0x28, 0x4F, 0x30, 0x5A, 0x84, 0xA5,
+       0x86, 0x12, 0x33, 0x3C, 0xE3, 0xA8, 0xAD, 0x13, 0xE5, 0xB9, 0x6D, 0xBF, 0x65, 0x55, 0xB8, 0x2A,
+       0x27, 0x90, 0x3F, 0xC4, 0x9A, 0x2B, 0x4D, 0x5A, 0x69, 0xD2, 0xC6, 0x6C, 0x2F, 0xBC, 0x18, 0xC8,
+       0x98, 0x8E, 0x4C, 0xDD, 0xCA, 0x3A, 0x48, 0x80, 0x32, 0x61, 0x8C, 0x81, 0x82, 0x4A, 0x88, 0x8A,
+       0x91, 0x67, 0xEF, 0xE4, 0xD8, 0x89, 0xBE, 0x4B, 0x83, 0x7A, 0x2B, 0x58, 0x23, 0x4F, 0xF9, 0xC9,
+       0xAB, 0xE1, 0x44, 0xAA, 0x5A, 0xB5, 0x9D, 0x39, 0x71, 0x60, 0xF5, 0xA4, 0xCD, 0x9F, 0x2F, 0x76,
+       0x76, 0xCC, 0xAB, 0xA0, 0x7B, 0xA9, 0xC5, 0xCF, 0xFD, 0xF1, 0xD5, 0x88, 0x15, 0x32, 0x6C, 0x92,
+       0x2D, 0x42, 0x65, 0x06, 0xA2, 0xA7, 0xE2, 0xE6, 0xA7, 0x25, 0xA8, 0x74, 0xD1, 0x83, 0x6A, 0x97,
+       0x06, 0x0F, 0x06, 0x59, 0x57, 0x89, 0xF6, 0xFE, 0x6B, 0xE5, 0x1D, 0x7B, 0x3C, 0xF8, 0xF7, 0x5F,
+       0xCB, 0x36, 0x44, 0x12, 0x3E, 0x53, 0xD2, 0x89, 0xCE, 0x44, 0x4B, 0x1B, 0x7D, 0x42, 0xC4, 0x62,
+       0xFB, 0xE7, 0x33, 0x48, 0x09, 0xED, 0xB9, 0x80, 0xA7, 0xF5, 0x4F, 0x95, 0xD0, 0xB0, 0xFE, 0xA6,
+       0xB8, 0xA8, 0x40, 0xF5, 0x4B, 0x0D, 0x43, 0xF8, 0xE4, 0x4C, 0x64, 0x88, 0x5E, 0xF7, 0x7E, 0x6A,
+       0x1D, 0x15, 0x25, 0x50, 0x1E, 0x3B, 0x67, 0xC3, 0xF5, 0x62, 0xA3, 0xD0, 0x99, 0x82, 0xB2, 0xFE,
+       0xFB, 0xA7, 0xD2, 0x56, 0x70, 0x89, 0xAA, 0x2F, 0x99, 0x62, 0xCF, 0xE6, 0xE9, 0xCA, 0x1C, 0xE3,
+       0x91, 0x28, 0x55, 0x4B, 0xE9, 0x7A, 0xD1, 0xC2, 0xA5, 0x89, 0x61, 0x8C, 0x1E, 0x0C, 0x22, 0x96,
+       0xEF, 0x19, 0x2A, 0x10, 0x79, 0xCD, 0x3A, 0x58, 0x39, 0xA5, 0xEE, 0xAF, 0xD5, 0x70, 0x6F, 0xA9,
+       0x81, 0xCF, 0xC9, 0x77, 0xC5, 0x43, 0x9D, 0x4A, 0xAA, 0xD1, 0xC1, 0x01, 0x2E, 0x6A, 0xD7, 0xD0,
+       0x9F, 0xDE, 0x67, 0x0B, 0xB6, 0xA1, 0x4D, 0xBD, 0xE6, 0x16, 0xDD, 0xEC, 0x4A, 0x63, 0xD8, 0xBD,
+       0x41, 0xD7, 0x4F, 0xC5, 0xE5, 0x43, 0x38, 0x72, 0xA5, 0x95, 0x37, 0x4F, 0x87, 0x4C, 0xAF, 0x78,
+       0x90, 0x0F, 0x76, 0x0E, 0x49, 0xE7, 0x11, 0xF9, 0x29, 0x4E, 0x5E, 0xC8, 0x2A, 0x02, 0xC7, 0x2F,
+       0x65, 0x81, 0x11, 0x97, 0xF1, 0x84, 0x9F, 0x99, 0xA8, 0x03, 0xE0, 0x69, 0x1A, 0xE3, 0x06, 0x40,
+       0x22, 0xD0, 0xE0, 0x5D, 0xFE, 0x3E, 0xE9, 0xEA, 0x90, 0xA0, 0xE2, 0x0F, 0x13, 0x01, 0x1B, 0xC1,
+       0xBC, 0x63, 0xDD, 0x84, 0x02, 0x1D, 0xC7, 0x35, 0x90, 0xBC, 0xEF, 0x19, 0x48, 0x5F, 0x68, 0xB6,
+       0x67, 0x72, 0x26, 0xEA, 0x2B, 0x01, 0x94, 0xE5, 0x37, 0xA4, 0x44, 0x68, 0x0F, 0xD1, 0x3E, 0x28,
+       0x8E, 0x43, 0xA5, 0x39, 0xE7, 0xFF, 0xCC, 0x8D, 0x27, 0x93, 0x3F, 0x59, 0x24, 0x3B, 0x93, 0x08,
+       0x51, 0x5A, 0x9F, 0x96, 0x04, 0x4D, 0x94, 0xE5, 0xCD, 0xFB, 0x90, 0x24, 0x23, 0x0C, 0xBB, 0x44,
+       0x3C, 0xEC, 0xB4, 0x48, 0x62, 0xFC, 0x86, 0xA8, 0x21, 0xA1, 0xF4, 0xA9, 0xF9, 0x29, 0x13, 0xA3,
+       0x83, 0x82, 0xF0, 0xF9, 0x51, 0x20, 0x9C, 0x6C, 0x01, 0xB7, 0xEA, 0x10, 0xE8, 0xF6, 0xC5, 0x85,
+       0x9B, 0xAE, 0xA3, 0x21, 0x30, 0x44, 0xE3, 0xE8, 0x29, 0xE2, 0x96, 0x97, 0x53, 0x66, 0x70, 0x44,
+       0x61, 0xB8, 0xDB, 0xA6, 0xED, 0xF5, 0x7A, 0x1E, 0x82, 0xC2, 0x42, 0x53, 0x27, 0xD7, 0x49, 0x77,
+       0x29, 0xCA, 0x6F, 0x41, 0x3A, 0xDB, 0xB2, 0x3B, 0xD6, 0xF8, 0x1F, 0xC5, 0xD2, 0x83, 0xEE, 0xD1,
+       0xFA, 0xF2, 0x79, 0x54, 0x8D, 0xB3, 0x36, 0x34, 0xA9, 0x07, 0x8E, 0x10, 0xB2, 0xEE, 0x7E, 0x55,
+       0x89, 0x79, 0x6E, 0x3B, 0xF0, 0xD6, 0x6A, 0xB7, 0x78, 0x7D, 0xF6, 0xB3, 0x4E, 0xAA, 0xFA, 0x36,
+       0x12, 0x64, 0xBE, 0x82, 0x33, 0x74, 0xAC, 0x5F, 0x9B, 0x17, 0xA2, 0x5B, 0x9E, 0x10, 0xCE, 0x89,
+       0xC2, 0x30, 0x20, 0x63, 0x60, 0xA0, 0x89, 0xA5, 0x26, 0xD6, 0x88, 0xF4, 0x5D, 0x14, 0xB9, 0xC1,
+       0x4C, 0x13, 0xBB, 0x39, 0xED, 0x4E, 0x16, 0x32, 0x4C, 0xDF, 0x82, 0xA4, 0xEA, 0xA6, 0x21, 0xA7,
+       0xA7, 0x20, 0xF8, 0xD4, 0x0F, 0xA7, 0x76, 0x5B, 0x31, 0x62, 0xCF, 0xD6, 0xFF, 0x92, 0x9A, 0xBA,
+       0xDE, 0xAF, 0x4A, 0xA2, 0xB7, 0x82, 0x10, 0x96, 0x5A, 0x15, 0x6A, 0x55, 0xE7, 0x71, 0x16, 0x3E,
+       0x25, 0x4F, 0x64, 0x47, 0x44, 0x60, 0xBC, 0x3D, 0x4A, 0x77, 0x1F, 0xC8, 0x1B, 0xF6, 0x9A, 0x0D,
+       0x6E, 0x7E, 0x25, 0x5E, 0x28, 0x29, 0x19, 0x40, 0xAE, 0x27, 0x83, 0x05, 0x7C, 0xF8, 0xBA, 0x3D,
+       0x96, 0x5C, 0x39, 0x9C, 0xEE, 0x9B, 0xDF, 0xD2, 0x9A, 0xAC, 0xAF, 0x36, 0x45, 0xB4, 0x65, 0x11,
+       0x2E, 0x4F, 0xAF, 0xC5, 0xFF, 0xAE, 0x69, 0xA7, 0x78, 0x39, 0x6B, 0x5D, 0x35, 0x79, 0x06, 0x28,
+       0x19, 0x9E, 0x35, 0x6A, 0xDE, 0x2D, 0x15, 0xA3, 0x1A, 0x12, 0x32, 0xCF, 0x76, 0x45, 0xA8, 0x8A,
+       0xA4, 0xB2, 0x3D, 0xEC, 0xFC, 0x17, 0x1E, 0x90, 0x31, 0x7D, 0x79, 0xED, 0x3E, 0x87, 0x79, 0x51,
+       0x29, 0xDF, 0x90, 0x94, 0x24, 0x0E, 0x41, 0x68, 0x73, 0xA5, 0xED, 0x20, 0xF8, 0x28, 0x48, 0xCC,
+       0xCC, 0x46, 0x3B, 0x20, 0xBF, 0x1A, 0xDB, 0x03, 0x78, 0xE4, 0x5A, 0xE2, 0xA1, 0xA4, 0x86, 0x3D,
+       0x47, 0xA3, 0x19, 0x6F, 0xE3, 0x30, 0xF9, 0x59, 0xF6, 0xEB, 0xE6, 0xEB, 0x7A, 0x65, 0x30, 0xF1,
+       0x5A, 0xDF, 0xA8, 0x41, 0x87, 0x01, 0x19, 0x6B, 0x1B, 0xC8, 0x4B, 0xFA, 0x79, 0x89, 0x69, 0xC7,
+       0xA2, 0xD3, 0xD8, 0xF3, 0x7F, 0xE2, 0x1C, 0x32, 0x98, 0x42, 0x23, 0xD1, 0x47, 0x50, 0x6D, 0x91,
+       0x46, 0xB3, 0xB4, 0xB6, 0xE3, 0x17, 0x23, 0xC1, 0x97, 0x07, 0x9A, 0x77, 0x8F, 0x68, 0x8A, 0x0B,
+       0xA8, 0x4B, 0x81, 0x2D, 0xF4, 0x9C, 0x20, 0x67, 0x2D, 0xC5, 0x36, 0xF7, 0x43, 0xB2, 0xE7, 0x5D,
+       0xD3, 0xD9, 0x44, 0x34, 0x6B, 0xFF, 0x9E, 0x47, 0x12, 0xCB, 0xBD, 0x2E, 0x0A, 0x86, 0x6A, 0xFE,
+       0x94, 0x82, 0x46, 0xC6, 0x44, 0xB2, 0xB3, 0x75, 0x5C, 0x2E, 0x08, 0xA5, 0xBE, 0x98, 0x3D, 0x98,
+       0x08, 0x07, 0xA8, 0x77, 0x0F, 0x78, 0xB6, 0xF0, 0x82, 0x30, 0x52, 0xEF, 0xC5, 0x65, 0xDA, 0xA7,
+       0x63, 0x52, 0xF1, 0x6D, 0x64, 0x1C, 0xBC, 0x9E, 0xEA, 0x38, 0x7A, 0x76, 0x01, 0xC8, 0x76, 0x93,
+       0xEC, 0x39, 0x56, 0x20, 0x2A, 0x39, 0xC7, 0x91, 0x57, 0x7C, 0x5A, 0xFC, 0x25, 0x60, 0xE0, 0x3D,
+       0x01, 0x59, 0xB9, 0x3C, 0xFC, 0x85, 0xD3, 0x5D, 0x75, 0x13, 0xDB, 0x47, 0x5B, 0xF7, 0xBD, 0x96,
+       0x09, 0xDB, 0x97, 0xBE, 0x96, 0x97, 0xE1, 0xCB, 0x4A, 0x11, 0xE4, 0xEE, 0xCE, 0xC5, 0x1F, 0x53,
+       0xAA, 0x5F, 0xCF, 0x0C, 0x37, 0xBF, 0xC3, 0xEC, 0xDA, 0x21, 0xA6, 0xA9, 0x5D, 0xCF, 0x84, 0xBF,
+       0xC3, 0x30, 0x3C, 0x0D, 0x1C, 0x11, 0x5F, 0x63, 0x94, 0x88, 0x05, 0xBF, 0x33, 0xA5, 0xD2, 0x75,
+       0xDD, 0xD9, 0x20, 0xA1, 0x4F, 0x11, 0x75, 0x29, 0xA9, 0x72, 0x60, 0x35, 0xF1, 0x90, 0xDA, 0xFE,
+       0x4D, 0xFD, 0xB2, 0x10, 0xD4, 0x3D, 0x3E, 0xBF, 0x1F, 0xA1, 0xC4, 0x0F, 0x5B, 0x36, 0x6D, 0x8A,
+       0x51, 0xBF, 0x87, 0xAA, 0x12, 0xC7, 0xC4, 0xF4, 0x1B, 0x0B, 0xFF, 0xDB, 0x1B, 0x2B, 0xEF, 0x9C,
+       0x2D, 0xC5, 0x8B, 0x70, 0xD2, 0x3B, 0xFE, 0xF5, 0xB4, 0x9D, 0x08, 0x46, 0x67, 0xDD, 0xAF, 0x41,
+       0x5B, 0xC5, 0x16, 0x8F, 0xD7, 0x51, 0x4D, 0x1C, 0x71, 0x15, 0x14, 0xA7, 0x7B, 0x43, 0x3F, 0x58,
+       0x58, 0x80, 0x70, 0xDE, 0x3D, 0x9B, 0x55, 0x39, 0xA4, 0x8D, 0x59, 0xF6, 0xC8, 0xAA, 0x81, 0xA0,
+       0x78, 0x45, 0xE5, 0x44, 0xAC, 0xCF, 0xD1, 0x01, 0x52, 0x3C, 0x6C, 0x98, 0x52, 0xE6, 0xC2, 0x10,
+       0xA9, 0x48, 0x40, 0xF6, 0xB1, 0xD5, 0xFF, 0xB3, 0x6F, 0xC5, 0xCC, 0x30, 0xF4, 0x81, 0xF8, 0x7F,
+       0xAD, 0x95, 0xED, 0xB9, 0x06, 0xEB, 0x70, 0x49, 0xFD, 0xA1, 0x67, 0x33, 0xBC, 0x5A, 0x0F, 0x0F,
+       0x83, 0x8C, 0x02, 0x91, 0x7D, 0xA1, 0x74, 0x3A, 0x9E, 0x13, 0x4D, 0x50, 0x51, 0x2E, 0xA4, 0xD1,
+       0x51, 0xF3, 0x9C, 0x8F, 0x85, 0x6F, 0xED, 0x10, 0xD7, 0x1A, 0x49, 0xE4, 0x80, 0x94, 0xC0, 0xAA,
+       0x4B, 0x0C, 0x7A, 0x4D, 0xFD, 0x69, 0x89, 0x20, 0x01, 0xDD, 0xBE, 0xFF, 0xFA, 0xF4, 0x15, 0xDB,
+       0xD6, 0x8D, 0xB3, 0x3D, 0x62, 0xD4, 0xFF, 0x36, 0x24, 0xF5, 0x88, 0x67, 0xEF, 0xEB, 0x65, 0x6B,
+       0xB6, 0x69, 0x0C, 0x53, 0xA7, 0x1B, 0x6A, 0x47, 0xC3, 0xB8, 0x54, 0xBE, 0xE5, 0x65, 0xA8, 0x75,
+       0xC1, 0xAE, 0xC7, 0x15, 0x35, 0x84, 0x2C, 0xB9, 0x8E, 0x97, 0x24, 0xDF, 0x52, 0x30, 0x1C, 0x4E,
+       0xE5, 0x1E, 0xF3, 0x35, 0x8B, 0xD7, 0xFE, 0x27, 0x6C, 0x80, 0xFE, 0x20, 0xA0, 0x0E, 0x28, 0xC9,
+       0xA3, 0x15, 0xA6, 0x52, 0x77, 0x93, 0x79, 0x1F, 0x0E, 0xDC, 0xF0, 0x44, 0x2B, 0x27, 0x67, 0x9D,
+       0x50, 0x99, 0xF8, 0x6D, 0xA7, 0x78, 0x76, 0x71, 0x9D, 0xBB, 0x94, 0xA1, 0x7D, 0x5C, 0xBA, 0x9A,
+       0x66, 0xC3, 0xF9, 0x92, 0x9F, 0x42, 0x20, 0xC1, 0x9A, 0xBC, 0xC2, 0x5E, 0x91, 0xFD, 0x8D, 0xD1,
+       0x96, 0xDC, 0x41, 0x1F, 0xA0, 0x4C, 0xCC, 0x92, 0x7C, 0x81, 0x88, 0x04, 0xC6, 0xF2, 0xEE, 0x49,
+       0xA6, 0xBE, 0x61, 0x2F, 0xF2, 0x07, 0x15, 0x79, 0x53, 0x7E, 0x1A, 0x0C, 0xA0, 0x32, 0x1E, 0x7D,
+       0x69, 0x2E, 0x48, 0xA8, 0x34, 0x27, 0xF2, 0x35, 0x93, 0xE8, 0x10, 0x25, 0x6E, 0xC7, 0x07, 0xAD,
+       0xB9, 0xA0, 0x56, 0x11, 0xFF, 0xBD, 0x19, 0x97, 0x39, 0x68, 0x1C, 0xB9, 0xF5, 0x53, 0x6B, 0x37,
+       0x1C, 0x05, 0xFF, 0xF4, 0x93, 0x69, 0x9C, 0x3B, 0x7C, 0x35, 0xF7, 0xFC, 0x94, 0xFF, 0x3A, 0x1F,
+       0x62, 0x5C, 0xAF, 0x4F, 0x69, 0x24, 0xE4, 0xA9, 0x14, 0xF5, 0x3F, 0xA6, 0x68, 0x53, 0x8B, 0x42,
+       0x6F, 0xE4, 0xEE, 0x24, 0xFA, 0x7D, 0xB7, 0x71, 0x8A, 0xF0, 0x9F, 0x6E, 0xD3, 0x2B, 0x74, 0xBD,
+       0x89, 0xA6, 0x79, 0x38, 0x32, 0xAB, 0x54, 0x60, 0xEA, 0x64, 0x1E, 0xB3, 0xFC, 0x6C, 0x67, 0x91,
+       0x6E, 0x0E, 0xBE, 0xB2, 0xFA, 0x74, 0x32, 0x60, 0x74, 0x2E, 0x24, 0x2B, 0x0F, 0x15, 0x03, 0xBC,
+       0x75, 0xCC, 0x8F, 0xAD, 0xA6, 0xDF, 0xCE, 0x51, 0xBC, 0x22, 0x68, 0x24, 0x4C, 0x60, 0xA0, 0x19,
+       0xB0, 0x1B, 0x90, 0x21, 0xB7, 0x3B, 0x8C, 0xDE, 0xAB, 0xB8, 0x60, 0xDE, 0x78, 0x4E, 0x28, 0x9D,
+       0x80, 0xFD, 0x09, 0x9C, 0xC4, 0xFB, 0xCC, 0xAC, 0x58, 0x89, 0xE3, 0xC2, 0x37, 0x54, 0x7F, 0xEE,
+       0x5B, 0x1F, 0x9E, 0xF6, 0x7C, 0xF6, 0xA5, 0xA5, 0xEF, 0x91, 0x9D, 0xC1, 0x27, 0xBA, 0xBA, 0x17,
+       0xAA, 0xDF, 0x03, 0x33, 0x16, 0x7A, 0xD2, 0x85, 0x3A, 0x33, 0xE0, 0x99, 0xA4, 0xAB, 0xC3, 0x0E,
+       0xD4, 0x4B, 0x21, 0x4D, 0x0D, 0x73, 0x1A, 0x46, 0x44, 0xA9, 0x0E, 0x6E, 0xD1, 0xA3, 0x1D, 0x5E,
+       0x37, 0x8A, 0xF1, 0x56, 0x11, 0xD1, 0xF2, 0xE5, 0x62, 0x0F, 0x1E, 0xDC, 0x76, 0x2D, 0x25, 0x04,
+       0xFB, 0x34, 0x4D, 0x27, 0x9B, 0x01, 0xF0, 0x73, 0xA5, 0xBA, 0x9C, 0x1D, 0x2A, 0x00, 0x91, 0x21,
+       0x31, 0x01, 0x87, 0x2D, 0x91, 0x53, 0xE4, 0xFE, 0x88, 0xB4, 0x47, 0xF1, 0xA4, 0xC5, 0x21, 0x9C,
+       0x48, 0x88, 0x81, 0x1E, 0x83, 0x9F, 0x2E, 0x1A, 0xE8, 0xC5, 0x59, 0xBC, 0x3F, 0x43, 0xFF, 0xC4,
+       0x06, 0xF3, 0x5C, 0x04, 0x46, 0x66, 0x20, 0xDC, 0xC0, 0xC3, 0x95, 0x88, 0x54, 0xC7, 0x83, 0x3D,
+       0x4C, 0xA8, 0x6D, 0x92, 0x9A, 0x77, 0x53, 0xAE, 0x92, 0x62, 0x0B, 0xDD, 0x68, 0xA9, 0xB7, 0x7F,
+       0xAC, 0x21, 0xB0, 0x82, 0xBF, 0x53, 0x18, 0x31, 0x6F, 0x5D, 0xE5, 0xD4, 0x08, 0x50, 0x1D, 0xBE,
+       0x4D, 0xDC, 0xAC, 0xE3, 0x5A, 0xF9, 0x05, 0xBB, 0x50, 0x61, 0x1D, 0x3C, 0xF2, 0x46, 0xD6, 0x07,
+       0x17, 0x89, 0x34, 0xCB, 0x77, 0x95, 0x9E, 0xBD, 0x97, 0xEB, 0x3A, 0x20, 0x50, 0x3A, 0xCC, 0x2E,
+       0xC4, 0xFA, 0xDC, 0x99, 0xB6, 0xB0, 0x24, 0xBF, 0xDA, 0x49, 0x04, 0x9D, 0xF2, 0xFE, 0xB1, 0x87,
+       0x67, 0x9B, 0x30, 0x81, 0x55, 0x69, 0x88, 0xD3, 0x0C, 0x67, 0x9F, 0x7C, 0x06, 0x56, 0x5B, 0x40,
+       0x7F, 0x73, 0xF4, 0x58, 0x75, 0xD4, 0x2D, 0xE6, 0xA0, 0xA9, 0xE0, 0x53, 0xFD, 0xB2, 0xF1, 0x60,
+       0xDB, 0x82, 0x2F, 0x10, 0x4A, 0x0D, 0x8F, 0xD5, 0x27, 0x4F, 0x72, 0xAF, 0x2D, 0x03, 0x22, 0xA0,
+       0x72, 0xA8, 0x56, 0xD3, 0x8F, 0xBD, 0x04, 0x00, 0x45, 0x6D, 0xB0, 0x64, 0xB3, 0x0D, 0x63, 0x8F,
+       0x58, 0xF1, 0xA0, 0xE8, 0x04, 0x23, 0xF0, 0x5A, 0x07, 0x61, 0x0E, 0xDF, 0x96, 0xCB, 0x98, 0x58,
+       0x73, 0x90, 0xDF, 0xBB, 0x05, 0x30, 0x7D, 0x39, 0x19, 0xBA, 0x46, 0x8C, 0x2C, 0xA8, 0xBC, 0xA1,
+       0x12, 0xBA, 0x8B, 0x01, 0xC5, 0x0C, 0xC4, 0x60, 0x53, 0x6F, 0xD1, 0xE2, 0x03, 0x63, 0x88, 0xD5,
+       0x54, 0x0D, 0xCD, 0xD6, 0xEB, 0x7F, 0xF8, 0x1D, 0xEF, 0x50, 0x53, 0x5D, 0xC6, 0x65, 0x75, 0xB5,
+       0x5D, 0xD9, 0x62, 0xAC, 0xE7, 0x94, 0x2D, 0xA7, 0xF2, 0x50, 0x7A, 0x68, 0x9B, 0x75, 0x4E, 0xC0,
+       0xD9, 0x31, 0xB9, 0x7E, 0x99, 0xA5, 0x28, 0xB4, 0x7D, 0x64, 0xF4, 0x51, 0xBE, 0x1A, 0xBA, 0xCD,
+       0xBD, 0xCC, 0xE4, 0xE1, 0x04, 0xEA, 0xBA, 0x1C, 0x43, 0x1D, 0x6C, 0x85, 0xF7, 0xEB, 0xA2, 0x14,
+       0x07, 0xDB, 0x41, 0xD0, 0x77, 0x7A, 0x9C, 0x46, 0xF8, 0xC7, 0xF2, 0xE6, 0x9F, 0x09, 0x8D, 0x86,
+       0x0C, 0x1B, 0xFC, 0x41, 0xD5, 0xD1, 0x7E, 0x19, 0xF1, 0x8C, 0xE5, 0x1B, 0xCB, 0x8F, 0x16, 0xF5,
+       0x65, 0x48, 0xAC, 0x57, 0x1A, 0xB1, 0x5A, 0x12, 0xD9, 0xBD, 0xA6, 0xF7, 0x32, 0x3C, 0x26, 0x1A,
+       0x29, 0x05, 0xB0, 0x18, 0x16, 0xE9, 0xEB, 0xF9, 0x06, 0x74, 0xCA, 0x3B, 0xB0, 0x20, 0x6B, 0x78,
+       0x8F, 0xE2, 0x33, 0x0A, 0x3D, 0xC7, 0x90, 0x2C, 0x28, 0x8F, 0x5C, 0x4A, 0xB8, 0x1E, 0x37, 0x3D,
+       0x24, 0xF5, 0xF1, 0x05, 0x72, 0x13, 0xB9, 0xBD, 0xAC, 0x32, 0xA5, 0x68, 0x68, 0xFF, 0x7E, 0x64,
+       0xD2, 0x84, 0xA4, 0x04, 0xF5, 0xE7, 0x2D, 0xF9, 0xA0, 0xDB, 0x58, 0x80, 0x5F, 0x46, 0xFE, 0xB9,
+       0x81, 0x4C, 0x40, 0x23, 0x93, 0x09, 0x44, 0xC7, 0x5B, 0xB7, 0x1E, 0x09, 0xB9, 0x78, 0x75, 0xAE,
+       0xD6, 0xFE, 0xB7, 0x33, 0x4E, 0xE7, 0x8A, 0x24, 0x2F, 0x3B, 0xB7, 0x2A, 0xC2, 0x76, 0x60, 0x6B,
+       0x70, 0x23, 0xA3, 0x87, 0x2F, 0xFA, 0xE2, 0x57, 0xDA, 0x4D, 0x10, 0xB9, 0x64, 0x65, 0xE5, 0x68,
+       0x3C, 0x83, 0xB9, 0x1D, 0xA5, 0x1B, 0xF3, 0xEC, 0x60, 0x6A, 0x75, 0x6D, 0x2D, 0x7D, 0xE5, 0x25,
+       0x5A, 0x4E, 0x4E, 0xB4, 0xF1, 0xFE, 0xA4, 0x42, 0xB2, 0x90, 0x7F, 0xA7, 0xEF, 0x50, 0xB9, 0xAC,
+       0xB6, 0x55, 0xE1, 0xD5, 0x96, 0x5C, 0x71, 0x8F, 0x62, 0xAD, 0xC3, 0x2B, 0xC9, 0xD8, 0x02, 0xCE,
+       0xD5, 0x59, 0xC1, 0xB6, 0x64, 0x20, 0x63, 0xE3, 0xE6, 0x61, 0x15, 0x01, 0x8A, 0xE7, 0xD1, 0xB0,
+       0xBA, 0xD9, 0x4E, 0x22, 0x1E, 0x7C, 0x12, 0x1B, 0xBC, 0xF3, 0x01, 0x01, 0x3D, 0x50, 0xC9, 0x72,
+       0xC4, 0x61, 0xF1, 0xC8, 0x46, 0x7D, 0x59, 0x0B, 0x7F, 0x93, 0x2E, 0x2F, 0xF1, 0x37, 0xBD, 0x0A,
+       0x4B, 0x0B, 0x5A, 0xD6, 0x6B, 0xAE, 0x58, 0x07, 0x00, 0xD8, 0x28, 0x20, 0x45, 0xD7, 0x5A, 0xED,
+       0x3F, 0xFE, 0x71, 0x98, 0xD9, 0xAB, 0x05, 0x4A, 0xB1, 0xC5, 0xEA, 0x43, 0x42, 0xC0, 0x4D, 0xDD,
+       0xAD, 0x0A, 0x6F, 0xA0, 0x54, 0x21, 0x13, 0x8F, 0x7B, 0x87, 0x05, 0x7A, 0x9D, 0x53, 0x7E, 0x69,
+       0xD3, 0x0E, 0x7E, 0x05, 0xAF, 0x6B, 0x67, 0xB0, 0x74, 0x62, 0x7F, 0x1D, 0x9E, 0x6B, 0x79, 0x41,
+       0x28, 0x05, 0x67, 0xC9, 0xF2, 0xA3, 0x04, 0x53, 0xC6, 0xB4, 0x11, 0x8A, 0x1F, 0xC2, 0xC3, 0xBA,
+       0x68, 0xBC, 0x71, 0x43, 0x32, 0x64, 0x58, 0x92, 0x06, 0x84, 0x73, 0x2C, 0xE6, 0x67, 0x3E, 0x87,
+       0x34, 0x5F, 0x3D, 0xC8, 0x79, 0xE4, 0xD6, 0xBE, 0x35, 0xA0, 0x47, 0x32, 0x8C, 0xE8, 0x56, 0x71,
+       0x9E, 0x16, 0xA7, 0x41, 0x24, 0xC7, 0x54, 0x09, 0xC6, 0xD9, 0xC2, 0x8A, 0x4B, 0x13, 0xC4, 0xD0,
+       0x5A, 0x0C, 0xFF, 0x96, 0xA1, 0xE9, 0xE4, 0xD9, 0x8D, 0x16, 0x26, 0x16, 0xDD, 0x64, 0xE7, 0x82,
+       0x86, 0xB3, 0xD0, 0x4C, 0x34, 0x64, 0x07, 0x3C, 0x01, 0x7A, 0xB4, 0x85, 0xC0, 0xF7, 0xED, 0x36,
+       0x77, 0x10, 0x7C, 0x56, 0xD7, 0xBB, 0x1E, 0x8A, 0x64, 0x91, 0x26, 0x4F, 0x18, 0x80, 0x3E, 0xB1,
+       0x21, 0xCD, 0x56, 0x44, 0x9C, 0xA1, 0x9A, 0x54, 0xCA, 0x0E, 0x23, 0xC5, 0xF9, 0x2E, 0x18, 0x00,
+       0xD8, 0x82, 0xD5, 0xBC, 0x53, 0x3A, 0xD9, 0xA1, 0xBB, 0x44, 0xAD, 0xB1, 0x9C, 0xA3, 0x0F, 0x48,
+       0x90, 0x09, 0xC6, 0x17, 0xC3, 0xF0, 0x23, 0x1C, 0x72, 0x5D, 0x8C, 0xDD, 0x8F, 0xD9, 0x9B, 0x3C,
+       0x8A, 0x8F, 0xBC, 0x4C, 0x60, 0x6F, 0x52, 0x5A, 0x87, 0x6F, 0xA6, 0x53, 0x04, 0x84, 0x29, 0x72,
+       0x4C, 0x47, 0xDE, 0x86, 0x11, 0xBC, 0x4A, 0x6D, 0x10, 0xC3, 0xD4, 0x2F, 0xAA, 0x99, 0x33, 0x8F,
+       0x74, 0x71, 0x41, 0x42, 0xFA, 0x7C, 0xA6, 0x4F, 0x34, 0xDA, 0xF2, 0xC5, 0x5D, 0xAE, 0x7A, 0x6C,
+       0x16, 0xB1, 0xCF, 0x34, 0x87, 0x8D, 0xAF, 0x4A, 0x37, 0x19, 0x04, 0xA7, 0x5B, 0x40, 0x67, 0x10,
+       0xFC, 0xA4, 0xDE, 0xD3, 0x43, 0xA5, 0xE0, 0x54, 0x15, 0xB5, 0x47, 0x64, 0x7E, 0xCA, 0x7E, 0x60,
+       0x6D, 0x4C, 0x26, 0xBA, 0x18, 0xB7, 0x24, 0xFB, 0x5F, 0xB4, 0x4C, 0x0C, 0x06, 0x7F, 0xAD, 0xEB,
+       0xA1, 0xE9, 0xF0, 0xFB, 0x11, 0xBD, 0xEF, 0xFA, 0x4F, 0xB5, 0x4A, 0xA1, 0xE7, 0x09, 0xA5, 0xB6,
+       0xD5, 0x8D, 0xA7, 0x42, 0xEF, 0xE4, 0x30, 0x3F, 0x2E, 0xD1, 0x49, 0xA0, 0x06, 0xE6, 0x62, 0xE8,
+       0xC7, 0x7D, 0x10, 0x26, 0xB4, 0xF2, 0x94, 0x8C, 0x68, 0x9B, 0x2E, 0xAE, 0x1B, 0x98, 0xB2, 0x1B,
+       0x20, 0x6C, 0xB2, 0x3C, 0x41, 0xA7, 0xE0, 0x4B, 0xDE, 0xFA, 0xA6, 0xCE, 0x91, 0xCA, 0xBC, 0x18,
+       0x86, 0x46, 0x07, 0x0D, 0x0A, 0x3D, 0xB7, 0x07, 0x89, 0xE5, 0x93, 0xB6, 0x32, 0xFF, 0xD9, 0x78,
+       0xA4, 0x60, 0xF5, 0xAB, 0x7B, 0x62, 0x63, 0x6B, 0x5F, 0x6A, 0xA1, 0x5E, 0x7C, 0x30, 0x75, 0x26,
+       0xD2, 0xA9, 0xE1, 0x01, 0x08, 0x8C, 0x96, 0xB3, 0xE0, 0x13, 0x05, 0xDA, 0x0E, 0xBB, 0x08, 0x1C,
+       0x51, 0xE6, 0x44, 0xC3, 0x02, 0xA8, 0x98, 0x92, 0x71, 0x49, 0x60, 0x28, 0x33, 0xEF, 0xE5, 0x10,
+       0x41, 0x21, 0x0A, 0x14, 0x6D, 0x54, 0x42, 0x1B, 0x42, 0xA9, 0x29, 0x16, 0xDB, 0x1F, 0x71, 0x63,
+       0x9E, 0x4A, 0x35, 0xD7, 0xC3, 0x2F, 0x41, 0x66, 0xB2, 0x85, 0xD6, 0xA4, 0x2A, 0x9C, 0xA0, 0x6F,
+       0x8D, 0x58, 0x43, 0x85, 0xE6, 0x46, 0x53, 0xDD, 0x5C, 0x2C, 0x4B, 0xC5, 0xC7, 0xDE, 0x79, 0x48,
+       0xAB, 0x0F, 0x48, 0x23, 0xCF, 0x01, 0x64, 0xA3, 0x0D, 0xE1, 0x5B, 0x14, 0xC5, 0xB2, 0x04, 0x0D,
+       0xE4, 0x41, 0xB5, 0x28, 0x7F, 0xD2, 0xAD, 0x3A, 0x9E, 0xF0, 0x31, 0x82, 0x58, 0xA8, 0xED, 0x9C,
+       0x53, 0x1C, 0x2F, 0x17, 0x53, 0x66, 0xCE, 0x20, 0x10, 0x1D, 0xAC, 0x53, 0x11, 0x82, 0xD3, 0xA8,
+       0x4F, 0x6F, 0xFE, 0x94, 0x3C, 0xF1, 0x57, 0x6F, 0x89, 0xD8, 0xF3, 0x1F, 0x2E, 0xD2, 0x19, 0x0C,
+       0x6A, 0x9D, 0x3D, 0x1A, 0xBE, 0x47, 0x16, 0x17, 0x4A, 0x7C, 0xD9, 0xB8, 0xE5, 0x09, 0x5A, 0x34,
+       0x85, 0x8A, 0x6A, 0x23, 0x5B, 0x0D, 0x3D, 0x02, 0xCC, 0x1C, 0x29, 0x26, 0xBE, 0x93, 0x80, 0x13,
+       0x2D, 0x39, 0x1F, 0x19, 0xDE, 0xF9, 0xF7, 0x08, 0x1A, 0x6E, 0x3A, 0x2A, 0x7D, 0x96, 0x13, 0x09,
+       0x1B, 0x85, 0x79, 0x41, 0xE8, 0x92, 0xA8, 0x47, 0x55, 0x3E, 0x47, 0xFA, 0x15, 0x8E, 0x13, 0xAE,
+       0x44, 0x83, 0xE2, 0xC7, 0xC7, 0x9F, 0x5F, 0x6D, 0x91, 0xEA, 0xDE, 0x60, 0x22, 0x27, 0x49, 0xAE,
+       0xC3, 0x7F, 0xB8, 0x8D, 0x68, 0xEA, 0x1B, 0x04, 0xA3, 0x92, 0x06, 0x01, 0x85, 0xED, 0xA9, 0xF9,
+       0x36, 0x45, 0x37, 0xC8, 0x3D, 0x93, 0x08, 0x08, 0x58, 0xCA, 0x16, 0xFB, 0x41, 0x0B, 0x26, 0x3D,
+       0x35, 0xE0, 0x6D, 0x59, 0xD4, 0x98, 0x4E, 0x4C, 0xE8, 0x0B, 0x96, 0x90, 0x2D, 0x85, 0x3A, 0x8B,
+       0xCB, 0x4B, 0x10, 0x5D, 0xDF, 0xE6, 0x60, 0x2E, 0x55, 0x95, 0x0B, 0x88, 0xAA, 0xCB, 0x91, 0xE1,
+       0xB4, 0x9C, 0xAF, 0x41, 0xF2, 0x28, 0xAC, 0x21, 0xC6, 0x8D, 0xEB, 0x96, 0x3F, 0xC5, 0xEF, 0xA7,
+       0x34, 0x91, 0xAA, 0x72, 0xCE, 0x1D, 0xA5, 0xEA, 0xF3, 0x9E, 0xE4, 0xBE, 0x08, 0x5F, 0xD1, 0xD9,
+       0xC6, 0xD2, 0x4F, 0x9D, 0xC1, 0xE1, 0xA1, 0x75, 0x99, 0x2A, 0xCA, 0x00, 0x82, 0x1B, 0x64, 0x94,
+       0xB8, 0x8F, 0x2B, 0xEB, 0x6C, 0xEE, 0x99, 0x54, 0x78, 0x4B, 0x17, 0x98, 0x62, 0xB5, 0x99, 0x20,
+       0x26, 0x33, 0x50, 0x92, 0xE8, 0xD0, 0xF3, 0xBA, 0x40, 0x89, 0x95, 0x65, 0x58, 0x4C, 0x75, 0x8A,
+       0xA0, 0xEB, 0x0C, 0xA1, 0xCA, 0x1E, 0x7E, 0x25, 0x5B, 0x14, 0x0F, 0x9D, 0xB5, 0xB5, 0x29, 0xC2,
+       0x78, 0xF8, 0xD4, 0x9E, 0x5F, 0xF1, 0x83, 0x68, 0xCC, 0x18, 0x73, 0x55, 0x3C, 0xAD, 0xED, 0x2D,
+       0x71, 0xA6, 0xDF, 0x99, 0x2E, 0x74, 0x74, 0xAE, 0xFA, 0xA1, 0xEB, 0x47, 0x88, 0x75, 0x9B, 0xCD,
+       0x93, 0x82, 0xE4, 0x0E, 0x05, 0x14, 0x5D, 0x47, 0x38, 0x28, 0x86, 0x82, 0x68, 0x4A, 0xD0, 0x57,
+       0x82, 0x62, 0xC7, 0x55, 0x26, 0x08, 0xF3, 0x38, 0xD7, 0x33, 0x3D, 0x69, 0x89, 0x5F, 0xEA, 0x7F,
+       0x24, 0xBC, 0xF0, 0x05, 0x93, 0x92, 0xD6, 0xFB, 0xA5, 0x2B, 0x08, 0x52, 0x7D, 0x71, 0x0B, 0xA9,
+       0x9F, 0x16, 0x93, 0x61, 0x0B, 0x89, 0x2C, 0x69, 0xDC, 0x2A, 0xFF, 0xC9, 0xB9, 0x3A, 0x76, 0xF0,
+       0xF4, 0x37, 0x0D, 0x9D, 0x3A, 0xDC, 0xA5, 0xA7, 0x27, 0x05, 0x2B, 0xFC, 0x62, 0x80, 0x41, 0x1B,
+       0x1E, 0x32, 0x64, 0xBE, 0x46, 0xA4, 0xF5, 0x32, 0xE0, 0xBC, 0x48, 0xA7, 0xDE, 0xAE, 0x87, 0xBE,
+       0x14, 0x26, 0x9D, 0xC6, 0x91, 0xA1, 0x56, 0x8A, 0xBD, 0x3A, 0xC9, 0x08, 0x34, 0x8C, 0xB5, 0x32,
+       0xFE, 0x9E, 0x45, 0x55, 0x97, 0x70, 0xD6, 0xC6, 0x3F, 0x12, 0xD7, 0xA2, 0x82, 0x6C, 0xA0, 0x28,
+       0x34, 0xDA, 0x6C, 0xCA, 0x19, 0xC4, 0x86, 0x41, 0x82, 0x79, 0x96, 0xA1, 0x3A, 0x77, 0x81, 0x9A,
+       0x43, 0x33, 0xF6, 0xF4, 0x89, 0x16, 0x45, 0x8D, 0xAA, 0xA9, 0xF9, 0xD5, 0x9A, 0xCB, 0x6C, 0xE2,
+       0xF3, 0x2C, 0xB9, 0xD9, 0x3F, 0x6F, 0x2B, 0x34, 0x80, 0xE4, 0x59, 0x76, 0x3A, 0x44, 0x64, 0x00,
+       0x73, 0x8A, 0x0A, 0x2C, 0xDA, 0x39, 0xE3, 0xB0, 0x1A, 0x5C, 0xC4, 0xAF, 0x22, 0x8F, 0xEA, 0xBD,
+       0xAD, 0x30, 0x1A, 0xC5, 0xA5, 0xCC, 0x66, 0x8A, 0x9C, 0x42, 0xE3, 0x11, 0x48, 0xFF, 0x5E, 0x2C,
+       0x46, 0xC9, 0xA2, 0x3B, 0x74, 0x18, 0x35, 0xF9, 0x25, 0x1F, 0xFA, 0xCA, 0xF8, 0xA5, 0x5C, 0x45,
+       0x3F, 0x05, 0x15, 0xA8, 0x23, 0xDC, 0x6F, 0x25, 0xC1, 0x29, 0xEF, 0x8B, 0xD8, 0xC0, 0x6C, 0x49,
+       0xC2, 0x44, 0xB7, 0xED, 0xA7, 0x18, 0x86, 0xF2, 0xCB, 0x71, 0xA9, 0x70, 0x2C, 0xD7, 0xFE, 0x7A,
+       0x7C, 0xCC, 0x68, 0xAD, 0xA6, 0x02, 0xDC, 0x85, 0xA3, 0xC9, 0x54, 0xB4, 0x46, 0xC4, 0x39, 0xBF,
+       0xB3, 0x6F, 0x13, 0xDB, 0xE8, 0x9C, 0xC8, 0x6B, 0xF6, 0xF5, 0x2B, 0xBE, 0x5D, 0xAB, 0xBA, 0xEE,
+       0x8D, 0xDC, 0x39, 0xE5, 0x79, 0x3A, 0x9C, 0x74, 0x77, 0xD7, 0x34, 0x01, 0xC7, 0x50, 0x2C, 0x75,
+       0xB0, 0x07, 0x64, 0x8C, 0xDE, 0x74, 0x14, 0xCB, 0x10, 0x15, 0xB4, 0x4C, 0x28, 0x13, 0x0D, 0x62,
+       0x55, 0xDF, 0xF0, 0xD5, 0xF7, 0x3C, 0x42, 0x4A, 0xAA, 0x49, 0x3F, 0x68, 0x75, 0x9E, 0xD9, 0xA8,
+       0x15, 0x7A, 0x32, 0xBD, 0x5A, 0xDB, 0x9F, 0x7E, 0x0A, 0x35, 0xAA, 0x21, 0x89, 0x5A, 0xE2, 0x91,
+       0xA2, 0xE4, 0xE4, 0x66, 0x24, 0x4F, 0x43, 0x18, 0x36, 0xF8, 0xF7, 0x04, 0xFA, 0x90, 0x87, 0x38,
+       0x21, 0xDF, 0x38, 0xAC, 0x0E, 0x58, 0x78, 0x2F, 0xFE, 0x87, 0x97, 0x4F, 0x8E, 0x3E, 0x31, 0x14,
+       0x98, 0x5B, 0xA7, 0x21, 0xAC, 0x33, 0x7F, 0xE9, 0x3D, 0xD6, 0xE4, 0x7D, 0x17, 0x35, 0x2B, 0xA6,
+       0x71, 0x3A, 0xEE, 0x47, 0x28, 0x1B, 0x2F, 0x93, 0xCE, 0x4F, 0xFE, 0x3D, 0x3E, 0xA4, 0x03, 0xB4,
+       0x8F, 0xE0, 0x91, 0x1C, 0x82, 0x45, 0x2D, 0xD3, 0xA8, 0xC7, 0xE9, 0xF3, 0x9A, 0x1F, 0x0C, 0x0B,
+       0x9F, 0x5E, 0x0C, 0x02, 0x37, 0x3F, 0xDE, 0x18, 0xB0, 0x93, 0x65, 0xD1, 0xB0, 0xCF, 0x4D, 0x6F,
+       0x7C, 0x32, 0x8F, 0xFA, 0xFC, 0x41, 0x0E, 0x6E, 0xCE, 0x72, 0xEB, 0xDB, 0x9A, 0xB1, 0xAC, 0x5B,
+       0xF5, 0x1A, 0x13, 0xE0, 0x43, 0x89, 0xA1, 0x22, 0xC8, 0x3A, 0x6A, 0x3D, 0xB8, 0x3F, 0x06, 0x57,
+       0xBC, 0x61, 0xA7, 0x1F, 0x5E, 0x14, 0x4F, 0xE9, 0x83, 0x9A, 0xEA, 0xD2, 0xD9, 0x7A, 0xF4, 0x07,
+       0x30, 0x95, 0x35, 0xEB, 0xBC, 0x81, 0x48, 0xDB, 0x08, 0xFA, 0xFF, 0xCF, 0x8B, 0xE5, 0x60, 0xCA,
+       0x4D, 0xBE, 0x9C, 0x78, 0xA9, 0x89, 0x1D, 0xCE, 0xE1, 0x44, 0xCC, 0x21, 0x87, 0xDA, 0x6F, 0x40,
+       0xC9, 0xFF, 0xC0, 0xA3, 0x5E, 0x96, 0x5D, 0x02, 0x6E, 0x1E, 0x61, 0x86, 0x9D, 0xC1, 0x53, 0x99,
+       0x73, 0x25, 0xD0, 0x03, 0x51, 0x0B, 0xED, 0x42, 0xFD, 0x60, 0x89, 0x6C, 0x08, 0xA3, 0x3E, 0xEF,
+       0xDA, 0xC9, 0x87, 0x1B, 0x44, 0x0F, 0x89, 0xCF, 0xA3, 0x69, 0xF3, 0xB9, 0x64, 0x99, 0x88, 0x30,
+       0x44, 0x6B, 0xDB, 0xC7, 0x78, 0x89, 0x6A, 0x9A, 0x09, 0x2C, 0x3A, 0xE7, 0xF4, 0x5A, 0x81, 0x04,
+       0x31, 0x41, 0x34, 0x7A, 0x5A, 0x8C, 0x27, 0xEF, 0xBC, 0xAF, 0x96, 0x2F, 0xDF, 0xF4, 0x49, 0xB0,
+       0x14, 0xF7, 0xF0, 0x7A, 0x80, 0x69, 0x11, 0x24, 0xEB, 0x67, 0xCB, 0x5A, 0x35, 0x06, 0xE9, 0x81,
+       0x60, 0xA4, 0x5A, 0xDE, 0x14, 0x89, 0x20, 0x8E, 0xF0, 0x87, 0x18, 0x45, 0x2B, 0xDE, 0xA7, 0x57,
+       0x4D, 0x48, 0xD1, 0x9F, 0xC2, 0xD4, 0x16, 0x39, 0x4B, 0xF8, 0x43, 0xEC, 0x07, 0x05, 0xD1, 0xCF,
+       0xC1, 0xFD, 0x46, 0x65, 0x7F, 0x0F, 0x0A, 0x18, 0x8A, 0xDB, 0x99, 0x0F, 0x93, 0xA7, 0x51, 0x6D,
+       0x07, 0x01, 0xF6, 0xC3, 0x35, 0xE8, 0xA1, 0xDE, 0x03, 0xBF, 0x99, 0x8C, 0x9C, 0xDA, 0x52, 0xE5,
+       0xEE, 0x9A, 0x4B, 0xD0, 0x76, 0x23, 0x97, 0x2E, 0x6C, 0x82, 0x48, 0x50, 0x20, 0x1D, 0xBB, 0x0B,
+       0xA2, 0x4D, 0x8A, 0x27, 0x13, 0x44, 0x0E, 0xFD, 0x35, 0xDE, 0xC6, 0x5D, 0x35, 0xD7, 0x98, 0xE6,
+       0x98, 0x61, 0x3C, 0x7F, 0xF5, 0xFE, 0x7E, 0x58, 0xDE, 0x02, 0x5E, 0x9C, 0x5E, 0x8B, 0xDD, 0x63,
+       0x51, 0x4C, 0x2A, 0x2B, 0xF5, 0x9E, 0xAB, 0x6C, 0x9A, 0x46, 0xDE, 0x4D, 0x94, 0x6F, 0xEB, 0x5C,
+       0x57, 0xB1, 0xBE, 0xC5, 0x95, 0x32, 0x11, 0x9E, 0x26, 0xD9, 0xBA, 0x3A, 0xA2, 0xE3, 0x3F, 0x61,
+       0xE4, 0x98, 0x87, 0xC1, 0xF6, 0xD7, 0xFB, 0x52, 0x9C, 0x44, 0xB4, 0x33, 0xB9, 0xF5, 0x42, 0x22,
+       0xDD, 0x94, 0xB1, 0x85, 0x72, 0x51, 0xFE, 0x07, 0x78, 0xE0, 0x12, 0x7D, 0xE7, 0xD4, 0xC2, 0x80,
+       0xCC, 0xAE, 0x91, 0x76, 0x52, 0xC0, 0xC7, 0x1A, 0x00, 0x81, 0xC0, 0xF2, 0x7B, 0x73, 0x6E, 0xB1,
+       0x5D, 0xA3, 0x0F, 0xB5, 0x3D, 0x44, 0xA6, 0x1F, 0x8C, 0x48, 0x56, 0x1B, 0x74, 0x4C, 0x4B, 0xC5,
+       0x15, 0x45, 0x98, 0xC3, 0x2C, 0x99, 0x73, 0xA6, 0x8B, 0xBA, 0x0F, 0x44, 0xD6, 0x0F, 0x86, 0x96,
+       0xE5, 0xDD, 0x2B, 0xF2, 0x00, 0x81, 0xD0, 0x78, 0x6D, 0x72, 0x01, 0x72, 0xCF, 0x34, 0x94, 0xAD,
+       0x41, 0x14, 0x87, 0xFD, 0xAF, 0x6F, 0x34, 0xE6, 0x12, 0x83, 0x34, 0x2B, 0x7E, 0x28, 0xF8, 0x08,
+       0x47, 0x13, 0xDE, 0x44, 0x11, 0x85, 0x63, 0x12, 0xF1, 0xD6, 0x74, 0x91, 0xDB, 0x22, 0x1C, 0x99,
+       0x0C, 0xE2, 0x1F, 0x27, 0x07, 0x76, 0x66, 0x29, 0x71, 0x0A, 0xB9, 0x39, 0x94, 0x2C, 0x85, 0x87,
+       0x5F, 0xF7, 0xD6, 0x51, 0xF3, 0x6C, 0x35, 0x79, 0xB7, 0x2D, 0x59, 0x3A, 0x5C, 0x2B, 0x32, 0x89,
+       0x1C, 0xCB, 0x7A, 0x93, 0x06, 0xA2, 0xD9, 0x9F, 0xE3, 0xD0, 0xB0, 0x2E, 0x1A, 0xEF, 0x48, 0xEF,
+       0x55, 0xE5, 0x7F, 0x05, 0x4F, 0x77, 0x13, 0xD1, 0x10, 0x41, 0x0C, 0x97, 0xA3, 0x54, 0x20, 0x59,
+       0x37, 0xF4, 0x82, 0xED, 0x88, 0x89, 0xED, 0x8A, 0xEB, 0x94, 0x37, 0x80, 0x0A, 0xF3, 0x98, 0xBF,
+       0x7C, 0x8C, 0x2C, 0xF2, 0xF8, 0x26, 0xE6, 0x80, 0xAA, 0x9B, 0x4B, 0x59, 0x91, 0x78, 0xB6, 0xBC,
+       0xE3, 0x73, 0xE8, 0x16, 0x96, 0x33, 0x37, 0xFC, 0xA7, 0x79, 0x9F, 0xBC, 0xDC, 0x77, 0x53, 0x1C,
+       0xFC, 0x58, 0x1B, 0xF1, 0x8B, 0x3A, 0xCA, 0x82, 0x6C, 0x98, 0x3A, 0x57, 0x3D, 0xA3, 0xE7, 0xD8,
+       0x24, 0x38, 0x8F, 0xF9, 0xA8, 0x8A, 0x98, 0x24, 0x25, 0x01, 0xD8, 0xDE, 0x49, 0x6D, 0x1F, 0x0D,
+       0x23, 0x93, 0x43, 0xB3, 0xBB, 0xA8, 0x56, 0x2A, 0xF3, 0x5E, 0xC7, 0x32, 0x9D, 0xB7, 0x2D, 0xEE,
+       0x4F, 0xA9, 0xA2, 0x7D, 0x1F, 0x66, 0xD0, 0x25, 0x38, 0xA0, 0x0A, 0x5A, 0x08, 0x86, 0x4D, 0x7E,
+       0xBD, 0x65, 0x8A, 0x42, 0xC2, 0xA2, 0xAB, 0xE9, 0x93, 0x7B, 0x0E, 0xA8, 0xDB, 0x49, 0x93, 0xDB,
+       0xA6, 0x09, 0xD8, 0x29, 0x58, 0xAA, 0x9C, 0x4B, 0x21, 0x6B, 0x26, 0xA8, 0x8A, 0x3F, 0x2C, 0x01,
+       0x4A, 0x0C, 0x7F, 0x0C, 0x11, 0xCE, 0x8F, 0xA7, 0x25, 0xB0, 0xB6, 0x2D, 0x90, 0x0D, 0x87, 0xE4,
+       0xD7, 0x19, 0xE6, 0xCE, 0x90, 0x3B, 0xA5, 0x57, 0xBB, 0x44, 0x62, 0xD0, 0x86, 0xEA, 0x44, 0xB3,
+       0xE2, 0xF2, 0x46, 0x73, 0x12, 0xC5, 0xB2, 0x65, 0xA1, 0x9F, 0xF3, 0xF8, 0x42, 0x0E, 0x8A, 0x3F,
+       0xE6, 0x5D, 0x64, 0x49, 0x53, 0xAA, 0xDD, 0xB4, 0xF4, 0x95, 0x4B, 0x03, 0xE2, 0x33, 0xA0, 0xEE,
+       0xE3, 0x8C, 0x3F, 0xAC, 0xF6, 0x16, 0xA4, 0x13, 0x3E, 0xEC, 0x30, 0x23, 0x57, 0x36, 0x66, 0x07,
+       0x30, 0x66, 0x7F, 0xEA, 0x97, 0xE7, 0x2B, 0x30, 0xFC, 0xBB, 0xC5, 0x45, 0xB5, 0x70, 0x36, 0xED,
+       0x7F, 0x9D, 0xB4, 0x2D, 0xEF, 0xF8, 0x6D, 0x36, 0xCC, 0x63, 0x2D, 0xEA, 0x2E, 0x7E, 0x93, 0xD0,
+       0xC3, 0xC7, 0x22, 0xFC, 0x8B, 0x86, 0x76, 0xF6, 0x6B, 0x29, 0x2D, 0x3F, 0xC9, 0xD9, 0x23, 0x0B,
+       0x4E, 0x51, 0x81, 0x95, 0xED, 0xD7, 0x15, 0x7F, 0xA8, 0x6A, 0x50, 0x4C, 0x40, 0x94, 0xD3, 0x4C,
+       0xF6, 0x8E, 0xAA, 0x8C, 0x1D, 0x51, 0xC9, 0xF3, 0x68, 0x76, 0xF7, 0xB7, 0xF6, 0x0E, 0x11, 0x35,
+       0x63, 0xFD, 0x99, 0x19, 0xEF, 0xE0, 0xE8, 0x39, 0x52, 0xB0, 0x6B, 0xB8, 0x2A, 0x00, 0xEC, 0x6F,
+       0x95, 0xAE, 0x27, 0xE6, 0x9C, 0x7B, 0x96, 0x11, 0x39, 0xA2, 0xE3, 0xD8, 0xC1, 0x5E, 0xAB, 0x6E,
+       0xDF, 0x53, 0xB4, 0x5F, 0x6E, 0x2A, 0x57, 0x5D, 0x20, 0x43, 0xB6, 0x01, 0x70, 0x2F, 0x47, 0xF3,
+       0xE3, 0xF7, 0xAD, 0xDB, 0x45, 0xFE, 0xC2, 0x38, 0xF1, 0xC6, 0x6E, 0xF8, 0xE4, 0xAA, 0xB9, 0x01,
+       0x48, 0xA3, 0x90, 0xA9, 0xA1, 0x82, 0x36, 0x8E, 0xFC, 0xAA, 0x18, 0xFA, 0x2C, 0x41, 0xCE, 0x9D,
+       0x87, 0xFB, 0xE6, 0x5B, 0x17, 0xDB, 0x44, 0x24, 0xF8, 0x89, 0x5C, 0x1D, 0xC9, 0x81, 0xC6, 0x45,
+       0x35, 0x4E, 0xB9, 0x13, 0xEF, 0xFE, 0x20, 0xBE, 0x84, 0x52, 0xC6, 0xED, 0x84, 0x0A, 0x12, 0x08,
+       0xDE, 0xC5, 0x91, 0x2A, 0x60, 0x67, 0xC3, 0x8D, 0xB1, 0xDD, 0x4B, 0x92, 0x69, 0x3C, 0x95, 0xAA,
+       0x05, 0x47, 0x13, 0x25, 0xA8, 0x54, 0xB9, 0x96, 0x75, 0x55, 0x9B, 0xDB, 0xD7, 0x7F, 0xE9, 0x80,
+       0xCE, 0x00, 0x9A, 0x88, 0x9E, 0xFD, 0x94, 0xAF, 0x6F, 0x17, 0x6E, 0x82, 0x8B, 0x15, 0x33, 0x41,
+       0xBD, 0xA8, 0x57, 0xC1, 0xC0, 0x4E, 0x66, 0xD4, 0x50, 0x93, 0xDA, 0x24, 0xD9, 0x77, 0x91, 0x5F,
+       0xDC, 0x7B, 0x89, 0x5B, 0x81, 0xA1, 0x38, 0xA5, 0xD2, 0xAE, 0x1E, 0x7B, 0xD4, 0xE1, 0x24, 0x62,
+       0xBF, 0xC5, 0x45, 0xF8, 0x24, 0xB4, 0xE1, 0x08, 0x20, 0x88, 0x66, 0x39, 0x22, 0xB9, 0x2F, 0xCB,
+       0x08, 0x4B, 0x72, 0xBD, 0x58, 0x1B, 0x46, 0x66, 0x39, 0x37, 0x75, 0x21, 0x32, 0x82, 0xBD, 0x8D,
+       0x0D, 0x5D, 0x07, 0xB5, 0xE0, 0xD3, 0x5D, 0x58, 0x77, 0x12, 0x54, 0x17, 0x85, 0xAA, 0x20, 0x7C,
+       0x6A, 0x38, 0x77, 0x02, 0x50, 0xBE, 0x11, 0x3D, 0x5A, 0xED, 0x60, 0xB0, 0x90, 0x40, 0x13, 0x8F,
+       0x51, 0xD7, 0xDE, 0x34, 0xA4, 0xDB, 0xFB, 0xAF, 0x18, 0x87, 0xA5, 0xF2, 0x32, 0x0D, 0x28, 0xF2,
+       0x4F, 0xF5, 0xD7, 0xEE, 0x94, 0x0C, 0xB8, 0xD8, 0x66, 0x3B, 0xFF, 0xAE, 0xC2, 0xD0, 0xE0, 0xAD,
+       0x03, 0x9F, 0x28, 0x81, 0x30, 0xCE, 0xC0, 0x8A, 0x7C, 0x2F, 0x6D, 0xD3, 0xE5, 0x9F, 0x85, 0x7A,
+       0xB1, 0x9D, 0xBF, 0x69, 0x30, 0x4D, 0x15, 0x5C, 0xA5, 0x82, 0xAB, 0x3F, 0xC2, 0x16, 0x95, 0xDC,
+       0xEB, 0x54, 0x31, 0xBA, 0x80, 0x01, 0x14, 0x55, 0x52, 0x12, 0x60, 0x95, 0x0E, 0x9E, 0x5A, 0x61,
+       0xA4, 0x8D, 0x51, 0x04, 0x61, 0x5D, 0xAC, 0x55, 0x51, 0x0B, 0xC8, 0xAA, 0x19, 0xF0, 0x08, 0x04,
+       0x1D, 0x21, 0x41, 0x2D, 0xD1, 0xA5, 0xE5, 0xD5, 0x86, 0x46, 0x26, 0xF1, 0x5A, 0x4D, 0x71, 0x2E,
+       0xDE, 0xC3, 0xD6, 0x18, 0x04, 0x6C, 0x6C, 0x8B, 0x7F, 0x7B, 0x27, 0xE1, 0xE4, 0xDC, 0x57, 0x87,
+       0xDA, 0xD2, 0x16, 0x12, 0x66, 0x7F, 0x58, 0x87, 0x00, 0x05, 0xCE, 0x20, 0x2C, 0xCE, 0x3E, 0x9E,
+       0xF7, 0x48, 0x55, 0xF1, 0x05, 0x41, 0x45, 0xDE, 0x18, 0xF9, 0x80, 0x81, 0x69, 0x14, 0x0A, 0x1F,
+       0xD0, 0x34, 0x79, 0x33, 0x92, 0x8F, 0x69, 0x53, 0x0F, 0xEC, 0x55, 0xB2, 0x4F, 0xC5, 0xEA, 0xA4,
+       0x82, 0x56, 0x81, 0x39, 0xF5, 0xA1, 0xD5, 0x81, 0x85, 0x39, 0x79, 0x19, 0x0B, 0xD6, 0xE8, 0xBD,
+       0xFD, 0x3C, 0x10, 0x4A, 0x62, 0x92, 0x52, 0x80, 0x5A, 0x3E, 0x6A, 0x22, 0x07, 0x70, 0x5A, 0x02,
+       0x2C, 0x60, 0x90, 0x12, 0x47, 0xBF, 0x36, 0x83, 0xCF, 0x4A, 0xB1, 0xD6, 0x36, 0x58, 0xD9, 0x63,
+       0xD3, 0x4C, 0x37, 0x5C, 0xF0, 0xAC, 0x17, 0xA5, 0x69, 0xFC, 0x9E, 0xE5, 0xD1, 0xBE, 0x7E, 0x37,
+       0x64, 0xDA, 0x8B, 0xC5, 0xE5, 0xAF, 0x8B, 0xCF, 0xE9, 0x62, 0x78, 0x6F, 0xDA, 0xAD, 0x85, 0x4F,
+       0x16, 0x75, 0xA2, 0xC4, 0x90, 0x3F, 0xD1, 0xAF, 0x3E, 0x8C, 0x1A, 0x8F, 0x30, 0x7A, 0x66, 0x6C,
+       0x63, 0x4F, 0xBE, 0xD2, 0x0E, 0xF6, 0xD4, 0x3D, 0xA1, 0x06, 0x7B, 0x27, 0xDA, 0x01, 0xAF, 0xAD,
+       0xB1, 0xD2, 0xAD, 0x12, 0x6A, 0xA9, 0x8C, 0x4A, 0x33, 0x81, 0x59, 0xFC, 0x6A, 0x41, 0xC3, 0xBE,
+       0x7C, 0xD6, 0x1F, 0xDF, 0x09, 0xCB, 0x90, 0x7F, 0xD3, 0x07, 0x8E, 0xAA, 0x27, 0xD7, 0x5B, 0xAF,
+       0xA0, 0x8A, 0x25, 0x96, 0xEE, 0x09, 0x2F, 0x81, 0x41, 0x0D, 0x94, 0x85, 0xA6, 0xDD, 0x73, 0x03,
+       0xA9, 0xE5, 0x01, 0x3E, 0x15, 0xC1, 0x5F, 0xCD, 0x2C, 0x61, 0x39, 0xF8, 0x87, 0x6E, 0x49, 0xC3,
+       0x41, 0x18, 0x67, 0x90, 0x79, 0x11, 0xD7, 0x3D, 0x11, 0xDE, 0x30, 0xAC, 0x78, 0xD6, 0xED, 0x86,
+       0x51, 0x6E, 0x8C, 0xFE, 0xF8, 0x66, 0xAD, 0x7B, 0x7F, 0x17, 0x1F, 0x14, 0x53, 0x36, 0xE9, 0xE0,
+       0xE6, 0xD3, 0xA9, 0x30, 0x1A, 0x24, 0x72, 0x2A, 0x94, 0x38, 0x05, 0x94, 0x38, 0x30, 0xBA, 0x6D,
+       0x9E, 0x4A, 0x63, 0x22, 0xFF, 0x1A, 0xD8, 0xC2, 0x67, 0x8F, 0x33, 0x34, 0xC8, 0x2E, 0x9F, 0x6A,
+       0x9A, 0xDA, 0x76, 0x40, 0x97, 0xCA, 0x53, 0x16, 0x0F, 0x9B, 0xA8, 0xF6, 0x97, 0x92, 0x06, 0x48,
+       0xF9, 0x18, 0x72, 0x76, 0xE2, 0x64, 0x00, 0x2C, 0xC8, 0xFE, 0xCA, 0x24, 0xC8, 0x5F, 0x32, 0x71,
+       0xD5, 0x20, 0xB3, 0xD3, 0xFB, 0xAE, 0x19, 0x6B, 0xC3, 0x60, 0xC8, 0xA7, 0xDE, 0x3A, 0x7F, 0x4E,
+       0x76, 0x8A, 0xEB, 0x2D, 0x5D, 0x9E, 0xFE, 0x3D, 0x5C, 0xC6, 0x36, 0x79, 0xB5, 0xD6, 0xED, 0xC9,
+       0x8B, 0x29, 0x1F, 0x98, 0x39, 0x09, 0x2E, 0x44, 0x10, 0x91, 0x77, 0x64, 0xA0, 0x15, 0x67, 0xFC,
+       0x79, 0x33, 0xD6, 0x9D, 0x43, 0x26, 0x2B, 0x17, 0xFC, 0x32, 0x57, 0x5C, 0x71, 0x17, 0xDC, 0x43,
+       0x51, 0x3D, 0x33, 0xEE, 0x6C, 0xC9, 0x28, 0xA5, 0x61, 0xFD, 0x0B, 0x41, 0xA3, 0x9D, 0xD6, 0x9A,
+       0xEC, 0xE4, 0x5B, 0x64, 0x81, 0x34, 0x76, 0xFE, 0x79, 0x47, 0xB0, 0x21, 0x64, 0xF7, 0x55, 0xB9,
+       0x6B, 0x53, 0x96, 0xD4, 0xC3, 0xAC, 0x39, 0x7A, 0x93, 0xA3, 0xDC, 0x15, 0x20, 0xBC, 0xDB, 0x44,
+       0xA2, 0x3F, 0xF9, 0x1B, 0x28, 0xE9, 0x49, 0x9B, 0x57, 0x3F, 0xE0, 0x1D, 0xA9, 0x6A, 0x47, 0x4C,
+       0x4A, 0xFC, 0x6D, 0x38, 0xBA, 0xBA, 0x71, 0x4A, 0xE4, 0x28, 0x67, 0x20, 0x27, 0x8F, 0xCB, 0xFB,
+       0x29, 0xE8, 0x94, 0xD2, 0xFC, 0x59, 0xB6, 0x72, 0x7F, 0x76, 0x6B, 0x1E, 0xBE, 0x17, 0x68, 0xBB,
+       0x32, 0x19, 0xCA, 0x17, 0x3F, 0x74, 0x03, 0x34, 0xC6, 0x54, 0x2E, 0xF9, 0x0E, 0x3B, 0x22, 0xC7,
+       0x08, 0xF9, 0x66, 0x9B, 0x52, 0x0E, 0x28, 0x34, 0x6C, 0x88, 0x98, 0x2B, 0x8D, 0xFF, 0xD9, 0xA7,
+       0xC4, 0xB6, 0x47, 0x4B, 0x54, 0xE2, 0x1D, 0x39, 0x2B, 0x9A, 0x83, 0x6F, 0x8D, 0x6A, 0xC9, 0x3E,
+       0x13, 0xE9, 0xF7, 0xE4, 0xF1, 0x90, 0xA3, 0x2A, 0x20, 0x94, 0x15, 0x65, 0xFB, 0x00, 0x52, 0x6D,
+       0xD4, 0xA2, 0x5E, 0x70, 0xE1, 0xD4, 0x7E, 0x89, 0x89, 0x86, 0x73, 0x77, 0xF5, 0x08, 0x67, 0xA2,
+       0x7B, 0x4C, 0x64, 0xE5, 0x3A, 0x29, 0x5A, 0x22, 0x6B, 0xBD, 0x2E, 0xC4, 0xA7, 0x90, 0x5B, 0xEF,
+       0x3B, 0x8E, 0x08, 0x3C, 0x84, 0xC6, 0x26, 0x6F, 0xED, 0xAB, 0x5F, 0xA5, 0xEE, 0x72, 0x40, 0xF0,
+       0xEF, 0x51, 0x10, 0x80, 0x28, 0xD1, 0x13, 0xE6, 0xBA, 0x69, 0x68, 0x71, 0xD0, 0x3C, 0x25, 0x90,
+       0x24, 0x8B, 0x0D, 0x1D, 0x84, 0xEE, 0xB7, 0xB4, 0x1F, 0x6E, 0xD2, 0x63, 0x7C, 0xC2, 0xE4, 0x01,
+       0x53, 0x8B, 0x98, 0xCF, 0x7B, 0x9A, 0xFE, 0x86, 0x9E, 0xA0, 0xC0, 0xEE, 0x58, 0xBD, 0xB1, 0x72,
+       0x55, 0x07, 0xDF, 0x08, 0xF3, 0x62, 0x7F, 0x68, 0x57, 0x37, 0xB8, 0x00, 0x94, 0x57, 0x41, 0x54,
+       0x11, 0xB1, 0x70, 0xC0, 0xC9, 0x44, 0x9F, 0xC0, 0xD0, 0xED, 0x21, 0x19, 0xF5, 0x49, 0x9E, 0xF2,
+       0x0F, 0x75, 0xB5, 0x05, 0x77, 0xBF, 0x07, 0x02, 0x72, 0x6C, 0x92, 0xAF, 0xEB, 0xA7, 0xDC, 0x79,
+       0x71, 0x81, 0x27, 0x4E, 0x6C, 0xEE, 0x9C, 0xB7, 0xB2, 0x8A, 0x7D, 0x96, 0xE5, 0x83, 0x7C, 0x23,
+       0x65, 0x59, 0x4D, 0xFB, 0xE6, 0x13, 0x5F, 0xA3, 0x12, 0x58, 0x53, 0x6F, 0xAD, 0xF9, 0xBA, 0x1B,
+       0xBB, 0x22, 0x0D, 0x26, 0xA3, 0x4B, 0x91, 0x39, 0x3E, 0xBD, 0x88, 0x1E, 0xBA, 0x89, 0x19, 0xC4,
+       0x23, 0x44, 0x36, 0xA8, 0xAC, 0x28, 0xD1, 0xA0, 0xDD, 0x41, 0x3C, 0xBB, 0x9F, 0x09, 0x70, 0xD8,
+       0xDD, 0x2D, 0xA8, 0x57, 0x7E, 0xFB, 0x39, 0x46, 0x70, 0x71, 0xC0, 0xCE, 0x03, 0x31, 0x64, 0x66,
+       0x9A, 0x41, 0x8C, 0x98, 0x78, 0xCC, 0x41, 0xCD, 0x5D, 0xE7, 0x8F, 0x2C, 0x89, 0x6F, 0xA0, 0x3D,
+       0x60, 0x80, 0x83, 0xD7, 0xBE, 0xF9, 0x19, 0xB7, 0x0F, 0xE5, 0x30, 0x81, 0xF5, 0x57, 0x31, 0x67,
+       0xEF, 0x5D, 0x91, 0x4B, 0xF5, 0x6A, 0x7B, 0xEB, 0x0A, 0xA7, 0x0B, 0x6B, 0x2D, 0x59, 0x47, 0x19,
+       0xB9, 0x04, 0xEC, 0xC5, 0x81, 0xEA, 0xE8, 0x35, 0x47, 0x0B, 0xCC, 0xDA, 0x67, 0x4B, 0x26, 0x12,
+       0x28, 0x1C, 0x61, 0x6A, 0x7D, 0xB8, 0xBB, 0xF5, 0x02, 0x31, 0x61, 0x9D, 0x65, 0x11, 0xCA, 0x04,
+       0x38, 0x6C, 0xAE, 0xC0, 0x0A, 0x4E, 0x89, 0xFF, 0x5E, 0x1F, 0x2B, 0xCE, 0x25, 0xEC, 0x4E, 0x5B,
+       0x3C, 0xEB, 0x3D, 0x39, 0xB3, 0x0E, 0x21, 0xBB, 0xF3, 0x0F, 0xE8, 0xE8, 0xDD, 0x4C, 0xDD, 0x0B,
+       0x76, 0x02, 0x9D, 0x1E, 0xFD, 0x35, 0x84, 0xA9, 0x78, 0xC0, 0x9C, 0x9B, 0xBF, 0x1A, 0x78, 0x77,
+       0x8D, 0x1F, 0x4C, 0x6B, 0x01, 0x86, 0x09, 0x9E, 0x7E, 0x28, 0x98, 0x38, 0x95, 0x88, 0x6D, 0xB3,
+       0x5A, 0xA8, 0x61, 0xA9, 0xE9, 0x7A, 0xEA, 0x89, 0x81, 0x26, 0xAD, 0x31, 0x51, 0x24, 0xB5, 0xBA,
+       0x68, 0x73, 0x17, 0xCF, 0x0A, 0x0D, 0x88, 0x3A, 0x19, 0x1F, 0x67, 0x76, 0xD9, 0xF2, 0x3C, 0x70,
+       0xF7, 0x69, 0x48, 0x54, 0x81, 0x2F, 0x26, 0x43, 0x7F, 0x2B, 0x9F, 0x17, 0x08, 0xE1, 0x1D, 0x95,
+       0xE3, 0xF6, 0x1C, 0x67, 0x98, 0xBA, 0x71, 0x40, 0x68, 0x43, 0xD6, 0x2E, 0x8D, 0xD8, 0xFC, 0xE7,
+       0x6E, 0x9C, 0xDE, 0x80, 0xC0, 0xEB, 0x8F, 0x9C, 0x3B, 0xA5, 0x3E, 0x20, 0x16, 0xFD, 0x82, 0xE1,
+       0x9F, 0x36, 0x0D, 0x06, 0x52, 0x75, 0xD7, 0x0F, 0x26, 0x1E, 0x9E, 0x45, 0x73, 0xA9, 0x4B, 0x99,
+       0x42, 0xF2, 0xB7, 0x3B, 0x13, 0x93, 0x1F, 0xA2, 0x52, 0xE3, 0x8D, 0xDF, 0x75, 0xE7, 0xFB, 0x45,
+       0xE8, 0xF2, 0xE4, 0xE2, 0xD4, 0xBE, 0x66, 0x1D, 0x5F, 0x6D, 0x57, 0xEC, 0x2A, 0xBB, 0x6E, 0x65,
+       0xF8, 0xE2, 0xCB, 0xCA, 0xCF, 0xF4, 0xB5, 0x94, 0x92, 0x0F, 0x2C, 0x5D, 0x30, 0x19, 0x23, 0x4F,
+       0x31, 0xE2, 0x48, 0x39, 0x63, 0x05, 0x8A, 0x83, 0x1B, 0x95, 0x01, 0x3F, 0x2B, 0xCC, 0x94, 0x37,
+       0xE4, 0x0C, 0x8C, 0xCA, 0xAE, 0x79, 0x97, 0x9C, 0x9D, 0x00, 0x16, 0xE7, 0x5E, 0x45, 0x32, 0x21,
+       0xFD, 0x99, 0x0D, 0x9A, 0x34, 0x37, 0x32, 0xF3, 0x09, 0xDC, 0xA2, 0xA6, 0x3F, 0x7D, 0x31, 0xAE,
+       0x65, 0x42, 0x18, 0x3A, 0x60, 0x7E, 0x47, 0xB6, 0xEE, 0x91, 0xED, 0x2D, 0x9C, 0xF4, 0xCE, 0xE8,
+       0x5D, 0x9A, 0x14, 0x74, 0x5D, 0x67, 0xCA, 0x9D, 0x71, 0xA5, 0x10, 0x91, 0x73, 0x93, 0x27, 0xC4,
+       0x3D, 0x88, 0xE9, 0x3C, 0x6A, 0x88, 0x1F, 0xD5, 0xBC, 0x5E, 0x03, 0xAD, 0x83, 0x0C, 0x7C, 0x6E,
+       0x0C, 0xAA, 0x09, 0x36, 0x1B, 0x91, 0x5F, 0xDC, 0xE4, 0x6A, 0x13, 0xC5, 0xA5, 0xFF, 0xF4, 0x26,
+       0x6F, 0x82, 0x6B, 0xBA, 0xBE, 0xEF, 0x0D, 0xF6, 0x2D, 0x4B, 0x3D, 0xC3, 0x29, 0x4C, 0xAA, 0xC8,
+       0x2D, 0xBF, 0x7B, 0x64, 0x1B, 0xB2, 0x1E, 0xC4, 0xA7, 0x7A, 0x1A, 0xB4, 0x19, 0xEA, 0x24, 0xBC,
+       0x58, 0x36, 0x8E, 0xF2, 0xBC, 0x97, 0x4D, 0x50, 0x1D, 0x1D, 0xE6, 0xB3, 0x40, 0xBA, 0x50, 0xA6,
+       0x09, 0xA7, 0x5E, 0xCE, 0x9F, 0x92, 0x25, 0x95, 0xB1, 0x16, 0xAF, 0xC2, 0x4B, 0x69, 0xB1, 0xE2,
+       0x96, 0x6F, 0x25, 0xC5, 0x53, 0x37, 0x45, 0x40, 0x09, 0x4B, 0x8B, 0x8C, 0x11, 0xBB, 0x36, 0x05,
+       0x95, 0xFF, 0x84, 0xC2, 0x3F, 0x35, 0x2E, 0x74, 0xE6, 0x3E, 0xF4, 0x72, 0x53, 0xCA, 0xCB, 0xC5,
+       0x8D, 0xE7, 0x52, 0x8B, 0x12, 0x45, 0xF2, 0xA7, 0x37, 0x79, 0xFD, 0xDA, 0xD6, 0x59, 0xB8, 0x7E,
+       0x9F, 0x5A, 0xBF, 0x43, 0x5D, 0xB4, 0x4F, 0xB6, 0xC8, 0x88, 0x9B, 0x05, 0xE7, 0x52, 0xE8, 0xD0,
+       0x8A, 0xE7, 0xD5, 0xAE, 0xCE, 0x81, 0x54, 0xE8, 0xCF, 0x85, 0x6E, 0xC7, 0x57, 0x36, 0xC7, 0x89,
+       0x9F, 0x5D, 0xA0, 0xBB, 0x96, 0x3E, 0x40, 0x7D, 0x5D, 0x52, 0xDE, 0xEC, 0xC5, 0x8A, 0x23, 0x16,
+       0xA5, 0xA7, 0xB1, 0xE4, 0x0D, 0xEB, 0xEC, 0xEC, 0x28, 0xC2, 0xFF, 0x9A, 0x2A, 0xBF, 0x9B, 0x84,
+       0x6B, 0x02, 0xC8, 0xBC, 0x4D, 0x12, 0x89, 0x0C, 0x3F, 0x7E, 0x24, 0xB4, 0xB5, 0xC8, 0x0F, 0x37,
+       0xEB, 0xC3, 0x30, 0xFD, 0xBE, 0x77, 0xF1, 0x3E, 0x0A, 0x02, 0x18, 0x3A, 0x63, 0xC1, 0x24, 0x63,
+       0x5B, 0x27, 0xA9, 0x9B, 0x24, 0x04, 0xE1, 0xD6, 0x48, 0x9A, 0xA6, 0x50, 0xCF, 0xF1, 0x1C, 0x95,
+       0xA5, 0x25, 0xAD, 0x5E, 0x85, 0x4C, 0x81, 0xD2, 0x73, 0x95, 0x4D, 0x65, 0x76, 0x87, 0x57, 0x99,
+       0xC1, 0x01, 0x13, 0x84, 0x89, 0xFF, 0x07, 0xCF, 0x4D, 0x4A, 0x1B, 0xDA, 0xA9, 0x9F, 0xD8, 0x1A,
+       0x96, 0xCA, 0xC0, 0x25, 0x6C, 0x71, 0xE9, 0xB8, 0xA4, 0xB5, 0x1A, 0xF6, 0x8C, 0xEC, 0x67, 0xA9,
+       0xBB, 0xFB, 0xF2, 0x76, 0x8A, 0xB6, 0xBD, 0xDB, 0x6E, 0xFB, 0x67, 0xB6, 0x12, 0x91, 0x06, 0x6A,
+       0xE6, 0x34, 0x5F, 0x4A, 0x19, 0x6B, 0x45, 0xDC, 0x1A, 0x3E, 0xD4, 0x5A, 0xBB, 0x18, 0x71, 0x30,
+       0xF1, 0x8A, 0x8D, 0x9B, 0x88, 0x39, 0x49, 0x03, 0x89, 0x83, 0xF6, 0xEE, 0x4E, 0x14, 0x39, 0xCE,
+       0xF5, 0x14, 0x4F, 0x81, 0x34, 0x40, 0xB0, 0x74, 0x95, 0xA2, 0xF3, 0x31, 0x0F, 0xC6, 0x40, 0x3F,
+       0x68, 0x08, 0x23, 0x6F, 0x87, 0x71, 0x27, 0x37, 0xB3, 0xEC, 0xA2, 0x53, 0x62, 0x44, 0x4C, 0xB6,
+       0x7A, 0xAE, 0xC6, 0x23, 0x31, 0x25, 0x2B, 0xF3, 0xDA, 0xF6, 0xBB, 0x97, 0x2C, 0xFF, 0xF5, 0x76,
+       0x86, 0xD2, 0x45, 0x3E, 0xBE, 0x63, 0xA8, 0xAF, 0xB2, 0x59, 0xA8, 0x54, 0x6C, 0x7D, 0xF2, 0x1F,
+       0x74, 0x16, 0x08, 0xA4, 0x73, 0x01, 0x1A, 0xFF, 0x3E, 0xA8, 0x15, 0xC5, 0xFB, 0xD0, 0x70, 0x8E,
+       0x05, 0x1C, 0xC4, 0x9C, 0x15, 0xF7, 0x2F, 0xE4, 0x2A, 0x30, 0xDE, 0x42, 0x4A, 0x6A, 0x0F, 0x4B,
+       0x64, 0xAF, 0xBC, 0x11, 0xE4, 0xA3, 0x1D, 0x1F, 0x77, 0xC9, 0xCB, 0x53, 0x8E, 0xB8, 0x6C, 0x02,
+       0xA0, 0xC1, 0xE4, 0x45, 0x04, 0x52, 0xC3, 0x6F, 0x19, 0xDC, 0xAE, 0x35, 0x10, 0xF9, 0x56, 0xC3,
+       0x4B, 0xB6, 0x16, 0x48, 0x37, 0x69, 0xFC, 0x14, 0x7A, 0xDC, 0xD8, 0x8F, 0x13, 0x56, 0x45, 0x50,
+       0x24, 0xE7, 0x40, 0x7E, 0x39, 0xFB, 0x58, 0x8E, 0x00, 0x00, 0xBB, 0xDB, 0xD5, 0xDD, 0xAA, 0x79,
+       0xF7, 0xD7, 0x52, 0x30, 0x17, 0xC5, 0xB4, 0xEC, 0xBD, 0x98, 0xB8, 0x7C, 0xB5, 0x68, 0x1B, 0xE3,
+       0x24, 0x44, 0x00, 0x73, 0xCF, 0x84, 0xDA, 0x30, 0x14, 0x1F, 0xB0, 0xF5, 0x3B, 0xBD, 0x45, 0x37,
+       0x6F, 0x97, 0x4F, 0xCA, 0x6E, 0x9C, 0x1F, 0xC4, 0xBC, 0x2B, 0x21, 0x6B, 0x11, 0x52, 0x3B, 0xF3,
+       0x62, 0xEB, 0x7C, 0xF6, 0x0A, 0xFA, 0x1F, 0xD5, 0xAC, 0x4F, 0x65, 0xEA, 0x60, 0x84, 0xC8, 0xFD,
+       0x6A, 0xAA, 0xF4, 0x11, 0x71, 0x96, 0x34, 0x93, 0x96, 0x6F, 0xC2, 0xC3, 0xA0, 0x11, 0xC7, 0xFA,
+       0x35, 0x69, 0x8B, 0xDB, 0x37, 0xBD, 0xC3, 0x50, 0x0D, 0xED, 0x31, 0x1B, 0x79, 0x8D, 0xA8, 0xB7,
+       0x2E, 0xA4, 0x41, 0x5F, 0x7F, 0xE7, 0x69, 0x0A, 0x56, 0xE8, 0x27, 0x8D, 0x89, 0x67, 0x11, 0x8E,
+       0xBE, 0xC2, 0x24, 0x5C, 0x2B, 0x76, 0x60, 0xBD, 0x7E, 0xF9, 0x53, 0x89, 0x8D, 0x39, 0x49, 0x73,
+       0x9B, 0xA5, 0x60, 0x7F, 0x4A, 0x68, 0x61, 0x9A, 0x05, 0x30, 0xB0, 0x49, 0xDF, 0xBA, 0x66, 0xDA,
+       0x75, 0xBD, 0x83, 0xF9, 0x12, 0x45, 0x2D, 0xA8, 0x42, 0xC8, 0xB8, 0x93, 0xBA, 0x83, 0xE4, 0x9B,
+       0x9E, 0x1A, 0x00, 0x3B, 0xC8, 0x3C, 0xE5, 0x8B, 0x2B, 0x3D, 0x48, 0x09, 0x5E, 0xCB, 0x9A, 0xF3,
+       0x92, 0xC2, 0xCC, 0x53, 0x13, 0xF4, 0x63, 0xEE, 0x63, 0x96, 0x78, 0xD8, 0x47, 0x6F, 0x7A, 0xEF,
+       0x52, 0xE9, 0x16, 0x98, 0xE9, 0x31, 0xDB, 0x10, 0x42, 0x5D, 0xC2, 0xD9, 0x16, 0x0E, 0x02, 0x98,
+       0x2F, 0x34, 0x52, 0x47, 0x96, 0xFB, 0x69, 0x43, 0x68, 0x0E, 0xB5, 0xE8, 0xCC, 0x40, 0x44, 0xE6,
+       0x0B, 0x8B, 0x10, 0xAA, 0xCF, 0x42, 0xDB, 0xDF, 0x30, 0xA5, 0x1F, 0x0F, 0x39, 0xC0, 0xC5, 0xBA,
+       0xF2, 0x1F, 0x20, 0x47, 0xEC, 0xA0, 0x4D, 0x42, 0x12, 0x24, 0x68, 0xE8, 0x9C, 0xF9, 0x0D, 0xCE,
+       0x50, 0xAA, 0x53, 0x98, 0x09, 0x85, 0x63, 0x6A, 0x93, 0x51, 0xAF, 0x55, 0x4B, 0x72, 0x43, 0x68,
+       0xDE, 0x79, 0xA8, 0x8D, 0x8C, 0xF8, 0x4D, 0x51, 0x89, 0xD1, 0xDF, 0x54, 0x33, 0x9B, 0xB9, 0x1F,
+       0x99, 0xAF, 0xD9, 0x19, 0xE1, 0xBF, 0x8F, 0x70, 0x64, 0xBE, 0x3C, 0xF8, 0x72, 0x8E, 0x07, 0x70,
+       0x95, 0x7A, 0xC7, 0x58, 0x0E, 0x0B, 0x7F, 0xC0, 0xE9, 0x4B, 0xF3, 0x93, 0x57, 0x0C, 0xC5, 0x95,
+       0x52, 0x2D, 0x5B, 0x05, 0x33, 0xE7, 0x88, 0x06, 0xB9, 0x92, 0x1C, 0xBD, 0x48, 0xBA, 0x10, 0xFE,
+       0x52, 0x24, 0xF8, 0x31, 0x84, 0xA7, 0x61, 0x80, 0x60, 0xAC, 0x45, 0x57, 0xAD, 0x14, 0x8F, 0xC8,
+       0xF8, 0xAD, 0xE1, 0x94, 0x98, 0x90, 0xA4, 0xB5, 0x78, 0xCB, 0xF2, 0x7A, 0x5F, 0x96, 0x6B, 0xED,
+       0xB2, 0xC9, 0x99, 0x7F, 0x85, 0xF3, 0x9B, 0xC1, 0x82, 0xFF, 0x8E, 0x4F, 0xF8, 0x51, 0xDA, 0x14,
+       0x7B, 0x7F, 0x65, 0xA4, 0x58, 0xD8, 0x93, 0xCB, 0xBF, 0x55, 0xF4, 0xA9, 0x65, 0xA5, 0x28, 0xC9,
+       0x84, 0xAA, 0xD9, 0xAF, 0xD3, 0x40, 0x34, 0xB9, 0xA1, 0x3D, 0xE9, 0xE5, 0x7E, 0x29, 0xE7, 0x62,
+       0x78, 0xD5, 0xC7, 0xB0, 0x18, 0x42, 0xB5, 0xD5, 0x18, 0x53, 0xAF, 0x8F, 0x48, 0x72, 0x84, 0x38,
+       0x8E, 0xA8, 0xF9, 0xDC, 0xA2, 0x6E, 0xAD, 0x42, 0x13, 0x18, 0x3B, 0xAF, 0x16, 0x37, 0xCB, 0xDE,
+       0xC4, 0x4B, 0xE9, 0xFA, 0x94, 0x6C, 0x99, 0x95, 0x69, 0xC5, 0xCF, 0x8D, 0x85, 0xC9, 0x0D, 0x7B,
+       0xBC, 0x13, 0x77, 0xF2, 0xBA, 0xBE, 0x6C, 0x75, 0x06, 0x97, 0xF0, 0xA4, 0x34, 0x6F, 0xB9, 0x3D,
+       0x65, 0xCC, 0xF5, 0xAE, 0x37, 0x9D, 0x8E, 0x2F, 0xF9, 0xC1, 0xFE, 0x2E, 0x4A, 0x52, 0x58, 0x09,
+       0xB6, 0x0E, 0x9A, 0x44, 0xA3, 0x44, 0xA4, 0x60, 0x2E, 0x51, 0x84, 0x8F, 0xA7, 0x54, 0xE5, 0x71,
+       0xAD, 0x61, 0x43, 0x96, 0x6A, 0x42, 0x95, 0x4F, 0x6C, 0x59, 0xEE, 0x92, 0xA8, 0x2E, 0x10, 0xF1,
+       0x0A, 0x8F, 0xCD, 0x85, 0xDE, 0x1A, 0x1C, 0x4C, 0x50, 0x47, 0x5A, 0x28, 0x04, 0x9C, 0x98, 0x2D,
+       0x90, 0x26, 0x0A, 0xC1, 0x2B, 0xE7, 0xC7, 0xF8, 0x19, 0xFC, 0xCE, 0x32, 0xB1, 0x13, 0x69, 0x24,
+       0xA1, 0x20, 0x4D, 0x57, 0xBF, 0x50, 0x2B, 0xEE, 0x80, 0x22, 0xF6, 0xD6, 0x49, 0x8A, 0xD1, 0xC4,
+       0x62, 0x81, 0xDA, 0x80, 0xB2, 0x3C, 0xD0, 0x7E, 0xC3, 0xA2, 0x76, 0x50, 0x50, 0x3E, 0xFC, 0xBC,
+       0xFC, 0xAD, 0xAB, 0xDB, 0xA5, 0xF6, 0xA0, 0x4F, 0x55, 0xF3, 0xF3, 0xF5, 0xCA, 0x22, 0x21, 0x16,
+       0x10, 0x9D, 0x75, 0xFE, 0x62, 0x46, 0x38, 0x83, 0x5E, 0xEA, 0xE4, 0xF8, 0x44, 0xD5, 0x87, 0x74,
+       0x68, 0x70, 0xAD, 0x79, 0x6F, 0x1F, 0x06, 0xAC, 0x80, 0x6B, 0x33, 0x2E, 0x86, 0x19, 0xF3, 0x31,
+       0xCA, 0xC4, 0x67, 0x2C, 0x9E, 0x82, 0xA3, 0xD8, 0xED, 0xB0, 0x03, 0x2C, 0x10, 0xB0, 0x66, 0xDE,
+       0xD9, 0xD5, 0x7F, 0xBC, 0x6B, 0xB2, 0x74, 0xF2, 0xAD, 0x51, 0x2F, 0xA2, 0xAB, 0x0A, 0x0B, 0xF2,
+       0xEA, 0xA3, 0x70, 0xD8, 0x5F, 0x9C, 0x9A, 0x13, 0x6D, 0x5E, 0x90, 0x7C, 0xFD, 0x7A, 0x64, 0x71,
+       0x78, 0x7A, 0xD6, 0xAF, 0x1B, 0x25, 0x72, 0xC9, 0xEA, 0x0A, 0xBC, 0x6A, 0x72, 0x60, 0x9E, 0x85,
+       0x95, 0x11, 0x64, 0x45, 0x9E, 0x54, 0xD2, 0x31, 0x8E, 0xCB, 0xEE, 0x6A, 0xC1, 0x2F, 0xD7, 0x07,
+       0xF1, 0xC5, 0xB5, 0xE5, 0x2B, 0x7B, 0xDE, 0x66, 0x74, 0x66, 0x97, 0x38, 0x1A, 0xBF, 0x13, 0x98,
+       0xF8, 0xDD, 0xF6, 0x1B, 0x64, 0x80, 0x1A, 0xF6, 0x35, 0x04, 0x51, 0xD6, 0xF9, 0x61, 0x21, 0xB2,
+       0x6E, 0x78, 0xCB, 0xB8, 0x09, 0xF5, 0xC1, 0xD3, 0xD8, 0xDD, 0xC6, 0xFB, 0x63, 0x47, 0x98, 0x90,
+       0x1E, 0xAF, 0x77, 0xB1, 0xB9, 0xDF, 0x22, 0x7B, 0x8D, 0x6F, 0x0D, 0xE8, 0x83, 0x3B, 0xEF, 0x02,
+       0x53, 0xA0, 0x02, 0xFC, 0xE9, 0xC3, 0xD9, 0xB4, 0x8E, 0xAF, 0xB5, 0xD3, 0x6F, 0x68, 0x9B, 0x35,
+       0x5B, 0xE8, 0x79, 0x6D, 0x11, 0x8C, 0x21, 0xDB, 0xBB, 0xEE, 0x56, 0xBE, 0xC5, 0xFF, 0x7D, 0xE8,
+       0x3E, 0xA1, 0xB7, 0xA5, 0x26, 0xEF, 0x14, 0x3F, 0x8D, 0x12, 0x97, 0xC4, 0x64, 0xDD, 0xD8, 0xA7,
+       0xC5, 0x3E, 0xC5, 0x7F, 0x2A, 0x00, 0xC3, 0x67, 0x80, 0x19, 0xC8, 0x3D, 0xAD, 0x17, 0x2E, 0x54,
+       0x94, 0xA9, 0x39, 0x43, 0xFF, 0xC2, 0x6F, 0x5F, 0x93, 0x8A, 0x3B, 0x43, 0x47, 0x47, 0xD4, 0xA8,
+       0x3A, 0xA1, 0x91, 0x40, 0x45, 0x54, 0xB6, 0x83, 0x60, 0x5F, 0x71, 0x49, 0x45, 0x9E, 0x42, 0x7A,
+       0x57, 0x85, 0x07, 0xE9, 0x45, 0x31, 0x35, 0xEF, 0x7B, 0x24, 0xEB, 0xA8, 0xE7, 0x11, 0xB1, 0x4E,
+       0x97, 0x32, 0xD6, 0x93, 0xAA, 0x2B, 0x5F, 0xFD, 0x64, 0xC3, 0x48, 0x5E, 0xE3, 0xAB, 0x3F, 0x51,
+       0x11, 0x86, 0x49, 0x41, 0x05, 0x3B, 0x0E, 0x29, 0x47, 0xA0, 0xBC, 0x31, 0x08, 0x3F, 0x2D, 0xDA,
+       0x9F, 0x3D, 0x27, 0xA2, 0x09, 0x54, 0x98, 0x99, 0x5E, 0x05, 0x3B, 0x31, 0x09, 0x01, 0xF1, 0x57,
+       0xAD, 0x5A, 0x27, 0x60, 0x38, 0x41, 0x64, 0x85, 0x2F, 0x2E, 0xCB, 0xA5, 0xB4, 0x33, 0x33, 0x35,
+       0xE2, 0xCA, 0xD7, 0xF4, 0xCE, 0x30, 0xB5, 0x01, 0xA4, 0x9D, 0x99, 0x18, 0x24, 0x6A, 0xAB, 0x21,
+       0x5F, 0x7D, 0xE2, 0xE9, 0x55, 0xF9, 0x8A, 0xDF, 0xE5, 0xF3, 0x88, 0x06, 0xD4, 0xC6, 0xEE, 0x35,
+       0xAB, 0x93, 0xA0, 0x79, 0x5B, 0x1E, 0x5F, 0x02, 0xAC, 0x6A, 0xA0, 0xCE, 0x2C, 0xAC, 0xC8, 0xAF,
+       0x8B, 0x8C, 0x20, 0xAA, 0x45, 0xC6, 0x83, 0x0C, 0xD0, 0x0C, 0x98, 0x8B, 0x8E, 0x56, 0x53, 0x63,
+       0xCB, 0xCA, 0x8A, 0xD4, 0xF3, 0x59, 0x8A, 0xBA, 0xEB, 0xD5, 0x97, 0x86, 0x96, 0x18, 0x28, 0xDD,
+       0xA1, 0xF4, 0xFB, 0x3E, 0xDC, 0xD5, 0x1E, 0xC3, 0x16, 0x54, 0x2F, 0x45, 0xD0, 0xED, 0xBC, 0xF9,
+       0xDB, 0x53, 0xB5, 0x19, 0x45, 0xC2, 0x16, 0x75, 0xFD, 0x26, 0x35, 0xA6, 0x75, 0xAB, 0xFA, 0xBC,
+       0xE4, 0x62, 0x45, 0xB1, 0xA2, 0x7F, 0x27, 0x9D, 0x2A, 0x1F, 0x18, 0xFA, 0x61, 0x2D, 0xD3, 0xB2,
+       0x88, 0xDE, 0xF8, 0x42, 0xC3, 0x74, 0xB3, 0x78, 0xA0, 0x40, 0x31, 0x55, 0xCD, 0x40, 0x84, 0xE2,
+       0x5E, 0x8F, 0x48, 0x4E, 0x84, 0x63, 0x40, 0xCF, 0xAD, 0x5F, 0xE1, 0x13, 0xAF, 0xAE, 0x45, 0x02,
+       0x78, 0xAC, 0xD8, 0xC4, 0xBC, 0xE6, 0xD8, 0x78, 0x17, 0x85, 0x01, 0x49, 0xEC, 0x91, 0x40, 0x4A,
+       0xF2, 0x0E, 0xC8, 0xBF, 0xA5, 0xF7, 0xFC, 0xCC, 0x4D, 0x95, 0x95, 0xDE, 0x57, 0xC3, 0x0E, 0xAE,
+       0xD4, 0xC3, 0xC2, 0x8A, 0x9E, 0xA7, 0x83, 0x30, 0x70, 0xA7, 0x8A, 0xCB, 0xE3, 0x6E, 0x8D, 0x06,
+       0x07, 0x9A, 0x2B, 0x7D, 0xEC, 0x1A, 0x9C, 0x8D, 0x6E, 0xEE, 0x12, 0xC1, 0x62, 0xB7, 0x7F, 0x51,
+       0xCF, 0x77, 0x78, 0xBF, 0xB8, 0xF7, 0x48, 0xE2, 0x0A, 0x20, 0x50, 0x98, 0x7A, 0x16, 0xAF, 0x6A,
+       0x62, 0x0C, 0xAC, 0x90, 0x78, 0x0B, 0x6C, 0xFF, 0xBC, 0x26, 0xA7, 0x23, 0x0D, 0xBA, 0x9E, 0x25,
+       0x1E, 0x50, 0xD6, 0x3C, 0xBE, 0xA2, 0x72, 0x39, 0xC1, 0x4D, 0xC6, 0x9B, 0x07, 0xD2, 0x6D, 0x00,
+       0xE1, 0xB6, 0x87, 0x2E, 0x15, 0x30, 0x56, 0x66, 0xEC, 0x7A, 0x9E, 0x30, 0x76, 0x21, 0x40, 0x1F,
+       0x47, 0xB7, 0x7E, 0xDE, 0x7D, 0xB1, 0x22, 0x29, 0x9B, 0x19, 0x38, 0xC9, 0x20, 0x60, 0xAA, 0x54,
+       0x2A, 0x84, 0xD6, 0x3F, 0x0F, 0x42, 0xA4, 0xF5, 0xE4, 0x92, 0x22, 0x93, 0x1F, 0xD6, 0x93, 0x44,
+       0x47, 0xDA, 0x6E, 0x3D, 0x34, 0xEA, 0x80, 0xB2, 0xC4, 0x99, 0xD1, 0x4D, 0x5C, 0x95, 0x2A, 0x74,
+       0xFC, 0x89, 0x33, 0x6A, 0xF3, 0x6E, 0x5F, 0x46, 0xC8, 0x1C, 0x91, 0x7C, 0x23, 0x4E, 0x18, 0x47,
+       0x52, 0x83, 0xCE, 0x05, 0x1D, 0xAF, 0xF1, 0x76, 0x1A, 0x92, 0x48, 0x32, 0x29, 0x7D, 0xFF, 0x23,
+       0xD6, 0xFB, 0x51, 0x5B, 0x79, 0x78, 0xFE, 0xD1, 0x78, 0xC2, 0x5B, 0x33, 0x9B, 0x5D, 0x45, 0xA2,
+       0x12, 0xE9, 0x7F, 0x2A, 0x41, 0x8A, 0xFA, 0x57, 0xFF, 0x5A, 0x46, 0x31, 0x81, 0x9E, 0x94, 0x46,
+       0x2B, 0x1D, 0x05, 0x35, 0x07, 0x6A, 0x0D, 0xAD, 0xF1, 0x06, 0x39, 0xE7, 0x98, 0x87, 0x81, 0x35,
+       0xF0, 0xD9, 0x0D, 0x43, 0xEE, 0x81, 0xAF, 0x17, 0x29, 0xEA, 0x97, 0x81, 0x65, 0x0E, 0xE9, 0x96,
+       0x62, 0x19, 0x28, 0x6B, 0x67, 0x4E, 0x29, 0xEC, 0x06, 0xF3, 0x34, 0x1E, 0xD4, 0xFE, 0xFE, 0x8D,
+       0xE6, 0xE2, 0xB8, 0x37, 0x0A, 0x1B, 0x14, 0x22, 0x26, 0xAC, 0x6C, 0x8E, 0xA0, 0xFC, 0xD2, 0x47,
+       0x14, 0x58, 0x33, 0x10, 0x81, 0xA7, 0x5F, 0x2F, 0xEB, 0x6B, 0x9C, 0x23, 0x40, 0xB3, 0x87, 0x3C,
+       0x32, 0x28, 0xE1, 0xD8, 0x84, 0xB7, 0x9D, 0x6F, 0x55, 0xF6, 0x19, 0xF8, 0x4F, 0xC5, 0x88, 0xC8,
+       0x27, 0xF3, 0x4F, 0xDA, 0x97, 0x4D, 0x40, 0xD5, 0xE4, 0x96, 0x68, 0xBC, 0x6E, 0x44, 0xD7, 0xAB,
+       0xAC, 0x6A, 0x07, 0xEA, 0x44, 0x18, 0xA4, 0x16, 0x52, 0x72, 0x6A, 0x37, 0x9E, 0x6D, 0x2B, 0x8B,
+       0x02, 0x7F, 0xC9, 0x85, 0xD9, 0x3D, 0x80, 0x39, 0x78, 0x39, 0x22, 0x89, 0x59, 0x62, 0xB7, 0xB9,
+       0xF1, 0xDF, 0x2A, 0x63, 0x65, 0xF6, 0x16, 0x3B, 0xAD, 0xD2, 0x78, 0xB4, 0x4F, 0x0D, 0x59, 0xA6,
+       0x76, 0xEE, 0xFC, 0x5C, 0xAB, 0x78, 0x58, 0x8E, 0xB8, 0x9B, 0xEB, 0x0F, 0xE4, 0x85, 0xB1, 0xED,
+       0x1E, 0x5E, 0x14, 0xBD, 0x80, 0xF7, 0x6F, 0x90, 0xD1, 0x52, 0x86, 0x5F, 0xCC, 0xE3, 0x30, 0x15,
+       0xE7, 0x33, 0x72, 0x3B, 0xCB, 0x2E, 0x5D, 0x79, 0x41, 0x0C, 0xF5, 0xD4, 0x99, 0x86, 0xB2, 0xB9,
+       0x3F, 0xD4, 0x7D, 0x65, 0x86, 0x91, 0x39, 0xCC, 0x98, 0x3A, 0x58, 0xCB, 0x1F, 0x08, 0x36, 0xCA,
+       0xD2, 0xE4, 0x7A, 0xD6, 0x5B, 0x88, 0x17, 0x82, 0x59, 0xC0, 0x0F, 0x2B, 0x68, 0x5E, 0x28, 0x3E,
+       0x8B, 0x3C, 0x9F, 0x42, 0x24, 0x8C, 0xB1, 0x99, 0x74, 0x7A, 0xEB, 0x14, 0xB9, 0x93, 0xE2, 0x20,
+       0x43, 0xEC, 0x7A, 0xF8, 0x02, 0xFC, 0x82, 0xC3, 0xF2, 0x4D, 0x07, 0xB9, 0x96, 0x89, 0xB4, 0x7F,
+       0xBB, 0x09, 0x92, 0x36, 0xE9, 0xA6, 0x78, 0x69, 0xBE, 0xCB, 0xD2, 0x10, 0xCE, 0x0B, 0xDE, 0x90,
+       0x6B, 0xF7, 0x69, 0x0D, 0x75, 0xC7, 0xF0, 0xDE, 0xB9, 0xDA, 0xF1, 0x9C, 0x9B, 0xF5, 0xFD, 0xAD,
+       0x47, 0xE2, 0x2F, 0xC1, 0x08, 0x3A, 0x3F, 0x15, 0x1F, 0xD0, 0x0D, 0x8B, 0x48, 0xAA, 0xE2, 0x29,
+       0xAD, 0x18, 0x95, 0x1A, 0x3C, 0x3B, 0x57, 0x97, 0xCB, 0x02, 0x6D, 0x39, 0xBD, 0x70, 0x68, 0x7B,
+       0x93, 0xA9, 0xCB, 0x8B, 0x0C, 0x9D, 0x21, 0xDA, 0x61, 0x26, 0x16, 0x28, 0xCF, 0x16, 0x49, 0x22,
+       0x56, 0xC9, 0xAA, 0x24, 0x88, 0xE1, 0x27, 0x5A, 0xC3, 0x98, 0xD2, 0xD8, 0x8B, 0xF5, 0xFD, 0x74,
+       0x3A, 0xA3, 0xC4, 0xD2, 0x03, 0xA9, 0x60, 0x0A, 0xED, 0x92, 0xC2, 0x1A, 0x23, 0x09, 0x6E, 0xC1,
+       0x22, 0xDE, 0x33, 0x7A, 0xEA, 0xF9, 0xAB, 0x79, 0xEC, 0x35, 0x40, 0x65, 0x82, 0x17, 0x80, 0x0E,
+       0xC0, 0xE5, 0x30, 0x09, 0xD2, 0x72, 0x14, 0x47, 0xB2, 0x3B, 0xE1, 0xAE, 0xE8, 0xE5, 0x82, 0xCB,
+       0xF6, 0x39, 0x12, 0x2F, 0x68, 0x08, 0x5E, 0xCA, 0x73, 0x7E, 0xB8, 0xA5, 0x1B, 0xE1, 0x6D, 0xA9,
+       0x04, 0x76, 0x2D, 0xED, 0xB8, 0x40, 0xF5, 0x14, 0xA3, 0xC7, 0x05, 0x0D, 0xD0, 0x0E, 0x0B, 0x67,
+       0x58, 0xB7, 0xD4, 0xD0, 0x3A, 0x91, 0xD9, 0x19, 0x01, 0xC1, 0x29, 0x46, 0xC9, 0xD3, 0x4D, 0x24,
+       0xAA, 0x35, 0x39, 0x8B, 0x56, 0xC1, 0x21, 0x42, 0x03, 0xC0, 0x9C, 0x1B, 0x64, 0x60, 0xFE, 0x9A,
+       0x7C, 0xA8, 0xA2, 0xCB, 0x29, 0x5C, 0xEB, 0x50, 0x35, 0x68, 0x78, 0xB5, 0xA0, 0xC1, 0xC4, 0xF2,
+       0x67, 0x56, 0xB0, 0xFF, 0xDA, 0x11, 0xCA, 0xB8, 0x00, 0xBB, 0x71, 0x74, 0xFA, 0xFB, 0x99, 0x5C,
+       0x00, 0x98, 0x08, 0xC1, 0x01, 0x16, 0x02, 0x15, 0x8B, 0x79, 0x4F, 0x5F, 0x61, 0x1F, 0x77, 0x41,
+       0xFB, 0x65, 0x3F, 0x4F, 0xE5, 0x8A, 0x26, 0xC4, 0x3F, 0x56, 0x0B, 0xBA, 0x75, 0x5F, 0x17, 0xF4,
+       0x16, 0xF9, 0x3C, 0x24, 0xF1, 0xC8, 0xFC, 0xF5, 0x14, 0x6A, 0x04, 0xD7, 0xC9, 0xAA, 0x33, 0xCB,
+       0x9C, 0x23, 0xC3, 0xC6, 0x0D, 0x0E, 0x49, 0xD4, 0xE5, 0xDD, 0x9C, 0xAD, 0xF3, 0x5E, 0x28, 0x33,
+       0xA2, 0x73, 0xFD, 0x8B, 0xBF, 0x67, 0xD8, 0xC7, 0xC2, 0xFF, 0x93, 0x04, 0xFB, 0x87, 0x8F, 0xE0,
+       0x32, 0xDC, 0xC9, 0x3B, 0xFE, 0x5C, 0x12, 0x98, 0xDC, 0x8F, 0x57, 0x11, 0xC8, 0x6D, 0xC9, 0xD3,
+       0x4A, 0xA4, 0x70, 0x32, 0x56, 0x79, 0x2E, 0x08, 0x48, 0x08, 0xB2, 0x74, 0x44, 0x27, 0x3A, 0x20,
+       0xE5, 0x45, 0xC2, 0x2E, 0xD1, 0x7E, 0xDD, 0x65, 0xA1, 0x70, 0xDD, 0xF1, 0x6F, 0x4D, 0x3E, 0xA8,
+       0x5B, 0x15, 0xB3, 0x41, 0x1E, 0xF4, 0x05, 0x27, 0x61, 0x26, 0x5E, 0xE0, 0xA6, 0x65, 0x74, 0x86,
+       0xBA, 0x61, 0x10, 0xC3, 0xED, 0xFF, 0xD2, 0xAE, 0x4A, 0xEC, 0x91, 0xAD, 0xD2, 0x0F, 0x83, 0x48,
+       0xCB, 0x6B, 0x7F, 0x2C, 0xA8, 0x85, 0xFC, 0xFA, 0xF4, 0x59, 0xD9, 0x24, 0x9C, 0x5D, 0x61, 0x52,
+       0x34, 0xCA, 0x03, 0xF4, 0x2B, 0x1B, 0xF7, 0x38, 0x7B, 0xDA, 0x60, 0xF5, 0x4C, 0x83, 0x11, 0x3F,
+       0x28, 0xE2, 0x9A, 0x37, 0x4D, 0x8C, 0xE3, 0x78, 0x9E, 0x3E, 0xC4, 0xE1, 0xEA, 0xD2, 0x9B, 0xF2,
+       0x4B, 0x16, 0x51, 0xCF, 0xD6, 0x12, 0x5A, 0x4B, 0x03, 0x65, 0x40, 0xE2, 0xFF, 0xEF, 0x50, 0x51,
+       0x4A, 0x29, 0x13, 0x96, 0xDB, 0x8E, 0x68, 0xCF, 0x61, 0x48, 0xA4, 0x67, 0x88, 0x5C, 0x0F, 0x9E,
+       0xE6, 0x9D, 0xF3, 0x6F, 0xFB, 0x6E, 0xE4, 0xF2, 0xA1, 0xFA, 0xE9, 0x54, 0x98, 0x27, 0x69, 0x5E,
+       0x51, 0x87, 0x1A, 0x55, 0x31, 0x6C, 0x1A, 0x59, 0x0A, 0xB7, 0x73, 0xA5, 0xD4, 0x92, 0x49, 0x84,
+       0x75, 0x80, 0x37, 0x9C, 0xB6, 0x6E, 0x34, 0x60, 0xD3, 0x67, 0xC4, 0xFA, 0x74, 0x8E, 0x09, 0x56,
+       0x99, 0x9F, 0x12, 0x0E, 0x7C, 0x2E, 0x59, 0xD0, 0xC7, 0x4A, 0xEC, 0xF7, 0x73, 0x72, 0xE5, 0x0E,
+       0x8E, 0x62, 0x34, 0x62, 0x60, 0x82, 0xDC, 0x84, 0x20, 0x09, 0xAD, 0x28, 0xF5, 0xD5, 0x40, 0xD6,
+       0xF4, 0x12, 0x24, 0xAD, 0x3B, 0xFE, 0x32, 0x41, 0xB6, 0x61, 0x99, 0x1E, 0xBD, 0xE4, 0x21, 0x97,
+       0x39, 0x69, 0xF1, 0xD6, 0x8D, 0xD8, 0xDB, 0xB7, 0x26, 0xA3, 0x1D, 0x98, 0xB4, 0xAD, 0xC0, 0x5C,
+       0xD5, 0x28, 0x2B, 0x93, 0xAD, 0xFC, 0x76, 0x17, 0x2F, 0x0D, 0xE3, 0xE4, 0x48, 0x54, 0xCD, 0x57,
+       0xC8, 0xAA, 0xE9, 0x9D, 0xDB, 0xA8, 0xE7, 0xA5, 0x8D, 0x23, 0x0B, 0xC0, 0x2F, 0xAF, 0x1E, 0x78,
+       0x8D, 0x78, 0x50, 0xCE, 0x8D, 0x6E, 0x12, 0xFB, 0xA2, 0x31, 0x65, 0x30, 0x19, 0x6C, 0x50, 0x7D,
+       0x44, 0x2F, 0xDD, 0x71, 0xC8, 0xE7, 0xF4, 0x39, 0x7F, 0x78, 0x5E, 0x3D, 0x6C, 0xE3, 0x18, 0xB9,
+       0xFF, 0x3B, 0xAD, 0xFF, 0x53, 0x13, 0x12, 0x8F, 0x30, 0xFB, 0x5C, 0x6D, 0xFF, 0x46, 0x97, 0xCF,
+       0xEB, 0x32, 0x0B, 0xB0, 0x91, 0x2D, 0xBF, 0x6F, 0xAE, 0x6E, 0x01, 0x15, 0xF5, 0x71, 0x08, 0x42,
+       0x1D, 0x6F, 0x1A, 0xF1, 0x4E, 0x71, 0x44, 0x6F, 0x73, 0xF3, 0x4C, 0x73, 0x32, 0x6A, 0x30, 0x99,
+       0x29, 0xDF, 0x60, 0xA0, 0x80, 0xF3, 0x71, 0xE5, 0x84, 0xBB, 0x29, 0xC8, 0x0D, 0x7B, 0x34, 0xAF,
+       0xDA, 0x0A, 0x65, 0xD6, 0x84, 0x62, 0xCB, 0x79, 0x86, 0x1A, 0x56, 0x94, 0xB6, 0x11, 0x97, 0x69,
+       0xBA, 0x25, 0xFB, 0x5A, 0xB1, 0xB4, 0xC0, 0xB6, 0xCA, 0xF1, 0xFA, 0x7E, 0x75, 0xE4, 0x6D, 0xDA,
+       0x9F, 0xE4, 0x56, 0x83, 0xE1, 0x9E, 0xFC, 0x83, 0x00, 0x43, 0x5B, 0xFC, 0x58, 0x43, 0x83, 0x95,
+       0xB9, 0xFB, 0xE6, 0x58, 0x5E, 0xA9, 0xAA, 0x2A, 0x51, 0xB7, 0xE2, 0x83, 0x88, 0x0E, 0x88, 0xF4,
+       0x30, 0x7F, 0x9B, 0xC4, 0x22, 0xE9, 0x1E, 0xA0, 0xB3, 0x8C, 0x14, 0x55, 0x6B, 0xC5, 0x0F, 0xA9,
+       0x87, 0xF3, 0xC8, 0x1C, 0x95, 0x2A, 0x63, 0xB3, 0xE7, 0x1F, 0xE1, 0x23, 0x8B, 0x26, 0x2E, 0x73,
+       0x22, 0x04, 0x2B, 0xE3, 0x1A, 0x23, 0x95, 0xA6, 0x8B, 0x18, 0x9B, 0x2E, 0x2D, 0xD8, 0xF2, 0x87,
+       0x4E, 0x52, 0xFB, 0x72, 0x48, 0xDF, 0x01, 0xAC, 0x09, 0x47, 0x9C, 0xB5, 0xD2, 0xD0, 0xF0, 0xDB,
+       0x5A, 0x8F, 0x0B, 0x8D, 0x6B, 0xFA, 0xF1, 0x0E, 0x47, 0xF4, 0x58, 0x86, 0xB7, 0xB6, 0x14, 0xC2,
+       0x36, 0x23, 0x90, 0x14, 0xBF, 0xE2, 0x8F, 0x40, 0xFC, 0xC7, 0xC5, 0xAC, 0x84, 0x04, 0x0F, 0xC4,
+       0x77, 0x6C, 0x9E, 0x4D, 0x9B, 0xB9, 0x56, 0xF2, 0xD0, 0x94, 0xE4, 0xDD, 0x31, 0x1C, 0xD7, 0x7C,
+       0x0F, 0xE2, 0x55, 0xBA, 0xC0, 0x92, 0x88, 0xA6, 0xEF, 0xD6, 0x54, 0xE1, 0x38, 0x45, 0xE7, 0xD2,
+       0xF6, 0x2F, 0x58, 0x4D, 0x7C, 0x67, 0xB0, 0xFC, 0xFB, 0xC9, 0xCE, 0xF3, 0x32, 0xFF, 0x13, 0xF2,
+       0x57, 0xB4, 0x82, 0x46, 0x82, 0x25, 0x8F, 0x5E, 0x88, 0x26, 0x65, 0x76, 0x20, 0x31, 0xC2, 0x94,
+       0x61, 0xCA, 0xFD, 0xFA, 0x0A, 0xAC, 0x16, 0x63, 0x4E, 0xA6, 0x5B, 0x68, 0xB9, 0x44, 0x26, 0xB2,
+       0xCF, 0x69, 0xB4, 0x5E, 0xCE, 0x94, 0xE0, 0x6B, 0xE1, 0x24, 0x01, 0xA9, 0xEB, 0xBC, 0xDE, 0x40,
+       0x65, 0x6F, 0x83, 0x15, 0x69, 0x5D, 0x09, 0xC2, 0xE3, 0x55, 0x0C, 0x1F, 0xAA, 0xC1, 0x07, 0x11,
+       0xCE, 0xCB, 0xAB, 0xB5, 0xB7, 0xC4, 0x1F, 0x21, 0x0D, 0x59, 0x1D, 0xB0, 0x6D, 0x10, 0x43, 0xAC,
+       0x8B, 0xE2, 0x54, 0x3D, 0x15, 0x60, 0xC7, 0x24, 0xF3, 0x78, 0x42, 0x57, 0xCE, 0x80, 0xE5, 0xB7,
+       0x46, 0xF7, 0xA7, 0x81, 0x41, 0xA0, 0xDB, 0xF6, 0x30, 0x76, 0x94, 0x5A, 0x38, 0x18, 0x96, 0x0D,
+       0x0E, 0x8A, 0x70, 0xA7, 0xFF, 0x1E, 0x45, 0xFB, 0x70, 0xA7, 0xD4, 0x29, 0x29, 0xDB, 0x4F, 0xAC,
+       0x3B, 0xF6, 0x9F, 0xC2, 0x1E, 0xE1, 0xAC, 0xEC, 0xAD, 0x4B, 0xA3, 0x2D, 0xCF, 0x98, 0x3F, 0x92,
+       0xD5, 0x7B, 0x58, 0xB2, 0xB2, 0xAB, 0x81, 0x4F, 0x56, 0x53, 0xB7, 0x0D, 0x15, 0xD3, 0x0F, 0x92,
+       0xE7, 0x8F, 0x4E, 0xA0, 0x6A, 0x99, 0xBD, 0x2C, 0xB5, 0x81, 0x2B, 0xA1, 0x03, 0x87, 0x50, 0x07,
+       0x30, 0xC3, 0x8C, 0xC7, 0x1C, 0x3F, 0x25, 0xFA, 0x66, 0x89, 0x70, 0x55, 0x86, 0xDF, 0x3D, 0xB7,
+       0x90, 0x1B, 0x61, 0xB1, 0x0F, 0xD2, 0xC9, 0x62, 0xD1, 0x58, 0xE3, 0x4C, 0xC7, 0xCD, 0xB1, 0xA5,
+       0x63, 0x7D, 0xF0, 0x0E, 0x23, 0x76, 0xC2, 0x66, 0x7D, 0x8C, 0x58, 0x41, 0xFE, 0x0E, 0x6B, 0x49,
+       0x81, 0x23, 0x93, 0x2E, 0xDF, 0x91, 0x3D, 0x9F, 0x5E, 0xBB, 0xF0, 0x07, 0xA9, 0x94, 0xF7, 0xF0,
+       0x0D, 0xD1, 0xF0, 0x99, 0x6E, 0xE7, 0x24, 0xEA, 0xA0, 0x04, 0x18, 0x4F, 0x8A, 0x2F, 0x8E, 0xA6,
+       0x35, 0x3F, 0x35, 0xE8, 0x26, 0xFA, 0x21, 0xAD, 0x74, 0xDC, 0xA8, 0x7B, 0xEB, 0xF6, 0x6D, 0xD0,
+       0x4E, 0x8D, 0x21, 0x11, 0x71, 0x71, 0x5F, 0xF6, 0x0E, 0xD7, 0xD7, 0x69, 0x2D, 0x41, 0xE3, 0xAB,
+       0x8A, 0xAA, 0x20, 0x5A, 0x9D, 0xC5, 0x7D, 0x85, 0x63, 0xD3, 0xCD, 0xF5, 0x3D, 0xEE, 0x58, 0x69,
+       0x48, 0xF0, 0x57, 0xB0, 0x64, 0xCA, 0x36, 0x2D, 0xF8, 0xF6, 0xE2, 0xA8, 0xDC, 0x7A, 0x33, 0xB5,
+       0xE8, 0x44, 0x40, 0x88, 0x4A, 0xBA, 0x03, 0xA0, 0x4F, 0x49, 0xDB, 0x15, 0x65, 0x6A, 0xE5, 0xF3,
+       0xFB, 0x01, 0x8A, 0x0B, 0x19, 0x6D, 0x92, 0x0E, 0x83, 0x6F, 0xFD, 0x6D, 0x54, 0xE4, 0x2C, 0xA6,
+       0x07, 0xFF, 0x50, 0xAE, 0xE9, 0x25, 0x2F, 0xB2, 0x56, 0xD2, 0x71, 0xC8, 0x8C, 0x21, 0x06, 0xD7,
+       0x13, 0x53, 0x65, 0x4C, 0xD2, 0xE7, 0xAE, 0x3D, 0xD5, 0x15, 0xD3, 0x0E, 0xAE, 0x23, 0x28, 0x4E,
+       0xEF, 0x66, 0x35, 0xAF, 0x65, 0x3E, 0xAC, 0x29, 0x15, 0xBC, 0xC2, 0x9A, 0x96, 0xD8, 0x6B, 0xB5,
+       0xAE, 0x54, 0xDC, 0xE8, 0x16, 0x31, 0xA3, 0xA6, 0x77, 0x19, 0x95, 0x22, 0x52, 0x06, 0x60, 0x39,
+       0x1D, 0x72, 0x0A, 0x20, 0x40, 0x9F, 0x01, 0xFE, 0x69, 0x3D, 0xA0, 0xEF, 0xEE, 0x79, 0xFD, 0xC7,
+       0x2B, 0x55, 0xE2, 0x51, 0x15, 0xDE, 0x11, 0x4D, 0x34, 0x8A, 0x1E, 0x03, 0x9E, 0xFB, 0xE0, 0xFD,
+       0x77, 0x62, 0x14, 0xCD, 0x29, 0x69, 0x1C, 0x4B, 0x10, 0x27, 0x68, 0xC1, 0x7E, 0x3D, 0x20, 0xD0,
+       0x11, 0xA2, 0x6A, 0x3E, 0xF9, 0xBF, 0x81, 0x0B, 0x16, 0xB1, 0x90, 0x22, 0x4A, 0x2D, 0x9C, 0x8E,
+       0x71, 0xC1, 0x58, 0xB9, 0x65, 0x12, 0x93, 0xF9, 0x7B, 0x12, 0x89, 0x0E, 0x5E, 0x70, 0xD9, 0xF7,
+       0xA9, 0x12, 0xF5, 0xA7, 0x9A, 0x35, 0xE1, 0x06, 0xB6, 0x3E, 0x09, 0x5B, 0x18, 0x10, 0x9F, 0x3D,
+       0x33, 0xA3, 0x53, 0x2B, 0x82, 0xC9, 0x17, 0x1A, 0xF5, 0xF8, 0x32, 0x94, 0xA7, 0x37, 0x21, 0x7A,
+       0x98, 0xE4, 0xFF, 0xEE, 0x26, 0x09, 0x74, 0x87, 0x96, 0xAA, 0xEE, 0x0D, 0xB4, 0x3D, 0xCE, 0x9A,
+       0xEC, 0x4D, 0x2E, 0x57, 0x11, 0x76, 0xFF, 0x62, 0xA8, 0x03, 0xFC, 0xC6, 0x91, 0x3F, 0x73, 0x8E,
+       0xF7, 0xB9, 0x34, 0xF1, 0xF1, 0x6E, 0x33, 0xCE, 0xF1, 0xEC, 0x48, 0xF6, 0x40, 0x01, 0x5C, 0xE6,
+       0x42, 0x55, 0xA4, 0xFF, 0xEB, 0x13, 0xB4, 0xD7, 0x8B, 0x21, 0x88, 0xA0, 0xFE, 0xF1, 0x47, 0xA9,
+       0x28, 0x36, 0x3A, 0x0E, 0x41, 0xDC, 0x07, 0x15, 0xAC, 0x5C, 0x41, 0x7D, 0x25, 0x11, 0x3D, 0x94,
+       0xDF, 0x1D, 0x2C, 0x60, 0x52, 0x77, 0x10, 0x02, 0x8F, 0xB4, 0x97, 0x0E, 0x76, 0x26, 0x92, 0xFE,
+       0xD9, 0xD5, 0x84, 0x6B, 0xD5, 0xA3, 0xDE, 0xE7, 0x37, 0xC8, 0x88, 0xAC, 0x06, 0xDD, 0x44, 0x90,
+       0x7E, 0xC2, 0x95, 0xFB, 0x89, 0x73, 0x1D, 0x3E, 0x8A, 0xDA, 0x95, 0x5E, 0xBA, 0x26, 0x3B, 0xEB,
+       0x2D, 0x49, 0xC3, 0x1F, 0xD2, 0x70, 0x76, 0x61, 0x41, 0x59, 0x0D, 0xF7, 0x88, 0x1E, 0x6E, 0x81,
+       0xBD, 0x2B, 0x3E, 0xAF, 0x2C, 0x8D, 0xEC, 0x1F, 0x80, 0xBD, 0x81, 0x26, 0xE0, 0x3C, 0x99, 0x3A,
+       0x41, 0xC7, 0x50, 0x3E, 0x37, 0xA0, 0x6B, 0xB0, 0x8A, 0x66, 0x74, 0x39, 0x37, 0x1E, 0xF8, 0x42,
+       0x39, 0x40, 0xB3, 0x23, 0x73, 0xC3, 0x03, 0xBB, 0x3F, 0x63, 0x51, 0x08, 0x53, 0x82, 0x4D, 0x8D,
+       0xE4, 0xC6, 0x08, 0xDE, 0xB8, 0x77, 0x77, 0xB2, 0x35, 0x24, 0x3D, 0x77, 0x49, 0x20, 0x3E, 0xF0,
+       0x51, 0xD6, 0xE6, 0xD7, 0xD5, 0xFC, 0x36, 0xAB, 0x28, 0x8D, 0xE3, 0x09, 0x48, 0x10, 0x48, 0x02,
+       0x7F, 0x53, 0x10, 0xB6, 0x28, 0xFB, 0x45, 0x86, 0xED, 0x71, 0x20, 0x28, 0xA9, 0x50, 0x50, 0xD0,
+       0xB2, 0x6D, 0xAB, 0x97, 0x5F, 0xA1, 0x59, 0x88, 0xDB, 0x55, 0xF3, 0x1E, 0x16, 0x02, 0xC9, 0xF7,
+       0xE2, 0x90, 0x8D, 0x5A, 0x8E, 0x89, 0x78, 0x2F, 0xD4, 0x4E, 0x7A, 0xAC, 0x87, 0x71, 0xF5, 0x88,
+       0xFA, 0x67, 0xD2, 0x42, 0xBB, 0xA1, 0x01, 0x80, 0xD2, 0x57, 0x86, 0x45, 0x34, 0x41, 0x20, 0xDB,
+       0xBD, 0x19, 0xA0, 0x5A, 0x73, 0x30, 0x4D, 0x0E, 0xC8, 0x4C, 0x73, 0x0A, 0x31, 0xE6, 0x49, 0x6A,
+       0xE9, 0x67, 0xA0, 0x99, 0xD4, 0x67, 0x2C, 0x5A, 0x6C, 0x0F, 0x75, 0x67, 0x9E, 0xC5, 0xBD, 0xF9,
+       0x66, 0xC6, 0x73, 0xC2, 0x72, 0xAC, 0x48, 0x50, 0x27, 0x63, 0x78, 0xD5, 0x90, 0x76, 0xF9, 0x8B,
+       0xE9, 0x9E, 0x9B, 0xA3, 0x71, 0x2C, 0x92, 0x55, 0x37, 0xC0, 0xB7, 0x0E, 0x20, 0x66, 0xB8, 0x12,
+       0xE2, 0x3F, 0xF7, 0x61, 0xE5, 0xBF, 0x94, 0xE2, 0x96, 0xA9, 0x42, 0x96, 0x21, 0xA5, 0x9B, 0xDC,
+       0x23, 0xD2, 0x3A, 0x56, 0x1B, 0xBB, 0xAD, 0xF4, 0x54, 0x56, 0x8C, 0x37, 0x47, 0xC6, 0x2A, 0x35,
+       0x4E, 0x5C, 0x18, 0xE0, 0xF3, 0x2F, 0xE5, 0x01, 0x4C, 0xA1, 0x0A, 0xB6, 0x24, 0xA1, 0x73, 0xDA,
+       0x85, 0xC7, 0xE4, 0xE3, 0x99, 0x67, 0x22, 0x02, 0xCF, 0x51, 0x15, 0x75, 0xE3, 0x07, 0x2F, 0x6B,
+       0xB3, 0xDE, 0x2F, 0x5D, 0x13, 0x40, 0xE8, 0x2B, 0xBC, 0x78, 0x55, 0x96, 0x1D, 0x15, 0x1E, 0x7D,
+       0x9F, 0xD0, 0x3A, 0x5C, 0x7B, 0xC7, 0xF6, 0x1A, 0x6D, 0xBC, 0x69, 0x97, 0xF2, 0xC8, 0x78, 0xA1,
+       0x20, 0x73, 0xFE, 0xDB, 0xF5, 0x57, 0xE2, 0x09, 0xC7, 0xF4, 0x1E, 0x85, 0x66, 0xDB, 0xEE, 0x4F,
+       0x64, 0x3C, 0x48, 0x78, 0xB2, 0xF5, 0x2B, 0x01, 0x3E, 0x53, 0x80, 0x7D, 0xA8, 0xBC, 0x72, 0x47,
+       0xF7, 0x10, 0x93, 0xA5, 0xA2, 0x82, 0x4C, 0x55, 0xF1, 0x78, 0xD3, 0xA9, 0xEC, 0xAC, 0x46, 0xD9,
+       0x0D, 0x04, 0xC2, 0x12, 0x26, 0xC5, 0x5B, 0x2B, 0x1A, 0x2C, 0xAD, 0x58, 0xAC, 0x1D, 0x9D, 0x56,
+       0x45, 0x15, 0xD2, 0xD0, 0xEA, 0x8E, 0xBE, 0xC6, 0xCB, 0x16, 0x9C, 0x17, 0x59, 0x23, 0x06, 0x52,
+       0xA8, 0x41, 0x40, 0x19, 0xE0, 0xCC, 0x96, 0x4E, 0xA6, 0x43, 0x85, 0xA3, 0x4A, 0xCD, 0x67, 0xAD,
+       0x48, 0xF0, 0x0D, 0x0A, 0xFF, 0xFC, 0x31, 0xE3, 0x8A, 0x4F, 0x50, 0xD9, 0xC7, 0xEE, 0x41, 0x51,
+       0x66, 0xF2, 0x97, 0xA9, 0x07, 0x5B, 0xD7, 0x0E, 0xDB, 0xFD, 0x7C, 0x10, 0x98, 0xDB, 0x3C, 0xBD,
+       0x41, 0x8E, 0x60, 0xDE, 0xB9, 0x0D, 0xDD, 0x9A, 0x19, 0x1E, 0xB9, 0x39, 0xD4, 0x2B, 0x13, 0x9B,
+       0x56, 0xF9, 0x53, 0x42, 0x93, 0xBA, 0x2C, 0x1D, 0x12, 0x57, 0xED, 0xAD, 0xA2, 0xA3, 0xF0, 0x76,
+       0xAD, 0x6F, 0x35, 0x6D, 0xDE, 0x9C, 0x42, 0xD1, 0x7D, 0x1E, 0x7D, 0xA8, 0x00, 0x16, 0x8E, 0x16,
+       0xA2, 0x20, 0xE4, 0xC4, 0x3E, 0x8A, 0x77, 0x21, 0xC8, 0xD9, 0xD9, 0x5D, 0xF1, 0x29, 0x3F, 0x1E,
+       0xCF, 0x1E, 0x2C, 0x84, 0x41, 0xC6, 0xB6, 0x76, 0x9D, 0x3F, 0xDB, 0x17, 0x5E, 0x4A, 0x40, 0x56,
+       0x9A, 0xFD, 0xD0, 0xFE, 0xEB, 0xC9, 0xB9, 0xC0, 0x06, 0xC1, 0x06, 0x68, 0x32, 0x3C, 0x6A, 0xAA,
+       0x5C, 0xF7, 0xEA, 0x5A, 0x58, 0x07, 0x64, 0xC4, 0x76, 0x30, 0x61, 0xD1, 0x1E, 0xB7, 0x0F, 0xDB,
+       0x84, 0xFC, 0xA7, 0x10, 0xD5, 0x8B, 0xFE, 0xBA, 0x71, 0x6C, 0xB6, 0xD6, 0x5D, 0xBD, 0x26, 0x6E,
+       0x22, 0xE9, 0x92, 0xB8, 0x3C, 0x13, 0xD4, 0xA9, 0xBF, 0x62, 0x12, 0x6D, 0xEC, 0x05, 0x46, 0xD1,
+       0xC9, 0x8E, 0xFA, 0x14, 0x64, 0x6E, 0x06, 0xE6, 0x46, 0xE6, 0x38, 0xC0, 0x0B, 0x90, 0x3E, 0x2D,
+       0xEB, 0x3C, 0x6B, 0x1D, 0x09, 0x01, 0x85, 0xD8, 0x2E, 0x76, 0x5E, 0x2F, 0x06, 0xA2, 0xE2, 0xB5,
+       0x2C, 0xEC, 0xDE, 0xC6, 0x5A, 0x2C, 0xA7, 0x9F, 0xFA, 0x6C, 0xC7, 0x11, 0x78, 0x17, 0xFA, 0x72,
+       0x87, 0x19, 0x2D, 0xEE, 0x17, 0x91, 0xB2, 0x34, 0x74, 0x53, 0x17, 0x64, 0xD1, 0x08, 0x33, 0x5B,
+       0xD1, 0x19, 0x84, 0xAB, 0x4D, 0x65, 0x9C, 0x1B, 0xD9, 0x09, 0x85, 0x4B, 0x5F, 0xCD, 0xD5, 0xF9,
+       0x8A, 0x0C, 0x0C, 0xE0, 0x3C, 0x8E, 0xC4, 0x1A, 0x8E, 0x4A, 0xA2, 0xE2, 0x7B, 0xF7, 0xED, 0x2F,
+       0x58, 0x39, 0x52, 0x10, 0x82, 0x25, 0x48, 0xDD, 0xFB, 0xCF, 0x07, 0xF6, 0xAE, 0x94, 0xBA, 0xA7,
+       0x41, 0xFE, 0x64, 0x3C, 0x3B, 0x65, 0x04, 0x71, 0x7E, 0x29, 0xCB, 0xF3, 0x59, 0xAD, 0xF5, 0x76,
+       0xAF, 0x88, 0x0B, 0x4A, 0x75, 0xC3, 0x77, 0x53, 0x05, 0xA2, 0x36, 0x68, 0xFB, 0x80, 0xFF, 0x4C,
+       0xF1, 0x0E, 0xA8, 0x12, 0x48, 0xC6, 0x6E, 0x3C, 0x7F, 0x91, 0x1D, 0x71, 0xE4, 0x98, 0x53, 0xC1,
+       0x97, 0xAE, 0x61, 0x7A, 0xC5, 0xBD, 0x9D, 0x48, 0x2F, 0x5A, 0x40, 0x0D, 0xF1, 0x3A, 0x55, 0x76,
+       0x51, 0x38, 0x4E, 0x81, 0xF5, 0x24, 0xD8, 0xF3, 0x9E, 0xDE, 0xAD, 0xE7, 0x69, 0x08, 0x78, 0xC5,
+       0xBE, 0xB2, 0x78, 0x63, 0xE3, 0x27, 0xA1, 0x95, 0xD0, 0xAB, 0x08, 0xD7, 0x8E, 0x87, 0x8C, 0xB1,
+       0xC3, 0xFE, 0xE0, 0x04, 0x5A, 0x02, 0xD6, 0x28, 0x27, 0x6D, 0x62, 0xA1, 0x5F, 0x5C, 0xC8, 0x00,
+       0x96, 0x48, 0x3F, 0x54, 0xAA, 0x5B, 0x20, 0x9F, 0x9F, 0xE0, 0x58, 0xD4, 0x54, 0xB7, 0x05, 0x77,
+       0x68, 0x44, 0x1C, 0x64, 0xEB, 0xEF, 0x3D, 0x56, 0x7E, 0x0C, 0x8A, 0x84, 0x46, 0x5D, 0x46, 0x38,
+       0xCB, 0xDF, 0x20, 0xE2, 0x26, 0xB5, 0x3B, 0x39, 0x37, 0xAB, 0x1B, 0xBC, 0x78, 0x39, 0x44, 0x55,
+       0x8A, 0x56, 0xA8, 0xC3, 0x1F, 0xD4, 0x7F, 0xB7, 0xCD, 0xA0, 0x2C, 0xEC, 0x24, 0xDB, 0xBD, 0xCF,
+       0xC5, 0x25, 0xC9, 0x74, 0x21, 0x29, 0xCF, 0xE1, 0xBC, 0xF2, 0xA6, 0x4B, 0x0E, 0xD4, 0x7A, 0xCB,
+       0xB6, 0xE9, 0xEB, 0xA3, 0xA4, 0x0B, 0x63, 0xB0, 0xD0, 0x2F, 0xE0, 0x44, 0x3F, 0x03, 0xB6, 0xDF,
+       0x32, 0x32, 0x21, 0x03, 0xEC, 0x84, 0x83, 0x56, 0x34, 0xAE, 0xE0, 0x57, 0x0B, 0xE1, 0x57, 0xB4,
+       0x7A, 0x40, 0xD9, 0xE1, 0x49, 0x85, 0xAE, 0xF4, 0xAF, 0x28, 0x07, 0x78, 0x3B, 0x12, 0x01, 0x08,
+       0x85, 0xCB, 0xDF, 0xE7, 0xEF, 0x93, 0x64, 0x31, 0x59, 0xBF, 0xF2, 0x96, 0x7B, 0xAA, 0x97, 0xA6,
+       0xBC, 0xD3, 0x1B, 0xE2, 0x4F, 0x5A, 0x60, 0x62, 0xA6, 0x12, 0x2D, 0x73, 0x07, 0x0B, 0x79, 0x1C,
+       0x97, 0xAF, 0x82, 0xD9, 0x79, 0x78, 0xF5, 0x8A, 0x91, 0x73, 0x7A, 0x39, 0x47, 0x79, 0x56, 0xF9,
+       0x64, 0xF6, 0x03, 0x09, 0xCC, 0xE3, 0x68, 0xE0, 0x9B, 0xC5, 0xF8, 0xF8, 0xB0, 0xFE, 0x44, 0xE4,
+       0xE3, 0xF9, 0x22, 0xBC, 0x6B, 0x99, 0xA3, 0x98, 0x37, 0x37, 0x0E, 0x22, 0xDB, 0x2A, 0x7A, 0xD9,
+       0xCC, 0xBF, 0xF8, 0x3C, 0x62, 0x73, 0x12, 0x63, 0xA0, 0xF4, 0x3D, 0x7F, 0x69, 0xD9, 0xA2, 0x09,
+       0x9F, 0xA0, 0xA9, 0xC2, 0x53, 0xFE, 0x58, 0xBC, 0x77, 0xAE, 0x2C, 0x0B, 0x6C, 0xC1, 0x93, 0xFD,
+       0x91, 0x2D, 0x3E, 0x6F, 0xBA, 0xA1, 0xFF, 0x95, 0xB5, 0xB6, 0x17, 0x88, 0x6A, 0x59, 0x8B, 0x9B,
+       0xDF, 0x55, 0x38, 0xD8, 0x8E, 0x51, 0x14, 0x2C, 0x01, 0x5B, 0xA6, 0xDE, 0xA8, 0xA0, 0xC8, 0xCD,
+       0xD3, 0x7A, 0x22, 0xB2, 0xCB, 0xB4, 0xE3, 0x02, 0x50, 0xAE, 0x52, 0xD0, 0xFE, 0x82, 0x09, 0xE7,
+       0x6A, 0xE8, 0x74, 0x0E, 0x63, 0x25, 0xF2, 0x2A, 0x41, 0xD1, 0x45, 0x08, 0x30, 0xCF, 0xD3, 0xA3,
+       0xA9, 0x8A, 0xF2, 0xD6, 0xBF, 0xF0, 0xA0, 0xD3, 0xDD, 0x73, 0xE4, 0x7F, 0x72, 0xD6, 0x1F, 0x7D,
+       0x78, 0x43, 0x5A, 0xDF, 0x25, 0xEF, 0xDA, 0xF3, 0xDB, 0x31, 0xE7, 0xC1, 0x78, 0x6C, 0xD5, 0xD8,
+       0xBE, 0xD8, 0xD1, 0xB1, 0x9F, 0x1B, 0xD8, 0xF9, 0x18, 0x73, 0xCE, 0x21, 0x90, 0x54, 0xC0, 0x6E,
+       0xD5, 0x6B, 0xDB, 0xE7, 0xAB, 0x0D, 0x18, 0x56, 0x21, 0x81, 0x93, 0x25, 0x57, 0x08, 0x12, 0x6C,
+       0x0E, 0x7C, 0x18, 0x10, 0x16, 0xD1, 0x2F, 0x64, 0xD8, 0x19, 0x97, 0xCD, 0x7F, 0xD5, 0x02, 0x8B,
+       0x44, 0xD4, 0xDE, 0x24, 0xE2, 0x29, 0x15, 0x1F, 0x2C, 0x1D, 0x32, 0x97, 0x28, 0xFD, 0xD1, 0x59,
+       0xD1, 0x2A, 0xBF, 0x64, 0xF8, 0xE8, 0xDF, 0x2C, 0x8C, 0x10, 0xA1, 0x11, 0xDB, 0x40, 0x36, 0xF7,
+       0x30, 0x2A, 0x2B, 0x5B, 0x30, 0x65, 0x8D, 0x64, 0x15, 0x69, 0xCB, 0x3A, 0x8A, 0x30, 0xC2, 0xF5,
+       0x76, 0xFF, 0xCB, 0xD4, 0x83, 0xEF, 0x9B, 0xB4, 0xFA, 0x3A, 0x57, 0xDB, 0x79, 0xE5, 0x17, 0x09,
+       0x03, 0xFE, 0x2B, 0x80, 0x31, 0x98, 0xCD, 0x0C, 0x05, 0xF6, 0xE0, 0xA1, 0x49, 0xC9, 0x7C, 0x95,
+       0x26, 0x57, 0x5E, 0xC5, 0x05, 0x38, 0xE9, 0x74, 0xF1, 0x1F, 0xFB, 0x5D, 0x9E, 0x83, 0xE7, 0x97,
+       0xEA, 0x4D, 0x4A, 0xEC, 0xE7, 0x75, 0x2B, 0x47, 0xC8, 0x9A, 0xEA, 0x2C, 0x56, 0xFF, 0x41, 0x3D,
+       0x12, 0x3E, 0x35, 0x00, 0x34, 0x81, 0xC9, 0x5F, 0xCA, 0x26, 0x3E, 0x32, 0x08, 0xE8, 0x73, 0xE4,
+       0xA2, 0xDF, 0x17, 0x35, 0xC3, 0x8B, 0x88, 0x88, 0x6E, 0x4B, 0x42, 0x7B, 0x95, 0x17, 0x29, 0x1A,
+       0x2C, 0xB4, 0xFF, 0xDA, 0x75, 0x03, 0x69, 0x3D, 0x78, 0x93, 0x9B, 0x3A, 0xCD, 0x09, 0x1B, 0x58,
+       0xE2, 0xAD, 0x3D, 0x93, 0x76, 0x66, 0x27, 0xEA, 0x0B, 0x88, 0x49, 0xD0, 0xDA, 0x12, 0xDB, 0xE2,
+       0x59, 0x40, 0x33, 0x1A, 0x64, 0xC2, 0xB4, 0x47, 0x48, 0x63, 0xBB, 0xC9, 0x49, 0x5A, 0xD2, 0xAA,
+       0xB1, 0x1C, 0xBC, 0x1E, 0xA5, 0x7E, 0x1B, 0x3A, 0x8B, 0x67, 0x28, 0xE6, 0x2F, 0xAF, 0x44, 0x1B,
+       0x74, 0xD6, 0x4F, 0x4C, 0x88, 0xE7, 0x93, 0x05, 0xC2, 0x21, 0x42, 0x8E, 0x65, 0x41, 0x6F, 0x34,
+       0x02, 0xC5, 0x4C, 0x93, 0x06, 0x7F, 0xB3, 0xBE, 0x92, 0x17, 0x0C, 0x34, 0x4E, 0xC8, 0xF9, 0xF6,
+       0xD3, 0x9F, 0x6B, 0xAB, 0x2E, 0x53, 0xD0, 0xB4, 0xFD, 0x93, 0xFB, 0xD9, 0x2D, 0xD8, 0x00, 0x7D,
+       0x19, 0x41, 0x23, 0xC1, 0xF9, 0x53, 0x1C, 0xFF, 0x9B, 0x85, 0x9C, 0x1C, 0x89, 0x8C, 0xA9, 0xBB,
+       0xE4, 0xB0, 0x74, 0xC8, 0x8F, 0xF5, 0xDC, 0x33, 0x15, 0xB8, 0x98, 0x96, 0x5B, 0x24, 0x2A, 0x1B,
+       0x87, 0x96, 0x32, 0x7B, 0xCB, 0x48, 0x3A, 0x1F, 0x4A, 0xF5, 0x3D, 0x34, 0x4E, 0x34, 0x0E, 0x45,
+       0xEA, 0xE6, 0x87, 0xC7, 0x76, 0x6C, 0x08, 0xA3, 0xB4, 0x11, 0xF9, 0x7D, 0x29, 0x60, 0x4C, 0x4C,
+       0x73, 0x4A, 0x1C, 0x65, 0xDC, 0x64, 0x6B, 0x86, 0xAA, 0xB1, 0xB8, 0xB7, 0x98, 0x77, 0x8F, 0x98,
+       0xDC, 0x16, 0xA0, 0xE5, 0xEE, 0xE1, 0xB1, 0x47, 0xEA, 0x33, 0x8D, 0xDC, 0x97, 0x24, 0x8D, 0x61,
+       0xC7, 0x8F, 0x50, 0xA9, 0x0A, 0xC5, 0x63, 0x0F, 0xBB, 0x8B, 0xDA, 0x91, 0x3E, 0x99, 0x74, 0x07,
+       0xE8, 0x8B, 0xB7, 0x63, 0x10, 0x4B, 0x89, 0x1F, 0x8F, 0xDB, 0x7A, 0x10, 0xA8, 0xB4, 0xDB, 0x67,
+       0x17, 0xCE, 0x8F, 0x31, 0x53, 0x30, 0x40, 0x46, 0x8D, 0x85, 0x31, 0xEC, 0x06, 0xA7, 0x3E, 0xE1,
+       0x99, 0x17, 0xAE, 0x3B, 0x91, 0xDD, 0xB5, 0xE9, 0x74, 0xC9, 0x00, 0xF3, 0x55, 0x8E, 0x1E, 0xA0,
+       0x97, 0xBF, 0x7F, 0x96, 0x2B, 0x98, 0x49, 0x1A, 0xDA, 0x42, 0x70, 0xA4, 0xFD, 0x38, 0x1D, 0x9C,
+       0x8B, 0xE5, 0x6E, 0x68, 0xD2, 0xB3, 0x5F, 0xDC, 0x56, 0xE0, 0xF4, 0x01, 0x0B, 0x0C, 0xFC, 0x75,
+       0xAA, 0x28, 0x47, 0xE5, 0xCD, 0x1B, 0xA9, 0x30, 0x26, 0x10, 0xFE, 0x9B, 0x10, 0xB1, 0xD7, 0x07,
+       0xD9, 0x11, 0x7C, 0x4C, 0x19, 0x8A, 0xAF, 0x02, 0x8B, 0x0C, 0x45, 0x6E, 0x54, 0x67, 0x1B, 0x2A,
+       0x3F, 0x7D, 0xC6, 0x67, 0x5C, 0x8D, 0xE3, 0xA8, 0x26, 0xB4, 0xEC, 0x08, 0xE3, 0x9B, 0xF6, 0x0B,
+       0x3F, 0xA7, 0xFA, 0xED, 0x80, 0x43, 0x56, 0xCC, 0x40, 0xCF, 0xAD, 0x20, 0x6A, 0x39, 0xA4, 0x8C,
+       0x16, 0x01, 0x0A, 0x65, 0xBD, 0x59, 0x15, 0x12, 0xB0, 0xC9, 0xF5, 0xCA, 0x0E, 0x74, 0x55, 0x2F,
+       0xAD, 0x9A, 0xC4, 0x80, 0xD9, 0x1E, 0xAA, 0x90, 0x99, 0x41, 0x14, 0xE9, 0xC5, 0xE0, 0x96, 0x35,
+       0xB3, 0x1F, 0x90, 0x5E, 0xEC, 0x0A, 0x77, 0xA6, 0xF9, 0xAC, 0x35, 0x95, 0xC8, 0xAC, 0x8A, 0x5D,
+       0xAF, 0x7F, 0xAB, 0x95, 0x88, 0x00, 0xCE, 0x22, 0x3A, 0xF8, 0x93, 0x22, 0x49, 0x10, 0xED, 0xA5,
+       0xDC, 0x43, 0x34, 0xA1, 0x19, 0x0F, 0x6A, 0x9C, 0xC4, 0x15, 0xD6, 0x67, 0x23, 0xCF, 0xCE, 0xF1,
+       0xAE, 0x1F, 0x98, 0xB2, 0x15, 0xBD, 0x56, 0x9A, 0x3B, 0x24, 0x07, 0xA3, 0x6C, 0xC5, 0xA4, 0x32,
+       0x91, 0x9B, 0x2E, 0xFA, 0x2F, 0x46, 0x1E, 0xBE, 0x03, 0xFB, 0xC6, 0x7E, 0xC3, 0x6C, 0x3D, 0xC9,
+       0xD2, 0x8A, 0x6C, 0x1A, 0xA4, 0xD5, 0xE2, 0x23, 0x5E, 0x49, 0xDE, 0x13, 0x2C, 0x33, 0x7A, 0x50,
+       0x79, 0x50, 0x0D, 0x65, 0xBB, 0x72, 0xF7, 0x59, 0xFD, 0xEA, 0x1C, 0x64, 0x80, 0xF4, 0x82, 0x95,
+       0x1D, 0x4C, 0x73, 0x15, 0xC3, 0x19, 0x9C, 0x42, 0x52, 0x44, 0x5E, 0x4D, 0xA2, 0x37, 0x9B, 0x32,
+       0xD4, 0xCD, 0xB5, 0x45, 0x9D, 0xC5, 0x70, 0x34, 0x56, 0x7E, 0xA9, 0x94, 0xD9, 0x99, 0x30, 0xDA,
+       0xF8, 0xE0, 0x78, 0x9E, 0x6A, 0xAD, 0xD4, 0x75, 0x9B, 0xE0, 0xC6, 0x9A, 0x45, 0x7F, 0xE3, 0xFC,
+       0x49, 0xD3, 0x22, 0x27, 0x24, 0xDE, 0xFA, 0x97, 0xA8, 0xB5, 0xB6, 0x8D, 0xE2, 0xD3, 0x8C, 0xD2,
+       0x7F, 0xBB, 0x2C, 0x31, 0x9C, 0x3D, 0x9E, 0xCE, 0x7D, 0x67, 0x7C, 0xBD, 0x6B, 0x89, 0x5C, 0xD1,
+       0x43, 0xFE, 0x06, 0x85, 0x0C, 0xF0, 0x03, 0xFA, 0xC7, 0x9E, 0xBC, 0xEC, 0x8B, 0xF7, 0x56, 0x62,
+       0xC7, 0x1C, 0xB2, 0x90, 0xCA, 0x6E, 0x6A, 0x7C, 0x07, 0x20, 0x03, 0x13, 0x7E, 0x08, 0x05, 0xB0,
+       0xB2, 0x37, 0xFD, 0xA1, 0xFE, 0x2D, 0xCF, 0xF0, 0x47, 0x42, 0x0A, 0x44, 0x5A, 0x4C, 0x7C, 0xA0,
+       0x42, 0xA6, 0x88, 0x89, 0x00, 0x00, 0xF5, 0xD5, 0xD8, 0x36, 0x99, 0x48, 0x44, 0x0B, 0x81, 0x08,
+       0xDF, 0x71, 0x72, 0xCC, 0x7D, 0x72, 0x02, 0x61, 0x27, 0x67, 0x81, 0x04, 0xBF, 0xA3, 0x81, 0x4E,
+       0xE7, 0x9D, 0x16, 0xD3, 0x6B, 0x75, 0x70, 0x38, 0xB6, 0xBC, 0xFC, 0xFF, 0x07, 0x36, 0x70, 0x9A,
+       0x47, 0x0A, 0xA7, 0x68, 0x64, 0x20, 0xCD, 0xD1, 0x35, 0xDC, 0x95, 0x2B, 0x23, 0x98, 0x4F, 0x01,
+       0x6F, 0x93, 0xC2, 0xC3, 0xAD, 0x48, 0x9F, 0x40, 0xA8, 0x65, 0xC7, 0xA0, 0x43, 0xC8, 0xF9, 0xD6,
+       0x7C, 0x4E, 0x1B, 0x35, 0xCE, 0x13, 0xF6, 0x22, 0x6F, 0x74, 0xD2, 0xC0, 0x92, 0xC3, 0xAA, 0xFB,
+       0x39, 0x43, 0x17, 0x5C, 0x6A, 0x2E, 0xA8, 0xAA, 0x3C, 0x1D, 0xB7, 0x6A, 0x55, 0xF6, 0x09, 0x37,
+       0x8E, 0x7B, 0xF1, 0xA4, 0x63, 0x58, 0x22, 0x7C, 0xB5, 0x5A, 0x72, 0x9A, 0x0C, 0xF0, 0xFA, 0xFA,
+       0x6D, 0x2D, 0xDC, 0x3F, 0x4A, 0xC6, 0x6A, 0x7C, 0x40, 0xD4, 0xA5, 0x0B, 0x07, 0x30, 0x52, 0x59,
+       0x9C, 0xE2, 0x28, 0x27, 0x22, 0xA6, 0xE1, 0x6A, 0x06, 0xAA, 0x47, 0xCF, 0x52, 0x4D, 0x29, 0x7E,
+       0x42, 0xC1, 0x18, 0xF0, 0xEE, 0xD5, 0x52, 0x01, 0x52, 0xC8, 0x57, 0x8B, 0x78, 0x30, 0x0D, 0xEB,
+       0xCD, 0x04, 0x91, 0x5E, 0x55, 0x40, 0x98, 0x77, 0xB5, 0x77, 0x9F, 0xCA, 0xA8, 0xDF, 0x8D, 0x76,
+       0x87, 0x34, 0xC5, 0xC8, 0xEA, 0x6D, 0x1F, 0x6C, 0x2B, 0x6A, 0x2A, 0xCF, 0x7C, 0x5C, 0x75, 0x75,
+       0x7F, 0xCD, 0xCC, 0xA9, 0x52, 0xFA, 0xAB, 0xD7, 0xB6, 0xE3, 0x92, 0xA1, 0x08, 0xBC, 0xB1, 0xA1,
+       0x0C, 0xE1, 0x1A, 0xC2, 0xCA, 0x5E, 0xE8, 0x01, 0xCB, 0xB3, 0x3A, 0xCD, 0x1D, 0xC2, 0xA4, 0x68,
+       0xEC, 0x74, 0xA1, 0x32, 0xF3, 0xD6, 0x93, 0x98, 0xC8, 0x13, 0xB2, 0x86, 0xE6, 0x00, 0x0D, 0x0F,
+       0x07, 0x78, 0x28, 0x02, 0x70, 0xBA, 0xD9, 0x22, 0x21, 0x3B, 0x57, 0x0C, 0x1E, 0x7D, 0x12, 0x7B,
+       0x5A, 0x28, 0x17, 0x80, 0x37, 0x2F, 0x2A, 0x22, 0x91, 0xC8, 0xB2, 0xDA, 0xCE, 0x83, 0x7A, 0x49,
+       0xF4, 0x85, 0x5A, 0x6D, 0x46, 0xF9, 0x0B, 0xAE, 0x1C, 0xBA, 0x9A, 0xEB, 0x06, 0xB7, 0x1F, 0x7F,
+       0x9A, 0x7B, 0x0D, 0xFE, 0x36, 0x85, 0x80, 0x07, 0xA0, 0xD1, 0x71, 0xBA, 0xFD, 0xFD, 0xF4, 0x73,
+       0x9B, 0xDD, 0xAA, 0x4F, 0x87, 0x9E, 0xBF, 0xA5, 0x8B, 0xEF, 0x83, 0xAE, 0xF2, 0xC6, 0x69, 0x13,
+       0x5C, 0x3D, 0x9A, 0x2E, 0xE4, 0xC9, 0x75, 0x4C, 0x4F, 0x9E, 0xC1, 0xE1, 0xDC, 0x03, 0xAB, 0x84,
+       0x86, 0x3F, 0x49, 0xF4, 0x03, 0xA3, 0x82, 0x38, 0x8C, 0x27, 0x8B, 0xF3, 0x2B, 0x57, 0xBA, 0x70,
+       0xDF, 0x39, 0x9F, 0xC2, 0xA6, 0x9B, 0xED, 0x89, 0xDB, 0x14, 0x69, 0x4E, 0x6D, 0xCA, 0x46, 0x1C,
+       0x0E, 0xD4, 0x44, 0x51, 0x2B, 0x92, 0x35, 0x9F, 0xCC, 0xB2, 0xFC, 0xED, 0xE6, 0xD3, 0x63, 0x8D,
+       0x2D, 0x1C, 0x3E, 0xFD, 0x73, 0xD7, 0x16, 0x10, 0xEF, 0xE0, 0x88, 0xD9, 0xF8, 0x73, 0x86, 0x02,
+       0xD7, 0x61, 0x28, 0x3E, 0x36, 0xB1, 0x03, 0x91, 0xA2, 0xB4, 0xFD, 0x3D, 0x7B, 0xE7, 0x5E, 0xBF,
+       0xCC, 0x20, 0x12, 0x02, 0xA8, 0x25, 0x0A, 0xDA, 0x6E, 0x32, 0xA8, 0xA1, 0xEA, 0xC3, 0x12, 0x40,
+       0x8A, 0xC9, 0x72, 0x68, 0x2D, 0x62, 0xCF, 0xDC, 0x76, 0x05, 0x01, 0x60, 0xCC, 0xDF, 0x4E, 0x36,
+       0xD3, 0x87, 0x96, 0x19, 0xDE, 0x17, 0xB8, 0x86, 0x78, 0xA6, 0x19, 0xCB, 0x89, 0x6A, 0xF0, 0xB0,
+       0x53, 0x3F, 0xF7, 0xA9, 0x74, 0xBB, 0x04, 0x27, 0x9D, 0x2B, 0x98, 0x57, 0xFD, 0x26, 0x32, 0xEB,
+       0xD2, 0x89, 0x0C, 0x49, 0x4F, 0x50, 0x46, 0x20, 0xD0, 0x22, 0x2C, 0x4C, 0x6C, 0x7F, 0xF3, 0xA0,
+       0x5A, 0x27, 0x6C, 0xAB, 0x6D, 0xFC, 0xE6, 0x50, 0x22, 0x17, 0x65, 0x6A, 0xD0, 0xC1, 0xCF, 0xB3,
+       0xF4, 0xC0, 0x03, 0x6C, 0x7F, 0xA4, 0x14, 0x1C, 0xBF, 0x95, 0xF9, 0x8B, 0xB3, 0x98, 0xA1, 0xCA,
+       0xC6, 0xE9, 0x0B, 0x56, 0xAD, 0xA9, 0x58, 0x9F, 0x9C, 0xAE, 0xB0, 0xDA, 0x42, 0x5D, 0x87, 0x79,
+       0x2F, 0xFF, 0xC5, 0x16, 0x80, 0x95, 0xB8, 0x1E, 0xCA, 0xB6, 0x4C, 0x00, 0x71, 0x06, 0x53, 0x27,
+       0xA1, 0x8E, 0xE5, 0x93, 0x6D, 0x33, 0x2E, 0x1E, 0xDB, 0x51, 0x7F, 0xA0, 0x50, 0xD3, 0x92, 0xD1,
+       0xE1, 0xB3, 0xED, 0xFB, 0x2A, 0x79, 0xD4, 0x92, 0xBE, 0xBF, 0xCA, 0xFE, 0x6D, 0xEB, 0x65, 0xBE,
+       0xD7, 0x91, 0x98, 0x9D, 0x70, 0xA7, 0xD5, 0x1E, 0x03, 0xD1, 0xD1, 0x43, 0x61, 0xDE, 0x09, 0x74,
+       0x2F, 0xB8, 0xA0, 0xC2, 0x94, 0xD6, 0x84, 0x1B, 0x54, 0x85, 0x3B, 0x2A, 0xC0, 0x5C, 0xA1, 0x85,
+       0x43, 0x12, 0x3E, 0xCD, 0x19, 0x0E, 0x44, 0x33, 0x34, 0xE9, 0xF7, 0xFB, 0xC6, 0xAD, 0x5A, 0x84,
+       0xDD, 0x60, 0x62, 0x4D, 0xE1, 0x50, 0x37, 0xE6, 0x1E, 0x57, 0xEC, 0x47, 0x7B, 0xBE, 0x2D, 0xB8,
+       0x0B, 0x40, 0x23, 0xF5, 0x71, 0x9A, 0xD5, 0x89, 0xCF, 0x7D, 0xCC, 0x3C, 0xFF, 0x90, 0x21, 0xC9,
+       0x88, 0x77, 0x9E, 0x0D, 0x20, 0x06, 0x7D, 0x6E, 0xF7, 0x51, 0xBB, 0xDF, 0x26, 0x75, 0x46, 0x6E,
+       0xDC, 0x3B, 0x62, 0x0A, 0x34, 0x89, 0x90, 0x5B, 0x19, 0x3B, 0xF8, 0xFB, 0x09, 0x7D, 0xEC, 0x8F,
+       0xF6, 0x0F, 0xBE, 0x30, 0x13, 0x7C, 0xDB, 0x59, 0x96, 0xD8, 0xB8, 0xE9, 0x73, 0xF0, 0x3A, 0xB8,
+       0x4E, 0x88, 0x7A, 0xC5, 0xC0, 0x37, 0xF9, 0xB6, 0x80, 0xB6, 0x33, 0xD6, 0x72, 0xC3, 0xB4, 0x9B,
+       0x96, 0xE6, 0x43, 0x8F, 0xEA, 0x35, 0x80, 0x21, 0x97, 0xFF, 0x08, 0xEC, 0xE1, 0xB8, 0xCE, 0xF8,
+       0x08, 0xBF, 0x68, 0xD0, 0x87, 0xD6, 0x4D, 0xDD, 0xA6, 0x7B, 0xE2, 0x16, 0x5A, 0x8E, 0xDB, 0x27,
+       0x59, 0xC6, 0x6C, 0x89, 0x24, 0x87, 0x43, 0x67, 0xFB, 0xC5, 0xC1, 0x68, 0x2F, 0x6D, 0x9A, 0xE0,
+       0x53, 0x65, 0xAE, 0xE7, 0x8F, 0x05, 0x1A, 0x50, 0x50, 0x5B, 0x08, 0x72, 0x7E, 0x54, 0xA8, 0x3A,
+       0xE1, 0x9D, 0x76, 0xB3, 0x01, 0x43, 0x61, 0x7A, 0x2D, 0x5C, 0x05, 0xB5, 0xC2, 0xDF, 0x66, 0xB5,
+       0xF9, 0x2C, 0xA6, 0x1B, 0x2E, 0xAE, 0xDD, 0x6E, 0xF7, 0x57, 0xC6, 0xB5, 0xB0, 0x9B, 0x88, 0xC0,
+       0xE9, 0x09, 0x39, 0x5C, 0x59, 0x7C, 0xF0, 0xC2, 0xA7, 0x81, 0x2A, 0x0D, 0x41, 0xF4, 0x60, 0x17,
+       0xBF, 0xC4, 0x04, 0xBA, 0x28, 0x1B, 0x35, 0xC3, 0x8C, 0xF7, 0xD0, 0x49, 0x5E, 0x37, 0xA7, 0x74,
+       0x5C, 0xB2, 0x46, 0x4B, 0x00, 0xAA, 0xEF, 0xB3, 0x52, 0x4B, 0x17, 0x27, 0x2F, 0xB6, 0x48, 0xF4,
+       0x09, 0x70, 0xD4, 0xF7, 0xF2, 0xAD, 0xED, 0x1B, 0x9A, 0x3D, 0x60, 0x56, 0x14, 0xF0, 0xCE, 0xCB,
+       0x59, 0x62, 0x33, 0xA8, 0xEF, 0xE4, 0x80, 0x6F, 0xD0, 0x4D, 0x21, 0x85, 0x1D, 0x5A, 0xAF, 0xFF,
+       0xEA, 0xC3, 0xC1, 0xCC, 0x9F, 0x53, 0x15, 0xBF, 0x56, 0x24, 0x8D, 0x64, 0x3A, 0x63, 0xEB, 0x57,
+       0x21, 0xEA, 0x71, 0xF8, 0xEB, 0x2A, 0x2E, 0x8E, 0x96, 0x7A, 0xDD, 0x05, 0xA0, 0x1F, 0x7E, 0x4F,
+       0xFC, 0xB3, 0x12, 0x74, 0x28, 0xB3, 0x71, 0x2A, 0xFF, 0x8F, 0x38, 0xA0, 0x3F, 0x3C, 0xBC, 0x16,
+       0x18, 0x0A, 0x99, 0xF6, 0x6B, 0x71, 0x97, 0xCA, 0x57, 0x72, 0xAB, 0xC6, 0xFE, 0xAD, 0xFA, 0x8F,
+       0xDE, 0x15, 0xA7, 0x62, 0x28, 0xAA, 0x70, 0xFE, 0xF0, 0xFF, 0xD3, 0x66, 0x07, 0xE1, 0x65, 0xF7,
+       0x99, 0x56, 0x2D, 0xE2, 0xB1, 0x08, 0xFB, 0xA3, 0xD9, 0x07, 0x28, 0x64, 0xA5, 0xB0, 0xCC, 0x7B,
+       0x38, 0xBB, 0x90, 0xFC, 0x8A, 0xC5, 0x12, 0xBB, 0x42, 0xEA, 0x5D, 0x20, 0x00, 0xBA, 0xF7, 0x6F,
+       0xEA, 0xC0, 0x81, 0x02, 0xAB, 0x5A, 0xD3, 0x4E, 0x1E, 0xE0, 0x8A, 0x25, 0xF0, 0xE1, 0xC9, 0x7B,
+       0x60, 0xBE, 0xD7, 0xF2, 0xB3, 0xCC, 0x92, 0xB6, 0xF5, 0xE2, 0x77, 0x91, 0x28, 0xDC, 0xE5, 0x65,
+       0x4C, 0xE1, 0x4A, 0x6C, 0xDD, 0x83, 0x3E, 0x6F, 0xF4, 0x9B, 0xFD, 0x8A, 0x8E, 0x79, 0x06, 0x06,
+       0xEC, 0x35, 0x53, 0x7C, 0xF8, 0x59, 0x3B, 0xBD, 0x75, 0x0C, 0xA3, 0xA9, 0x7A, 0x8F, 0xF1, 0xEA,
+       0x39, 0x84, 0x35, 0x2F, 0xFE, 0x6C, 0xEB, 0x5F, 0x5C, 0x25, 0x66, 0x7F, 0x05, 0x5F, 0x38, 0xB8,
+       0x93, 0xB7, 0x39, 0xCA, 0x04, 0x66, 0x10, 0x99, 0x79, 0xC6, 0x29, 0x35, 0x34, 0x40, 0xC1, 0x54,
+       0x4E, 0xD7, 0x15, 0x26, 0xAB, 0xC2, 0xAA, 0xDE, 0x69, 0x15, 0xC6, 0x52, 0x94, 0x50, 0x54, 0xD7,
+       0x92, 0x04, 0x9E, 0x1C, 0x0F, 0xEB, 0xE7, 0x6E, 0x03, 0xA2, 0x87, 0x55, 0xD1, 0x89, 0xD8, 0x20,
+       0x32, 0xCD, 0x04, 0x7B, 0xCE, 0x78, 0x41, 0x8A, 0x22, 0xA0, 0x33, 0xD6, 0x7A, 0xEE, 0x1D, 0x7E,
+       0x5D, 0xBC, 0xF6, 0x6F, 0x0E, 0x85, 0xD2, 0xFB, 0x88, 0x63, 0x00, 0x53, 0x00, 0x57, 0x96, 0xEE,
+       0xB2, 0x5A, 0x72, 0x28, 0xB7, 0x4C, 0x1A, 0x22, 0x9E, 0x3A, 0xCC, 0x34, 0xB4, 0x58, 0xE6, 0x8A,
+       0x75, 0xB4, 0xD4, 0x49, 0x1F, 0xB9, 0x5B, 0x8D, 0x8F, 0x35, 0x99, 0xBD, 0xE9, 0x32, 0x0B, 0xFD,
+       0xCA, 0x71, 0xD9, 0x59, 0x9B, 0x65, 0x62, 0x10, 0x5C, 0xEE, 0x47, 0x27, 0x0B, 0x56, 0xA9, 0x32,
+       0xBE, 0x67, 0x67, 0x8B, 0x54, 0x19, 0xBB, 0xB6, 0x48, 0x14, 0x54, 0xE2, 0x25, 0x89, 0x03, 0x79,
+       0x80, 0x55, 0xD9, 0xA8, 0x2A, 0x3D, 0x9E, 0x55, 0x02, 0x20, 0xA2, 0x66, 0x31, 0x85, 0x2F, 0x21,
+       0xC0, 0xBA, 0x46, 0x0C, 0x00, 0x3D, 0x94, 0x9E, 0x4A, 0x4E, 0x9F, 0x73, 0x51, 0x98, 0x91, 0x12,
+       0x22, 0xA8, 0x63, 0xFF, 0x9A, 0x4A, 0x5E, 0xF7, 0x33, 0xCF, 0xF4, 0x96, 0x76, 0x79, 0x6E, 0xD5,
+       0xB6, 0x33, 0x1A, 0xAA, 0x0C, 0x88, 0x41, 0xEC, 0xB1, 0xAE, 0x4D, 0x24, 0x78, 0xFD, 0x8B, 0x77,
+       0xE2, 0xBC, 0xF9, 0x4E, 0x49, 0x00, 0x2E, 0x10, 0xCA, 0xBB, 0x17, 0x01, 0x9B, 0x83, 0x49, 0xA2,
+       0xBD, 0x51, 0x90, 0x09, 0x68, 0xE2, 0x44, 0xF0, 0xA9, 0xED, 0xE8, 0x5D, 0x78, 0xDD, 0x47, 0x0F,
+       0x69, 0x49, 0xE1, 0x2B, 0x46, 0x9C, 0xBD, 0x5A, 0xC8, 0xC4, 0x82, 0x08, 0x07, 0xF9, 0x74, 0x72,
+       0x4B, 0x00, 0xE5, 0x3D, 0x1D, 0xF4, 0x9E, 0x93, 0x22, 0x6A, 0xC4, 0x8E, 0x13, 0x80, 0x05, 0x28,
+       0xE1, 0x8B, 0xB4, 0x1F, 0x58, 0x64, 0xD9, 0xFA, 0x33, 0x0E, 0x9E, 0xA2, 0x6C, 0x9F, 0x1A, 0x83,
+       0xAB, 0xCE, 0xC1, 0x51, 0x3F, 0x29, 0xC0, 0x51, 0x3D, 0xA3, 0x67, 0xB5, 0xFE, 0x49, 0x1A, 0x75,
+       0xB0, 0x92, 0xC3, 0x82, 0x7E, 0xDD, 0x18, 0x2F, 0xF6, 0xFF, 0x0C, 0x65, 0x1C, 0x7A, 0xAF, 0xDB,
+       0x9E, 0xCD, 0x4E, 0x3F, 0x85, 0x6A, 0x48, 0xE7, 0xDA, 0x50, 0x4B, 0x7D, 0x27, 0x78, 0x69, 0xEA,
+       0xE0, 0x88, 0xF8, 0xD2, 0xF0, 0x17, 0x42, 0x50, 0x1B, 0x22, 0x2E, 0x22, 0x87, 0xA7, 0xF0, 0x61,
+       0xC0, 0xE6, 0xF9, 0xE2, 0xB4, 0x75, 0xCB, 0x9A, 0x2C, 0xFA, 0x6C, 0x4E, 0x69, 0x3F, 0x2C, 0x59,
+       0x1D, 0xAA, 0x57, 0x34, 0xD7, 0x0D, 0x30, 0x30, 0x8B, 0x60, 0xA8, 0x74, 0x81, 0x51, 0xA3, 0x10,
+       0xDB, 0x93, 0x74, 0x70, 0xAF, 0xDD, 0x4D, 0x29, 0x2E, 0x8C, 0x59, 0x96, 0xCB, 0x4A, 0x0E, 0x0C,
+       0x78, 0x1D, 0x76, 0x6C, 0xE7, 0x14, 0xA9, 0x86, 0x52, 0x7C, 0x01, 0xA3, 0x03, 0x25, 0xA6, 0x63,
+       0xFF, 0x64, 0x06, 0xF7, 0x27, 0x88, 0x71, 0x6B, 0x84, 0x30, 0x7E, 0x2F, 0x5E, 0xA2, 0x87, 0x05,
+       0xEF, 0xBA, 0x75, 0xAD, 0xB9, 0xEC, 0x4C, 0xFF, 0x62, 0xD0, 0x6A, 0x92, 0xB8, 0x0E, 0x68, 0xA2,
+       0xFE, 0xE6, 0x29, 0xCE, 0x15, 0x00, 0xD1, 0xF0, 0xD8, 0x25, 0x19, 0xAB, 0x6E, 0xA0, 0x2B, 0xFE,
+       0x97, 0x42, 0x34, 0x92, 0xB7, 0x7B, 0x59, 0x22, 0xDA, 0xAB, 0x4D, 0xAB, 0x60, 0x9F, 0x59, 0x5D,
+       0x24, 0xBA, 0xE8, 0xA4, 0xDC, 0xFB, 0xF2, 0x3C, 0xC0, 0x07, 0x7E, 0xC4, 0xFF, 0x4E, 0xA9, 0x53,
+       0x1C, 0x79, 0x92, 0x78, 0x78, 0x51, 0xB9, 0xD9, 0x06, 0xC6, 0x18, 0xC5, 0xB7, 0x2A, 0x7B, 0x0E,
+       0xA5, 0x59, 0xD8, 0x5D, 0xF2, 0xEF, 0x04, 0x46, 0x7B, 0xAA, 0xFA, 0xAD, 0xC8, 0xB8, 0x82, 0x1E,
+       0x77, 0x33, 0xA2, 0xE1, 0xC6, 0xFB, 0x26, 0x6B, 0x11, 0x14, 0x54, 0xD0, 0x89, 0x4F, 0x78, 0xEF,
+       0x88, 0x8D, 0xC1, 0xCD, 0x7A, 0x07, 0x96, 0x0F, 0xC8, 0x00, 0x74, 0x86, 0x9E, 0x40, 0x20, 0x58,
+       0x8C, 0xFF, 0xA5, 0x34, 0x93, 0x3F, 0x4C, 0x50, 0xC0, 0x87, 0xDD, 0x73, 0x96, 0xE8, 0x1B, 0x64,
+       0x09, 0x6C, 0xA0, 0x50, 0xF0, 0x62, 0xBE, 0x2C, 0x81, 0x6A, 0x82, 0xA3, 0xB4, 0x4A, 0x81, 0x5B,
+       0x4C, 0x13, 0x7E, 0xCB, 0xD7, 0x23, 0x9D, 0x7D, 0x32, 0x11, 0x86, 0xBA, 0xE7, 0xB9, 0x9E, 0x50,
+       0xF5, 0xA4, 0x3C, 0x36, 0xD3, 0xD0, 0x85, 0x66, 0xF0, 0xEA, 0x77, 0x70, 0x67, 0x8A, 0xA1, 0x19,
+       0xEC, 0x6A, 0x60, 0xDD, 0x63, 0x5C, 0x4A, 0xC1, 0xDC, 0x0A, 0x35, 0x35, 0x3A, 0x35, 0x11, 0xFB,
+       0x5D, 0x0D, 0xDF, 0x6A, 0xDD, 0x8E, 0x81, 0xB0, 0xD0, 0xF0, 0xB2, 0xA4, 0x6A, 0xEC, 0xD8, 0xA5,
+       0x29, 0x7D, 0xB4, 0x67, 0x4B, 0xF6, 0xF4, 0xDF, 0xF1, 0xCF, 0xE6, 0x03, 0x8D, 0x90, 0x0D, 0x32,
+       0x6A, 0x30, 0x5F, 0x3D, 0xA2, 0x68, 0x56, 0x7F, 0x2D, 0x98, 0x2C, 0x75, 0x84, 0x54, 0xDC, 0xCA,
+       0x6D, 0xA4, 0xA9, 0x41, 0x94, 0x55, 0x8C, 0xBB, 0xE6, 0xD0, 0x44, 0x0F, 0xED, 0x86, 0x3C, 0x7C,
+       0x91, 0xA4, 0x9D, 0x20, 0x67, 0x5D, 0x01, 0x1D, 0x28, 0x18, 0xC7, 0x63, 0xF0, 0x9E, 0x34, 0x57,
+       0x8C, 0x4E, 0xCF, 0x4B, 0x74, 0xFA, 0x76, 0x9C, 0x79, 0x24, 0x1F, 0xD9, 0x78, 0xC9, 0x0C, 0xE7,
+       0x28, 0xCC, 0x5F, 0xA6, 0x5D, 0xAB, 0x3F, 0x5F, 0x0E, 0xB1, 0xD7, 0x4E, 0xFB, 0x67, 0x9F, 0x9C,
+       0x53, 0x28, 0x40, 0x70, 0x7B, 0x09, 0xE8, 0x97, 0xC2, 0xA7, 0x8C, 0x07, 0x42, 0xA2, 0xBE, 0x78,
+       0xBB, 0x0F, 0x10, 0x24, 0x6F, 0x43, 0xCE, 0x52, 0x35, 0xBB, 0x18, 0x2C, 0xE5, 0xD8, 0x42, 0x3E,
+       0xF3, 0xA7, 0xC3, 0xFE, 0x99, 0xC6, 0x59, 0x29, 0x74, 0x32, 0x77, 0xAE, 0xB9, 0x2C, 0x1E, 0x5B,
+       0x8A, 0xCE, 0x19, 0xE7, 0x8B, 0x26, 0x31, 0x9A, 0x86, 0x45, 0x6A, 0x78, 0x18, 0x46, 0x89, 0x23,
+       0x8C, 0xDC, 0x17, 0x29, 0xED, 0x14, 0x90, 0x2C, 0xA8, 0x53, 0xFF, 0x64, 0x53, 0x45, 0x65, 0x23,
+       0xAA, 0xDC, 0x4D, 0xD8, 0x39, 0xD9, 0x2D, 0xD1, 0xCF, 0x39, 0x1D, 0x12, 0xD5, 0x30, 0x2B, 0x06,
+       0x19, 0xA0, 0x30, 0xB6, 0x32, 0xF7, 0xC2, 0xAF, 0x35, 0xEC, 0xB6, 0x99, 0x5A, 0x61, 0x2A, 0x29,
+       0x60, 0x0A, 0x9D, 0x2C, 0xFD, 0x72, 0x9F, 0xAF, 0xE0, 0x29, 0x86, 0xCB, 0x18, 0x70, 0x4D, 0xF9,
+       0x91, 0xD1, 0xFD, 0xB4, 0x18, 0xCD, 0xE1, 0xA5, 0x08, 0x6A, 0x7C, 0xEA, 0x1F, 0x0F, 0x53, 0xF1,
+       0x34, 0x2D, 0xCA, 0xC5, 0x0F, 0xA8, 0xF8, 0xA5, 0xF9, 0x30, 0xE9, 0xF4, 0x37, 0xB9, 0x3C, 0x61,
+       0x7F, 0xB8, 0x7B, 0x26, 0x4B, 0x20, 0x89, 0xAF, 0x9B, 0x90, 0x59, 0x9E, 0x82, 0xE2, 0x45, 0x02,
+       0x37, 0xC4, 0x9A, 0x9F, 0xE4, 0x11, 0x1F, 0x8C, 0x41, 0xFA, 0xE6, 0xAF, 0x2C, 0xE3, 0x8E, 0xEF,
+       0x04, 0x30, 0x02, 0x90, 0x98, 0x13, 0x1D, 0x5F, 0x24, 0xDD, 0x4D, 0x9C, 0x2C, 0x0B, 0x45, 0x6A,
+       0xA1, 0xA6, 0x84, 0x6F, 0x70, 0xFD, 0x44, 0x09, 0xE9, 0x3D, 0x99, 0xBB, 0xE3, 0xE3, 0x24, 0x56,
+       0x23, 0xE8, 0x34, 0xCC, 0x52, 0x26, 0x8A, 0xA9, 0x84, 0xCF, 0x94, 0x55, 0x21, 0x6B, 0xAE, 0x88,
+       0x56, 0xFF, 0xB8, 0x38, 0x62, 0x30, 0xD3, 0x78, 0xF8, 0x90, 0x0A, 0x94, 0x10, 0x22, 0x76, 0xAE,
+       0x35, 0x15, 0x5F, 0xC9, 0x33, 0x29, 0x1D, 0x6F, 0x84, 0x43, 0xC6, 0x58, 0x20, 0x36, 0x3E, 0x58,
+       0x2B, 0x6B, 0xBC, 0x2F, 0x35, 0x60, 0xDA, 0x09, 0xB0, 0x86, 0x3E, 0x2F, 0x38, 0x2F, 0x24, 0x6C,
+       0x1B, 0x8F, 0x88, 0xF3, 0x8F, 0xE0, 0x89, 0xC0, 0x67, 0x7C, 0x15, 0x80, 0x35, 0xA1, 0x96, 0x09,
+       0x43, 0x4B, 0x2A, 0x3A, 0x1F, 0x6B, 0xCA, 0x0D, 0x68, 0x6B, 0x00, 0x66, 0xD1, 0xFB, 0x5E, 0xC5,
+       0x61, 0xE5, 0xFE, 0xCD, 0xCB, 0xFE, 0x20, 0x9E, 0x6D, 0x0D, 0x3F, 0x22, 0xA8, 0xBD, 0xB6, 0x89,
+       0x72, 0x93, 0x07, 0x55, 0x09, 0x83, 0x7B, 0x89, 0x56, 0x0E, 0x3E, 0x74, 0x3A, 0xD1, 0x46, 0x88,
+       0x52, 0x63, 0x85, 0xAD, 0xC7, 0x66, 0x49, 0xF0, 0xA8, 0x21, 0x05, 0xB5, 0xA2, 0xC5, 0x7A, 0x42,
+       0xAB, 0xBD, 0x18, 0x63, 0x81, 0x11, 0xEA, 0xE7, 0x76, 0x90, 0x7A, 0xE2, 0x41, 0x37, 0xC8, 0x20,
+       0xFD, 0x85, 0x24, 0x58, 0x1C, 0x17, 0xB6, 0xC1, 0x3D, 0x11, 0x5C, 0x2B, 0xE2, 0xC9, 0xCE, 0x7D,
+       0x83, 0x4D, 0xD8, 0x1F, 0xF5, 0xB5, 0x4D, 0x9D, 0x28, 0x1B, 0x35, 0xD4, 0x92, 0x08, 0x0E, 0xCE,
+       0x95, 0x7A, 0x5E, 0x74, 0xB0, 0x91, 0xDD, 0x63, 0x87, 0xC5, 0xC6, 0x01, 0x54, 0x68, 0x92, 0x00,
+       0x7A, 0x03, 0xC8, 0x20, 0xFC, 0x5F, 0xA4, 0xCA, 0x78, 0x6F, 0xBC, 0x8E, 0xF2, 0x64, 0x17, 0xA2,
+       0xFC, 0x3A, 0x68, 0x04, 0xA2, 0x28, 0x9F, 0x35, 0x72, 0xF3, 0x0C, 0xAD, 0x19, 0x74, 0xC6, 0xD1,
+       0x25, 0x60, 0xEA, 0xF6, 0x89, 0x0C, 0x62, 0x7F, 0x4D, 0xC0, 0x78, 0x69, 0x0D, 0xB7, 0x8E, 0x08,
+       0x6D, 0xF8, 0x38, 0xC6, 0xB6, 0x12, 0x36, 0x25, 0x96, 0xE7, 0x65, 0xCD, 0xE7, 0xB6, 0x63, 0x36,
+       0x9D, 0x7D, 0x64, 0x92, 0x1F, 0xDB, 0x69, 0xA7, 0x75, 0x12, 0x41, 0xBA, 0xE6, 0xDD, 0xF9, 0x1C,
+       0xFA, 0xF8, 0x8C, 0x0E, 0x8F, 0x86, 0x1E, 0xDA, 0x54, 0x4F, 0xC4, 0x75, 0x12, 0x66, 0x64, 0xC0,
+       0x04, 0x7F, 0xB8, 0x9C, 0x20, 0x46, 0x8A, 0x20, 0x03, 0xC8, 0xBC, 0x1F, 0xD6, 0x3E, 0xD6, 0xC1,
+       0x3E, 0xD3, 0x5B, 0x84, 0x0B, 0x8F, 0x50, 0x2B, 0x98, 0x7A, 0xD7, 0x5F, 0xD3, 0x76, 0x94, 0x0D,
+       0x53, 0x2D, 0x86, 0xD3, 0x5C, 0x61, 0x0E, 0x97, 0x7C, 0x69, 0x60, 0xB6, 0x73, 0xC1, 0x84, 0xA3,
+       0x8E, 0xFA, 0x9F, 0x2B, 0x2B, 0x38, 0xFF, 0x97, 0xE2, 0xC3, 0xA4, 0x4E, 0x72, 0x20, 0xE6, 0x49,
+       0x02, 0x7B, 0xCC, 0x2C, 0x91, 0xED, 0x9C, 0xAC, 0x28, 0x1A, 0x30, 0x31, 0xDB, 0x79, 0xFC, 0x14,
+       0xCC, 0x2A, 0x67, 0x9B, 0x97, 0x70, 0xAC, 0x25, 0xCD, 0xD2, 0x5E, 0xEA, 0x73, 0x13, 0xDB, 0xAB,
+       0x44, 0x48, 0xAF, 0x35, 0x57, 0xCE, 0x2B, 0xF0, 0x7A, 0xCC, 0xC5, 0xC1, 0xD7, 0xC9, 0x63, 0x15,
+       0x59, 0xF0, 0x6D, 0x73, 0x08, 0x74, 0x27, 0x4E, 0x81, 0x23, 0x3D, 0xE6, 0xFA, 0xC9, 0xDC, 0x10,
+       0x99, 0x94, 0xFA, 0x55, 0x3F, 0xD3, 0x72, 0x6F, 0xDF, 0x59, 0xF9, 0x41, 0x89, 0x2D, 0x1C, 0x92,
+       0x9E, 0xA3, 0xE6, 0x4B, 0xCD, 0x44, 0x93, 0x85, 0xCB, 0xB4, 0x55, 0x52, 0x13, 0x62, 0xFF, 0xC4,
+       0x38, 0x93, 0xA3, 0x79, 0x51, 0xDB, 0xC6, 0xF8, 0x86, 0x90, 0x6C, 0x9C, 0x32, 0x18, 0x02, 0x17,
+       0x17, 0x41, 0xF8, 0x42, 0x46, 0x5B, 0x36, 0xFB, 0x7A, 0x2B, 0xCC, 0xCE, 0x43, 0x03, 0xE8, 0x7D,
+       0x7C, 0x67, 0xA0, 0x2E, 0xF4, 0xC3, 0x72, 0xAD, 0x13, 0xEE, 0x61, 0xFD, 0x50, 0xD6, 0xBF, 0xA2,
+       0xDC, 0xD5, 0x56, 0xB3, 0xAD, 0xA1, 0x3A, 0xC7, 0xCC, 0x75, 0x76, 0xDE, 0x21, 0x7C, 0x88, 0xE5,
+       0x86, 0x95, 0x07, 0xB6, 0xE6, 0xEF, 0x04, 0x07, 0x5D, 0xBE, 0x00, 0xFE, 0xC8, 0x4A, 0xC0, 0xD4,
+       0x5D, 0x8F, 0xA2, 0x55, 0xD0, 0xDB, 0x67, 0xAD, 0x04, 0x45, 0x2F, 0xBD, 0xA8, 0xCB, 0x79, 0x06,
+       0x6A, 0xEE, 0x6C, 0xF4, 0xCF, 0x7F, 0x2F, 0xF4, 0x19, 0x15, 0xD8, 0x0F, 0xC8, 0x55, 0x64, 0x1D,
+       0x32, 0x67, 0x4E, 0xAF, 0xE4, 0x92, 0xE8, 0x00, 0xF7, 0x7C, 0x68, 0x8A, 0x3E, 0x9B, 0x52, 0xB1,
+       0xD7, 0xAC, 0x74, 0x04, 0xAD, 0x82, 0x4B, 0x67, 0xE9, 0x12, 0x69, 0xAC, 0x74, 0xC6, 0xB6, 0x8A,
+       0x59, 0x30, 0x11, 0x2C, 0x60, 0xE4, 0x93, 0x91, 0xEB, 0xE6, 0x82, 0x9C, 0xA3, 0x24, 0xFE, 0x00,
+       0x9E, 0xED, 0x31, 0x7C, 0xAF, 0xA8, 0x1B, 0x0C, 0x3F, 0xDC, 0x75, 0xB0, 0xF9, 0x3B, 0x1A, 0x02,
+       0x45, 0x2B, 0x27, 0xB2, 0x67, 0x10, 0xBD, 0xE2, 0x47, 0x70, 0xB7, 0xA7, 0x29, 0x55, 0x07, 0x88,
+       0x9C, 0x00, 0x72, 0x44, 0x06, 0x1F, 0x90, 0xBC, 0x8C, 0xA6, 0x1F, 0x33, 0xD6, 0xA6, 0xA3, 0xF1,
+       0xF1, 0x65, 0xA5, 0x97, 0x9B, 0x30, 0x19, 0xFD, 0x0E, 0x74, 0x0F, 0xC2, 0x47, 0x66, 0x31, 0x17,
+       0xB1, 0xED, 0x38, 0x46, 0x86, 0xC9, 0x9A, 0x1A, 0x5E, 0x17, 0xEC, 0xD4, 0xE9, 0x28, 0xB4, 0xA6,
+       0xCB, 0x88, 0xCF, 0x06, 0xDB, 0xAE, 0x2A, 0x88, 0x8C, 0xBE, 0x17, 0x89, 0x8E, 0xD5, 0xAC, 0x0D,
+       0x11, 0xBC, 0xB8, 0x4E, 0xFD, 0x5E, 0x27, 0xAC, 0xC9, 0xE9, 0x52, 0xCD, 0xA8, 0xA7, 0xC9, 0x13,
+       0xC9, 0x08, 0xAE, 0xF4, 0x0E, 0x94, 0xEF, 0xBD, 0xB7, 0xF8, 0xCA, 0x90, 0xE5, 0x20, 0xE1, 0x79,
+       0x80, 0x29, 0x06, 0xC7, 0x03, 0x3E, 0x35, 0xE9, 0xA9, 0x9A, 0x04, 0xF4, 0xF1, 0x0D, 0x09, 0x83,
+       0x41, 0x9A, 0xEE, 0x77, 0x75, 0x69, 0x8C, 0x89, 0xD4, 0xB5, 0xD8, 0xAE, 0x37, 0x05, 0x0C, 0x29,
+       0x62, 0x1F, 0x91, 0xFC, 0xF3, 0xED, 0xEA, 0x3A, 0x42, 0x34, 0xA5, 0x19, 0x1C, 0x7D, 0x12, 0x38,
+       0x08, 0xD2, 0x44, 0x18, 0xD7, 0x7D, 0xBF, 0x82, 0xB4, 0x5F, 0x5F, 0x1A, 0x4B, 0x04, 0x34, 0x67,
+       0x5C, 0xC9, 0xBC, 0x94, 0x8C, 0x85, 0xCA, 0xE6, 0x2F, 0x1F, 0x0E, 0xDE, 0x92, 0x44, 0x80, 0xF3,
+       0xFE, 0x0F, 0x46, 0x2F, 0x3C, 0x17, 0x2D, 0x2D, 0xC6, 0x02, 0x88, 0x51, 0x94, 0xF6, 0x5F, 0xBD,
+       0xDA, 0xC1, 0x7A, 0x77, 0x50, 0xD9, 0x43, 0xC8, 0x78, 0x8C, 0x93, 0x41, 0x36, 0xDA, 0x62, 0x9C,
+       0xE6, 0xB9, 0x06, 0x82, 0xF9, 0xEE, 0xBC, 0x8A, 0x13, 0x95, 0x35, 0x1E, 0xD3, 0x86, 0xA9, 0x17,
+       0xC8, 0x7D, 0xDB, 0x07, 0x77, 0x7B, 0xA3, 0xA3, 0x43, 0xF4, 0x5F, 0x20, 0x2C, 0xCB, 0xB5, 0xE0,
+       0x00, 0x9D, 0x8A, 0xF0, 0x05, 0x61, 0xE2, 0x96, 0xFE, 0x11, 0x17, 0xF8, 0xAB, 0xE0, 0x04, 0x35,
+       0xB1, 0xEC, 0x78, 0x93, 0x21, 0x30, 0x7A, 0xCA, 0x6D, 0xAF, 0x29, 0xDC, 0xF4, 0xD3, 0x3A, 0x2A,
+       0xA4, 0x64, 0xEA, 0x09, 0xEE, 0xA8, 0x63, 0x57, 0x85, 0x0A, 0x39, 0x3A, 0x4B, 0xEB, 0x18, 0x17,
+       0x06, 0x09, 0xB3, 0x38, 0x9D, 0x4A, 0x54, 0x9D, 0x04, 0x2C, 0xBF, 0xA6, 0x8A, 0x48, 0x22, 0xBD,
+       0xC7, 0xA2, 0x70, 0xAD, 0x7C, 0x33, 0x34, 0xB5, 0xBB, 0x8A, 0x0E, 0x4C, 0xC8, 0xF6, 0xA3, 0xE6,
+       0xEB, 0xFA, 0x84, 0xAF, 0x94, 0x57, 0x4E, 0xD7, 0xCE, 0x49, 0xBD, 0xBD, 0x96, 0x53, 0x3A, 0xAE,
+       0xD5, 0xBF, 0xB5, 0xA1, 0x90, 0x37, 0xA3, 0x11, 0x87, 0x0A, 0x9B, 0x0D, 0x62, 0xC1, 0x40, 0x66,
+       0x7D, 0x51, 0xFB, 0xB3, 0x54, 0x74, 0xCA, 0x0D, 0x98, 0xB1, 0x11, 0x15, 0x5F, 0x49, 0xA0, 0x92,
+       0xD7, 0xBF, 0xBA, 0x1A, 0x5D, 0x08, 0x8B, 0xE7, 0xC2, 0x5F, 0x6C, 0xB4, 0x6E, 0x6C, 0xBB, 0xF9,
+       0x12, 0xF4, 0x42, 0xE1, 0x0A, 0xE3, 0x09, 0x9B, 0x5D, 0xD8, 0x97, 0x39, 0x93, 0x4F, 0x5E, 0xBE,
+       0x68, 0xED, 0xCD, 0xFB, 0x8E, 0xD2, 0x8E, 0x91, 0x0A, 0x74, 0xA3, 0x61, 0x03, 0x4E, 0x56, 0x21,
+       0x63, 0x79, 0x89, 0x64, 0x52, 0xE1, 0x81, 0xE3, 0x6F, 0x45, 0x24, 0x25, 0x6F, 0x35, 0xFF, 0x36,
+       0xCC, 0xE9, 0x1F, 0xA3, 0x4F, 0x8E, 0x29, 0x6E, 0x5E, 0x9B, 0x0E, 0xC7, 0xAC, 0x15, 0x02, 0x43,
+       0xE1, 0x15, 0x9F, 0xB9, 0xA1, 0x6A, 0xDD, 0x81, 0xBC, 0xA6, 0x65, 0xD4, 0x1E, 0x6A, 0x1B, 0x6F,
+       0x9B, 0x89, 0x6B, 0x45, 0x90, 0x29, 0xA2, 0x33, 0x21, 0xC7, 0x5E, 0xF0, 0xBC, 0x03, 0x63, 0x9C,
+       0x23, 0xF6, 0x2E, 0xC1, 0x28, 0xFB, 0x5F, 0x93, 0x20, 0x24, 0xC4, 0xBA, 0xAB, 0x08, 0x11, 0x93,
+       0x69, 0xAA, 0x26, 0xD6, 0xE0, 0x77, 0xB4, 0x9F, 0x4C, 0x85, 0xE9, 0x7F, 0x7C, 0x9A, 0x8D, 0x01,
+       0xB5, 0x7C, 0xFF, 0x82, 0x06, 0xA8, 0x7E, 0x19, 0xB1, 0x2B, 0xEA, 0x2D, 0x54, 0xBB, 0x85, 0x19,
+       0x78, 0x7C, 0xC0, 0xAD, 0x5C, 0x24, 0x25, 0x4F, 0x4F, 0xA4, 0x7A, 0xC2, 0xAF, 0x0F, 0xC9, 0x8A,
+       0xA2, 0xF1, 0xF0, 0x7F, 0xC2, 0x84, 0xE5, 0x1C, 0x67, 0x22, 0xE8, 0x0E, 0x30, 0x9E, 0xCB, 0x07,
+       0x22, 0x34, 0x9D, 0x66, 0xB8, 0x58, 0x4E, 0xEB, 0xA8, 0x09, 0x84, 0x87, 0x7E, 0xF4, 0xFC, 0x38,
+       0x44, 0xA1, 0x8E, 0xC3, 0x33, 0x35, 0x7A, 0xBE, 0x12, 0xCF, 0x7E, 0xD2, 0x2F, 0xD9, 0xDA, 0x03,
+       0xF3, 0x80, 0xE1, 0x59, 0xD2, 0xD8, 0xB8, 0x3F, 0xE9, 0x5C, 0xE1, 0xAB, 0xE6, 0x86, 0x5E, 0x3C,
+       0x12, 0xC4, 0xE6, 0x8C, 0xCC, 0x94, 0x6A, 0x0C, 0xB8, 0xE5, 0x4C, 0x72, 0x11, 0x8F, 0x08, 0xFD,
+       0x97, 0x2D, 0x84, 0xE4, 0x7D, 0x8B, 0xF1, 0xBD, 0xFF, 0x09, 0x73, 0x86, 0x3B, 0x8E, 0x4D, 0x28,
+       0x90, 0x18, 0x22, 0xE8, 0x3A, 0x22, 0x5F, 0x96, 0x8A, 0x3D, 0xEC, 0xCE, 0x8B, 0x9F, 0x3D, 0xAD,
+       0x8E, 0x13, 0xA6, 0x87, 0x05, 0xEB, 0xA0, 0x6B, 0x8F, 0x82, 0xBA, 0xBF, 0x63, 0xEE, 0x5C, 0x30,
+       0x30, 0x97, 0xFD, 0x91, 0xA0, 0xBA, 0xD7, 0x7E, 0x9D, 0xDC, 0x22, 0x13, 0x87, 0x22, 0xEB, 0xEC,
+       0x3A, 0x86, 0xEB, 0xA6, 0x14, 0x30, 0x5A, 0xC7, 0x91, 0x5A, 0xCE, 0x0A, 0x5B, 0x67, 0x0E, 0x24,
+       0x56, 0x59, 0x18, 0x93, 0x5D, 0x88, 0xCB, 0xB6, 0x0C, 0xDA, 0x3D, 0xF2, 0x14, 0xF0, 0xDF, 0xF4,
+       0x5D, 0x93, 0x60, 0x30, 0x35, 0x9C, 0xF3, 0x0D, 0xB9, 0xEE, 0xB1, 0x1D, 0x29, 0x5D, 0x1A, 0x64,
+       0xAF, 0xD3, 0x1E, 0x97, 0x22, 0x05, 0x42, 0xF5, 0xFC, 0x24, 0xED, 0xF1, 0xFC, 0x0E, 0xED, 0x25,
+       0xD9, 0x55, 0x3E, 0xC6, 0xB7, 0x95, 0x73, 0xD6, 0x18, 0x0F, 0x02, 0x97, 0x58, 0x3D, 0x0D, 0x63,
+       0x0B, 0xA4, 0xCD, 0x4E, 0x03, 0x66, 0xF7, 0xF8, 0x3D, 0x91, 0x0B, 0x45, 0x03, 0xF0, 0x13, 0x68,
+       0x72, 0x4B, 0xFD, 0xDA, 0xEF, 0xAE, 0x57, 0x59, 0x88, 0xDE, 0x98, 0x76, 0x11, 0x01, 0x27, 0x08,
+       0xCF, 0xD8, 0xAB, 0xA2, 0x91, 0xA3, 0x61, 0xB4, 0xD3, 0x62, 0xA4, 0xCD, 0xDE, 0x10, 0x98, 0x33,
+       0x6E, 0x40, 0xFB, 0xF1, 0xA9, 0xDA, 0x44, 0x17, 0xE7, 0xC5, 0x98, 0x60, 0x37, 0x6D, 0x08, 0x21,
+       0x5C, 0xE6, 0x38, 0xEA, 0xFB, 0xA7, 0x04, 0x1F, 0x6B, 0x84, 0x93, 0xDF, 0x31, 0xB6, 0x3C, 0x21,
+       0x39, 0xED, 0xC8, 0x9B, 0x99, 0x5B, 0xAB, 0x5E, 0x0E, 0x6C, 0x93, 0x9B, 0x47, 0xB4, 0xAF, 0x8A,
+       0x10, 0x51, 0x64, 0xEE, 0x08, 0xC0, 0xEB, 0x6B, 0xE4, 0x98, 0x11, 0x13, 0x32, 0x87, 0x86, 0x4D,
+       0x02, 0xFA, 0x0D, 0x55, 0xA1, 0x8D, 0x79, 0xF8, 0xC9, 0xB9, 0x02, 0xC7, 0x03, 0xA6, 0x3D, 0x82,
+       0x90, 0xC2, 0xEB, 0x90, 0xF4, 0xF8, 0x69, 0xA2, 0x4F, 0x2B, 0xE4, 0x1E, 0x08, 0x8E, 0x66, 0x40,
+       0x24, 0x6E, 0x99, 0xD7, 0x11, 0x1E, 0xD5, 0xE3, 0xE6, 0xA1, 0x32, 0xBD, 0x51, 0xDB, 0x45, 0xAB,
+       0xFF, 0xC5, 0xD4, 0xE3, 0x3F, 0x84, 0x1F, 0x9B, 0x78, 0x98, 0x12, 0x8C, 0xD8, 0x4C, 0xD7, 0x63,
+       0xC9, 0x56, 0xE8, 0x72, 0x8E, 0xA0, 0xC6, 0x47, 0x1D, 0x5C, 0x9A, 0xC1, 0x15, 0x93, 0x53, 0xA2,
+       0x6A, 0xE1, 0x34, 0x2F, 0x2A, 0xE1, 0x16, 0xB1, 0x49, 0x7A, 0x5C, 0xE8, 0x5F, 0x2F, 0xC0, 0x08,
+       0x8E, 0x08, 0x57, 0x6F, 0xB7, 0x8D, 0x03, 0xED, 0x88, 0x87, 0x47, 0x4F, 0x4D, 0xB0, 0xC9, 0x54,
+       0x6D, 0xA1, 0x72, 0xE4, 0xBF, 0x2C, 0x8E, 0x7B, 0x63, 0xDE, 0xF5, 0xAC, 0x73, 0xF4, 0x9B, 0x6A,
+       0x52, 0xAF, 0x08, 0xBF, 0x33, 0xE6, 0x8C, 0xBB, 0xF0, 0xBB, 0x98, 0x0A, 0xB8, 0x6E, 0xCA, 0xEF,
+       0x55, 0xF9, 0xCA, 0x60, 0xEC, 0x6A, 0xFB, 0x72, 0x76, 0xA5, 0xE3, 0xF0, 0xB3, 0x02, 0x8B, 0x97,
+       0x1D, 0x9A, 0x3F, 0x4B, 0x86, 0xE2, 0x79, 0x0D, 0xD2, 0x2F, 0x92, 0x67, 0x88, 0x7E, 0xBA, 0x6F,
+       0xC5, 0x86, 0x8B, 0x27, 0x12, 0x88, 0x80, 0x11, 0xF4, 0x1B, 0xBC, 0xE4, 0x1B, 0xCD, 0x97, 0x99,
+       0xFB, 0x9B, 0x42, 0x76, 0x95, 0x52, 0x5A, 0xBE, 0xEE, 0x9C, 0x3D, 0xDF, 0xB0, 0xDA, 0xA7, 0x92,
+       0xBF, 0xB6, 0x68, 0x5F, 0xC0, 0x27, 0x8C, 0x91, 0xBB, 0x33, 0x3C, 0x49, 0xD7, 0x58, 0x04, 0x12,
+       0x83, 0x5F, 0xBC, 0x50, 0x30, 0x22, 0xA3, 0xA1, 0x3A, 0x30, 0x9A, 0x7F, 0xA7, 0xD5, 0xD7, 0x24,
+       0x32, 0x29, 0xD0, 0x0F, 0x3F, 0xF2, 0x27, 0x15, 0xBF, 0x12, 0x02, 0x7E, 0xCA, 0xC7, 0x98, 0x9D,
+       0xD8, 0xC5, 0x55, 0xB2, 0x65, 0x03, 0xF0, 0x8D, 0x41, 0x07, 0xFC, 0xB0, 0x56, 0x3E, 0x70, 0x85,
+       0xEC, 0x78, 0x9A, 0x38, 0xA6, 0xAC, 0x87, 0x7E, 0x52, 0x56, 0x92, 0x9D, 0x2D, 0x3E, 0x68, 0x4A,
+       0x47, 0xA7, 0x77, 0x0F, 0x52, 0x3C, 0xF6, 0x0F, 0xEF, 0x80, 0xC9, 0xFB, 0x9A, 0x29, 0x4C, 0x5F,
+       0x1E, 0xB8, 0xBB, 0x66, 0xCE, 0xD0, 0xAF, 0xBD, 0xAB, 0x36, 0xD4, 0xAA, 0xD7, 0xAA, 0xCB, 0x1A,
+       0xEB, 0xEB, 0x77, 0xE3, 0xF6, 0x4E, 0xE1, 0xD3, 0xCD, 0x8B, 0xF7, 0xA8, 0x32, 0x9D, 0x85, 0xE9,
+       0xED, 0x8A, 0x34, 0x35, 0x95, 0x9A, 0x85, 0xD0, 0x9B, 0x42, 0xD1, 0xBE, 0xCE, 0x9B, 0x14, 0x3E,
+       0x9C, 0x14, 0xEF, 0xE6, 0x8C, 0x52, 0x43, 0x1C, 0x2D, 0x32, 0x41, 0xBA, 0x1E, 0x75, 0x04, 0xE6,
+       0x15, 0xA6, 0xA1, 0xEB, 0x84, 0x82, 0x88, 0x30, 0x26, 0xE2, 0x37, 0x2F, 0xC4, 0xE6, 0x00, 0x02,
+       0x13, 0x60, 0xDF, 0x53, 0xDF, 0x59, 0x46, 0x80, 0x23, 0xA7, 0x68, 0xE1, 0xC3, 0x0F, 0x89, 0x73,
+       0xF2, 0xE5, 0x7E, 0x83, 0x39, 0x90, 0x87, 0x06, 0xAA, 0x2E, 0x75, 0x5E, 0xDD, 0xC5, 0xC7, 0x20,
+       0x7B, 0x4F, 0x8A, 0x12, 0xAF, 0xD1, 0xDF, 0x6B, 0xE8, 0x23, 0x2F, 0x49, 0x8F, 0x72, 0xF6, 0xE3,
+       0xB7, 0xCD, 0x3C, 0xA5, 0x2A, 0x2B, 0xFE, 0x48, 0x5C, 0x88, 0x3A, 0xB7, 0x3D, 0xA2, 0x83, 0xCD,
+       0xAD, 0xEB, 0x23, 0x57, 0x5C, 0xAE, 0xEE, 0x3A, 0x33, 0x3B, 0xAD, 0xBB, 0x4C, 0x95, 0xF3, 0x9A,
+       0x83, 0x7C, 0x30, 0xDF, 0xF3, 0x0E, 0xC5, 0x5F, 0x5B, 0xCB, 0x86, 0x83, 0x5B, 0x0A, 0xD3, 0x95,
+       0x4B, 0xE2, 0x8D, 0x72, 0x58, 0xE1, 0xFD, 0x7D, 0xBB, 0x44, 0x31, 0xA0, 0x93, 0x9A, 0xF5, 0xDD,
+       0xC8, 0xAD, 0xE4, 0xFE, 0x3A, 0x8C, 0x4F, 0x9A, 0x70, 0x29, 0x7B, 0xC9, 0x2C, 0x9D, 0x7A, 0x94,
+       0x91, 0x8C, 0x8C, 0x9A, 0x8D, 0x70, 0xE2, 0x11, 0xEB, 0x8D, 0xD3, 0xE5, 0xD6, 0x67, 0x95, 0xD9,
+       0x88, 0x59, 0x19, 0x29, 0x14, 0xE6, 0x7B, 0xF6, 0x3F, 0x67, 0x29, 0xDC, 0x6D, 0xBD, 0xA4, 0xE4,
+       0xCD, 0x5E, 0x35, 0x25, 0x13, 0x5D, 0x3C, 0x3E, 0x9C, 0xE3, 0x5F, 0xF2, 0x78, 0x29, 0xE0, 0xD6,
+       0xEC, 0x8F, 0x9E, 0xAC, 0x75, 0xDC, 0xFD, 0x89, 0x53, 0xE7, 0x62, 0x6B, 0x38, 0x0D, 0x8B, 0x79,
+       0xB7, 0x05, 0x45, 0xF5, 0x72, 0x9E, 0xE5, 0x3C, 0xFB, 0xB4, 0xD3, 0x9F, 0x62, 0x38, 0x3A, 0x80,
+       0xDA, 0x59, 0x53, 0x3B, 0xBB, 0x55, 0x4B, 0xD0, 0xE1, 0x63, 0xF4, 0xBC, 0x99, 0xD3, 0x63, 0x5A,
+       0xCC, 0x0D, 0x2D, 0x09, 0x80, 0x46, 0x62, 0xEE, 0xE4, 0x50, 0xF2, 0x5B, 0xBB, 0x96, 0xC6, 0x1D,
+       0x05, 0xE6, 0x5C, 0x68, 0x7E, 0xCC, 0xBD, 0x96, 0x0B, 0x8E, 0xDC, 0x45, 0x62, 0x9C, 0x48, 0x24,
+       0x9B, 0x72, 0x47, 0x2F, 0xB3, 0x14, 0xCF, 0xB8, 0x1A, 0x93, 0x73, 0x83, 0x11, 0x7C, 0x27, 0xC4,
+       0x99, 0x4B, 0x4F, 0x5E, 0x32, 0x86, 0x85, 0xFD, 0x5C, 0x36, 0xA6, 0xC6, 0x02, 0x47, 0x3E, 0xF0,
+       0x66, 0xDF, 0x9C, 0x88, 0x72, 0x0D, 0xA7, 0xB7, 0xAA, 0x14, 0x91, 0x86, 0xAF, 0x08, 0x2D, 0xC8,
+       0x6A, 0x08, 0x12, 0x40, 0x3E, 0xBB, 0x5B, 0x1A, 0xC3, 0x2F, 0x97, 0x44, 0xAD, 0xD6, 0x70, 0xCA,
+       0x23, 0x15, 0x3D, 0xF8, 0x81, 0xDD, 0xE6, 0x1B, 0xFC, 0x24, 0x42, 0x70, 0xBC, 0x47, 0xAB, 0xA1,
+       0xCA, 0x6F, 0x27, 0x18, 0x4D, 0x82, 0xBA, 0x34, 0x31, 0x44, 0xA1, 0x84, 0x8D, 0x70, 0x1A, 0xC5,
+       0x02, 0xA5, 0xED, 0x67, 0xC7, 0x18, 0xFA, 0xD2, 0xF3, 0x0F, 0x7A, 0x12, 0x40, 0x77, 0xA5, 0x0E,
+       0x03, 0xF0, 0xC8, 0xEA, 0xE9, 0x36, 0xDF, 0xCB, 0xDA, 0xA6, 0x25, 0x73, 0xD2, 0x7B, 0x57, 0xB4,
+       0x40, 0xAD, 0x90, 0x35, 0x27, 0x2C, 0x99, 0xE2, 0x34, 0x50, 0x12, 0xF9, 0xF4, 0xBE, 0xF2, 0x86,
+       0x4E, 0xAD, 0xFA, 0x83, 0x92, 0x33, 0x48, 0x4F, 0x1E, 0xB4, 0xB2, 0x0D, 0x88, 0xCF, 0x0B, 0xDF,
+       0x03, 0x48, 0x2C, 0xA8, 0x9D, 0x60, 0xFC, 0x44, 0x24, 0x9B, 0xF8, 0x86, 0xE2, 0x23, 0xFE, 0xC7,
+       0xF7, 0x9C, 0xA1, 0xE0, 0x97, 0x8E, 0x23, 0x8D, 0x60, 0x0D, 0xAF, 0xB2, 0xF1, 0x6D, 0xC4, 0xE4,
+       0x48, 0xF6, 0xC0, 0xC0, 0xF2, 0xDA, 0x1E, 0x15, 0x27, 0x99, 0x78, 0x9F, 0xCC, 0x8D, 0xF9, 0xC1,
+       0x2F, 0xF6, 0x7B, 0x45, 0x65, 0xD2, 0x4F, 0x78, 0x4E, 0xB2, 0x39, 0x3D, 0xC9, 0xA3, 0x20, 0x2A,
+       0xC8, 0xC6, 0x67, 0x2B, 0xA0, 0x2C, 0x4A, 0x75, 0x03, 0xEA, 0xD7, 0xB1, 0xD4, 0x57, 0x07, 0x11,
+       0x4A, 0xB0, 0xF8, 0x86, 0xCE, 0x4F, 0xF1, 0xD0, 0x19, 0x62, 0xE3, 0xD7, 0xE3, 0x59, 0xDD, 0x38,
+       0xD6, 0x12, 0xCE, 0xE4, 0x7A, 0x18, 0xEB, 0x5C, 0x3E, 0xFF, 0xDB, 0xF6, 0xBC, 0x9C, 0x18, 0xF3,
+       0x1A, 0xF8, 0xC4, 0x69, 0xC0, 0x0D, 0x75, 0x38, 0xA9, 0x6D, 0xFC, 0xA5, 0x10, 0x71, 0x0B, 0xB3,
+       0xA4, 0xCC, 0xDF, 0x32, 0x12, 0x94, 0x4B, 0x17, 0xDE, 0x79, 0xA0, 0x4A, 0x23, 0x3C, 0x02, 0xCA,
+       0xBD, 0x13, 0x23, 0xDD, 0x44, 0x60, 0x15, 0x51, 0x2F, 0xC5, 0xFE, 0x61, 0x93, 0xCB, 0xDE, 0x2A,
+       0x4A, 0xF0, 0xF7, 0xC9, 0x83, 0x91, 0xB4, 0xCD, 0x27, 0x42, 0x43, 0x85, 0x03, 0x49, 0x2F, 0x08,
+       0x93, 0x50, 0x1F, 0x19, 0x82, 0x0D, 0x7A, 0xF6, 0x3A, 0xB9, 0xCF, 0xC1, 0x7B, 0x5B, 0x73, 0xAC,
+       0x8E, 0x03, 0x8B, 0x99, 0x8C, 0x68, 0x85, 0xD7, 0xAE, 0x2D, 0x1B, 0xF3, 0x1B, 0xBA, 0x2F, 0x37,
+       0x42, 0x4D, 0x3D, 0x91, 0xB4, 0x77, 0x4A, 0x78, 0xB9, 0xB4, 0x0E, 0x08, 0x62, 0x9C, 0x8E, 0x6C,
+       0xB6, 0x97, 0x7D, 0x40, 0x9F, 0x97, 0xE2, 0x49, 0x26, 0x7F, 0xD5, 0xDB, 0x98, 0xB5, 0x77, 0x35,
+       0x4A, 0x18, 0x1E, 0x3E, 0xC5, 0xCE, 0x55, 0x87, 0xC9, 0x34, 0xE2, 0x4E, 0x05, 0x3E, 0xE1, 0x9D,
+       0x4F, 0x0A, 0x02, 0x46, 0xC6, 0x11, 0x00, 0x66, 0x45, 0x32, 0xB0, 0x21, 0xB2, 0xCD, 0xC6, 0xA7,
+       0x35, 0xF5, 0xFC, 0xA2, 0x58, 0xD3, 0x22, 0x03, 0xE4, 0x25, 0xE3, 0x52, 0x7C, 0x1D, 0xC8, 0xF8,
+       0x83, 0xB8, 0xC8, 0xBE, 0x6A, 0xAD, 0xFA, 0x5E, 0x54, 0x21, 0x18, 0xF8, 0x8F, 0x6A, 0x8D, 0x39,
+       0xA4, 0x31, 0x67, 0x0D, 0xF5, 0xB3, 0xE8, 0xCC, 0x80, 0xDC, 0xD6, 0xAA, 0xB5, 0x85, 0x13, 0x01,
+       0x5F, 0x25, 0x83, 0xA1, 0xFC, 0x96, 0xF8, 0x17, 0xB7, 0x80, 0x0E, 0x36, 0x80, 0xF1, 0x48, 0xA4,
+       0x50, 0x76, 0x96, 0x77, 0x0A, 0x5D, 0xA4, 0x1F, 0x12, 0x37, 0xEB, 0x2B, 0xB8, 0x5C, 0x18, 0xEA,
+       0x4B, 0x31, 0x59, 0x39, 0x42, 0x06, 0x7A, 0x36, 0x77, 0x90, 0xE3, 0x3E, 0xB0, 0xD5, 0xB2, 0x6E,
+       0xEE, 0xFD, 0xB0, 0xB6, 0x06, 0xB7, 0xC1, 0x38, 0x69, 0x6A, 0xF0, 0x47, 0x28, 0xEA, 0x54, 0xAA,
+       0x9A, 0x40, 0x85, 0x93, 0x52, 0xA5, 0x84, 0x4F, 0x0A, 0x9F, 0x27, 0xEA, 0x10, 0xFE, 0xBB, 0x07,
+       0x35, 0x42, 0x89, 0x39, 0xBF, 0x76, 0x70, 0xCC, 0xD1, 0xC7, 0x3E, 0x89, 0x65, 0xF5, 0xA2, 0xC1,
+       0x82, 0x4F, 0x5D, 0xDD, 0xFB, 0xA6, 0xAB, 0xF0, 0xDC, 0xEC, 0xCA, 0xCA, 0x4B, 0xC0, 0x63, 0x56,
+       0xC9, 0x8F, 0xE0, 0xCB, 0x38, 0xB4, 0x33, 0x4E, 0x74, 0x3F, 0xF2, 0x23, 0xE2, 0xA9, 0x71, 0x40,
+       0x8B, 0x63, 0x74, 0xA4, 0xBD, 0x10, 0x99, 0xB4, 0x5E, 0x41, 0x1A, 0x79, 0x26, 0x1B, 0x63, 0x5B,
+       0x5A, 0x1E, 0xCF, 0x33, 0xD3, 0xC7, 0x95, 0x3D, 0xD4, 0xAC, 0x58, 0x1F, 0xB2, 0x59, 0xF6, 0x3E,
+       0xDF, 0x05, 0xF4, 0xA0, 0x1C, 0xAF, 0x4F, 0x06, 0xFF, 0x16, 0x2E, 0xE1, 0xD2, 0x13, 0x41, 0x6F,
+       0xAE, 0x46, 0xC9, 0x6F, 0xC9, 0x8F, 0x56, 0x8E, 0x69, 0x8D, 0x43, 0xAE, 0x3D, 0x74, 0x78, 0x5C,
+       0x10, 0xE0, 0xB8, 0xAD, 0xA0, 0xD9, 0xAC, 0x46, 0x0D, 0x29, 0x55, 0xCC, 0x1B, 0x66, 0x92, 0x64,
+       0xD9, 0xE3, 0xDB, 0xDA, 0x07, 0x7C, 0x31, 0xD9, 0xCA, 0xC8, 0xE0, 0x64, 0x3C, 0xFC, 0xE9, 0xA9,
+       0xD5, 0x8E, 0x17, 0xEC, 0xA6, 0x0A, 0x6C, 0x5D, 0xD2, 0x3C, 0x1F, 0x88, 0x33, 0xAF, 0xF0, 0x7B,
+       0x40, 0x61, 0x96, 0xA2, 0xDF, 0x2F, 0x43, 0x8B, 0x65, 0x46, 0xD3, 0xD8, 0xB7, 0x3B, 0x04, 0xFB,
+       0x47, 0x7F, 0xCE, 0x5A, 0x7F, 0x08, 0xE8, 0xE8, 0x5E, 0x6E, 0xDF, 0xB7, 0xFF, 0x2F, 0x37, 0x04,
+       0x87, 0xB0, 0x63, 0xE5, 0x15, 0x2E, 0x6A, 0x1A, 0xCE, 0x55, 0x7A, 0xFA, 0x32, 0x49, 0x99, 0x75,
+       0x9C, 0xB0, 0x91, 0x5F, 0x8F, 0x18, 0x2C, 0xF9, 0xEC, 0xB3, 0xB0, 0xC9, 0x12, 0x9E, 0x3E, 0x0A,
+       0x26, 0xB5, 0xAA, 0x17, 0x41, 0x03, 0xE2, 0xB9, 0x8B, 0x6E, 0x27, 0xA3, 0xCE, 0xDD, 0x0B, 0x57,
+       0x86, 0x5E, 0x82, 0x4B, 0x10, 0x88, 0x90, 0x85, 0xD0, 0x24, 0xBD, 0xF6, 0x37, 0x7C, 0xD9, 0x8C,
+       0xD3, 0x55, 0x20, 0x20, 0xC4, 0xEB, 0x5B, 0x16, 0xF6, 0x17, 0xB8, 0x51, 0x91, 0xE7, 0xBC, 0xC6,
+       0x9B, 0xC3, 0x76, 0xB7, 0x93, 0x25, 0x53, 0x4E, 0x29, 0x66, 0x27, 0x67, 0xCE, 0x64, 0x57, 0xB5,
+       0xF4, 0xC5, 0xF3, 0x55, 0x34, 0xD1, 0xC9, 0xD1, 0x17, 0xBD, 0x3E, 0x44, 0x6D, 0x25, 0x54, 0xCB,
+       0x2A, 0xE8, 0x4F, 0x71, 0x6B, 0x71, 0xCA, 0x9D, 0xA8, 0x2C, 0x89, 0xAF, 0x24, 0x90, 0xBA, 0x19,
+       0x2A, 0xEA, 0x1E, 0xFF, 0x0E, 0xDA, 0x54, 0xF9, 0x85, 0x30, 0x27, 0x9D, 0xA8, 0x4F, 0xDF, 0xE3,
+       0xBC, 0xB0, 0x04, 0x4A, 0x9A, 0xAE, 0xDE, 0xFD, 0x06, 0xC7, 0x1A, 0x88, 0x46, 0x57, 0x5A, 0x16,
+       0x60, 0x3A, 0x62, 0x45, 0x88, 0x35, 0x92, 0xFD, 0x4D, 0x18, 0x1F, 0xAD, 0x3D, 0x33, 0xED, 0x6D,
+       0x48, 0x2E, 0x63, 0x92, 0x35, 0x78, 0x4F, 0x20, 0xFE, 0x3F, 0x58, 0xE2, 0x71, 0x58, 0x92, 0x69,
+       0x39, 0xA2, 0xA0, 0x8C, 0x5E, 0x61, 0x7F, 0x12, 0x8A, 0xF7, 0x6E, 0x0B, 0x71, 0xF7, 0x04, 0x38,
+       0xF7, 0x49, 0x80, 0x56, 0x6F, 0x9B, 0x8B, 0x1E, 0x8E, 0xDF, 0x2B, 0x85, 0xE7, 0xC8, 0xE7, 0xCD,
+       0xFD, 0x38, 0xCC, 0x96, 0xBD, 0x60, 0x54, 0xCE, 0x35, 0x16, 0x67, 0xDE, 0xE9, 0xDF, 0x57, 0xF3,
+       0xAD, 0x6D, 0x11, 0x35, 0xC3, 0xEE, 0xEF, 0x85, 0x92, 0x44, 0xF7, 0xEF, 0x8A, 0xD6, 0xB5, 0x91,
+       0x4C, 0x30, 0x3E, 0xFB, 0x3C, 0x9A, 0x7B, 0xBE, 0xDE, 0xDA, 0xA9, 0xFF, 0x66, 0xAD, 0xF1, 0x3A,
+       0x54, 0x7E, 0xF2, 0xE7, 0x04, 0xE1, 0x9A, 0x93, 0x46, 0xA9, 0xF1, 0x1A, 0x90, 0x44, 0x41, 0xDB,
+       0x9B, 0xEE, 0x63, 0x70, 0x38, 0x26, 0xFE, 0xE7, 0xD1, 0x96, 0xDD, 0xED, 0x8D, 0xB4, 0x33, 0xFE,
+       0xBA, 0xC7, 0x18, 0xDD, 0xE4, 0xE9, 0x2C, 0x45, 0xB3, 0x6B, 0x5B, 0x2D, 0xE9, 0xF1, 0xA8, 0x4B,
+       0xEF, 0x51, 0x4C, 0x35, 0x5F, 0xBE, 0x4E, 0x0A, 0xB8, 0x03, 0x83, 0x5A, 0xB9, 0x6B, 0x4C, 0x5C,
+       0x29, 0x87, 0x52, 0xEA, 0xD1, 0x34, 0x7E, 0x9D, 0x23, 0x68, 0x8A, 0xDD, 0xA8, 0x7E, 0x9B, 0x7E,
+       0xE7, 0xEA, 0xB6, 0xDF, 0xBB, 0x3B, 0x35, 0x7D, 0x20, 0x9D, 0x89, 0xE9, 0x98, 0x63, 0x96, 0x3A,
+       0x94, 0x6B, 0x89, 0x59, 0x15, 0x83, 0x51, 0x21, 0x94, 0x60, 0xC4, 0x14, 0xC8, 0x8E, 0x6A, 0x85,
+       0x32, 0x6A, 0x66, 0x92, 0xD6, 0x6C, 0xE9, 0x9E, 0x08, 0x93, 0x0D, 0x55, 0xD7, 0x79, 0xAD, 0xE6,
+       0xC6, 0xF2, 0x6A, 0x6B, 0xD1, 0x14, 0x0A, 0x07, 0xA8, 0x90, 0x6A, 0xFF, 0x0F, 0xDF, 0xC7, 0x55,
+       0x93, 0x94, 0x7F, 0x4D, 0x70, 0x07, 0x7C, 0x64, 0x10, 0x63, 0x93, 0xF3, 0x89, 0xA5, 0x20, 0x7F,
+       0x63, 0xD7, 0xA8, 0x69, 0xBE, 0x3F, 0x5A, 0xD7, 0x3C, 0x91, 0x6E, 0x23, 0xF9, 0x78, 0x92, 0xB2,
+       0x63, 0xA0, 0x21, 0x9E, 0x9E, 0x98, 0x9C, 0xBF, 0x2B, 0xB5, 0xA5, 0x62, 0x2A, 0xB6, 0x13, 0xC9,
+       0x19, 0xB4, 0x1B, 0x11, 0x01, 0x40, 0x5B, 0xB9, 0x03, 0x1D, 0x3B, 0x4A, 0xE9, 0x12, 0xCD, 0x37,
+       0xDE, 0x97, 0xBA, 0xA5, 0x7A, 0xAA, 0xA2, 0xAC, 0xD4, 0x21, 0xD9, 0x44, 0x59, 0xE2, 0x39, 0x41,
+       0x9C, 0xD1, 0xF0, 0x15, 0xEE, 0x7B, 0x04, 0x3B, 0xFC, 0x07, 0xB2, 0xA2, 0x1D, 0xF8, 0x65, 0x2B,
+       0x9E, 0xED, 0x84, 0xAC, 0x0E, 0x24, 0x38, 0x08, 0xB2, 0xB1, 0x5F, 0xE1, 0x9A, 0x65, 0x7D, 0x0F,
+       0xCE, 0xAF, 0x28, 0x37, 0x18, 0x0C, 0xB2, 0x79, 0xF0, 0x1D, 0xFF, 0x91, 0xC1, 0xDC, 0x5F, 0x97,
+       0x37, 0xE7, 0x9D, 0x27, 0x96, 0x63, 0x24, 0xFD, 0x1F, 0x2C, 0xE5, 0x6C, 0x5C, 0xBF, 0x62, 0x3A,
+       0x78, 0x41, 0x18, 0x96, 0xE2, 0xBA, 0x91, 0xF3, 0x6C, 0x87, 0xC3, 0x97, 0x98, 0x5D, 0xD8, 0xB3,
+       0x4B, 0x46, 0xA1, 0x0E, 0xD5, 0x23, 0x1B, 0x2A, 0x0B, 0x51, 0x2F, 0xC6, 0xE8, 0x0A, 0x71, 0xC4,
+       0xC4, 0x6B, 0xCF, 0x85, 0x96, 0x81, 0xEB, 0x6F, 0xE1, 0x0A, 0xD8, 0xD3, 0x26, 0x38, 0x5A, 0xE0,
+       0x5C, 0x5E, 0xBC, 0x1A, 0xFE, 0x15, 0x9E, 0xA4, 0x5C, 0x37, 0x49, 0x36, 0x3C, 0x5C, 0x20, 0x3B,
+       0xA1, 0xBB, 0xF0, 0xB6, 0x94, 0x03, 0x1D, 0xCD, 0x79, 0xF8, 0x91, 0x0A, 0xE3, 0x9B, 0x03, 0x85,
+       0x78, 0x0E, 0x8C, 0xD9, 0x68, 0x06, 0xC6, 0xA1, 0x64, 0x6D, 0x7C, 0xFB, 0x31, 0x3F, 0x13, 0xA1,
+       0x78, 0xC0, 0x65, 0x0D, 0x65, 0xB2, 0xB0, 0x60, 0x40, 0x34, 0x6E, 0xFA, 0x28, 0x7B, 0xA2, 0x57,
+       0x03, 0x30, 0x66, 0xD5, 0x86, 0xF1, 0xA4, 0xF5, 0x96, 0x82, 0xC1, 0xAD, 0x1F, 0x9C, 0xD8, 0x83,
+       0x4A, 0xEA, 0xF5, 0xB3, 0x8C, 0x54, 0xCA, 0x9F, 0x76, 0x08, 0xE7, 0x6E, 0xD8, 0xDF, 0xE2, 0x08,
+       0xD6, 0x96, 0x53, 0xA6, 0x87, 0xA6, 0xB2, 0x67, 0xB0, 0x09, 0x67, 0xEC, 0x3A, 0xBA, 0xBC, 0x20,
+       0x47, 0x90, 0x16, 0xB6, 0x0C, 0x18, 0x5F, 0x70, 0xEB, 0x4B, 0x1C, 0x1D, 0x3C, 0x6D, 0x4C, 0xC7,
+       0x34, 0x6D, 0x6B, 0xC6, 0xBB, 0xF7, 0xF0, 0x4F, 0x46, 0x5D, 0x6B, 0xCB, 0xE2, 0x2D, 0x60, 0x54,
+       0x27, 0x7D, 0x59, 0xF3, 0x72, 0xE2, 0xFF, 0x07, 0xC1, 0x6F, 0x37, 0x3D, 0xAC, 0x38, 0x7A, 0x89,
+       0x6B, 0x99, 0xBD, 0x34, 0x76, 0xF5, 0x52, 0x61, 0x5C, 0x09, 0xD8, 0x49, 0x00, 0xDF, 0x3A, 0x93,
+       0x05, 0xE6, 0x3F, 0x84, 0x7C, 0xE4, 0x8E, 0xF3, 0xF0, 0xF3, 0x17, 0x2C, 0xD5, 0x00, 0x9D, 0x46,
+       0x0C, 0xE2, 0x26, 0x9D, 0xC0, 0x9E, 0xA0, 0x52, 0x13, 0x53, 0x2F, 0xF4, 0x2C, 0x99, 0x11, 0x6D,
+       0x60, 0x6B, 0x2D, 0xDD, 0xF1, 0x7C, 0x53, 0x04, 0x9C, 0xB6, 0x33, 0x2F, 0x8C, 0x6C, 0x19, 0x7C,
+       0x65, 0x16, 0xB3, 0xF6, 0x57, 0x02, 0xE2, 0x0E, 0xCD, 0x22, 0xCF, 0x61, 0x3D, 0x77, 0xAF, 0x44,
+       0x38, 0x8A, 0x33, 0x05, 0xD9, 0xDE, 0xDD, 0xB7, 0x59, 0x6E, 0xCD, 0x69, 0x95, 0xA5, 0x69, 0x9A,
+       0x15, 0x29, 0x6A, 0x67, 0xAB, 0xCB, 0xCF, 0x67, 0xC8, 0x7C, 0x43, 0x2E, 0x9E, 0xF7, 0x2E, 0x0C,
+       0xE4, 0xC5, 0x9F, 0x7C, 0xBF, 0x11, 0x45, 0xF0, 0x64, 0xED, 0x6F, 0xCE, 0x26, 0xD2, 0xDD, 0xCB,
+       0x7C, 0x71, 0x92, 0xF1, 0x7F, 0xF6, 0x16, 0x27, 0xC7, 0x15, 0x6B, 0x26, 0x13, 0x86, 0x68, 0xC3,
+       0x88, 0xA6, 0xEA, 0x2A, 0x0F, 0xA3, 0x89, 0xB2, 0x03, 0x98, 0xB3, 0x3C, 0xF8, 0x40, 0x0B, 0xD8,
+       0x35, 0xC8, 0xDD, 0xCD, 0x9A, 0x10, 0xFD, 0x4D, 0x35, 0x0E, 0x22, 0x5D, 0xA2, 0xCE, 0x35, 0xE4,
+       0xB9, 0xC8, 0x69, 0x70, 0x07, 0xEE, 0xA5, 0x53, 0xC1, 0x05, 0x40, 0x02, 0x05, 0x74, 0x80, 0x5A,
+       0x33, 0x2B, 0x04, 0x7F, 0x77, 0xF1, 0x40, 0xDF, 0x2C, 0xB4, 0xE3, 0xEF, 0x76, 0x63, 0xB0, 0xE5,
+       0x37, 0x2D, 0x4E, 0xD3, 0xF7, 0x4F, 0xA6, 0x12, 0x1C, 0x84, 0x33, 0xBE, 0xBD, 0x06, 0xAF, 0x07,
+       0x5C, 0xB2, 0x4F, 0x39, 0x3D, 0x10, 0x65, 0x24, 0xAF, 0x80, 0xCA, 0x44, 0xCC, 0x32, 0x8B, 0x2B,
+       0x94, 0xA3, 0x75, 0xAE, 0xDE, 0x27, 0x22, 0xF2, 0xF2, 0xA7, 0x4E, 0x0F, 0x90, 0x20, 0x45, 0xC5,
+       0xFA, 0xFE, 0xFE, 0x09, 0xA5, 0xFD, 0x23, 0x06, 0x8A, 0x38, 0x1A, 0xE3, 0x67, 0x84, 0xA9, 0xC6,
+       0x41, 0x61, 0x1F, 0x6C, 0x1E, 0xE4, 0x78, 0x6C, 0x35, 0x52, 0xC8, 0x12, 0xBC, 0x0C, 0xBE, 0x1B,
+       0xAB, 0x9B, 0x2A, 0x64, 0x9D, 0x40, 0x74, 0x1A, 0x89, 0xD1, 0x2B, 0xA6, 0x1F, 0x27, 0x06, 0xDB,
+       0x46, 0x09, 0x5B, 0x49, 0x70, 0xA6, 0x97, 0x8A, 0x55, 0x87, 0x18, 0x38, 0xA4, 0xD6, 0x0A, 0x9F,
+       0xF5, 0x2D, 0xFA, 0x13, 0xF6, 0x27, 0xD8, 0x6E, 0x92, 0x46, 0x49, 0x02, 0xF8, 0x47, 0xD2, 0x5C,
+       0x82, 0x92, 0xA7, 0x31, 0xF5, 0x1A, 0xD9, 0x66, 0xC5, 0x52, 0x6B, 0xD5, 0xD0, 0x74, 0xA4, 0x0B,
+       0x66, 0xFE, 0xF2, 0xE3, 0x08, 0x3C, 0x86, 0x95, 0x54, 0x51, 0x73, 0xAC, 0x1D, 0xA9, 0x8D, 0xA2,
+       0xA5, 0x66, 0xC4, 0x27, 0x5C, 0xB3, 0xA2, 0xB7, 0xDF, 0xEC, 0xD6, 0x15, 0xFF, 0xF7, 0x6C, 0x38,
+       0xF3, 0x32, 0x18, 0xFA, 0x41, 0x32, 0xEE, 0xAC, 0xDD, 0xB3, 0x18, 0xAB, 0x47, 0x66, 0xB6, 0x3C,
+       0x69, 0xB8, 0x88, 0x80, 0x39, 0xDF, 0x54, 0x21, 0x90, 0x09, 0xC4, 0x18, 0x10, 0x18, 0xAE, 0x13,
+       0xF2, 0xFA, 0x31, 0xBF, 0x39, 0x79, 0x03, 0x09, 0x09, 0x09, 0x1D, 0x86, 0xAC, 0xCD, 0x4D, 0xDB,
+       0xA6, 0x86, 0x06, 0x6F, 0x79, 0x1D, 0xE1, 0x7C, 0x8E, 0x39, 0x15, 0xC4, 0x26, 0xB7, 0x45, 0x2B,
+       0xF7, 0x8B, 0xB1, 0x97, 0x8A, 0x69, 0x3A, 0xE2, 0x85, 0xD1, 0x39, 0x57, 0x05, 0xD2, 0x60, 0xC7,
+       0xD7, 0xE4, 0x05, 0xCF, 0xFD, 0x7D, 0xB4, 0x33, 0xAB, 0x48, 0x79, 0x3E, 0x93, 0x29, 0xD8, 0xCC,
+       0xC5, 0x22, 0x7E, 0xA8, 0x9D, 0x76, 0xF8, 0xA5, 0xD1, 0x85, 0x32, 0x71, 0xED, 0x33, 0x4C, 0xD1,
+       0x1B, 0x61, 0x7F, 0x6A, 0x2A, 0x34, 0xF0, 0xE2, 0xC6, 0x08, 0x5E, 0x32, 0x79, 0x06, 0x96, 0x5A,
+       0x03, 0x07, 0xD9, 0x22, 0x3F, 0xE4, 0xEB, 0xD9, 0x7D, 0x0C, 0xAD, 0x63, 0x91, 0x74, 0x86, 0x5C,
+       0xED, 0xD9, 0x8D, 0x23, 0xFE, 0xCC, 0x0A, 0xE8, 0xA0, 0xC6, 0xF4, 0x7D, 0x08, 0xC3, 0x5E, 0x11,
+       0x5D, 0x56, 0x64, 0x73, 0x25, 0xE7, 0x10, 0xE5, 0x9B, 0xB1, 0xE7, 0xDC, 0xD4, 0xC5, 0x3B, 0xA4,
+       0x20, 0x12, 0x05, 0x19, 0x04, 0x3F, 0x03, 0x1E, 0x05, 0x20, 0xB1, 0x08, 0x0B, 0x19, 0x19, 0x00,
+       0x00, 0x00, 0x05, 0x80, 0x07, 0x03, 0x1A, 0x1E, 0x05, 0x2D, 0xEB, 0x0F, 0x92, 0x09, 0x01, 0x36,
+       0x30, 0x00, 0x30, 0x00, 0xDD, 0x48, 0xB0, 0x42, 0xAD, 0xEB, 0x3D, 0xE7, 0x00, 0xA0, 0x1D, 0x1D,
+       0x1D, 0x1D, 0x0A, 0x04, 0xC0, 0x5C, 0x17, 0x1A, 0x5A, 0xF4, 0x06, 0x19, 0x00, 0x00, 0x0A, 0x00,
+       0x08, 0xA1, 0x00, 0x38, 0x03, 0x01, 0xEF, 0x1A, 0x10, 0x00, 0x02, 0x0B, 0x01, 0x80, 0x02, 0x0E,
+       0x1F, 0x16, 0x2B, 0x00, 0x19, 0x04, 0x00, 0x00, 0x10, 0x0A, 0x00, 0x14, 0x11, 0x12, 0x10, 0x0F,
+       0x0E, 0x0A, 0x09, 0x07, 0x08, 0x01, 0x18, 0x19, 0x1B, 0x1A, 0x15, 0x16, 0x17, 0x0D, 0x0C, 0x06,
+       0x05, 0x0B, 0x04, 0x03, 0x02, 0x00, 0x0B, 0x13, 0x0C, 0x05, 0x0A, 0x02, 0x04, 0x06, 0x08, 0x01,
+       0x0D, 0x07, 0x0E, 0x10, 0x0F, 0x12, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x2A, 0x2A,
+       0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x00, 0xFF,
+       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xC0, 0x80, 0x00, 0x18,
+       0x00, 0x18, 0x00, 0x10, 0x00, 0x10, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+       0x80, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x20, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20,
+       0x20, 0x51, 0x7E, 0x56, 0x58, 0x5A, 0x5C, 0x5E, 0x60, 0x00, 0xFF, 0xFF, 0x10, 0x0A, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x0C, 0x00, 0x04, 0x00, 0x0D,
+       0x00, 0x10, 0x00, 0xA2, 0xB7, 0xAD, 0xAD, 0xCD, 0x0D, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0x49, 0xC7, 0xF3,
+       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x3F, 0x03, 0x1E,
+       0x05, 0x20, 0xB1, 0x08, 0x0B, 0x19, 0x19, 0x00, 0x00, 0x4C, 0x04, 0x6C, 0x07, 0x02, 0x14, 0x1E,
+       0x05, 0x28, 0xF5, 0x28, 0x1E, 0x05, 0x01, 0x3C, 0x30, 0x00, 0x30, 0x00, 0x00, 0x48, 0x00, 0x48,
+       0xF0, 0xD2, 0xF0, 0xD2, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x04, 0xC0, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x19, 0x01, 0x00, 0x0A, 0x00, 0x08, 0xA2, 0x02, 0x32, 0x0A, 0x0A, 0x96, 0x1B,
+       0x10, 0x00, 0x00, 0x56, 0x35, 0x05, 0x10, 0x00, 0x00, 0x0B, 0x20, 0x00, 0x01, 0xE0, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x33, 0x32, 0x30, 0x32, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x01, 0x02, 0x0F, 0x05, 0x00, 0x38, 0x15, 0x10, 0x1B, 0x2B, 0xC0, 0xD1, 0xFF, 0x0C, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xA2, 0x63,
+       0x15, 0x21, 0x11, 0xAC, 0xA1, 0x5C, 0x13, 0x01, 0x01, 0xA3, 0x00, 0x58, 0x00, 0x01, 0x34, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xF4, 0x01, 0x80,
+       0x03, 0x0E, 0x1F, 0x00, 0xDB, 0x01, 0x19, 0x04, 0x00, 0x00, 0x10, 0x0A, 0x00, 0x00, 0x01, 0x02,
+       0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
+       0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x01, 0x02, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0A,
+       0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x12, 0x13, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xC0, 0x80,
+       0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+       0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+       0x80, 0x80, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x10, 0x0A,
+       0x00, 0x00, 0x00, 0x1B, 0x10, 0x44, 0x88, 0x13, 0x01, 0x01, 0xBF, 0x01, 0x7E, 0x3D, 0x00, 0x00,
+       0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB3, 0xB2, 0x0B, 0x00, 0x01, 0x54, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
diff --git a/drivers/input/touchscreen/rmi4/rmi_spi.c b/drivers/input/touchscreen/rmi4/rmi_spi.c
new file mode 100755 (executable)
index 0000000..a19e49a
--- /dev/null
@@ -0,0 +1,909 @@
+/*
+ * Copyright (c) 2011 Synaptics Incorporated
+ * Copyright (c) 2011 Unixphere
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/gpio.h>
+#include <linux/rmi.h>
+
+#define COMMS_DEBUG 0
+#define FF_DEBUG 0
+
+#define RMI_PROTOCOL_VERSION_ADDRESS   0xa0fd
+#define SPI_V2_UNIFIED_READ            0xc0
+#define SPI_V2_WRITE                   0x40
+#define SPI_V2_PREPARE_SPLIT_READ      0xc8
+#define SPI_V2_EXECUTE_SPLIT_READ      0xca
+
+#define RMI_SPI_BLOCK_DELAY_US         65
+#define RMI_SPI_BYTE_DELAY_US          65
+#define RMI_SPI_WRITE_DELAY_US         0
+
+#define RMI_V1_READ_FLAG               0x80
+
+#define RMI_PAGE_SELECT_REGISTER 0x00FF
+#define RMI_SPI_PAGE(addr) (((addr) >> 8) & 0x80)
+
+#define DEFAULT_POLL_INTERVAL_MS       13
+
+static char *spi_v1_proto_name = "spi";
+static char *spi_v2_proto_name = "spiv2";
+
+struct rmi_spi_data {
+       struct mutex page_mutex;
+       int page;
+       int (*set_page) (struct rmi_phys_device *phys, u8 page);
+       bool split_read_pending;
+       int enabled;
+       int irq;
+       int irq_flags;
+       struct rmi_phys_device *phys;
+       struct completion irq_comp;
+
+       /* Following are used when polling. */
+       struct hrtimer poll_timer;
+       struct work_struct poll_work;
+       int poll_interval;
+
+};
+
+static irqreturn_t rmi_spi_hard_irq(int irq, void *p)
+{
+       struct rmi_phys_device *phys = p;
+       struct rmi_spi_data *data = phys->data;
+       struct rmi_device_platform_data *pdata = phys->dev->platform_data;
+
+       if (data->split_read_pending &&
+                     gpio_get_value(pdata->attn_gpio) ==
+                     pdata->attn_polarity) {
+               phys->info.attn_count++;
+               complete(&data->irq_comp);
+               return IRQ_HANDLED;
+       }
+
+       return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t rmi_spi_irq_thread(int irq, void *p)
+{
+       struct rmi_phys_device *phys = p;
+       struct rmi_device *rmi_dev = phys->rmi_dev;
+       struct rmi_driver *driver = rmi_dev->driver;
+       struct rmi_device_platform_data *pdata = phys->dev->platform_data;
+
+       if (gpio_get_value(pdata->attn_gpio) == pdata->attn_polarity) {
+               phys->info.attn_count++;
+               if (driver && driver->irq_handler)
+                       driver->irq_handler(rmi_dev, irq);
+       }
+
+       return IRQ_HANDLED;
+}
+
+static void spi_poll_work(struct work_struct *work)
+{
+       struct rmi_spi_data *data =
+                       container_of(work, struct rmi_spi_data, poll_work);
+       struct rmi_device *rmi_dev = data->phys->rmi_dev;
+       struct rmi_driver *driver = rmi_dev->driver;
+
+       if (driver && driver->irq_handler)
+               driver->irq_handler(rmi_dev, 0);
+}
+
+/* This is the timer function for polling - it simply has to schedule work
+ * and restart the timer. */
+static enum hrtimer_restart spi_poll_timer(struct hrtimer *timer)
+{
+       struct rmi_spi_data *data =
+                       container_of(timer, struct rmi_spi_data, poll_timer);
+
+       if (!work_pending(&data->poll_work))
+               schedule_work(&data->poll_work);
+       hrtimer_start(&data->poll_timer, ktime_set(0, data->poll_interval),
+                     HRTIMER_MODE_REL);
+       return HRTIMER_NORESTART;
+}
+
+
+
+static int rmi_spi_xfer(struct rmi_phys_device *phys,
+                   const u8 *txbuf, unsigned n_tx, u8 *rxbuf, unsigned n_rx)
+{
+       struct spi_device *client = to_spi_device(phys->dev);
+       struct rmi_spi_data *v2_data = phys->data;
+       struct rmi_device_platform_data *pdata = phys->dev->platform_data;
+       int status;
+       struct spi_message message;
+       struct spi_transfer *xfers;
+       int total_bytes = n_tx + n_rx;
+       u8 local_buf[total_bytes];
+       int xfer_count = 0;
+       int xfer_index = 0;
+       int block_delay = n_rx > 0 ? pdata->spi_data.block_delay_us : 0;
+       int byte_delay = n_rx > 1 ? pdata->spi_data.read_delay_us : 0;
+       int write_delay = n_tx > 1 ? pdata->spi_data.write_delay_us : 0;
+#if FF_DEBUG
+       bool bad_data = true;
+#endif
+#if COMMS_DEBUG || FF_DEBUG
+       int i;
+#endif
+
+       if (v2_data->split_read_pending) {
+               block_delay =
+                   n_rx > 0 ? pdata->spi_data.split_read_block_delay_us : 0;
+               byte_delay =
+                   n_rx > 1 ? pdata->spi_data.split_read_byte_delay_us : 0;
+               write_delay = 0;
+       }
+
+       if (n_tx) {
+               phys->info.tx_count++;
+               phys->info.tx_bytes += n_tx;
+               if (write_delay)
+                       xfer_count += n_tx;
+               else
+                       xfer_count += 1;
+       }
+
+       if (n_rx) {
+               phys->info.rx_count++;
+               phys->info.rx_bytes += n_rx;
+               if (byte_delay)
+                       xfer_count += n_rx;
+               else
+                       xfer_count += 1;
+       }
+
+       xfers = kcalloc(xfer_count,
+                           sizeof(struct spi_transfer), GFP_KERNEL);
+       if (!xfers)
+               return -ENOMEM;
+
+       spi_message_init(&message);
+
+       if (n_tx) {
+               if (write_delay) {
+                       for (xfer_index = 0; xfer_index < n_tx;
+                                       xfer_index++) {
+                               memset(&xfers[xfer_index], 0,
+                                      sizeof(struct spi_transfer));
+                               xfers[xfer_index].len = 1;
+                               xfers[xfer_index].delay_usecs = write_delay;
+                               xfers[xfer_index].tx_buf = txbuf + xfer_index;
+                               spi_message_add_tail(&xfers[xfer_index],
+                                                    &message);
+                       }
+               } else {
+                       memset(&xfers[0], 0, sizeof(struct spi_transfer));
+                       xfers[0].len = n_tx;
+                       spi_message_add_tail(&xfers[0], &message);
+                       memcpy(local_buf, txbuf, n_tx);
+                       xfers[0].tx_buf = local_buf;
+                       xfer_index++;
+               }
+               if (block_delay)
+                       xfers[xfer_index-1].delay_usecs = block_delay;
+       }
+       if (n_rx) {
+               if (byte_delay) {
+                       int buffer_offset = n_tx;
+                       for (; xfer_index < xfer_count; xfer_index++) {
+                               memset(&xfers[xfer_index], 0,
+                                      sizeof(struct spi_transfer));
+                               xfers[xfer_index].len = 1;
+                               xfers[xfer_index].delay_usecs = byte_delay;
+                               xfers[xfer_index].rx_buf =
+                                   local_buf + buffer_offset;
+                               buffer_offset++;
+                               spi_message_add_tail(&xfers[xfer_index],
+                                                    &message);
+                       }
+               } else {
+                       memset(&xfers[xfer_index], 0,
+                              sizeof(struct spi_transfer));
+                       xfers[xfer_index].len = n_rx;
+                       xfers[xfer_index].rx_buf = local_buf + n_tx;
+                       spi_message_add_tail(&xfers[xfer_index], &message);
+                       xfer_index++;
+               }
+       }
+
+#if COMMS_DEBUG
+       if (n_tx) {
+               dev_dbg(&client->dev, "SPI sends %d bytes: ", n_tx);
+               for (i = 0; i < n_tx; i++)
+                       pr_info("%02X ", txbuf[i]);
+               pr_info("\n");
+       }
+#endif
+
+       /* do the i/o */
+       if (pdata->spi_data.cs_assert) {
+               status = pdata->spi_data.cs_assert(
+                       pdata->spi_data.cs_assert_data, true);
+               if (status) {
+                       dev_err(phys->dev, "Failed to assert CS, code %d.\n",
+                               status);
+                       /* nonzero means error */
+                       status = -1;
+                       goto error_exit;
+               } else
+                       status = 0;
+       }
+
+       if (pdata->spi_data.pre_delay_us)
+               udelay(pdata->spi_data.pre_delay_us);
+
+       status = spi_sync(client, &message);
+
+       if (pdata->spi_data.post_delay_us)
+               udelay(pdata->spi_data.post_delay_us);
+
+       if (pdata->spi_data.cs_assert) {
+               status = pdata->spi_data.cs_assert(
+                       pdata->spi_data.cs_assert_data, false);
+               if (status) {
+                       dev_err(phys->dev, "Failed to deassert CS. code %d.\n",
+                               status);
+                       /* nonzero means error */
+                       status = -1;
+                       goto error_exit;
+               } else
+                       status = 0;
+       }
+
+       if (status == 0) {
+               memcpy(rxbuf, local_buf + n_tx, n_rx);
+               status = message.status;
+       } else {
+               if (n_tx) phys->info.tx_errs++;
+               if (n_rx) phys->info.rx_errs++;
+               dev_err(phys->dev, "spi_sync failed with error code %d.",
+                      status);
+               goto error_exit;
+       }
+
+#if COMMS_DEBUG
+       if (n_rx) {
+               dev_dbg(&client->dev, "SPI received %d bytes: ", n_rx);
+               for (i = 0; i < n_rx; i++)
+                       pr_info("%02X ", rxbuf[i]);
+               pr_info("\n");
+       }
+#endif
+#if FF_DEBUG
+       if (n_rx) {
+               for (i = 0; i < n_rx; i++) {
+                       if (rxbuf[i] != 0xFF) {
+                               bad_data = false;
+                               break;
+                       }
+               }
+               if (bad_data) {
+                       phys->info.rx_errs++;
+                       dev_err(phys->dev, "BAD READ %lu out of %lu.\n",
+                               phys->info.rx_errs, phys->info.rx_count);
+               }
+       }
+#endif
+
+error_exit:
+       kfree(xfers);
+       return status;
+}
+
+static int rmi_spi_v2_write_block(struct rmi_phys_device *phys, u16 addr,
+                                 u8 *buf, int len)
+{
+       struct rmi_spi_data *data = phys->data;
+       u8 txbuf[len + 4];
+       int error;
+
+       txbuf[0] = SPI_V2_WRITE;
+       txbuf[1] = (addr >> 8) & 0x00FF;
+       txbuf[2] = addr & 0x00FF;
+       txbuf[3] = len;
+
+       memcpy(&txbuf[4], buf, len);
+
+       mutex_lock(&data->page_mutex);
+
+       if (RMI_SPI_PAGE(addr) != data->page) {
+               error = data->set_page(phys, RMI_SPI_PAGE(addr));
+               if (error < 0)
+                       goto exit;
+       }
+
+       error = rmi_spi_xfer(phys, buf, len + 4, NULL, 0);
+       if (error < 0)
+               goto exit;
+       error = len;
+
+exit:
+       mutex_unlock(&data->page_mutex);
+       return error;
+}
+
+static int rmi_spi_v2_write(struct rmi_phys_device *phys, u16 addr, u8 data)
+{
+       int error = rmi_spi_v2_write_block(phys, addr, &data, 1);
+
+       return (error == 1) ? 0 : error;
+}
+
+static int rmi_spi_v1_write_block(struct rmi_phys_device *phys, u16 addr,
+                                 u8 *buf, int len)
+{
+       struct rmi_spi_data *data = phys->data;
+       unsigned char txbuf[len + 2];
+       int error;
+
+       txbuf[0] = (addr >> 8) & ~RMI_V1_READ_FLAG;
+       txbuf[1] = addr;
+       memcpy(txbuf+2, buf, len);
+
+       mutex_lock(&data->page_mutex);
+
+       if (RMI_SPI_PAGE(addr) != data->page) {
+               error = data->set_page(phys, RMI_SPI_PAGE(addr));
+               if (error < 0)
+                       goto exit;
+       }
+
+       error = rmi_spi_xfer(phys, txbuf, len + 2, NULL, 0);
+       if (error < 0)
+               goto exit;
+       error = len;
+
+exit:
+       mutex_unlock(&data->page_mutex);
+       return error;
+}
+
+static int rmi_spi_v1_write(struct rmi_phys_device *phys, u16 addr, u8 data)
+{
+       int error = rmi_spi_v1_write_block(phys, addr, &data, 1);
+
+       return (error == 1) ? 0 : error;
+}
+
+static int rmi_spi_v2_split_read_block(struct rmi_phys_device *phys, u16 addr,
+                                      u8 *buf, int len)
+{
+       struct rmi_spi_data *data = phys->data;
+       u8 txbuf[4];
+       u8 rxbuf[len + 1]; /* one extra byte for read length */
+       int error;
+
+       txbuf[0] = SPI_V2_PREPARE_SPLIT_READ;
+       txbuf[1] = (addr >> 8) & 0x00FF;
+       txbuf[2] = addr & 0x00ff;
+       txbuf[3] = len;
+
+       mutex_lock(&data->page_mutex);
+
+       if (RMI_SPI_PAGE(addr) != data->page) {
+               error = data->set_page(phys, RMI_SPI_PAGE(addr));
+               if (error < 0)
+                       goto exit;
+       }
+
+       data->split_read_pending = true;
+
+       error = rmi_spi_xfer(phys, txbuf, 4, NULL, 0);
+       if (error < 0) {
+               data->split_read_pending = false;
+               goto exit;
+       }
+
+       wait_for_completion(&data->irq_comp);
+
+       txbuf[0] = SPI_V2_EXECUTE_SPLIT_READ;
+       txbuf[1] = 0;
+
+       error = rmi_spi_xfer(phys, txbuf, 2, rxbuf, len + 1);
+       data->split_read_pending = false;
+       if (error < 0)
+               goto exit;
+
+       /* first byte is length */
+       if (rxbuf[0] != len) {
+               error = -EIO;
+               goto exit;
+       }
+
+       memcpy(buf, rxbuf + 1, len);
+       error = len;
+
+exit:
+       mutex_unlock(&data->page_mutex);
+       return error;
+}
+
+static int rmi_spi_v2_read_block(struct rmi_phys_device *phys, u16 addr,
+                                u8 *buf, int len)
+{
+       struct rmi_spi_data *data = phys->data;
+       u8 txbuf[4];
+       int error;
+
+       txbuf[0] = SPI_V2_UNIFIED_READ;
+       txbuf[1] = (addr >> 8) & 0x00FF;
+       txbuf[2] = addr & 0x00ff;
+       txbuf[3] = len;
+
+       mutex_lock(&data->page_mutex);
+
+       if (RMI_SPI_PAGE(addr) != data->page) {
+               error = data->set_page(phys, RMI_SPI_PAGE(addr));
+               if (error < 0)
+                       goto exit;
+       }
+
+       error = rmi_spi_xfer(phys, txbuf, 4, buf, len);
+       if (error < 0)
+               goto exit;
+       error = len;
+
+exit:
+       mutex_unlock(&data->page_mutex);
+       return error;
+}
+
+static int rmi_spi_v2_read(struct rmi_phys_device *phys, u16 addr, u8 *buf)
+{
+       int error = rmi_spi_v2_read_block(phys, addr, buf, 1);
+
+       return (error == 1) ? 0 : error;
+}
+
+static int rmi_spi_v1_read_block(struct rmi_phys_device *phys, u16 addr,
+                                u8 *buf, int len)
+{
+       struct rmi_spi_data *data = phys->data;
+       u8 txbuf[2];
+       int error;
+
+       txbuf[0] = (addr >> 8) | RMI_V1_READ_FLAG;
+       txbuf[1] = addr;
+
+       mutex_lock(&data->page_mutex);
+
+       if (RMI_SPI_PAGE(addr) != data->page) {
+               error = data->set_page(phys, RMI_SPI_PAGE(addr));
+               if (error < 0)
+                       goto exit;
+       }
+
+       error = rmi_spi_xfer(phys, txbuf, 2, buf, len);
+       if (error < 0)
+               goto exit;
+       error = len;
+
+exit:
+       mutex_unlock(&data->page_mutex);
+       return error;
+}
+
+static int rmi_spi_v1_read(struct rmi_phys_device *phys, u16 addr, u8 *buf)
+{
+       int error = rmi_spi_v1_read_block(phys, addr, buf, 1);
+
+       return (error == 1) ? 0 : error;
+}
+
+#define RMI_SPI_PAGE_SELECT_WRITE_LENGTH 1
+
+static int rmi_spi_v1_set_page(struct rmi_phys_device *phys, u8 page)
+{
+       struct rmi_spi_data *data = phys->data;
+       u8 txbuf[] = {RMI_PAGE_SELECT_REGISTER >> 8,
+               RMI_PAGE_SELECT_REGISTER & 0xFF, page};
+       int error;
+
+       error = rmi_spi_xfer(phys, txbuf, sizeof(txbuf), NULL, 0);
+       if (error < 0) {
+               dev_err(phys->dev, "Failed to set page select, code: %d.\n",
+                       error);
+               return error;
+       }
+
+       data->page = page;
+
+       return RMI_SPI_PAGE_SELECT_WRITE_LENGTH;
+}
+
+static int rmi_spi_v2_set_page(struct rmi_phys_device *phys, u8 page)
+{
+       struct rmi_spi_data *data = phys->data;
+       u8 txbuf[] = {SPI_V2_WRITE, RMI_PAGE_SELECT_REGISTER >> 8,
+               RMI_PAGE_SELECT_REGISTER & 0xFF,
+               RMI_SPI_PAGE_SELECT_WRITE_LENGTH, page};
+       int error;
+
+       error = rmi_spi_xfer(phys, txbuf, sizeof(txbuf), NULL, 0);
+       if (error < 0) {
+               dev_err(phys->dev, "Failed to set page select, code: %d.\n",
+                       error);
+               return error;
+       }
+
+       data->page = page;
+
+       return RMI_SPI_PAGE_SELECT_WRITE_LENGTH;
+}
+
+
+static int acquire_attn_irq(struct rmi_spi_data *data)
+{
+       int retval;
+       struct rmi_phys_device *rmi_phys = data->phys;
+
+       retval = request_threaded_irq(data->irq, rmi_spi_hard_irq,
+                               rmi_spi_irq_thread, data->irq_flags,
+                               dev_name(rmi_phys->dev), rmi_phys);
+       if (retval < 0) {
+               dev_err(&(rmi_phys->rmi_dev->dev), "request_threaded_irq "
+                       "failed, code: %d.\n", retval);
+       }
+       return retval;
+}
+
+static int setup_attn(struct rmi_spi_data *data)
+{
+       int retval;
+       struct rmi_phys_device *rmi_phys = data->phys;
+       struct rmi_device_platform_data *pdata = rmi_phys->dev->platform_data;
+
+       retval = acquire_attn_irq(data);
+       if (retval < 0)
+               return retval;
+
+#if defined(CONFIG_RMI4_DEV)
+       retval = gpio_export(pdata->attn_gpio, false);
+       if (retval) {
+               dev_warn(&(rmi_phys->rmi_dev->dev),
+                        "WARNING: Failed to export ATTN gpio!\n");
+               retval = 0;
+       } else {
+               retval = gpio_export_link(&(rmi_phys->rmi_dev->dev), "attn",
+                                       pdata->attn_gpio);
+               if (retval) {
+                       dev_warn(&(rmi_phys->rmi_dev->dev), "WARNING: "
+                               "Failed to symlink ATTN gpio!\n");
+                       retval = 0;
+               } else {
+                       dev_info(&(rmi_phys->rmi_dev->dev),
+                               "%s: Exported GPIO %d.", __func__,
+                               pdata->attn_gpio);
+               }
+       }
+#endif /* CONFIG_RMI4_DEV */
+
+       return retval;
+}
+
+static int setup_polling(struct rmi_spi_data *data)
+{
+       INIT_WORK(&data->poll_work, spi_poll_work);
+       hrtimer_init(&data->poll_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       data->poll_timer.function = spi_poll_timer;
+       hrtimer_start(&data->poll_timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+
+       return 0;
+}
+
+static int enable_device(struct rmi_phys_device *phys)
+{
+       int retval = 0;
+
+       struct rmi_spi_data *data = phys->data;
+
+       if (data->enabled) {
+               dev_dbg(phys->dev, "Physical device already enabled.\n");
+               return 0;
+       }
+
+       retval = acquire_attn_irq(data);
+       if (retval)
+               goto error_exit;
+
+       data->enabled = true;
+       dev_dbg(phys->dev, "Physical device enabled.\n");
+       return 0;
+
+error_exit:
+       dev_err(phys->dev, "Failed to enable physical device. Code=%d.\n",
+               retval);
+       return retval;
+}
+
+static void disable_device(struct rmi_phys_device *phys)
+{
+       struct rmi_spi_data *data = phys->data;
+
+       if (!data->enabled) {
+               dev_warn(phys->dev, "Physical device already disabled.\n");
+               return;
+       }
+       disable_irq(data->irq);
+       free_irq(data->irq, data->phys);
+
+       dev_dbg(phys->dev, "Physical device disabled.\n");
+       data->enabled = false;
+}
+
+#define DUMMY_READ_SLEEP_US 10
+
+static int rmi_spi_check_device(struct rmi_phys_device *rmi_phys)
+{
+       u8 buf[6];
+       int error;
+       int i;
+
+       /* Some SPI subsystems return 0 for the very first read you do.  So
+        * we use this dummy read to get that out of the way.
+        */
+       error = rmi_spi_v1_read_block(rmi_phys, PDT_START_SCAN_LOCATION,
+                                     buf, sizeof(buf));
+       if (error < 0) {
+               dev_err(rmi_phys->dev, "dummy read failed with %d.\n", error);
+               return error;
+       }
+       udelay(DUMMY_READ_SLEEP_US);
+
+       /* Force page select to 0.
+        */
+       error = rmi_spi_v1_set_page(rmi_phys, 0x00);
+       if (error < 0)
+               return error;
+
+       /* Now read the first PDT entry.  We know where this is, and if the
+        * RMI4 device is out there, these 6 bytes will be something other
+        * than all 0x00 or 0xFF.  We need to check for 0x00 and 0xFF,
+        * because many (maybe all) SPI implementations will return all 0x00
+        * or all 0xFF on read if the device is not connected.
+        */
+       error = rmi_spi_v1_read_block(rmi_phys, PDT_START_SCAN_LOCATION,
+                                     buf, sizeof(buf));
+       if (error < 0) {
+               dev_err(rmi_phys->dev, "probe read failed with %d.\n", error);
+               return error;
+       }
+       for (i = 0; i < sizeof(buf); i++) {
+               if (buf[i] != 0x00 && buf[i] != 0xFF)
+                       return error;
+       }
+
+       dev_err(rmi_phys->dev, "probe read returned invalid block.\n");
+       return -ENODEV;
+}
+
+
+static int __devinit rmi_spi_probe(struct spi_device *spi)
+{
+       struct rmi_phys_device *rmi_phys;
+       struct rmi_spi_data *data;
+       struct rmi_device_platform_data *pdata = spi->dev.platform_data;
+       u8 buf[2];
+       int retval;
+
+       if (!pdata) {
+               dev_err(&spi->dev, "no platform data\n");
+               return -EINVAL;
+       }
+
+       if (spi->master->flags & SPI_MASTER_HALF_DUPLEX)
+               return -EINVAL;
+
+       spi->bits_per_word = 8;
+       spi->mode = SPI_MODE_3;
+       retval = spi_setup(spi);
+       if (retval < 0) {
+               dev_err(&spi->dev, "spi_setup failed!\n");
+               return retval;
+       }
+
+       rmi_phys = kzalloc(sizeof(struct rmi_phys_device), GFP_KERNEL);
+       if (!rmi_phys)
+               return -ENOMEM;
+
+       data = kzalloc(sizeof(struct rmi_spi_data), GFP_KERNEL);
+       if (!data) {
+               retval = -ENOMEM;
+               goto err_phys;
+       }
+       data->enabled = true;   /* We plan to come up enabled. */
+       data->irq = gpio_to_irq(pdata->attn_gpio);
+       if (pdata->level_triggered) {
+               data->irq_flags = IRQF_ONESHOT |
+                       ((pdata->attn_polarity == RMI_ATTN_ACTIVE_HIGH) ?
+                       IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW);
+       } else {
+               data->irq_flags =
+                       (pdata->attn_polarity == RMI_ATTN_ACTIVE_HIGH) ?
+                       IRQF_TRIGGER_RISING : IRQF_TRIGGER_FALLING;
+       }
+       data->phys = rmi_phys;
+
+       rmi_phys->data = data;
+       rmi_phys->dev = &spi->dev;
+
+       rmi_phys->write = rmi_spi_v1_write;
+       rmi_phys->write_block = rmi_spi_v1_write_block;
+       rmi_phys->read = rmi_spi_v1_read;
+       rmi_phys->read_block = rmi_spi_v1_read_block;
+       rmi_phys->enable_device = enable_device;
+       rmi_phys->disable_device = disable_device;
+       data->set_page = rmi_spi_v1_set_page;
+
+       rmi_phys->info.proto = spi_v1_proto_name;
+
+       mutex_init(&data->page_mutex);
+
+       dev_set_drvdata(&spi->dev, rmi_phys);
+
+       pdata->spi_data.block_delay_us = pdata->spi_data.block_delay_us ?
+                       pdata->spi_data.block_delay_us : RMI_SPI_BLOCK_DELAY_US;
+       pdata->spi_data.read_delay_us = pdata->spi_data.read_delay_us ?
+                       pdata->spi_data.read_delay_us : RMI_SPI_BYTE_DELAY_US;
+       pdata->spi_data.write_delay_us = pdata->spi_data.write_delay_us ?
+                       pdata->spi_data.write_delay_us : RMI_SPI_BYTE_DELAY_US;
+       pdata->spi_data.split_read_block_delay_us =
+                       pdata->spi_data.split_read_block_delay_us ?
+                       pdata->spi_data.split_read_block_delay_us :
+                       RMI_SPI_BLOCK_DELAY_US;
+       pdata->spi_data.split_read_byte_delay_us =
+                       pdata->spi_data.split_read_byte_delay_us ?
+                       pdata->spi_data.split_read_byte_delay_us :
+                       RMI_SPI_BYTE_DELAY_US;
+
+       if (pdata->gpio_config) {
+               retval = pdata->gpio_config(pdata->gpio_data, true);
+               if (retval < 0) {
+                       dev_err(&spi->dev, "Failed to setup GPIOs, code: %d.\n",
+                               retval);
+                       goto err_data;
+               }
+       }
+
+       retval = rmi_spi_check_device(rmi_phys);
+       if (retval < 0)
+               goto err_gpio;
+
+       /* check if this is an SPI v2 device */
+       retval = rmi_spi_v1_read_block(rmi_phys, RMI_PROTOCOL_VERSION_ADDRESS,
+                                     buf, 2);
+       if (retval < 0) {
+               dev_err(&spi->dev, "failed to get SPI version number!\n");
+               goto err_gpio;
+       }
+       dev_dbg(&spi->dev, "SPI version is %d", buf[0]);
+
+       if (buf[0] == 1) {
+               /* SPIv2 */
+               rmi_phys->write         = rmi_spi_v2_write;
+               rmi_phys->write_block   = rmi_spi_v2_write_block;
+               rmi_phys->read          = rmi_spi_v2_read;
+               data->set_page          = rmi_spi_v2_set_page;
+
+               rmi_phys->info.proto = spi_v2_proto_name;
+
+               if (pdata->attn_gpio > 0) {
+                       init_completion(&data->irq_comp);
+                       rmi_phys->read_block = rmi_spi_v2_split_read_block;
+               } else {
+                       dev_warn(&spi->dev, "WARNING: SPI V2 detected, but no "
+                               "attention GPIO was specified. This is unlikely"
+                               " to work well.\n");
+                       rmi_phys->read_block = rmi_spi_v2_read_block;
+               }
+       } else if (buf[0] != 0) {
+               dev_err(&spi->dev, "Unrecognized SPI version %d.\n", buf[0]);
+               retval = -ENODEV;
+               goto err_gpio;
+       }
+
+       retval = rmi_register_phys_device(rmi_phys);
+       if (retval) {
+               dev_err(&spi->dev, "failed to register physical driver\n");
+               goto err_gpio;
+       }
+
+       if (pdata->attn_gpio > 0) {
+               retval = setup_attn(data);
+               if (retval < 0)
+                       goto err_unregister;
+       } else {
+               retval = setup_polling(data);
+               if (retval < 0)
+                       goto err_unregister;
+       }
+
+       dev_info(&spi->dev, "registered RMI SPI driver\n");
+       return 0;
+
+err_unregister:
+       rmi_unregister_phys_device(rmi_phys);
+err_gpio:
+       if (pdata->gpio_config)
+               pdata->gpio_config(pdata->gpio_data, false);
+err_data:
+       kfree(data);
+err_phys:
+       kfree(rmi_phys);
+       return retval;
+}
+
+static int __devexit rmi_spi_remove(struct spi_device *spi)
+{
+       struct rmi_phys_device *phys = dev_get_drvdata(&spi->dev);
+       struct rmi_device_platform_data *pd = spi->dev.platform_data;
+
+       disable_device(phys);
+       rmi_unregister_phys_device(phys);
+       kfree(phys->data);
+       kfree(phys);
+
+       if (pd->gpio_config)
+               pd->gpio_config(pdata->gpio_data, false);
+
+       return 0;
+}
+
+static const struct spi_device_id rmi_id[] = {
+       { "rmi", 0 },
+       { "rmi_spi", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, rmi_id);
+
+static struct spi_driver rmi_spi_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "rmi_spi",
+       },
+       .id_table       = rmi_id,
+       .probe          = rmi_spi_probe,
+       .remove         = __devexit_p(rmi_spi_remove),
+};
+
+static int __init rmi_spi_init(void)
+{
+       return spi_register_driver(&rmi_spi_driver);
+}
+
+static void __exit rmi_spi_exit(void)
+{
+       spi_unregister_driver(&rmi_spi_driver);
+}
+
+module_init(rmi_spi_init);
+module_exit(rmi_spi_exit);
+
+MODULE_AUTHOR("Christopher Heiny <cheiny@synaptics.com>");
+MODULE_DESCRIPTION("RMI SPI driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(RMI_DRIVER_VERSION);
\ No newline at end of file
diff --git a/include/linux/rmi.h b/include/linux/rmi.h
new file mode 100755 (executable)
index 0000000..354eea9
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ * Copyright (c) 2011 Synaptics Incorporated
+ * Copyright (c) 2011 Unixphere
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _RMI_H
+#define _RMI_H
+#include <linux/kernel.h>
+#include <linux/lockdep.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include <linux/stat.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/interrupt.h>
+
+#ifdef CONFIG_RMI_DEBUG
+#include <linux/debugfs.h>
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+
+/* Permissions for sysfs attributes.  Since the permissions policy will change
+ * on a global basis in the future, rather than edit all sysfs attrs everywhere
+ * in the driver (and risk screwing that up in the process), we use this handy
+ * set of #defines.  That way when we change the policy for sysfs permissions,
+ * we only need to change them here.
+ */
+#define RMI_RO_ATTR S_IRUGO
+#define RMI_RW_ATTR (S_IRUGO | S_IWUGO)
+#define RMI_WO_ATTR S_IWUGO
+
+#define PDT_START_SCAN_LOCATION 0x00e9
+
+enum rmi_attn_polarity {
+       RMI_ATTN_ACTIVE_LOW = 0,
+       RMI_ATTN_ACTIVE_HIGH = 1
+};
+
+/**
+ * struct rmi_f11_axis_alignment - target axis alignment
+ * @swap_axes: set to TRUE if desired to swap x- and y-axis
+ * @flip_x: set to TRUE if desired to flip direction on x-axis
+ * @flip_y: set to TRUE if desired to flip direction on y-axis
+ */
+struct rmi_f11_2d_axis_alignment {
+       bool swap_axes;
+       bool flip_x;
+       bool flip_y;
+       int clip_X_low;
+       int clip_Y_low;
+       int clip_X_high;
+       int clip_Y_high;
+       int offset_X;
+       int offset_Y;
+       int rel_report_enabled;
+};
+
+/**
+ * struct rmi_f01_power - override default power management settings.
+ *
+ */
+enum rmi_f01_nosleep {
+       RMI_F01_NOSLEEP_DEFAULT = 0,
+       RMI_F01_NOSLEEP_OFF = 1,
+       RMI_F01_NOSLEEP_ON = 2
+};
+
+struct rmi_f01_power_management {
+       enum rmi_f01_nosleep nosleep;
+       u8 wakeup_threshold;
+       u8 doze_holdoff;
+       u8 doze_interval;
+};
+
+struct rmi_f19_button_map {
+       unsigned char nbuttons;
+       unsigned char *map;
+};
+
+struct rmi_f1a_button_map {
+       unsigned char nbuttons;
+       unsigned char *map;
+};
+
+struct virtualbutton_map {
+       u16 x;
+       u16 y;
+       u16 width;
+       u16 height;
+       u16 code;
+};
+
+struct rmi_f11_virtualbutton_map {
+       u8 buttons;
+       struct virtualbutton_map *map;
+};
+struct rmi_device_platform_data_spi {
+       int block_delay_us;
+       int split_read_block_delay_us;
+       int read_delay_us;
+       int write_delay_us;
+       int split_read_byte_delay_us;
+       int pre_delay_us;
+       int post_delay_us;
+
+       void *cs_assert_data;
+       int (*cs_assert) (const void *cs_assert_data, const bool assert);
+};
+
+struct rmi_device_platform_data {
+       char *driver_name;
+       char *sensor_name;      /* Used for diagnostics. */
+
+       int attn_gpio;
+       enum rmi_attn_polarity attn_polarity;
+       bool level_triggered;
+       void *gpio_data;
+       int (*gpio_config)(void *gpio_data, bool configure);
+
+       int reset_delay_ms;
+
+       struct rmi_device_platform_data_spi spi_data;
+
+       /* function handler pdata */
+       struct rmi_f01_power_management power_management;
+       struct rmi_f11_2d_axis_alignment axis_align;
+       struct rmi_f19_button_map *button_map;
+       struct rmi_f1a_button_map *f1a_button_map;
+       struct rmi_f11_virtualbutton_map *virtualbutton_map;
+       int (*init_hw)(void);
+#ifdef CONFIG_PM
+       void *pm_data;
+       int (*pre_suspend) (const void *pm_data);
+       int (*post_resume) (const void *pm_data);
+#endif
+};
+
+/**
+ * struct rmi_function_descriptor - RMI function base addresses
+ * @query_base_addr: The RMI Query base address
+ * @command_base_addr: The RMI Command base address
+ * @control_base_addr: The RMI Control base address
+ * @data_base_addr: The RMI Data base address
+ * @interrupt_source_count: The number of irqs this RMI function needs
+ * @function_number: The RMI function number
+ *
+ * This struct is used when iterating the Page Description Table. The addresses
+ * are 16-bit values to include the current page address.
+ *
+ */
+struct rmi_function_descriptor {
+       u16 query_base_addr;
+       u16 command_base_addr;
+       u16 control_base_addr;
+       u16 data_base_addr;
+       u8 interrupt_source_count;
+       u8 function_number;
+       u8 function_version;
+};
+
+struct rmi_function_container;
+struct rmi_device;
+
+/**
+ * struct rmi_function_handler - an RMI function handler
+ * @func: The RMI function number
+ * @init: Callback for RMI function init
+ * @attention: Callback for RMI function attention
+ * @suspend: Callback for function suspend, returns 0 for success.
+ * @resume: Callback for RMI function resume, returns 0 for success.
+ * @remove: Callback for RMI function removal
+ *
+ * This struct describes the interface of an RMI function. These are
+ * registered to the bus using the rmi_register_function_driver() call.
+ *
+ */
+struct rmi_function_handler {
+       int func;
+       int (*init)(struct rmi_function_container *fc);
+       int (*config)(struct rmi_function_container *fc);
+       int (*reset)(struct rmi_function_container *fc);
+       int (*attention)(struct rmi_function_container *fc, u8 *irq_bits);
+#ifdef CONFIG_PM
+       int (*suspend)(struct rmi_function_container *fc);
+       int (*resume)(struct rmi_function_container *fc);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       int (*early_suspend)(struct rmi_function_container *fc);
+       int (*late_resume)(struct rmi_function_container *fc);
+#endif
+#endif
+       void (*remove)(struct rmi_function_container *fc);
+};
+
+/**
+ * struct rmi_function_container - an element in a function handler list
+ * @list: The list
+ * @fd: The function descriptor of the RMI function
+ * @rmi_dev: Pointer to the RMI device associated with this function container
+ * @fh: The callbacks connected to this function
+ * @num_of_irqs: The number of irqs needed by this function
+ * @irq_pos: The position in the irq bitfield this function holds
+ * @data: Private data pointer
+ *
+ */
+struct rmi_function_container {
+       struct list_head list;
+
+       struct rmi_function_descriptor fd;
+       struct rmi_device *rmi_dev;
+       struct rmi_function_handler *fh;
+       struct device dev;
+
+#ifdef CONFIG_RMI4_DEBUG
+       struct dentry *debugfs_root;
+#endif
+
+       int num_of_irqs;
+       int irq_pos;
+       u8 *irq_mask;
+
+       void *data;
+};
+#define to_rmi_function_container(d) \
+               container_of(d, struct rmi_function_container, dev);
+
+
+/**
+ * struct rmi_driver - represents an RMI driver
+ * @driver: Device driver model driver
+ * @probe: Callback for device probe
+ * @remove: Callback for device removal
+ * @shutdown: Callback for device shutdown
+ * @irq_handler: Callback for handling irqs
+ * @fh_add: Callback for function handler add
+ * @fh_remove: Callback for function handler remove
+ * @get_func_irq_mask: Callback for calculating interrupt mask
+ * @store_irq_mask: Callback for storing and replacing interrupt mask
+ * @restore_irq_mask: Callback for restoring previously stored interrupt mask
+ * @data: Private data pointer
+ *
+ * The RMI driver implements a driver on the RMI bus.
+ *
+ */
+struct rmi_driver {
+       struct device_driver driver;
+
+       int (*probe)(struct rmi_device *rmi_dev);
+       int (*remove)(struct rmi_device *rmi_dev);
+       void (*shutdown)(struct rmi_device *rmi_dev);
+       int (*irq_handler)(struct rmi_device *rmi_dev, int irq);
+       int (*reset_handler)(struct rmi_device *rmi_dev);
+       void (*fh_add)(struct rmi_device *rmi_dev,
+                      struct rmi_function_handler *fh);
+       void (*fh_remove)(struct rmi_device *rmi_dev,
+                         struct rmi_function_handler *fh);
+       u8* (*get_func_irq_mask)(struct rmi_device *rmi_dev,
+                           struct rmi_function_container *fc);
+       int (*store_irq_mask)(struct rmi_device *rmi_dev, u8* new_interupts);
+       int (*restore_irq_mask)(struct rmi_device *rmi_dev);
+       void *data;
+};
+#define to_rmi_driver(d) \
+       container_of(d, struct rmi_driver, driver);
+
+/** struct rmi_phys_info - diagnostic information about the RMI physical
+ * device, used in the phys sysfs file.
+ * @proto String indicating the protocol being used.
+ * @tx_count Number of transmit operations.
+ * @tx_bytes Number of bytes transmitted.
+ * @tx_errs  Number of errors encountered during transmit operations.
+ * @rx_count Number of receive operations.
+ * @rx_bytes Number of bytes received.
+ * @rx_errs  Number of errors encountered during receive operations.
+ * @att_count Number of times ATTN assertions have been handled.
+ */
+struct rmi_phys_info {
+       char *proto;
+       long tx_count;
+       long tx_bytes;
+       long tx_errs;
+       long rx_count;
+       long rx_bytes;
+       long rx_errs;
+       long attn_count;
+};
+
+/**
+ * struct rmi_phys_device - represent an RMI physical device
+ * @dev: Pointer to the communication device, e.g. i2c or spi
+ * @rmi_dev: Pointer to the RMI device
+ * @write: Callback for write
+ * @write_block: Callback for writing a block of data
+ * @read: Callback for read
+ * @read_block: Callback for reading a block of data
+ * @data: Private data pointer
+ *
+ * The RMI physical device implements the glue between different communication
+ * buses such as I2C and SPI.
+ *
+ */
+struct rmi_phys_device {
+       struct device *dev;
+       struct rmi_device *rmi_dev;
+
+       int (*write)(struct rmi_phys_device *phys, u16 addr, u8 data);
+       int (*write_block)(struct rmi_phys_device *phys, u16 addr, u8 *buf,
+                          int len);
+       int (*read)(struct rmi_phys_device *phys, u16 addr, u8 *buf);
+       int (*read_block)(struct rmi_phys_device *phys, u16 addr, u8 *buf,
+                         int len);
+
+       int (*enable_device) (struct rmi_phys_device *phys);
+       void (*disable_device) (struct rmi_phys_device *phys);
+
+       void *data;
+
+       struct rmi_phys_info info;
+};
+
+/**
+ * struct rmi_device - represents an RMI device
+ * @dev: The device created for the RMI bus
+ * @number: Unique number for the device on the bus.
+ * @driver: Pointer to associated driver
+ * @phys: Pointer to the physical interface
+ * @early_suspend_handler: Pointers to early_suspend and late_resume, if
+ * configured.
+ *
+ * This structs represent an RMI device.
+ *
+ */
+struct rmi_device {
+       struct device dev;
+       int number;
+
+       struct rmi_driver *driver;
+       struct rmi_phys_device *phys;
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       struct early_suspend early_suspend_handler;
+#endif
+#ifdef CONFIG_RMI4_DEBUG
+       struct dentry *debugfs_root;
+#endif
+};
+#define to_rmi_device(d) container_of(d, struct rmi_device, dev);
+#define to_rmi_platform_data(d) ((d)->phys->dev->platform_data);
+
+static inline void rmi_set_driverdata(struct rmi_device *d, void *data)
+{
+       dev_set_drvdata(&d->dev, data);
+}
+
+static inline void *rmi_get_driverdata(struct rmi_device *d)
+{
+       return dev_get_drvdata(&d->dev);
+}
+
+/**
+ * rmi_read - RMI read byte
+ * @d: Pointer to an RMI device
+ * @addr: The address to read from
+ * @buf: The read buffer
+ *
+ * Reads a byte of data using the underlaying physical protocol in to buf. It
+ * returns zero or a negative error code.
+ */
+static inline int rmi_read(struct rmi_device *d, u16 addr, u8 *buf)
+{
+       return d->phys->read(d->phys, addr, buf);
+}
+
+/**
+ * rmi_read_block - RMI read block
+ * @d: Pointer to an RMI device
+ * @addr: The start address to read from
+ * @buf: The read buffer
+ * @len: Length of the read buffer
+ *
+ * Reads a block of byte data using the underlaying physical protocol in to buf.
+ * It returns the amount of bytes read or a negative error code.
+ */
+static inline int rmi_read_block(struct rmi_device *d, u16 addr, u8 *buf,
+                                int len)
+{
+       return d->phys->read_block(d->phys, addr, buf, len);
+}
+
+/**
+ * rmi_write - RMI write byte
+ * @d: Pointer to an RMI device
+ * @addr: The address to write to
+ * @data: The data to write
+ *
+ * Writes a byte from buf using the underlaying physical protocol. It
+ * returns zero or a negative error code.
+ */
+static inline int rmi_write(struct rmi_device *d, u16 addr, u8 data)
+{
+       return d->phys->write(d->phys, addr, data);
+}
+
+/**
+ * rmi_write_block - RMI write block
+ * @d: Pointer to an RMI device
+ * @addr: The start address to write to
+ * @buf: The write buffer
+ * @len: Length of the write buffer
+ *
+ * Writes a block of byte data from buf using the underlaying physical protocol.
+ * It returns the amount of bytes written or a negative error code.
+ */
+static inline int rmi_write_block(struct rmi_device *d, u16 addr, u8 *buf,
+                                 int len)
+{
+       return d->phys->write_block(d->phys, addr, buf, len);
+}
+
+/**
+ * rmi_register_driver - register rmi driver
+ * @driver: the driver to register
+ *
+ * This function registers an RMI driver to the RMI bus.
+ */
+int rmi_register_driver(struct rmi_driver *driver);
+
+/**
+ * rmi_unregister_driver - unregister rmi driver
+ * @driver: the driver to unregister
+ *
+ * This function unregisters an RMI driver to the RMI bus.
+ */
+void rmi_unregister_driver(struct rmi_driver *driver);
+
+/**
+ * rmi_register_phys_device - register a physical device connection
+ * @phys: the physical driver to register
+ *
+ * This function registers a physical driver to the RMI bus. These drivers
+ * provide a communication layer for the drivers connected to the bus, e.g.
+ * I2C, SPI and so on.
+ */
+int rmi_register_phys_device(struct rmi_phys_device *phys);
+
+/**
+ * rmi_unregister_phys_device - unregister a physical device connection
+ * @phys: the physical driver to unregister
+ *
+ * This function unregisters a physical driver from the RMI bus.
+ */
+void rmi_unregister_phys_device(struct rmi_phys_device *phys);
+
+/**
+ * rmi_register_function_driver - register an RMI function driver
+ * @fh: the function handler to register
+ *
+ * This function registers support for a new RMI function to the bus. All
+ * drivers on the bus will be notified of the presence of the new function
+ * driver.
+ */
+int rmi_register_function_driver(struct rmi_function_handler *fh);
+
+/**
+ * rmi_unregister_function_driver - unregister an RMI function driver
+ * @fh: the function handler to unregister
+ *
+ * This function unregisters a RMI function from the RMI bus. All drivers on
+ * the bus will be notified of the removal of a function driver.
+ */
+void rmi_unregister_function_driver(struct rmi_function_handler *fh);
+
+/**
+ * rmi_get_function_handler - get a pointer to specified RMI function
+ * @id: the RMI function id
+ *
+ * This function gets the specified RMI function handler from the list of
+ * supported functions.
+ */
+struct rmi_function_handler *rmi_get_function_handler(int id);
+
+
+struct rmi_char_device;
+
+/**
+ * rmi_char_driver - a general driver that doesn't handle specific functions,
+ * operating outside the bus::sensor::functions
+ * @match: returns 1 if the driver wants to talk to the specified rmi_dev.
+ *
+ * All of the above are optional except driver and init which are required.
+ *
+ */
+struct rmi_char_driver {
+       struct device_driver driver;
+
+       int (*match)(struct rmi_device *rmi_dev);
+       int (*init)(struct rmi_char_device *cd);
+       int (*attention)(struct rmi_char_device *cd, u8 *irq_bits);
+#ifdef CONFIG_PM
+       int (*suspend)(struct rmi_char_device *cd);
+       int (*resume)(struct rmi_char_device *cd);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       int (*early_suspend)(struct rmi_char_device *cd);
+       int (*late_resume)(struct rmi_char_device *cd);
+#endif
+#endif
+       void (*remove)(struct rmi_char_device *cd);
+
+       struct list_head devices;
+};
+
+struct rmi_char_device {
+       struct list_head list;
+
+       struct rmi_device *rmi_dev;
+       struct rmi_char_driver *driver;
+       struct device dev;
+
+#ifdef CONFIG_RMI4_DEBUG
+       struct dentry *debugfs_root;
+#endif
+
+       void *data;
+};
+#define to_rmi_char_device(d) \
+               container_of(d, struct rmi_char_device, dev)
+
+int rmi_register_character_driver(struct rmi_char_driver *char_driver);
+int rmi_unregister_character_driver(struct rmi_char_driver *char_driver);
+
+
+/* Helper fn to convert a byte array representing a short in the RMI
+ * endian-ness to a short in the native processor's specific endianness.
+ * We don't use ntohs/htons here because, well, we're not dealing with
+ * a pair of shorts. And casting dest to short* wouldn't work, because
+ * that would imply knowing the byte order of short in the first place.
+ */
+static inline void batohs(unsigned short *dest, unsigned char *src)
+{
+       *dest = src[1] * 0x100 + src[0];
+}
+
+/* Helper function to convert a short (in host processor endianess) to
+ * a byte array in the RMI endianess for shorts.  See above comment for
+ * why we dont us htons or something like that.
+ */
+static inline void hstoba(unsigned char *dest, unsigned short src)
+{
+       dest[0] = src % 0x100;
+       dest[1] = src / 0x100;
+}
+
+/* Utility routine to handle writes to read-only attributes.  Hopefully
+ * this will never happen, but if the user does something stupid, we don't
+ * want to accept it quietly (which is what can happen if you just put NULL
+ * for the attribute's store function).
+ */
+static inline ssize_t rmi_store_error(struct device *dev,
+                       struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       dev_warn(dev,
+                "RMI4 WARNING: Attempt to write %d characters to read-only "
+                "attribute %s.", count, attr->attr.name);
+       return -EPERM;
+}
+
+/* Utility routine to handle reads of write-only attributes.  Hopefully
+ * this will never happen, but if the user does something stupid, we don't
+ * want to accept it quietly (which is what can happen if you just put NULL
+ * for the attribute's show function).
+ */
+static inline ssize_t rmi_show_error(struct device *dev,
+                      struct device_attribute *attr,
+                      char *buf)
+{
+       dev_warn(dev,
+                "RMI4 WARNING: Attempt to read from write-only attribute %s.",
+                attr->attr.name);
+       return -EPERM;
+}
+
+/* utility function for bit access of u8*'s */
+void u8_set_bit(u8 *target, int pos);
+void u8_clear_bit(u8 *target, int pos);
+bool u8_is_set(u8 *target, int pos);
+bool u8_is_any_set(u8 *target, int size);
+void u8_or(u8 *dest, u8* target1, u8* target2, int size);
+void u8_and(u8 *dest, u8* target1, u8* target2, int size);
+#endif