summaryrefslogtreecommitdiff
path: root/ANDROID_3.4.5/drivers/input/sensor
diff options
context:
space:
mode:
Diffstat (limited to 'ANDROID_3.4.5/drivers/input/sensor')
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/Kconfig224
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/Makefile26
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/Kconfig50
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/Makefile13
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt08_gsensor/Makefile6
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt08_gsensor/dmt08.c870
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt08_gsensor/dmt08.h105
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt10_gsensor/Makefile6
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt10_gsensor/dmt10.c950
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt10_gsensor/dmt10.h187
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/gsensor.c180
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/gsensor.h43
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/kxti9_gsensor/Makefile6
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/kxti9_gsensor/kxti9.c1134
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/kxti9_gsensor/kxti9.h103
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/cm3232/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/cm3232/cm3232.c855
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard06_gsensor/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard06_gsensor/dmard06.c980
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/cyclequeue.c68
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/cyclequeue.h18
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/dmard08.c1019
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/dmard08.h75
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard09_gsensor/Makefile35
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard09_gsensor/dmt09.c1685
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard09_gsensor/dmt09.h183
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard10_gsensor/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard10_gsensor/dmt10.c1702
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/dmard10_gsensor/dmt10.h192
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/isl29023_lsensor/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/isl29023_lsensor/isl29023.c1164
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/kionix_gsensor/Makefile35
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/kionix_gsensor/kionix_accel.c2427
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/kionix_gsensor/kionix_accel.h85
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/kxte9.c1798
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/kxte9.h116
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/readme.txt47
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/l3g4200d_gyro/Makefile5
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/l3g4200d_gyro/l3g4200d.h108
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/l3g4200d_gyro/l3g4200d_gyr.c1681
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/mc32x0.c2580
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/mc32x0_driver.c505
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/mc32x0_driver.h219
-rw-r--r--ANDROID_3.4.5/drivers/input/sensor/mc3xxx_gsensor/Makefile34
-rw-r--r--ANDROID_3.4.5/drivers/input/sensor/mc3xxx_gsensor/mc3xxx.c2719
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mma7660_gsensor/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mma7660_gsensor/mma7660.c1052
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mma7660_gsensor/mma7660.h106
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mma8452q_gsensor/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mma8452q_gsensor/mma8x5x.c982
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mma8452q_gsensor/mma8x5x.h107
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/Makefile4
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mecs.c433
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mecs.h60
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mmc328x.c505
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mmc328x.h91
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mxc622x_gsensor/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mxc622x_gsensor/mxc622x.c1151
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/mxc622x_gsensor/mxc622x.h83
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/sensor.c114
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/sensor.h91
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/stk3310/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/stk3310/stk3310.c644
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/stk8312.h51
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/stk8313.h52
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/stk831x.c3590
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/us5182_lpsensor/Makefile34
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/us5182_lpsensor/us5182.c1098
-rwxr-xr-xANDROID_3.4.5/drivers/input/sensor/us5182_lpsensor/us5182.h255
73 files changed, 35149 insertions, 0 deletions
diff --git a/ANDROID_3.4.5/drivers/input/sensor/Kconfig b/ANDROID_3.4.5/drivers/input/sensor/Kconfig
new file mode 100755
index 00000000..cff1aa40
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/Kconfig
@@ -0,0 +1,224 @@
+#
+# WMT Sensor configuration
+#
+menuconfig INPUT_SENSOR
+ bool "WMT Sensor"
+ default y
+ help
+ Say Y here, and a list of supported sensor will be displayed.
+ This option doesn't affect the kernel.
+
+ If unsure, say Y.
+
+if INPUT_SENSOR
+
+config WMT_SENSOR_KXTE9
+ tristate "KXTE9 G-Sensor Support"
+ depends on ARCH_WMT
+ default n
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_gsensor_mc3230.
+config WMT_SENSOR_KIONIX
+ tristate "KIONIX G-Sensor Support"
+ depends on ARCH_WMT
+ default n
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_gsensor_kionix.
+config WMT_SENSOR_MC3XXX
+ tristate "Mcube G-Sensor Support"
+ depends on ARCH_WMT
+ default m
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_gsensor_mc3xxx.
+
+config WMT_SENSOR_DMARD08
+ tristate "DMARD08 G-Sensor Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_dmard08.
+config WMT_SENSOR_DMARD06
+ tristate "DMARD06 G-Sensor Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_dmard06.
+config WMT_SENSOR_DMARD10
+ tristate "DMARD10 G-Sensor Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_dmard10.
+config WMT_SENSOR_DMARD09
+ tristate "DMARD09 G-Sensor Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_dmard09.
+config WMT_SENSOR_MXC622X
+ tristate "MXC622X G-Sensor Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_mxc622x.
+config WMT_SENSOR_MMA7660
+ tristate "MMA7660 G-Sensor Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_mma7660.
+config WMT_SENSOR_MMC328x
+ tristate "MMC328x M-Sensor Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with m-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_mmc328x.
+config WMT_SENSOR_ISL29023
+ tristate "ISL29023 Light sensor Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with l-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_isl29023.
+config WMT_SENSOR_CM3232
+ tristate "CM3232 Light sensor Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with l-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_cm3232.
+config WMT_SENSOR_STK3310
+ tristate "STK3310 Light sensor Support"
+ depends on ARCH_WMT
+ default y
+ help
+ Say Y here if you have an WMT based board with l-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_stk3310.
+config WMT_GYRO_L3G4200D
+ tristate "L3G4200D Gyroscope Support"
+ depends on ARCH_WMT
+ default m
+ help
+ Say Y here if you have an WMT based board with ST L3g4200d
+ gyroscope attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_gyro_l3g4200d.
+
+config WMT_SENSOR_US5182
+ tristate "US5182 Light&Promixity sensor Support"
+ depends on ARCH_WMT
+ default m
+ help
+ Say Y here if you have an WMT based board with l&p-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_lsensor_us5182.
+
+config WMT_SENSOR_MMA8452Q
+ tristate "MMA8452Q G-Sensor Support"
+ depends on ARCH_WMT
+ default m
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_gsensor_mma8542.
+
+config WMT_SENSOR_STK8312
+ tristate "STK8312 G-Sensor Support"
+ depends on ARCH_WMT
+ default m
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called s_wmt_gsensor_STK8312.
+
+endif
diff --git a/ANDROID_3.4.5/drivers/input/sensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/Makefile
new file mode 100755
index 00000000..cc06e871
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/Makefile
@@ -0,0 +1,26 @@
+#
+# Makefile for the Sensor driver
+#
+
+# Each configuration option enables a list of files.
+
+#obj-$(CONFIG_INPUT_SENSOR) += gsensor.o
+obj-y += sensor.o
+obj-$(CONFIG_WMT_SENSOR_KXTE9) += kxte9_gsensor/
+obj-$(CONFIG_WMT_SENSOR_MC3XXX) += mc3xxx_gsensor/
+obj-$(CONFIG_WMT_SENSOR_DMARD08) += dmard08_gsensor/
+obj-$(CONFIG_WMT_SENSOR_DMARD06) += dmard06_gsensor/
+obj-$(CONFIG_WMT_SENSOR_MMA7660) += mma7660_gsensor/
+obj-$(CONFIG_WMT_SENSOR_ISL29023) += isl29023_lsensor/
+obj-$(CONFIG_WMT_SENSOR_CM3232) += cm3232/
+obj-$(CONFIG_WMT_SENSOR_CM3232) += stk3310/
+obj-$(CONFIG_WMT_SENSOR_DMARD10) += dmard10_gsensor/
+obj-$(CONFIG_WMT_SENSOR_DMARD09) += dmard09_gsensor/
+obj-$(CONFIG_WMT_SENSOR_MXC622X) += mxc622x_gsensor/
+obj-$(CONFIG_WMT_SENSOR_MMC328x) += mmc328x_msensor/
+#obj-$(CONFIG_WMT_SENSOR_CM3232) += cm3232/cm3232.o
+obj-$(CONFIG_WMT_GYRO_L3G4200D) += l3g4200d_gyro/
+obj-$(CONFIG_WMT_SENSOR_US5182) += us5182_lpsensor/
+obj-$(CONFIG_WMT_SENSOR_MMA8452Q) += mma8452q_gsensor/
+obj-$(CONFIG_WMT_SENSOR_STK8312) += stk8312_gsensor/
+obj-$(CONFIG_WMT_SENSOR_KIONIX) += kionix_gsensor/ \ No newline at end of file
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/Kconfig b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/Kconfig
new file mode 100755
index 00000000..9bf96e92
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/Kconfig
@@ -0,0 +1,50 @@
+#
+# WMT Sensor configuration
+#
+menuconfig INPUT_SENSOR
+ bool "WMT Sensor"
+ help
+ Say Y here, and a list of supported sensor will be displayed.
+ This option doesn't affect the kernel.
+
+ If unsure, say Y.
+
+if INPUT_SENSOR
+
+
+config WMT_SENSOR_KXTI9
+ tristate "KXTI9 G-Sensor Support"
+ depends on ARCH_WMT
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_kxti9.
+
+config WMT_SENSOR_DMT08
+ tristate "DMT08 G-Sensor Support"
+ depends on ARCH_WMT
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_dmt08.
+
+config WMT_SENSOR_DMT10
+ tristate "DMT10 G-Sensor Support"
+ depends on ARCH_WMT
+ help
+ Say Y here if you have an WMT based board with g-sensor
+ attached to it.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called sensor_dmt10.
+endif
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/Makefile b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/Makefile
new file mode 100755
index 00000000..ee1a0ac5
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/Makefile
@@ -0,0 +1,13 @@
+#
+# Makefile for the Sensor driver
+#
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_INPUT_SENSOR) += gsensor.o
+
+obj-$(CONFIG_WMT_SENSOR_KXTI9) += kxti9_gsensor/
+
+obj-$(CONFIG_WMT_SENSOR_DMT08) += dmt08_gsensor/
+
+obj-$(CONFIG_WMT_SENSOR_DMT10) += dmt10_gsensor/
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt08_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt08_gsensor/Makefile
new file mode 100755
index 00000000..6edce54a
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt08_gsensor/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the DMARD06 Sensor driver
+#
+
+sensor_dmt08-objs := dmt08.o
+obj-$(CONFIG_WMT_SENSOR_DMT08) += sensor_dmt08.o
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt08_gsensor/dmt08.c b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt08_gsensor/dmt08.c
new file mode 100755
index 00000000..2ed5f502
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt08_gsensor/dmt08.c
@@ -0,0 +1,870 @@
+/*
+ * @file drivers/misc/dmt0308.c
+ * @brief DMT g-sensor Linux device driver
+ * @author Domintech Technology Co., Ltd (http://www.domintech.com.tw)
+ * @version 1.31
+ * @date 2012/3/27
+ *
+ * @section LICENSE
+ *
+ * Copyright 2011 Domintech Technology Co., Ltd
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/cdev.h>
+#include <linux/wakelock.h>
+#include <asm/uaccess.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/serio.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <linux/miscdevice.h>
+#include <mach/gpio.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/syscalls.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include "dmt08.h"
+#include "../gsensor.h"
+
+wait_queue_head_t open_wq;
+atomic_t active;
+static unsigned int interval;
+struct mutex DMT_mutex;
+struct delayed_work work;
+struct work_struct irq_work;
+atomic_t delay;
+
+static struct gsensor_conf gs_conf;
+
+void gsensor_write_offset_to_file(void);
+void gsensor_read_offset_from_file(void);
+char OffsetFileName[] = "/data/misc/dmt/offset.txt";
+static int Device_First_Time_Opened_flag=1;
+//*************************************************
+static char const *const ACCELEMETER_CLASS_NAME = "accelemeter";
+#define CHIP_ENABLE 137
+#if (defined(CONFIG_SENSORS_DMARD03) || defined(CONFIG_SENSORS_DMARD03_MODULE))
+static char const *const GSENSOR_DEVICE_NAME = "dmard03";
+#elif (defined(CONFIG_SENSORS_DMARD08) || defined(CONFIG_SENSORS_DMARD08_MODULE) || defined(CONFIG_WMT_SENSOR_DMT08))
+static char const *const GSENSOR_DEVICE_NAME = "dmard08";
+#endif
+
+static int device_init(void);
+static void device_exit(void);
+
+static int device_open(struct inode*, struct file*);
+static ssize_t device_write(struct file*, const char*, size_t, loff_t*);
+static ssize_t device_read(struct file*, char*, size_t, loff_t*);
+static long device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+static int device_close(struct inode*, struct file*);
+
+//static int device_i2c_suspend(struct i2c_client *client, pm_message_t mesg);
+//static int device_i2c_resume(struct i2c_client *client);
+static int __devinit device_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
+static int __devexit device_i2c_remove(struct i2c_client *client);
+static inline void device_i2c_correct_accel_sign(s16 *val);
+void device_i2c_read_xyz(struct i2c_client *client, s16 *xyz);
+void device_i2c_merge_register_values(struct i2c_client *client, s16 *val, u8 msb, u8 lsb);
+
+struct input_dev *input;
+
+static int DMT_GetOpenStatus(void)
+{
+#if DMT_DEBUG_DATA
+ IN_FUNC_MSG;
+ printk("%s:start active=%d\n",__func__,active.counter);
+#endif
+ wait_event_interruptible(open_wq, (atomic_read(&active) != 0));
+ return 0;
+}
+
+static int DMT_GetCloseStatus(void)
+{
+#if DMT_DEBUG_DATA
+ IN_FUNC_MSG;
+ printk("%s:start active=%d\n",__func__,active.counter);
+#endif
+ wait_event_interruptible(open_wq, (atomic_read(&active) <= 0));
+ return 0;
+}
+
+static void DMT_sysfs_update_active_status(int en)
+{
+ unsigned long dmt_delay;
+ if(en)
+ {
+ dmt_delay = msecs_to_jiffies(atomic_read(&delay));
+ if(dmt_delay < 1)
+ dmt_delay = 1;
+ //printk("schedule_delayed_work start with delay time=%lu\n",dmt_delay);
+ schedule_delayed_work(&work,dmt_delay);
+ }
+ else
+ cancel_delayed_work_sync(&work);
+}
+
+static ssize_t DMT_enable_acc_show( struct device *dev, struct device_attribute *attr, char *buf)
+{
+ buf="show";
+ return 1;
+}
+
+static ssize_t DMT_enable_acc_store( struct device *dev, struct device_attribute *attr, char const *buf, size_t count)
+{
+ int en;
+#if DMT_DEBUG_DATA
+ printk("%s:buf=%x %x\n",__func__,buf[0],buf[1]);
+#endif
+ if(buf[0]!= 0x30 && buf[0]!= 0x31)
+ {
+ printk("%s:illegle data !!\n",__func__);
+ return 0;
+ }
+ en= (buf[0]-0x30 > 0) ? 1:0;
+ DMT_sysfs_update_active_status(en);
+ return 1;
+}
+
+static ssize_t DMT_delay_acc_show( struct device *dev, struct device_attribute *attr, char *buf){
+ return 1;
+}
+
+static ssize_t DMT_delay_acc_store( struct device *dev, struct device_attribute *attr,char const *buf, size_t count)
+{
+ int error;
+ unsigned long data;
+ error = strict_strtoul(buf, 10, &data);
+ if(error) {
+ pr_err("%s strict_strtoul error\n", __FUNCTION__);
+ return -1;
+ }
+ mutex_lock(&DMT_mutex);
+ interval=(unsigned int)data;
+ mutex_unlock(&DMT_mutex);
+ atomic_set(&delay, (unsigned int) data);
+#if DMT_DEBUG_DATA
+ printk("Driver attribute set delay =%lu\n",data);
+#endif
+ return 1;
+}
+
+static struct device_attribute DMT_attributes[] = {
+ __ATTR(enable_acc, 0755, DMT_enable_acc_show, DMT_enable_acc_store),
+ __ATTR(delay_acc, 0755, DMT_delay_acc_show, DMT_delay_acc_store),
+ __ATTR_NULL,
+};
+
+static int create_device_attributes(struct device *dev, struct device_attribute *attrs)
+{
+ int i;
+ int err = 0;
+#if DMT_DEBUG_DATA
+ IN_FUNC_MSG;
+#endif
+ for (i = 0 ; NULL != attrs[i].attr.name ; ++i) {
+ err = device_create_file(dev, &attrs[i]);
+ if (0 != err)
+ break;
+ }
+
+ if (0 != err) {
+ for (; i >= 0 ; --i)
+ device_remove_file(dev, &attrs[i]);
+ }
+ return err;
+}
+
+int input_init(void)
+{
+ int err=0;
+ input=input_allocate_device();
+ if (!input)
+ return -ENOMEM;
+ else
+ printk("input device allocate Success !!\n");
+ /* Setup input device */
+ set_bit(EV_ABS, input->evbit);
+ /* Accelerometer [-78.5, 78.5]m/s2 in Q16*/
+ input_set_abs_params(input, ABS_X, -1024, 1024, 0, 0);
+ input_set_abs_params(input, ABS_Y, -1024, 1024, 0, 0);
+ input_set_abs_params(input, ABS_Z, -1024, 1024, 0, 0);
+
+ /* Set name */
+ input->name = "g-sensor";
+
+ /* Register */
+ err = input_register_device(input);
+ if (err) {
+ input_free_device(input);
+ return err;
+ }
+ atomic_set(&active, 0);
+#if DMT_DEBUG_DATA
+ printk("in driver ,active=%d\n",active.counter);
+#endif
+ init_waitqueue_head(&open_wq);
+
+ return err;
+}
+
+typedef union {
+ struct {
+ s16 x;
+ s16 y;
+ s16 z;
+ } u;
+ s16 v[SENSOR_DATA_SIZE];
+} raw_data;
+static raw_data offset;
+
+struct dev_data {
+ dev_t devno;
+ struct cdev cdev;
+ struct class *class;
+ struct i2c_client *client;
+};
+static struct dev_data dev;
+
+s16 sensorlayout[3][3] = {
+#if defined(CONFIG_GSEN_LAYOUT_PAT_1)
+ { 1, 0, 0}, { 0, 1, 0}, { 0, 0, 1},
+#elif defined(CONFIG_GSEN_LAYOUT_PAT_2)
+ { 0, 1, 0}, {-1, 0, 0}, { 0, 0, 1},
+#elif defined(CONFIG_GSEN_LAYOUT_PAT_3)
+ {-1, 0, 0}, { 0,-1, 0}, { 0, 0, 1},
+#elif defined(CONFIG_GSEN_LAYOUT_PAT_4)
+ { 0,-1, 0}, { 1, 0, 0}, { 0, 0, 1},
+#elif defined(CONFIG_GSEN_LAYOUT_PAT_5)
+ {-1, 0, 0}, { 0, 1, 0}, { 0, 0,-1},
+#elif defined(CONFIG_GSEN_LAYOUT_PAT_6)
+ { 0,-1, 0}, {-1, 0, 0}, { 0, 0,-1},
+#elif defined(CONFIG_GSEN_LAYOUT_PAT_7)
+ { 1, 0, 0}, { 0,-1, 0}, { 0, 0,-1},
+#elif defined(CONFIG_GSEN_LAYOUT_PAT_8)
+ { 0, 1, 0}, { 1, 0, 0}, { 0, 0,-1},
+#endif
+};
+
+void gsensor_read_accel_avg(int num_avg, raw_data *avg_p )
+{
+ long xyz_acc[SENSOR_DATA_SIZE];
+ s16 xyz[SENSOR_DATA_SIZE];
+ int i, j;
+
+ //initialize the accumulation buffer
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ xyz_acc[i] = 0;
+
+ for(i = 0; i < num_avg; i++)
+ {
+ device_i2c_read_xyz(dev.client, (s16 *)&xyz);
+ for(j = 0; j < SENSOR_DATA_SIZE; j++)
+ xyz_acc[j] += xyz[j];
+ }
+
+ // calculate averages
+ for(i = 0; i < SENSOR_DATA_SIZE; i++)
+ avg_p->v[i] = (s16) (xyz_acc[i] / num_avg);
+}
+/* calc delta offset */
+int gsensor_calculate_offset(int gAxis,raw_data avg)
+{
+ switch(gAxis)
+ {
+ case CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_NEGATIVE:
+ offset.u.x = avg.u.x ;
+ offset.u.y = avg.u.y ;
+ offset.u.z = avg.u.z + DEFAULT_SENSITIVITY;
+ break;
+ case CONFIG_GSEN_CALIBRATION_GRAVITY_ON_X_POSITIVE:
+ offset.u.x = avg.u.x + DEFAULT_SENSITIVITY;
+ offset.u.y = avg.u.y ;
+ offset.u.z = avg.u.z ;
+ break;
+ case CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_POSITIVE:
+ offset.u.x = avg.u.x ;
+ offset.u.y = avg.u.y ;
+ offset.u.z = avg.u.z - DEFAULT_SENSITIVITY;
+ break;
+ case CONFIG_GSEN_CALIBRATION_GRAVITY_ON_X_NEGATIVE:
+ offset.u.x = avg.u.x - DEFAULT_SENSITIVITY;
+ offset.u.y = avg.u.y ;
+ offset.u.z = avg.u.z ;
+ break;
+ case CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Y_NEGATIVE:
+ offset.u.x = avg.u.x ;
+ offset.u.y = avg.u.y + DEFAULT_SENSITIVITY;
+ offset.u.z = avg.u.z ;
+ break;
+ case CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Y_POSITIVE:
+ offset.u.x = avg.u.x ;
+ offset.u.y = avg.u.y - DEFAULT_SENSITIVITY;
+ offset.u.z = avg.u.z ;
+ break;
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+void gsensor_calibrate(int side){
+ raw_data avg;
+ int avg_num = 16;
+#if DMT_DEBUG_DATA
+ IN_FUNC_MSG;
+#endif
+ // get acceleration average reading
+ gsensor_read_accel_avg(avg_num, &avg);
+ // calculate and set the offset
+ gsensor_calculate_offset(side, avg);
+}
+
+void ce_on(void){
+ //omap_mux_set_gpio(OMAP_PIN_INPUT_PULLUP, CHIP_ENABLE);
+}
+
+void ce_off(void){
+ //omap_mux_set_gpio(OMAP_PIN_INPUT_PULLDOWN, CHIP_ENABLE);
+}
+
+void gsensor_reset(void){
+ ce_off();
+ msleep(300);
+ ce_on();
+}
+
+void gsensor_set_offset(int val[3])
+{
+ int i;
+#if DMT_DEBUG_DATA
+ IN_FUNC_MSG;
+#endif
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ offset.v[i] = (s16) val[i];
+}
+
+static int device_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ return 0;
+}
+
+static int device_i2c_resume(struct i2c_client *client)
+{
+ return 0;
+}
+
+static void device_i2c_shutdown(struct i2c_client *client)
+{
+ flush_delayed_work_sync(&work);
+ cancel_delayed_work_sync(&work);
+}
+
+struct file_operations dmt_g_sensor_fops = {
+ .owner = THIS_MODULE,
+ .read = device_read,
+ .write = device_write,
+ .unlocked_ioctl = device_ioctl,
+ .open = device_open,
+ .release = device_close,
+};
+
+static const struct i2c_device_id device_i2c_ids[] = {
+ {DEVICE_I2C_NAME, 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, device_i2c_ids);
+
+static struct i2c_driver device_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DEVICE_I2C_NAME,
+ },
+ .class = I2C_CLASS_HWMON,
+ .probe = device_i2c_probe,
+ .remove = __devexit_p(device_i2c_remove),
+ .suspend = device_i2c_suspend,
+ .resume = device_i2c_resume,
+ .shutdown = device_i2c_shutdown,
+ .id_table = device_i2c_ids,
+};
+
+static int device_open(struct inode *inode, struct file *filp){
+#if DMT_DEBUG_DATA
+ IN_FUNC_MSG;
+#endif
+ //Device_First_Time_Opened_flag
+ if(Device_First_Time_Opened_flag)
+ {
+ Device_First_Time_Opened_flag=0;
+ //gsensor_read_offset_from_file();
+ }
+ return 0;
+}
+
+static ssize_t device_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
+{
+ return 0;
+}
+
+static ssize_t device_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
+{
+ s16 xyz[SENSOR_DATA_SIZE];
+ int i;
+
+ device_i2c_read_xyz(dev.client, (s16 *)&xyz);
+ //offset compensation
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ xyz[i] -= offset.v[i];
+
+ if(copy_to_user(buf, &xyz, count))
+ return -EFAULT;
+#if DMT_DEBUG_DATA
+ IN_FUNC_MSG;
+ PRINT_X_Y_Z(xyz[0], xyz[1], xyz[2]);
+#endif
+
+ return count;
+}
+
+static long device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ int err = 0, ret = 0, i;
+ int intBuf[SENSOR_DATA_SIZE];
+ s16 xyz[SENSOR_DATA_SIZE];
+ //check type and number
+ if (_IOC_TYPE(cmd) != IOCTL_MAGIC) return -ENOTTY;
+ if (_IOC_NR(cmd) > SENSOR_MAXNR) return -ENOTTY;
+
+ //check user space pointer is valid
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
+ if (err) return -EFAULT;
+
+ switch(cmd)
+ {
+ case SENSOR_RESET:
+ //gsensor_reset();
+ printk("RUN RESET");
+ return ret;
+
+ case SENSOR_CALIBRATION:
+ // get orientation info
+ if(copy_from_user(&intBuf, (int*)arg, sizeof(int))) return -EFAULT;
+ gsensor_calibrate(intBuf[0]);
+ // write in to file
+ gsensor_write_offset_to_file();
+
+ // return the offset
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ intBuf[i] = offset.v[i];
+
+ ret = copy_to_user((int *)arg, &intBuf, sizeof(intBuf));
+ return ret;
+
+ case SENSOR_GET_OFFSET:
+ // get offset from file
+ gsensor_read_offset_from_file();
+
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ intBuf[i] = offset.v[i];
+
+ ret = copy_to_user((int *)arg, &intBuf, sizeof(intBuf));
+ return ret;
+
+ case SENSOR_SET_OFFSET:
+ ret = copy_from_user(&intBuf, (int *)arg, sizeof(intBuf));
+ gsensor_set_offset(intBuf);
+ // write in to file
+ gsensor_write_offset_to_file();
+ return ret;
+
+ case SENSOR_READ_ACCEL_XYZ:
+ device_i2c_read_xyz(dev.client, (s16 *)&xyz);
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ intBuf[i] = xyz[i] - offset.v[i];
+
+ ret = copy_to_user((int*)arg, &intBuf, sizeof(intBuf));
+ return ret;
+ case SENSOR_SETYPR:
+ if(copy_from_user(&intBuf, (int*)arg, sizeof(intBuf)))
+ {
+ printk("%s:copy_from_user(&intBuf, (int*)arg, sizeof(intBuf)) ERROR, -EFAULT\n",__func__);
+ return -EFAULT;
+ }
+ input_report_abs(input, ABS_X, intBuf[0]);
+ input_report_abs(input, ABS_Y, intBuf[1]);
+ input_report_abs(input, ABS_Z, intBuf[2]);
+ input_sync(input);
+ //printk("%s:SENSOR_SETYPR OK! x=%d,y=%d,z=%d\n",__func__,intBuf[0],intBuf[1],intBuf[2]);
+
+ return 1;
+ case SENSOR_GET_OPEN_STATUS:
+ //printk("%s:Going into DMT_GetOpenStatus()\n",__func__);
+ DMT_GetOpenStatus();
+ //printk("%s:DMT_GetOpenStatus() finished\n",__func__);
+ return 1;
+ break;
+ case SENSOR_GET_CLOSE_STATUS:
+ //printk("%s:Going into DMT_GetCloseStatus()\n",__func__);
+ DMT_GetCloseStatus();
+ //printk("%s:DMT_GetCloseStatus() finished\n",__func__);
+ return 1;
+ break;
+ case SENSOR_GET_DELAY:
+
+ ret = copy_to_user((int*)arg, &interval, sizeof(interval));
+ return 1;
+ break;
+ default: /* redundant, as cmd was checked against MAXNR */
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+static int device_close(struct inode *inode, struct file *filp)
+{
+ printk("Close device\n");
+ return 0;
+}
+
+static int device_i2c_xyz_read_reg(struct i2c_client *client,u8 *buffer, int length)
+{
+ struct i2c_msg msg[] =
+ {
+ {.addr = client->addr, .flags = 0, .len = 1, .buf = buffer,},
+ {.addr = client->addr, .flags = I2C_M_RD, .len = length, .buf = buffer,},
+ };
+#if DMT_DEBUG_DATA
+ IN_FUNC_MSG;
+#endif
+ return i2c_transfer(client->adapter, msg, 2);
+}
+
+void device_i2c_read_xyz(struct i2c_client *client, s16 *xyz_p)
+{
+ u8 buffer[6];
+ s16 xyzTmp[SENSOR_DATA_SIZE];
+ int i, j;
+
+ //get xyz high/low bytes, 0x02~0x07
+ buffer[0] = 2;
+ device_i2c_xyz_read_reg(client, buffer, 6);
+
+ //merge to 11-bits value
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ xyz_p[i] = 0;
+ device_i2c_merge_register_values(client, (xyzTmp + i), buffer[2*i], buffer[2*i + 1]);
+ //transfer to the default layout
+ for(j = 0; j < 3; j++)
+ xyz_p[i] += sensorlayout[i][j] * xyzTmp[j];
+ }
+}
+
+void device_i2c_merge_register_values(struct i2c_client *client, s16 *val, u8 msb, u8 lsb)
+{
+ *val = (((u16)msb) << 3) | (u16)lsb;
+ device_i2c_correct_accel_sign(val);
+}
+
+static inline void device_i2c_correct_accel_sign(s16 *val)
+{
+ *val<<= (sizeof(s16) * BITS_PER_BYTE - 11);
+ *val>>= (sizeof(s16) * BITS_PER_BYTE - 11);
+}
+
+static void DMT_work_func(struct work_struct *fakework)
+{
+ int i;
+ static int firsttime=0;
+ s16 xyz[SENSOR_DATA_SIZE];
+ unsigned long t=atomic_read(&delay);
+ unsigned long dmt_delay = msecs_to_jiffies(t);
+ if(!firsttime)
+ {
+ //gsensor_read_offset_from_file();
+ firsttime=1;
+ }
+
+ //dmt_delay/=1000;
+
+#if DMT_DEBUG_DATA
+ IN_FUNC_MSG;
+ printk("t=%lu ,dmt_delay=%lu\n",t,dmt_delay);
+#endif
+
+ device_i2c_read_xyz(dev.client, (s16 *)&xyz);
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ xyz[i] -= offset.v[i];
+
+#if DMT_DEBUG_DATA
+ printk("x: %d, y: %d, z: %d\n", xyz[0], xyz[1], xyz[2]);
+#endif
+ input_report_abs(input, ABS_X, xyz[gs_conf.xyz_axis[ABS_X][0]]*gs_conf.xyz_axis[ABS_X][1]);
+ input_report_abs(input, ABS_Y, xyz[gs_conf.xyz_axis[ABS_Y][0]]*gs_conf.xyz_axis[ABS_Y][1]);
+ input_report_abs(input, ABS_Z, xyz[gs_conf.xyz_axis[ABS_Z][0]]*gs_conf.xyz_axis[ABS_Z][1]);
+ input_sync(input);
+
+ if(dmt_delay<1)
+ dmt_delay=1;
+
+ schedule_delayed_work(&work, dmt_delay);
+}
+
+
+static int __devinit device_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
+{
+ u8 buffer[4];
+ int i;
+
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ offset.v[i] = 0;
+
+ if(!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ {
+ printk("%s, functionality check failed\n", __func__);
+ return -1;
+ }
+
+ gsensor_reset();
+
+ buffer[0] = CONTROL_REGISTERS;
+ device_i2c_xyz_read_reg(client, buffer, 4);
+ if( buffer[0] == 0x00 && buffer[1] == 0x00 && buffer[2] == 0x88 && buffer[3] == 0x08)
+ {
+ printk(KERN_INFO "i2c Read 0x08 = %d!\n",buffer[0]);
+ printk(KERN_INFO "i2c Read 0x09 = %d!\n",buffer[1]);
+ printk(KERN_INFO "i2c Read 0x0a = %d!\n",buffer[2]);
+ printk(KERN_INFO "i2c Read 0x0b = %d!\n",buffer[3]);
+ printk(KERN_INFO "@@@ %s DMT_DEVICE_NAME registered I2C driver!\n",__FUNCTION__);
+ dev.client = client;
+ }
+ else
+ {
+ printk(KERN_INFO "err : i2c Read 0x08 = %d!\n",buffer[0]);
+ printk(KERN_INFO "err : i2c Read 0x09 = %d!\n",buffer[1]);
+ printk(KERN_INFO "err : i2c Read 0x0a = %d!\n",buffer[2]);
+ printk(KERN_INFO "err : i2c Read 0x0b = %d!\n",buffer[3]);
+ dev.client = NULL;
+ return -1;
+ }
+#if DMT_DEBUG_DATA
+ IN_FUNC_MSG;
+ //check sensorlayout[i][j]
+ for(i = 0; i < 3; ++i)
+ {
+ for(j = 0; j < 3; j++)
+ printk("%d",sensorlayout[i][j]);
+ printk("\n");
+ }
+#endif
+ return 0;
+}
+
+static int __devexit device_i2c_remove(struct i2c_client *client)
+{
+#if DMT_DEBUG_DATA
+ IN_FUNC_MSG;
+#endif
+ return 0;
+}
+
+int dmt08_enable(int en)
+{
+ printk(KERN_DEBUG "%s: enable = %d\n", __func__, en);
+ DMT_sysfs_update_active_status(en);
+ return 0;
+}
+
+int dmt08_setDelay(int mdelay)
+{
+ printk(KERN_DEBUG "%s: delay = %d\n", __func__, mdelay);
+ atomic_set(&delay, mdelay);
+ return 0;
+}
+
+int dmt08_getLSG(int *lsg)
+{
+ *lsg = 256;
+ return 0;
+}
+
+struct gsensor_data dmt08_gs_data = {
+ .i2c_addr = DMT08_I2C_ADDR,
+ .enable = dmt08_enable,
+ .setDelay = dmt08_setDelay,
+ .getLSG = dmt08_getLSG,
+};
+
+static int __init device_init(void)
+{
+ int err=-1;
+ struct device *device;
+ int ret = 0;
+ IN_FUNC_MSG;
+
+ if (get_gsensor_conf(&gs_conf))
+ return -1;
+
+ if (gs_conf.op != 1)
+ return -1;
+
+ printk("G-Sensor dmt08 init\n");
+
+ if (gsensor_register(&dmt08_gs_data))
+ return -1;
+
+ if (gsensor_i2c_register_device() < 0)
+ return -1;
+
+ atomic_set(&delay, 200);
+
+ ret = alloc_chrdev_region(&dev.devno, 0, 1, GSENSOR_DEVICE_NAME);
+ if(ret)
+ {
+ printk("%s, can't allocate chrdev\n", __func__);
+ return ret;
+ }
+ printk("%s, register chrdev(%d, %d)\n", __func__, MAJOR(dev.devno), MINOR(dev.devno));
+
+ cdev_init(&dev.cdev, &dmt_g_sensor_fops);
+ dev.cdev.owner = THIS_MODULE;
+ ret = cdev_add(&dev.cdev, dev.devno, 1);
+ if(ret < 0)
+ {
+ printk("%s, add character device error, ret %d\n", __func__, ret);
+ return ret;
+ }
+ dev.class = class_create(THIS_MODULE, ACCELEMETER_CLASS_NAME);
+ if(IS_ERR(dev.class))
+ {
+ printk("%s, create class, error\n", __func__);
+ return ret;
+ }
+ device=device_create(dev.class, NULL, dev.devno, NULL, GSENSOR_DEVICE_NAME);
+
+ mutex_init(&DMT_mutex);
+
+ INIT_DELAYED_WORK(&work, DMT_work_func);
+ printk("DMT: INIT_DELAYED_WORK\n");
+
+ err=input_init();
+ if(err)
+ {
+ printk("%s:input_init fail, error code= %d\n", __func__, err);
+ }
+
+ err = create_device_attributes(device,DMT_attributes);
+
+ return i2c_add_driver(&device_i2c_driver);
+}
+
+
+static void __exit device_exit(void)
+{
+ IN_FUNC_MSG;
+ input_unregister_device(input);
+ input_free_device(input);
+ cdev_del(&dev.cdev);
+ unregister_chrdev_region(dev.devno, 1);
+ device_destroy(dev.class, dev.devno);
+ class_destroy(dev.class);
+ i2c_del_driver(&device_i2c_driver);
+}
+
+
+void gsensor_write_offset_to_file(void)
+{
+ char data[18];
+ unsigned int orgfs;
+ long lfile=-1;
+ spinlock_t lock; //add by yang
+ spin_lock_init(&lock); //add by yang
+ sprintf(data,"%5d %5d %5d",offset.u.x,offset.u.y,offset.u.z);
+
+ orgfs = get_fs();
+// Set segment descriptor associated to kernel space
+ set_fs(KERNEL_DS);
+
+ lfile=sys_open(OffsetFileName,O_WRONLY|O_CREAT, 0777);
+ if (lfile < 0)
+ {
+ printk("sys_open %s error!!. %ld\n",OffsetFileName,lfile);
+ }
+ else
+ {
+ spin_lock(&lock); //add by yang
+ sys_write(lfile, data,18);
+ sys_close(lfile);
+ spin_unlock(&lock); //add by yang
+ }
+ set_fs(orgfs);
+}
+
+void gsensor_read_offset_from_file(void)
+{
+ unsigned int orgfs;
+ char data[18];
+ long lfile=-1;
+ orgfs = get_fs();
+// Set segment descriptor associated to kernel space
+ set_fs(KERNEL_DS);
+
+ lfile = sys_open(OffsetFileName, O_RDONLY, 0);
+ if (lfile < 0)
+ {
+ printk("sys_open %s error!!. %ld\n",OffsetFileName,lfile);
+ strcpy(data,"00000 00000 00000");
+
+ }
+ else
+ {
+ sys_read(lfile, data, 18);
+ sys_close(lfile);
+ }
+ sscanf(data,"%hd %hd %hd",&offset.u.x,&offset.u.y,&offset.u.z);
+ printk("%5d %5d %5d",offset.u.x,offset.u.y,offset.u.z);
+ set_fs(orgfs);
+}
+
+MODULE_AUTHOR("DMT_RD");
+MODULE_DESCRIPTION("DMT Gsensor Driver");
+MODULE_LICENSE("GPL");
+
+module_init(device_init);
+module_exit(device_exit);
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt08_gsensor/dmt08.h b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt08_gsensor/dmt08.h
new file mode 100755
index 00000000..5a1ac3b7
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt08_gsensor/dmt08.h
@@ -0,0 +1,105 @@
+/*
+ * @file include/linux/dmt.h
+ * @brief DMARD05 & DMARD06 & DMARD07 g-sensor Linux device driver
+ * @author Domintech Technology Co., Ltd (http://www.domintech.com.tw)
+ * @version 1.31
+ * @date 2012/3/27
+ *
+ * @section LICENSE
+ *
+ * Copyright 2011 Domintech Technology Co., Ltd
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ */
+#ifndef DMT_H
+#define DMT_H
+
+#if (defined(CONFIG_SENSORS_DMARD05) || defined(CONFIG_SENSORS_DMARD05_MODULE))
+#define DEVICE_I2C_NAME "dmard05"
+#define DEFAULT_SENSITIVITY 64
+#define WHO_AM_I_VALUE 0x05
+#define X_OUT 0x41
+#define SW_RESET 0x53
+#define WHO_AM_I 0x0f
+#elif (defined(CONFIG_SENSORS_DMARD06) || defined(CONFIG_SENSORS_DMARD06_MODULE))
+#define DEVICE_I2C_NAME "dmard06"
+#define DEFAULT_SENSITIVITY 32
+#define WHO_AM_I_VALUE 0x06
+#define X_OUT 0x41
+#define SW_RESET 0x53
+#define WHO_AM_I 0x0f
+#elif (defined(CONFIG_SENSORS_DMARD07) || defined(CONFIG_SENSORS_DMARD07_MODULE))
+#define DEVICE_I2C_NAME "dmard07"
+#define DEFAULT_SENSITIVITY 64
+#define WHO_AM_I_VALUE 0x07
+#define X_OUT 0x41
+#define SW_RESET 0x53
+#define WHO_AM_I 0x0f
+#elif (defined(CONFIG_SENSORS_DMARD03) || defined(CONFIG_SENSORS_DMARD03_MODULE))
+#define DEVICE_I2C_NAME "dmard03"
+#define DEFAULT_SENSITIVITY 256
+#define CONTROL_REGISTERS 0x08
+#elif (defined(CONFIG_SENSORS_DMARD08) || defined(CONFIG_SENSORS_DMARD08_MODULE) || defined(CONFIG_WMT_SENSOR_DMT08))
+#define DEVICE_I2C_NAME "g-sensor"
+#define DEFAULT_SENSITIVITY 256
+#define CONTROL_REGISTERS 0x08
+#define DMT08_I2C_ADDR 0x1c
+#endif
+
+//#define DMT_DEBUG_DATA 1
+#define DMT_DEBUG_DATA 0
+
+#if DMT_DEBUG_DATA
+#define IN_FUNC_MSG printk(KERN_INFO "@DMT@ In %s\n", __func__)
+#define PRINT_X_Y_Z(x, y, z) printk(KERN_INFO "@DMT@ X/Y/Z axis: %04d , %04d , %04d\n", (x), (y), (z))
+#define PRINT_OFFSET(x, y, z) printk(KERN_INFO "@offset@ X/Y/Z axis: %04d , %04d , %04d\n",offset.x,offset.y,offset.z);
+#else
+#define IN_FUNC_MSG
+#define PRINT_X_Y_Z(x, y, z)
+#define PRINT_OFFSET(x, y, z)
+#endif
+
+//g-senor layout configuration, choose one of the following configuration
+#define CONFIG_GSEN_LAYOUT_PAT_1
+//#define CONFIG_GSEN_LAYOUT_PAT_2
+//#define CONFIG_GSEN_LAYOUT_PAT_3
+//#define CONFIG_GSEN_LAYOUT_PAT_4
+//#define CONFIG_GSEN_LAYOUT_PAT_5
+//#define CONFIG_GSEN_LAYOUT_PAT_6
+//#define CONFIG_GSEN_LAYOUT_PAT_7
+//#define CONFIG_GSEN_LAYOUT_PAT_8
+
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_NEGATIVE 1
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_POSITIVE 2
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Y_NEGATIVE 3
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Y_POSITIVE 4
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_X_NEGATIVE 5
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_X_POSITIVE 6
+
+#define AVG_NUM 16
+
+#define IOCTL_MAGIC 0x09
+#define SENSOR_DATA_SIZE 3
+
+#define SENSOR_RESET _IO(IOCTL_MAGIC, 0)
+#define SENSOR_CALIBRATION _IOWR(IOCTL_MAGIC, 1, int[SENSOR_DATA_SIZE])
+#define SENSOR_GET_OFFSET _IOR(IOCTL_MAGIC, 2, int[SENSOR_DATA_SIZE])
+#define SENSOR_SET_OFFSET _IOWR(IOCTL_MAGIC, 3, int[SENSOR_DATA_SIZE])
+#define SENSOR_READ_ACCEL_XYZ _IOR(IOCTL_MAGIC, 4, int[SENSOR_DATA_SIZE])
+#define SENSOR_SETYPR _IOW(IOCTL_MAGIC, 5, int[SENSOR_DATA_SIZE])
+#define SENSOR_GET_OPEN_STATUS _IO(IOCTL_MAGIC, 6)
+#define SENSOR_GET_CLOSE_STATUS _IO(IOCTL_MAGIC, 7)
+#define SENSOR_GET_DELAY _IOR(IOCTL_MAGIC, 8, unsigned int*)
+
+#define SENSOR_MAXNR 8
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt10_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt10_gsensor/Makefile
new file mode 100755
index 00000000..de723bf5
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt10_gsensor/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the DMARD10 Sensor driver
+#
+
+sensor_dmt10-objs := dmt10.o
+obj-$(CONFIG_WMT_SENSOR_DMT10) += sensor_dmt10.o
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt10_gsensor/dmt10.c b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt10_gsensor/dmt10.c
new file mode 100755
index 00000000..e8e7b288
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt10_gsensor/dmt10.c
@@ -0,0 +1,950 @@
+/*
+ * @file drivers/misc/dmt10.c
+ * @brief DMT g-sensor Linux device driver
+ * @author Domintech Technology Co., Ltd (http://www.domintech.com.tw)
+ * @version 1.03
+ *
+ * @section LICENSE
+ *
+ * Copyright 2012 Domintech Technology Co., Ltd
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * V1.00 D10 First Release date 2012/09/21
+ * V1.01 static struct dmt_data s_dmt Refresh to device_i2c_probe date 2012/11/23
+ * V1.02 0x0D cck : adjustment 204.8KHz core clock date 2012/11/30
+ * V1.03 write TCGYZ & TCGX : set value to 0x00 date 2012/12/10
+ *
+ * @DMT Package version D10_General_driver v1.4
+ *
+ */
+#include "dmt10.h"
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/wakelock.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/clk.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include "../gsensor.h"
+
+static struct gsensor_conf gs_conf;
+
+static unsigned int interval;
+void gsensor_write_offset_to_file(void);
+void gsensor_read_offset_from_file(void);
+char OffsetFileName[] = "/data/misc/dmt/offset.txt"; /* FILE offset.txt */
+static raw_data offset;
+static struct dmt_data *s_dmt;
+static int device_init(void);
+static void device_exit(void);
+
+static int device_open(struct inode*, struct file*);
+static long device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+static int device_close(struct inode*, struct file*);
+
+static int device_i2c_suspend(struct i2c_client *client, pm_message_t mesg);
+static int device_i2c_resume(struct i2c_client *client);
+static int __devinit device_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
+static int __devexit device_i2c_remove(struct i2c_client *client);
+void device_i2c_read_xyz(struct i2c_client *client, s16 *xyz);
+static int device_i2c_rxdata(struct i2c_client *client, unsigned char *rxDat, int length);
+static int device_i2c_txdata(struct i2c_client *client, unsigned char *txData, int length);
+
+static int DMT_GetOpenStatus(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ GSE_LOG("start active=%d\n",dmt->active.counter);
+ wait_event_interruptible(dmt->open_wq, (atomic_read(&dmt->active) != 0));
+ return 0;
+}
+
+static int DMT_GetCloseStatus(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ GSE_LOG("start active=%d\n",dmt->active.counter);
+ wait_event_interruptible(dmt->open_wq, (atomic_read(&dmt->active) <= 0));
+ return 0;
+}
+
+static void DMT_sysfs_update_active_status(struct dmt_data *dmt , int en){
+ unsigned long dmt_delay;
+ if(en){
+ dmt_delay = msecs_to_jiffies(atomic_read(&dmt->delay));
+ if(dmt_delay < 1)
+ dmt_delay = 1;
+
+ GSE_LOG("schedule_delayed_work start with delay time=%lu\n",dmt_delay);
+ schedule_delayed_work(&dmt->delaywork,dmt_delay);
+ }
+ else
+ cancel_delayed_work_sync(&dmt->delaywork);
+}
+
+static bool get_value_as_int(char const *buf, size_t size, int *value){
+ long tmp;
+ if (size == 0)
+ return false;
+ /* maybe text format value */
+ if ((buf[0] == '0') && (size > 1)) {
+ if ((buf[1] == 'x') || (buf[1] == 'X')) {
+ /* hexadecimal format */
+ if (0 != strict_strtol(buf, 16, &tmp))
+ return false;
+ } else {
+ /* octal format */
+ if (0 != strict_strtol(buf, 8, &tmp))
+ return false;
+ }
+ } else {
+ /* decimal format */
+ if (0 != strict_strtol(buf, 10, &tmp))
+ return false;
+ }
+
+ if (tmp > INT_MAX)
+ return false;
+
+ *value = tmp;
+ return true;
+}
+static bool get_value_as_int64(char const *buf, size_t size, long long *value)
+{
+ long long tmp;
+ if (size == 0)
+ return false;
+ /* maybe text format value */
+ if ((buf[0] == '0') && (size > 1)) {
+ if ((buf[1] == 'x') || (buf[1] == 'X')) {
+ /* hexadecimal format */
+ if (0 != strict_strtoll(buf, 16, &tmp))
+ return false;
+ } else {
+ /* octal format */
+ if (0 != strict_strtoll(buf, 8, &tmp))
+ return false;
+ }
+ } else {
+ /* decimal format */
+ if (0 != strict_strtoll(buf, 10, &tmp))
+ return false;
+ }
+
+ if (tmp > LLONG_MAX)
+ return false;
+
+ *value = tmp;
+ return true;
+}
+
+static ssize_t dmt_sysfs_enable_show(
+ struct dmt_data *dmt, char *buf, int pos)
+{
+ char str[2][16]={"ACC enable OFF","ACC enable ON"};
+ int flag;
+ flag=atomic_read(&dmt->enable);
+ return sprintf(buf, "%s\n", str[flag]);
+}
+
+static ssize_t dmt_sysfs_enable_store(
+ struct dmt_data *dmt, char const *buf, size_t count, int pos)
+{
+ int en = 0;
+ if (NULL == buf)
+ return -EINVAL;
+ GSE_LOG("buf=%x %x\n", buf[0], buf[1]);
+ if (0 == count)
+ return 0;
+
+ if (false == get_value_as_int(buf, count, &en))
+ return -EINVAL;
+
+ en = en ? 1 : 0;
+
+ atomic_set(&dmt->enable,en);
+ DMT_sysfs_update_active_status(dmt , en);
+ return count;
+}
+
+/***** Acceleration ***/
+static ssize_t DMT_enable_acc_show(struct device *dev, struct device_attribute *attr, char *buf){
+ return dmt_sysfs_enable_show( dev_get_drvdata(dev), buf, ACC_DATA_FLAG);
+}
+
+static ssize_t DMT_enable_acc_store( struct device *dev, struct device_attribute *attr, char const *buf, size_t count){
+ return dmt_sysfs_enable_store( dev_get_drvdata(dev), buf, count, ACC_DATA_FLAG);
+}
+
+/***** sysfs delay **************************************************/
+static ssize_t dmt_sysfs_delay_show( struct dmt_data *dmt, char *buf, int pos){
+ return sprintf(buf, "%d\n", atomic_read(&dmt->delay));
+}
+
+static ssize_t dmt_sysfs_delay_store( struct dmt_data *dmt, char const *buf, size_t count, int pos){
+ long long val = 0;
+
+ if (NULL == buf)
+ return -EINVAL;
+
+ if (0 == count)
+ return 0;
+
+ if (false == get_value_as_int64(buf, count, &val))
+ return -EINVAL;
+
+ atomic_set(&dmt->delay, (unsigned int) val);
+ GSE_LOG("Driver attribute set delay =%lld\n", val);
+
+ return count;
+}
+
+/***** Accelerometer ***/
+static ssize_t DMT_delay_acc_show( struct device *dev, struct device_attribute *attr, char *buf){
+ return dmt_sysfs_delay_show( dev_get_drvdata(dev), buf, ACC_DATA_FLAG);
+}
+
+static ssize_t DMT_delay_acc_store( struct device *dev, struct device_attribute *attr,char const *buf, size_t count){
+ return dmt_sysfs_delay_store( dev_get_drvdata(dev), buf, count, ACC_DATA_FLAG);
+}
+
+static struct device_attribute DMT_attributes[] = {
+ __ATTR(enable_acc, 0755, DMT_enable_acc_show, DMT_enable_acc_store),
+ __ATTR(delay_acc, 0755, DMT_delay_acc_show, DMT_delay_acc_store),
+ __ATTR_NULL,
+};
+
+static char const *const ACCELEMETER_CLASS_NAME = "accelemeter";
+static char const *const GSENSOR_DEVICE_NAME = "dmard10";
+static char const *const device_link_name = "i2c";
+static dev_t const dmt_device_dev_t = MKDEV(MISC_MAJOR, 240);
+
+/***** dmt sysfs functions ******************************************/
+static int create_device_attributes(struct device *dev, struct device_attribute *attrs){
+ int i;
+ int err = 0;
+ for (i = 0 ; NULL != attrs[i].attr.name ; ++i) {
+ err = device_create_file(dev, &attrs[i]);
+ if (0 != err)
+ break;
+ }
+
+ if (0 != err) {
+ for (; i >= 0 ; --i)
+ device_remove_file(dev, &attrs[i]);
+ }
+ return err;
+}
+
+static void remove_device_attributes(
+ struct device *dev,
+ struct device_attribute *attrs)
+{
+ int i;
+
+ for (i = 0 ; NULL != attrs[i].attr.name ; ++i)
+ device_remove_file(dev, &attrs[i]);
+}
+
+static int create_sysfs_interfaces(struct dmt_data *dmt)
+{
+ int err;
+
+ if (NULL == dmt)
+ return -EINVAL;
+
+ err = 0;
+ dmt->class = class_create(THIS_MODULE, ACCELEMETER_CLASS_NAME);
+ if (IS_ERR(dmt->class)) {
+ err = PTR_ERR(dmt->class);
+ goto exit_class_create_failed;
+ }
+
+ dmt->class_dev = device_create(
+ dmt->class,
+ NULL,
+ dmt_device_dev_t,
+ dmt,
+ GSENSOR_DEVICE_NAME);
+ if (IS_ERR(dmt->class_dev)) {
+ err = PTR_ERR(dmt->class_dev);
+ goto exit_class_device_create_failed;
+ }
+
+ err = sysfs_create_link(
+ &dmt->class_dev->kobj,
+ &dmt->client->dev.kobj,
+ device_link_name);
+ if (0 > err)
+ goto exit_sysfs_create_link_failed;
+
+ err = create_device_attributes(
+ dmt->class_dev,
+ DMT_attributes);
+ if (0 > err)
+ goto exit_device_attributes_create_failed;
+#if 0
+ err = create_device_binary_attributes(
+ &dmt->class_dev->kobj,
+ dmt_bin_attributes);
+ if (0 > err)
+ goto exit_device_binary_attributes_create_failed;
+#endif
+
+ return err;
+
+#if 0
+exit_device_binary_attributes_create_failed:
+ remove_device_attributes(dmt->class_dev, dmt_attributes);
+#endif
+exit_device_attributes_create_failed:
+ sysfs_remove_link(&dmt->class_dev->kobj, device_link_name);
+exit_sysfs_create_link_failed:
+ device_destroy(dmt->class, dmt_device_dev_t);
+exit_class_device_create_failed:
+ dmt->class_dev = NULL;
+ class_destroy(dmt->class);
+exit_class_create_failed:
+ dmt->class = NULL;
+ return err;
+}
+
+static void remove_sysfs_interfaces(struct dmt_data *dmt)
+{
+ if (NULL == dmt)
+ return;
+
+ if (NULL != dmt->class_dev) {
+
+ remove_device_attributes(
+ dmt->class_dev,
+ DMT_attributes);
+ sysfs_remove_link(
+ &dmt->class_dev->kobj,
+ device_link_name);
+ dmt->class_dev = NULL;
+ }
+ if (NULL != dmt->class) {
+ device_destroy(
+ dmt->class,
+ dmt_device_dev_t);
+ class_destroy(dmt->class);
+ dmt->class = NULL;
+ }
+}
+
+int input_init(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ int err=0;
+ dmt->input=input_allocate_device();
+ if (!dmt->input){
+ GSE_ERR("input device allocate ERROR !!\n");
+ return -ENOMEM;
+ }
+ else
+ GSE_LOG("input device allocate Success !!\n");
+ /* Setup input device */
+ set_bit(EV_ABS, dmt->input->evbit);
+ /* Accelerometer [-78.5, 78.5]m/s2 in Q16 */
+ input_set_abs_params(dmt->input, ABS_X, -1024, 1024, 0, 0);
+ input_set_abs_params(dmt->input, ABS_Y, -1024, 1024, 0, 0);
+ input_set_abs_params(dmt->input, ABS_Z, -1024, 1024, 0, 0);
+ /* Set InputDevice Name */
+ dmt->input->name = INPUT_NAME_ACC;
+ /* Register */
+ err = input_register_device(dmt->input);
+ if (err) {
+ GSE_ERR("input_register_device ERROR !!\n");
+ input_free_device(dmt->input);
+ return err;
+ }
+ GSE_LOG("input_register_device SUCCESS %d !! \n",err);
+
+ return err;
+}
+
+int gsensor_calibrate(void)
+{
+ //struct dmt_data *dmt = i2c_get_clientdata(client);
+ raw_data avg;
+ int i, j;
+ long xyz_acc[SENSOR_DATA_SIZE];
+ s16 xyz[SENSOR_DATA_SIZE];
+
+ offset.u.x=0;
+ offset.u.y=0;
+ offset.u.z=0;
+ /* initialize the accumulation buffer */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ xyz_acc[i] = 0;
+
+ for(i = 0; i < AVG_NUM; i++) {
+ device_i2c_read_xyz(s_dmt->client, (s16 *)&xyz);
+ for(j = 0; j < SENSOR_DATA_SIZE; ++j)
+ xyz_acc[j] += xyz[j];
+ }
+ /* calculate averages */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ avg.v[i] = (s16) (xyz_acc[i] / AVG_NUM);
+
+ if(avg.v[2] < 0){
+ offset.u.x = avg.v[0] ;
+ offset.u.y = avg.v[1] ;
+ offset.u.z = avg.v[2] + DEFAULT_SENSITIVITY;
+ return CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_POSITIVE;
+ }
+ else{
+ offset.u.x = avg.v[0] ;
+ offset.u.y = avg.v[1] ;
+ offset.u.z = avg.v[2] - DEFAULT_SENSITIVITY;
+ return CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_NEGATIVE;
+ }
+ return 0;
+}
+
+int gsensor_reset(struct i2c_client *client){
+ unsigned char buffer[7], buffer2[2];
+ /* 1. check D10 , VALUE_STADR = 0x55 , VALUE_STAINT = 0xAA */
+ buffer[0] = REG_STADR;
+ buffer2[0] = REG_STAINT;
+
+ device_i2c_rxdata(client, buffer, 2);
+ device_i2c_rxdata(client, buffer2, 2);
+
+ if( buffer[0] == VALUE_STADR || buffer2[0] == VALUE_STAINT){
+ GSE_LOG(" REG_STADR_VALUE = %d , REG_STAINT_VALUE = %d\n", buffer[0], buffer2[0]);
+ }
+ else{
+ GSE_LOG(" REG_STADR_VALUE = %d , REG_STAINT_VALUE = %d \n", buffer[0], buffer2[0]);
+ return -1;
+ }
+ /* 2. Powerdown reset */
+ buffer[0] = REG_PD;
+ buffer[1] = VALUE_PD_RST;
+ device_i2c_txdata(client, buffer, 2);
+ /* 3. ACTR => Standby mode => Download OTP to parameter reg => Standby mode => Reset data path => Standby mode */
+ buffer[0] = REG_ACTR;
+ buffer[1] = MODE_Standby;
+ buffer[2] = MODE_ReadOTP;
+ buffer[3] = MODE_Standby;
+ buffer[4] = MODE_ResetDataPath;
+ buffer[5] = MODE_Standby;
+ device_i2c_txdata(client, buffer, 6);
+ /* 4. OSCA_EN = 1 ,TSTO = b'000(INT1 = normal, TEST0 = normal) */
+ buffer[0] = REG_MISC2;
+ buffer[1] = VALUE_MISC2_OSCA_EN;
+ device_i2c_txdata(client, buffer, 2);
+ /* 5. AFEN = 1(AFE will powerdown after ADC) */
+ buffer[0] = REG_AFEM;
+ buffer[1] = VALUE_AFEM_AFEN_Normal;
+ buffer[2] = VALUE_CKSEL_ODR_100_204;
+ buffer[3] = VALUE_INTC;
+ buffer[4] = VALUE_TAPNS_Ave_2;
+ buffer[5] = 0x00; // DLYC, no delay timing
+ buffer[6] = 0x07; // INTD=1 (push-pull), INTA=1 (active high), AUTOT=1 (enable T)
+ device_i2c_txdata(client, buffer, 7);
+ /* 6. write TCGYZ & TCGX */
+ buffer[0] = REG_WDAL; // REG:0x01
+ buffer[1] = 0x00; // set TC of Y,Z gain value
+ buffer[2] = 0x00; // set TC of X gain value
+ buffer[3] = 0x03; // Temperature coefficient of X,Y,Z gain
+ device_i2c_txdata(client, buffer, 4);
+
+ buffer[0] = REG_ACTR; // REG:0x00
+ buffer[1] = MODE_Standby; // Standby
+ buffer[2] = MODE_WriteOTPBuf; // WriteOTPBuf
+ buffer[3] = MODE_Standby; // Standby
+ device_i2c_txdata(client, buffer, 4);
+ //buffer[0] = REG_TCGYZ;
+ //device_i2c_rxdata(client, buffer, 2);
+ //GSE_LOG(" TCGYZ = %d, TCGX = %d \n", buffer[0], buffer[1]);
+
+ /* 7. Activation mode */
+ buffer[0] = REG_ACTR;
+ buffer[1] = MODE_Active;
+ device_i2c_txdata(client, buffer, 2);
+ return 0;
+}
+
+void gsensor_set_offset(int val[3]){
+ int i;
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ offset.v[i] = (s16) val[i];
+}
+
+struct file_operations dmt_g_sensor_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = device_ioctl,
+ .open = device_open,
+ .release = device_close,
+};
+
+static struct miscdevice dmt_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = DEVICE_I2C_NAME,
+ .fops = &dmt_g_sensor_fops,
+};
+
+static int sensor_close_dev(struct i2c_client *client){
+ char buffer[3];
+ buffer[0] = REG_ACTR;
+ buffer[1] = MODE_Standby;
+ buffer[2] = MODE_Off;
+ GSE_FUN();
+ return device_i2c_txdata(client,buffer, 3);
+}
+
+static int device_i2c_suspend(struct i2c_client *client, pm_message_t mesg){
+ GSE_FUN();
+ return sensor_close_dev(client);
+}
+
+static int device_i2c_resume(struct i2c_client *client){
+ GSE_FUN();
+ return gsensor_reset(client);
+}
+
+static void device_i2c_shutdown(struct i2c_client *client)
+{
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ flush_delayed_work_sync(&dmt->delaywork);
+ cancel_delayed_work_sync(&dmt->delaywork);
+}
+
+static int __devexit device_i2c_remove(struct i2c_client *client){
+ return 0;
+}
+
+static const struct i2c_device_id device_i2c_ids[] = {
+ {DEVICE_I2C_NAME, 0},
+ {}
+};
+
+//MODULE_DEVICE_TABLE(i2c, device_i2c_ids);
+
+static struct i2c_driver device_i2c_driver =
+{
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DEVICE_I2C_NAME,
+ },
+ .class = I2C_CLASS_HWMON,
+ .id_table = device_i2c_ids,
+ .probe = device_i2c_probe,
+ .remove = __devexit_p(device_i2c_remove),
+ .shutdown = device_i2c_shutdown,
+#ifndef CONFIG_ANDROID_POWER
+ .suspend = device_i2c_suspend,
+ .resume = device_i2c_resume,
+#endif
+
+};
+
+static int device_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static long device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+ //struct i2c_client *client = (struct i2c_client*)filp->private_data;
+ //struct dmt_data *dmt = (struct dmt_data*)i2c_get_clientdata(client);
+
+ int err = 0, ret = 0, i;
+ int intBuf[SENSOR_DATA_SIZE];
+ s16 xyz[SENSOR_DATA_SIZE];
+ /* check type */
+ if (_IOC_TYPE(cmd) != IOCTL_MAGIC) return -ENOTTY;
+
+ /* check user space pointer is valid */
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
+ if (err) return -EFAULT;
+
+ switch(cmd)
+ {
+ case SENSOR_RESET:
+ gsensor_reset(s_dmt->client);
+ return ret;
+
+ case SENSOR_CALIBRATION:
+ /* get orientation info */
+ //if(copy_from_user(&intBuf, (int*)arg, sizeof(intBuf))) return -EFAULT;
+ gsensor_calibrate();
+ GSE_LOG("Sensor_calibration:%d %d %d\n",offset.u.x,offset.u.y,offset.u.z);
+ /* save file */
+ gsensor_write_offset_to_file();
+
+ /* return the offset */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ intBuf[i] = offset.v[i];
+
+ ret = copy_to_user((int *)arg, &intBuf, sizeof(intBuf));
+ return ret;
+
+ case SENSOR_GET_OFFSET:
+ /* get data from file */
+ gsensor_read_offset_from_file();
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ intBuf[i] = offset.v[i];
+
+ ret = copy_to_user((int *)arg, &intBuf, sizeof(intBuf));
+ return ret;
+
+ case SENSOR_SET_OFFSET:
+ ret = copy_from_user(&intBuf, (int *)arg, sizeof(intBuf));
+ gsensor_set_offset(intBuf);
+ /* write in to file */
+ gsensor_write_offset_to_file();
+ return ret;
+
+ case SENSOR_READ_ACCEL_XYZ:
+ device_i2c_read_xyz(s_dmt->client, (s16 *)&xyz);
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ intBuf[i] = xyz[i] - offset.v[i];
+
+ ret = copy_to_user((int*)arg, &intBuf, sizeof(intBuf));
+ return ret;
+
+ case SENSOR_SETYPR:
+ if(copy_from_user(&intBuf, (int*)arg, sizeof(intBuf))) {
+ GSE_LOG("%s:copy_from_user(&intBuf, (int*)arg, sizeof(intBuf)) ERROR, -EFAULT\n",__func__);
+ return -EFAULT;
+ }
+ input_report_abs(s_dmt->input, ABS_X, intBuf[0]);
+ input_report_abs(s_dmt->input, ABS_Y, -intBuf[1]);
+ input_report_abs(s_dmt->input, ABS_Z, -intBuf[2]);
+ input_sync(s_dmt->input);
+ GSE_LOG(KERN_INFO "%s:SENSOR_SETYPR OK! x=%d,y=%d,z=%d\n",__func__,intBuf[0],intBuf[1],intBuf[2]);
+ return 1;
+
+ case SENSOR_GET_OPEN_STATUS:
+ GSE_LOG(KERN_INFO "%s:Going into DMT_GetOpenStatus()\n",__func__);
+ DMT_GetOpenStatus(s_dmt->client);
+ GSE_LOG(KERN_INFO "%s:DMT_GetOpenStatus() finished\n",__func__);
+ return 1;
+ break;
+
+ case SENSOR_GET_CLOSE_STATUS:
+ GSE_LOG(KERN_INFO "%s:Going into DMT_GetCloseStatus()\n",__func__);
+ DMT_GetCloseStatus(s_dmt->client);
+ GSE_LOG(KERN_INFO "%s:DMT_GetCloseStatus() finished\n",__func__);
+ return 1;
+ break;
+
+ case SENSOR_GET_DELAY:
+ ret = copy_to_user((int*)arg, &interval, sizeof(interval));
+ return 1;
+ break;
+
+ default: /* redundant, as cmd was checked against MAXNR */
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+static int device_close(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+/***** I2C I/O function ***********************************************/
+static int device_i2c_rxdata( struct i2c_client *client, unsigned char *rxData, int length)
+{
+ struct i2c_msg msgs[] =
+ {
+ {.addr = client->addr, .flags = 0, .len = 1, .buf = rxData,},
+ {.addr = client->addr, .flags = I2C_M_RD, .len = length, .buf = rxData,},
+ };
+ //unsigned char addr = rxData[0];
+ if (i2c_transfer(client->adapter, msgs, 2) < 0) {
+ dev_err(&client->dev, "%s: transfer failed.", __func__);
+ return -EIO;
+ }
+ //DMT_DATA(&client->dev, "RxData: len=%02x, addr=%02x, data=%02x\n",
+ //length, addr, rxData[0]);
+
+ return 0;
+}
+
+static int device_i2c_txdata( struct i2c_client *client, unsigned char *txData, int length)
+{
+ struct i2c_msg msg[] =
+ {
+ {.addr = client->addr, .flags = 0, .len = length, .buf = txData,},
+ };
+
+ if (i2c_transfer(client->adapter, msg, 1) < 0) {
+ dev_err(&client->dev, "%s: transfer failed.", __func__);
+ return -EIO;
+ }
+ //DMT_DATA(&client->dev, "TxData: len=%02x, addr=%02x data=%02x\n",
+ //length, txData[0], txData[1]);
+ return 0;
+}
+/* 1g = 128 becomes 1g = 1024 */
+static inline void device_i2c_correct_accel_sign(s16 *val){
+ *val<<= 3;
+}
+
+void device_i2c_merge_register_values(struct i2c_client *client, s16 *val, u8 msb, u8 lsb){
+ *val = (((u16)msb) << 8) | (u16)lsb;
+ device_i2c_correct_accel_sign(val);
+}
+
+void device_i2c_read_xyz(struct i2c_client *client, s16 *xyz_p){
+ u8 buffer[11];
+ s16 xyzTmp[SENSOR_DATA_SIZE];
+ int i, j;
+ /* get xyz high/low bytes, 0x12 */
+ buffer[0] = REG_STADR;
+ device_i2c_rxdata(client, buffer, 10);
+
+ /* merge to 10-bits value */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ xyz_p[i] = 0;
+ device_i2c_merge_register_values(client, (xyzTmp + i), buffer[2*(i+1)+1], buffer[2*(i+1)]);
+ /* transfer to the default layout */
+ for(j = 0; j < 3; j++)
+ xyz_p[i] += sensorlayout[i][j] * xyzTmp[j];
+ }
+ GSE_LOG("xyz_p: %04d , %04d , %04d\n", xyz_p[0], xyz_p[1], xyz_p[2]);
+}
+
+static void DMT_work_func(struct work_struct *delaywork)
+{
+ struct dmt_data *dmt = container_of(delaywork, struct dmt_data, delaywork.work);
+ int i;
+ static int firsttime=0;
+ s16 xyz[SENSOR_DATA_SIZE];
+
+ unsigned long t=atomic_read(&dmt->delay);
+ unsigned long dmt_delay = msecs_to_jiffies(t);
+ if(!firsttime){
+ //gsensor_read_offset_from_file();
+ firsttime=1;
+ }
+
+ GSE_LOG("t=%lu , dmt_delay=%lu\n", t, dmt_delay);
+ device_i2c_read_xyz(dmt->client, (s16 *)&xyz);
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ xyz[i] -= offset.v[i];
+
+ GSE_LOG("@DMTRaw@ X/Y/Z axis: %04d , %04d , %04d\n", xyz[0], xyz[1], xyz[2]);
+ GSE_LOG("@Offset@ X/Y/Z axis: %04d , %04d , %04d\n", offset.u.x, offset.u.y, offset.u.z);
+ input_report_abs(dmt->input, ABS_X, xyz[gs_conf.xyz_axis[ABS_X][0]]*gs_conf.xyz_axis[ABS_X][1]);
+ input_report_abs(dmt->input, ABS_Y, xyz[gs_conf.xyz_axis[ABS_Y][0]]*gs_conf.xyz_axis[ABS_Y][1]);
+ input_report_abs(dmt->input, ABS_Z, xyz[gs_conf.xyz_axis[ABS_Z][0]]*gs_conf.xyz_axis[ABS_Z][1]);
+ input_sync(dmt->input);
+
+ if(dmt_delay < 1)
+ dmt_delay = 1;
+ schedule_delayed_work(&dmt->delaywork, dmt_delay);
+}
+
+static int __devinit device_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id){
+ int i, ret = 0;
+ //struct dmt_data *s_dmt;
+
+ GSE_FUN();
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ offset.v[i] = 0;
+
+ if(!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)){
+ GSE_ERR("check_functionality failed.\n");
+ ret = -ENODEV;
+ goto exit0;
+ }
+
+ /* Allocate memory for driver data */
+ s_dmt = kzalloc(sizeof(struct dmt_data), GFP_KERNEL);
+ memset(s_dmt, 0, sizeof(struct dmt_data));
+ if (s_dmt == NULL) {
+ GSE_ERR("alloc data failed.\n");
+ ret = -ENOMEM;
+ goto exit1;
+ }
+
+ /***** I2C initialization *****/
+ s_dmt->client = client;
+ /* set client data */
+ i2c_set_clientdata(client, s_dmt);
+ ret = gsensor_reset(client);
+ if (ret < 0)
+ goto exit2;
+
+ /***** input *****/
+ ret = input_init(client);
+ if (ret){
+ GSE_ERR("input_init fail, error code= %d\n",ret);
+ goto exit3;
+ }
+
+ /**** initialize variables in dmt_data *****/
+ init_waitqueue_head(&s_dmt->open_wq);
+ atomic_set(&s_dmt->active, 0);
+ atomic_set(&s_dmt->enable, 0);
+ atomic_set(&s_dmt->delay, 0);
+ mutex_init(&s_dmt->sensor_mutex);
+ /***** misc *****/
+ /* we have been register miscdevice in device_init, and
+ * marked by Eason 2013/2/4*/
+ /*ret = misc_register(&dmt_device);
+ if (ret){
+ GSE_ERR("dmt_dev register failed");
+ goto exit5;
+ }*/
+
+ /***** sysfs *****/
+ ret = create_sysfs_interfaces(s_dmt);
+ if (ret < 0){
+ GSE_ERR("create sysfs failed.");
+ goto exit6;
+ }
+
+ INIT_DELAYED_WORK(&s_dmt->delaywork, DMT_work_func);
+ GSE_LOG("DMT: INIT_DELAYED_WORK\n");
+ return 0;
+
+exit6:
+ //misc_deregister(&dmt_device);
+exit5:
+ input_unregister_device(s_dmt->input);
+exit3:
+ kfree(s_dmt);
+exit2:
+exit1:
+exit0:
+ return ret;
+}
+
+int dmt10_enable(int en)
+{
+ printk(KERN_DEBUG "%s: enable = %d\n", __func__, en);
+ DMT_sysfs_update_active_status(s_dmt,en);
+ return 0;
+}
+
+int dmt10_setDelay(int mdelay)
+{
+ printk(KERN_DEBUG "%s: delay = %d\n", __func__, mdelay);
+ atomic_set(&s_dmt->delay, mdelay);
+ return 0;
+}
+
+int dmt10_getLSG(int *lsg)
+{
+ *lsg = 1024;
+ return 0;
+}
+
+struct gsensor_data dmt10_gs_data = {
+ .i2c_addr = DMT10_I2C_ADDR,
+ .enable = dmt10_enable,
+ .setDelay = dmt10_setDelay,
+ .getLSG = dmt10_getLSG,
+};
+
+static int __init device_init(void){
+ int ret = 0;
+
+ if (get_gsensor_conf(&gs_conf))
+ return -1;
+
+ if (gs_conf.op != 3)
+ return -1;
+ printk("G-Sensor dmt10 init\n");
+
+ if (gsensor_register(&dmt10_gs_data))
+ return -1;
+
+ if (gsensor_i2c_register_device() < 0)
+ return -1;
+
+ return i2c_add_driver(&device_i2c_driver);
+}
+
+static void __exit device_exit(void){
+ i2c_del_driver(&device_i2c_driver);
+}
+
+void gsensor_write_offset_to_file(void){
+ char data[18];
+ unsigned int orgfs;
+ struct file *fp;
+
+ sprintf(data,"%5d %5d %5d",offset.u.x,offset.u.y,offset.u.z);
+ orgfs = get_fs();
+ /* Set segment descriptor associated to kernel space */
+ set_fs(KERNEL_DS);
+ fp = filp_open(OffsetFileName, O_RDWR | O_CREAT, 0777);
+ if(IS_ERR(fp)){
+ GSE_ERR("filp_open %s error!!.\n",OffsetFileName);
+ }
+ else{
+ GSE_LOG("filp_open %s SUCCESS!!.\n",OffsetFileName);
+ fp->f_op->write(fp,data,18, &fp->f_pos);
+ filp_close(fp,NULL);
+ }
+ set_fs(orgfs);
+}
+
+void gsensor_read_offset_from_file(void){
+ unsigned int orgfs;
+ char data[18];
+ struct file *fp;
+ int ux,uy,uz;
+ orgfs = get_fs();
+ /* Set segment descriptor associated to kernel space */
+ set_fs(KERNEL_DS);
+
+ fp = filp_open(OffsetFileName, O_RDWR , 0);
+ GSE_FUN();
+ if(IS_ERR(fp)){
+ GSE_ERR("Sorry,file open ERROR !\n");
+ offset.u.x=0;offset.u.y=0;offset.u.z=0;
+#if AUTO_CALIBRATION
+ /* get acceleration average reading */
+ gsensor_calibrate();
+ gsensor_write_offset_to_file();
+#endif
+ }
+ else{
+ GSE_LOG("filp_open %s SUCCESS!!.\n",OffsetFileName);
+ fp->f_op->read(fp,data,18, &fp->f_pos);
+ GSE_LOG("filp_read result %s\n",data);
+ sscanf(data,"%d %d %d",&ux,&uy,&uz);
+ offset.u.x=ux;
+ offset.u.y=uy;
+ offset.u.z=uz;
+ filp_close(fp,NULL);
+ }
+ set_fs(orgfs);
+}
+//*********************************************************************************************************
+MODULE_AUTHOR("DMT_RD");
+MODULE_DESCRIPTION("DMT Gsensor Driver");
+MODULE_LICENSE("GPL");
+
+module_init(device_init);
+module_exit(device_exit);
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt10_gsensor/dmt10.h b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt10_gsensor/dmt10.h
new file mode 100755
index 00000000..61343657
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/dmt10_gsensor/dmt10.h
@@ -0,0 +1,187 @@
+/*
+ * @file include/linux/dmt10.h
+ * @brief DMT g-sensor Linux device driver
+ * @author Domintech Technology Co., Ltd (http://www.domintech.com.tw)
+ * @version 1.02
+ * @date 2012/12/10
+ *
+ * @section LICENSE
+ *
+ * Copyright 2012 Domintech Technology Co., Ltd
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * @DMT Package version D10_General_driver v1.4
+ *
+ *
+ */
+#ifndef DMT10_H
+#define DMT10_H
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include <linux/syscalls.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+
+#define AUTO_CALIBRATION 0
+
+#define DMT_DEBUG_DATA 0
+#define GSE_TAG "[DMT_Gsensor]"
+#if DMT_DEBUG_DATA
+#define GSE_ERR(fmt, args...) printk(KERN_ERR GSE_TAG"%s %d : "fmt, __FUNCTION__, __LINE__, ##args)
+#define GSE_LOG(fmt, args...) printk(KERN_INFO GSE_TAG fmt, ##args)
+#define GSE_FUN(f) printk(KERN_INFO GSE_TAG" %s: %s: %i\n", __FILE__, __func__, __LINE__)
+#define DMT_DATA(dev, ...) dev_dbg((dev), ##__VA_ARGS__)
+#else
+#define GSE_ERR(fmt, args...)
+#define GSE_LOG(fmt, args...)
+#define GSE_FUN(f)
+#define DMT_DATA(dev, format, ...)
+#endif
+
+#define DMT10_I2C_ADDR 0x18
+
+
+#define INPUT_NAME_ACC "g-sensor" /* Input Device Name */
+#define DEVICE_I2C_NAME "g-sensor" /* Device name for DMARD10 misc. device */
+#define REG_ACTR 0x00
+#define REG_WDAL 0x01
+#define REG_TAPNS 0x0f
+#define REG_MISC2 0x1f
+#define REG_AFEM 0x0c
+#define REG_CKSEL 0x0d
+#define REG_INTC 0x0e
+#define REG_STADR 0x12
+#define REG_STAINT 0x1C
+#define REG_PD 0x21
+#define REG_TCGYZ 0x26
+#define REG_X_OUT 0x41
+
+#define MODE_Off 0x00
+#define MODE_ResetAtOff 0x01
+#define MODE_Standby 0x02
+#define MODE_ResetAtStandby 0x03
+#define MODE_Active 0x06
+#define MODE_Trigger 0x0a
+#define MODE_ReadOTP 0x12
+#define MODE_WriteOTP 0x22
+#define MODE_WriteOTPBuf 0x42
+#define MODE_ResetDataPath 0x82
+
+#define VALUE_STADR 0x55
+#define VALUE_STAINT 0xAA
+#define VALUE_AFEM_AFEN_Normal 0x8f// AFEN set 1 , ATM[2:0]=b'000(normal),EN_Z/Y/X/T=1
+#define VALUE_AFEM_Normal 0x0f// AFEN set 0 , ATM[2:0]=b'000(normal),EN_Z/Y/X/T=1
+#define VALUE_INTC 0x00// INTC[6:5]=b'00
+#define VALUE_INTC_Interrupt_En 0x20// INTC[6:5]=b'01 (Data ready interrupt enable, active high at INT0)
+#define VALUE_CKSEL_ODR_0_204 0x04// ODR[3:0]=b'0000 (0.78125Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_1_204 0x14// ODR[3:0]=b'0001 (1.5625Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_3_204 0x24// ODR[3:0]=b'0010 (3.125Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_6_204 0x34// ODR[3:0]=b'0011 (6.25Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_12_204 0x44// ODR[3:0]=b'0100 (12.5Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_25_204 0x54// ODR[3:0]=b'0101 (25Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_50_204 0x64// ODR[3:0]=b'0110 (50Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_100_204 0x74// ODR[3:0]=b'0111 (100Hz), CCK[3:0]=b'0100 (204.8kHZ)
+
+#define VALUE_TAPNS_NoFilter 0x00 // TAP1/TAP2 NO FILTER
+#define VALUE_TAPNS_Ave_2 0x11 // TAP1/TAP2 Average 2
+#define VALUE_TAPNS_Ave_4 0x22 // TAP1/TAP2 Average 4
+#define VALUE_TAPNS_Ave_8 0x33 // TAP1/TAP2 Average 8
+#define VALUE_TAPNS_Ave_16 0x44 // TAP1/TAP2 Average 16
+#define VALUE_TAPNS_Ave_32 0x55 // TAP1/TAP2 Average 32
+#define VALUE_MISC2_OSCA_EN 0x08
+#define VALUE_PD_RST 0x52
+
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_NEGATIVE 1
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_POSITIVE 2
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Y_NEGATIVE 3
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Y_POSITIVE 4
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_X_NEGATIVE 5
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_X_POSITIVE 6
+
+#define AVG_NUM 16
+#define SENSOR_DATA_SIZE 3
+#define DEFAULT_SENSITIVITY 1024
+
+#define IOCTL_MAGIC 0x09
+#define SENSOR_RESET _IO(IOCTL_MAGIC, 0)
+#define SENSOR_CALIBRATION _IOWR(IOCTL_MAGIC, 1, int[SENSOR_DATA_SIZE])
+#define SENSOR_GET_OFFSET _IOR(IOCTL_MAGIC, 2, int[SENSOR_DATA_SIZE])
+#define SENSOR_SET_OFFSET _IOWR(IOCTL_MAGIC, 3, int[SENSOR_DATA_SIZE])
+#define SENSOR_READ_ACCEL_XYZ _IOR(IOCTL_MAGIC, 4, int[SENSOR_DATA_SIZE])
+#define SENSOR_SETYPR _IOW(IOCTL_MAGIC, 5, int[SENSOR_DATA_SIZE])
+#define SENSOR_GET_OPEN_STATUS _IO(IOCTL_MAGIC, 6)
+#define SENSOR_GET_CLOSE_STATUS _IO(IOCTL_MAGIC, 7)
+#define SENSOR_GET_DELAY _IOR(IOCTL_MAGIC, 8, unsigned int*)
+#define SENSOR_MAXNR 8
+
+/* g-senor layout configuration, choose one of the following configuration */
+#define CONFIG_GSEN_LAYOUT_PAT_1 1
+#define CONFIG_GSEN_LAYOUT_PAT_2 0
+#define CONFIG_GSEN_LAYOUT_PAT_3 0
+#define CONFIG_GSEN_LAYOUT_PAT_4 0
+#define CONFIG_GSEN_LAYOUT_PAT_5 0
+#define CONFIG_GSEN_LAYOUT_PAT_6 0
+#define CONFIG_GSEN_LAYOUT_PAT_7 0
+#define CONFIG_GSEN_LAYOUT_PAT_8 0
+
+s16 sensorlayout[3][3] = {
+#if CONFIG_GSEN_LAYOUT_PAT_1
+ { 1, 0, 0}, { 0, 1, 0}, { 0, 0, 1},
+#elif CONFIG_GSEN_LAYOUT_PAT_2
+ { 0, 1, 0}, {-1, 0, 0}, { 0, 0, 1},
+#elif CONFIG_GSEN_LAYOUT_PAT_3
+ {-1, 0, 0}, { 0,-1, 0}, { 0, 0, 1},
+#elif CONFIG_GSEN_LAYOUT_PAT_4
+ { 0,-1, 0}, { 1, 0, 0}, { 0, 0, 1},
+#elif CONFIG_GSEN_LAYOUT_PAT_5
+ {-1, 0, 0}, { 0, 1, 0}, { 0, 0,-1},
+#elif CONFIG_GSEN_LAYOUT_PAT_6
+ { 0,-1, 0}, {-1, 0, 0}, { 0, 0,-1},
+#elif CONFIG_GSEN_LAYOUT_PAT_7
+ { 1, 0, 0}, { 0,-1, 0}, { 0, 0,-1},
+#elif CONFIG_GSEN_LAYOUT_PAT_8
+ { 0, 1, 0}, { 1, 0, 0}, { 0, 0,-1},
+#endif
+};
+
+typedef union {
+ struct {
+ s16 x;
+ s16 y;
+ s16 z;
+ } u;
+ s16 v[SENSOR_DATA_SIZE];
+} raw_data;
+
+struct dmt_data {
+ dev_t devno;
+ struct cdev cdev;
+ struct device *class_dev;
+ struct class *class;
+ struct input_dev *input;
+ struct i2c_client *client;
+ struct delayed_work delaywork;
+ struct work_struct work;
+ struct mutex sensor_mutex;
+ wait_queue_head_t open_wq;
+ atomic_t active;
+ atomic_t delay;
+ atomic_t enable;
+};
+
+#define ACC_DATA_FLAG 0
+#define MAG_DATA_FLAG 1
+#define ORI_DATA_FLAG 2
+#define DMT_NUM_SENSORS 3
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/gsensor.c b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/gsensor.c
new file mode 100755
index 00000000..bd0b16af
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/gsensor.c
@@ -0,0 +1,180 @@
+/*++
+Copyright (c) 2012 WonderMedia Technologies, Inc. All Rights Reserved.
+This PROPRIETARY SOFTWARE is the property of WonderMedia Technologies, Inc.
+and may contain trade secrets and/or other confidential information of
+WonderMedia Technologies, Inc. This file shall not be disclosed to any
+third party, in whole or in part, without prior written consent of
+WonderMedia.
+
+THIS PROPRIETARY SOFTWARE AND ANY RELATED DOCUMENTATION ARE PROVIDED
+AS IS, WITH ALL FAULTS, AND WITHOUT WARRANTY OF ANY KIND EITHER EXPRESS
+OR IMPLIED, AND WonderMedia TECHNOLOGIES, INC. DISCLAIMS ALL EXPRESS
+OR IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
+QUIET ENJOYMENT OR NON-INFRINGEMENT.
+--*/
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include "gsensor.h"
+
+#define GSENSOR_I2C_NAME "g-sensor"
+
+#ifdef CONFIG_WMT_SENSOR_DMT08
+#define GSENSOR_I2C_ADDR 0x1c
+#elif defined CONFIG_WMT_SENSOR_KXTI9
+#define GSENSOR_I2C_ADDR 0x0f
+#endif
+
+struct gsensor_data *gs_data;
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+
+struct i2c_board_info gsensor_i2c_board_info = {
+ .type = GSENSOR_I2C_NAME,
+ .flags = 0x00,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+};
+
+int gsensor_i2c_register_device (void)
+{
+ struct i2c_board_info *gsensor_i2c_bi;
+ struct i2c_adapter *adapter = NULL;
+ struct i2c_client *client = NULL;
+ gsensor_i2c_bi = &gsensor_i2c_board_info;
+ adapter = i2c_get_adapter(0);/*in bus 0*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return -1;
+ }
+ gsensor_i2c_bi->addr = gs_data->i2c_addr;
+ client = i2c_new_device(adapter, gsensor_i2c_bi);
+ if (client == NULL) {
+ printk("allocate i2c client failed\n");
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+
+/*
+ * Get the configure of sensor from u-boot.
+ * Return: 0--success, other--error.
+ */
+int get_gsensor_conf(struct gsensor_conf *gs_conf)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.gsensor", varbuf, &varlen)) {
+ printk("wmt.io.gsensor not defined!\n");
+ return -1;
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d",
+ &gs_conf->op,
+ &gs_conf->samp,
+ &(gs_conf->xyz_axis[0][0]),
+ &(gs_conf->xyz_axis[0][1]),
+ &(gs_conf->xyz_axis[1][0]),
+ &(gs_conf->xyz_axis[1][1]),
+ &(gs_conf->xyz_axis[2][0]),
+ &(gs_conf->xyz_axis[2][1]));
+ printk(KERN_INFO "wmt.io.gsensor = %d:%d:%d:%d:%d:%d:%d:%d\n",
+ gs_conf->op,
+ gs_conf->samp,
+ gs_conf->xyz_axis[0][0],
+ gs_conf->xyz_axis[0][1],
+ gs_conf->xyz_axis[1][0],
+ gs_conf->xyz_axis[1][1],
+ gs_conf->xyz_axis[2][0],
+ gs_conf->xyz_axis[2][1]);
+ if (n != 8) {
+ printk("wmt.io.gsensor format is incorrect!\n");
+ return -1;
+ }
+
+ if (gs_conf->op <= 0) {
+ printk(KERN_INFO "wmt.io.gsensor is disabled\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static long gsensor_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int flag;
+
+ if (!gs_data)
+ return -1;
+
+ switch (cmd) {
+ case WMT_IOCTL_APP_SET_AFLAG:
+ if (copy_from_user(&flag, argp, sizeof(flag)))
+ return -EFAULT;
+ else {
+ if (flag < 0 || flag > 1)
+ return -EINVAL;
+ gs_data->enable(flag);
+ }
+ break;
+ case WMT_IOCTL_APP_GET_AFLAG:
+ if (copy_to_user(argp, &flag, sizeof(flag)))
+ return -EFAULT;
+ break;
+ case WMT_IOCTL_APP_SET_DELAY:
+ if (copy_from_user(&flag, argp, sizeof(flag)))
+ return -EFAULT;
+ else
+ gs_data->setDelay(flag);
+
+ break;
+ case WMT_IOCTL_APP_GET_DELAY:
+ if (copy_to_user(argp, &flag, sizeof(flag)))
+ return -EFAULT;
+ break;
+ case WMT_IOCTL_APP_GET_LSG:
+ gs_data->getLSG(&flag);
+ if (copy_to_user(argp, &flag, sizeof(flag)))
+ return -EFAULT;
+ break;
+ default:
+ return -ENOTTY;
+ }
+ return 0;
+}
+
+struct file_operations gsensor_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = gsensor_ioctl,
+};
+
+struct miscdevice gsensor_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "g-sensor",
+ .fops = &gsensor_fops,
+};
+
+int gsensor_register(struct gsensor_data *data)
+{
+ int err=-1;
+
+ gs_data = data;
+ err = misc_register(&gsensor_device);
+ if (err)
+ printk(KERN_ERR "%s: gsensor misc register failed\n", __func__);
+ return err;
+}
+
+EXPORT_SYMBOL_GPL(gsensor_i2c_register_device);
+EXPORT_SYMBOL_GPL(get_gsensor_conf);
+EXPORT_SYMBOL_GPL(gsensor_register);
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/gsensor.h b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/gsensor.h
new file mode 100755
index 00000000..db644d77
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/gsensor.h
@@ -0,0 +1,43 @@
+/*++
+Copyright (c) 2012 WonderMedia Technologies, Inc. All Rights Reserved.
+This PROPRIETARY SOFTWARE is the property of WonderMedia Technologies, Inc.
+and may contain trade secrets and/or other confidential information of
+WonderMedia Technologies, Inc. This file shall not be disclosed to any
+third party, in whole or in part, without prior written consent of
+WonderMedia.
+
+THIS PROPRIETARY SOFTWARE AND ANY RELATED DOCUMENTATION ARE PROVIDED
+AS IS, WITH ALL FAULTS, AND WITHOUT WARRANTY OF ANY KIND EITHER EXPRESS
+OR IMPLIED, AND WonderMedia TECHNOLOGIES, INC. DISCLAIMS ALL EXPRESS
+OR IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
+QUIET ENJOYMENT OR NON-INFRINGEMENT.
+--*/
+
+#ifndef __GSENSOR_H__
+#define __GSENSOR_H__
+
+#define IOCTL_WMT 0x01
+#define WMT_IOCTL_APP_SET_AFLAG _IOW(IOCTL_WMT, 0x01, int)
+#define WMT_IOCTL_APP_SET_DELAY _IOW(IOCTL_WMT, 0x02, int)
+#define WMT_IOCTL_APP_GET_AFLAG _IOW(IOCTL_WMT, 0x03, int)
+#define WMT_IOCTL_APP_GET_DELAY _IOW(IOCTL_WMT, 0x04, int)
+#define WMT_IOCTL_APP_GET_LSG _IOW(IOCTL_WMT, 0x05, int)
+
+struct gsensor_conf {
+ int op;
+ int samp;
+ int xyz_axis[3][2];
+};
+
+struct gsensor_data {
+ int i2c_addr;
+ int (*enable) (int en);
+ int (*setDelay) (int mdelay);
+ int (*getLSG) (int *lsg);
+};
+
+extern int gsensor_i2c_register_device (void);
+extern int get_gsensor_conf(struct gsensor_conf *gs_conf);
+extern int gsensor_register(struct gsensor_data *gs_data);
+
+#endif \ No newline at end of file
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/kxti9_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/kxti9_gsensor/Makefile
new file mode 100755
index 00000000..3df5b74c
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/kxti9_gsensor/Makefile
@@ -0,0 +1,6 @@
+#
+# Makefile for the KXTI9 Sensor driver
+#
+
+sensor_kxti9-objs := kxti9.o
+obj-$(CONFIG_WMT_SENSOR_KXTI9) += sensor_kxti9.o
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/kxti9_gsensor/kxti9.c b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/kxti9_gsensor/kxti9.c
new file mode 100755
index 00000000..c385842e
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/kxti9_gsensor/kxti9.c
@@ -0,0 +1,1134 @@
+/*
+ * Copyright (C) 2009 Kionix, Inc.
+ * Written by Chris Hudson <chudson@kionix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ * 02111-1307, USA
+ */
+
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#ifdef KXTI9_INT_MODE
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#endif
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include "kxti9.h"
+#include "../gsensor.h"
+
+#define NAME "g-sensor"
+#define G_MAX 2048 //8000
+/* OUTPUT REGISTERS */
+#define XOUT_L 0x06
+#define INT_SRC_REG1 0x15
+#define INT_STATUS_REG 0x16
+#define TILT_POS_CUR 0x10
+#define INT_REL 0x1A
+#define WHO_AM_I 0x0F
+/* CONTROL REGISTERS */
+#define DATA_CTRL 0x21
+#define CTRL_REG1 0x1B
+#define INT_CTRL1 0x1E
+#define CTRL_REG3 0x1D
+#define TILT_TIMER 0x28
+#define WUF_TIMER 0x29
+#define WUF_THRESH 0x5A
+#define TDT_TIMER 0x2B
+/* CONTROL REGISTER 1 BITS */
+#define PC1_OFF 0x00
+#define PC1_ON 0x80
+/* INTERRUPT SOURCE 2 BITS */
+#define TPS 0x01
+#define TDTS0 0x04
+#define TDTS1 0x08
+/* INPUT_ABS CONSTANTS */
+#define FUZZ 0 //32
+#define FLAT 0 //32
+/* RESUME STATE INDICES */
+#define RES_DATA_CTRL 0
+#define RES_CTRL_REG1 1
+#define RES_INT_CTRL1 2
+#define RES_TILT_TIMER 3
+#define RES_CTRL_REG3 4
+#define RES_WUF_TIMER 5
+#define RES_WUF_THRESH 6
+#define RES_TDT_TIMER 7
+#define RES_TDT_H_THRESH 8
+#define RES_TDT_L_THRESH 9
+#define RES_TAP_TIMER 10
+#define RES_TOTAL_TIMER 11
+#define RES_LAT_TIMER 12
+#define RES_WIN_TIMER 13
+#define RESUME_ENTRIES 14
+
+static struct gsensor_conf gs_conf;
+static struct kxti9_data *gs_ti9;
+
+extern int gsensor_i2c_register_device (void);
+
+struct kxti9_platform_data kxti9_pdata = {
+ .min_interval = 1,
+ .poll_interval = 200,//1000,
+
+ .g_range = KXTI9_G_2G,
+ .shift_adj = SHIFT_ADJ_2G,
+
+ .axis_map_x = 0,
+ .axis_map_y = 1,
+ .axis_map_z = 2,
+
+ .negate_x = 0,
+ .negate_y = 0,
+ .negate_z = 0,
+
+ .data_odr_init = ODR12_5F,
+#ifdef KXTI9_INT_MODE
+ .ctrl_reg1_init = KXTI9_G_8G | RES_12BIT | TDTE | WUFE | TPE,
+ .int_ctrl_init = KXTI9_IEN | KXTI9_IEA | KXTI9_IEL,
+#else
+ .ctrl_reg1_init = KXTI9_G_2G | RES_12BIT,
+ .int_ctrl_init = 0,
+#endif
+ .tilt_timer_init = 0x03,
+ .engine_odr_init = OTP12_5 | OWUF50 | OTDT400,
+ .wuf_timer_init = 0x16,
+ .wuf_thresh_init = 0x28,
+ .tdt_timer_init = 0x78,
+ .tdt_h_thresh_init = 0xFF,
+ .tdt_l_thresh_init = 0x14,
+ .tdt_tap_timer_init = 0x53,
+ .tdt_total_timer_init = 0x24,
+ .tdt_latency_timer_init = 0x10,
+ .tdt_window_timer_init = 0xA0,
+};
+
+/*
+ * The following table lists the maximum appropriate poll interval for each
+ * available output data rate.
+ */
+struct {
+ unsigned int cutoff;
+ u8 mask;
+} kxti9_odr_table[] = {
+ {
+ 3, ODR800F}, {
+ 5, ODR400F}, {
+ 10, ODR200F}, {
+ 20, ODR100F}, {
+ 40, ODR50F}, {
+ 80, ODR25F}, {
+ 0, ODR12_5F},
+};
+
+struct kxti9_data {
+ struct i2c_client *client;
+ struct kxti9_platform_data *pdata;
+ struct mutex lock;
+ struct delayed_work input_work;
+ struct input_dev *input_dev;
+#ifdef KXTI9_INT_MODE
+ struct work_struct irq_work;
+#endif
+
+ int hw_initialized;
+ atomic_t enabled;
+ u8 resume[RESUME_ENTRIES];
+ int res_interval;
+#ifdef KXTI9_INT_MODE
+ int irq;
+#endif
+};
+
+static int kxti9_i2c_read(struct kxti9_data *ti9, u8 addr, u8 *data, int len)
+{
+ int err;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = ti9->client->addr,
+ .flags = ti9->client->flags & I2C_M_TEN,
+ .len = 1,
+ .buf = &addr,
+ },
+ {
+ .addr = ti9->client->addr,
+ .flags = (ti9->client->flags & I2C_M_TEN) | I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+ err = i2c_transfer(ti9->client->adapter, msgs, 2);
+
+ if (err != 2)
+ dev_err(&ti9->client->dev, "read transfer error\n");
+ else
+ err = 0;
+
+ return err;
+}
+
+static int kxti9_i2c_write(struct kxti9_data *ti9, u8 addr, u8 *data, int len)
+{
+ int err;
+ int i;
+ u8 buf[len + 1];
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = ti9->client->addr,
+ .flags = ti9->client->flags & I2C_M_TEN,
+ .len = len + 1,
+ .buf = buf,
+ },
+ };
+
+ buf[0] = addr;
+ for (i = 0; i < len; i++) {
+ buf[i + 1] = data[i];
+ }
+
+ err = i2c_transfer(ti9->client->adapter, msgs, 1);
+
+ if (err != 1)
+ dev_err(&ti9->client->dev, "write transfer error\n");
+ else
+ err = 0;
+
+ return err;
+}
+
+static int kxti9_verify(struct kxti9_data *ti9)
+{
+ int err;
+ u8 buf;
+
+ err = kxti9_i2c_read(ti9, WHO_AM_I, &buf, 1);
+ /*** DEBUG OUTPUT - REMOVE ***/
+ dev_info(&ti9->client->dev, "WHO_AM_I = 0x%02x\n", buf);
+ /*** <end> DEBUG OUTPUT - REMOVE ***/
+ if (err < 0)
+ dev_err(&ti9->client->dev, "read err int source\n");
+ if (buf != 0x04 && buf != 0x08) // jakie add 0x8 for kxtj9
+ err = -1;
+ return err;
+}
+
+int kxti9_update_g_range(struct kxti9_data *ti9, u8 new_g_range)
+{
+ int err;
+ u8 shift;
+ u8 buf;
+
+ switch (new_g_range) {
+ case KXTI9_G_2G:
+ shift = SHIFT_ADJ_2G;
+ break;
+ case KXTI9_G_4G:
+ shift = SHIFT_ADJ_4G;
+ break;
+ case KXTI9_G_8G:
+ shift = SHIFT_ADJ_8G;
+ break;
+ default:
+ dev_err(&ti9->client->dev, "invalid g range request\n");
+ return -EINVAL;
+ }
+ if (shift != ti9->pdata->shift_adj) {
+ if (ti9->pdata->shift_adj > shift)
+ ti9->resume[RES_WUF_THRESH] >>=
+ (ti9->pdata->shift_adj - shift);
+ if (ti9->pdata->shift_adj < shift)
+ ti9->resume[RES_WUF_THRESH] <<=
+ (shift - ti9->pdata->shift_adj);
+
+ if (atomic_read(&ti9->enabled)) {
+ buf = PC1_OFF;
+ err = kxti9_i2c_write(ti9, CTRL_REG1, &buf, 1);
+ if (err < 0)
+ return err;
+ buf = ti9->resume[RES_WUF_THRESH];
+ err = kxti9_i2c_write(ti9, WUF_THRESH, &buf, 1);
+ if (err < 0)
+ return err;
+ buf = (ti9->resume[RES_CTRL_REG1] & 0xE7) | new_g_range;
+ err = kxti9_i2c_write(ti9, CTRL_REG1, &buf, 1);
+ if (err < 0)
+ return err;
+ ti9->resume[RES_CTRL_REG1] = buf;
+ ti9->pdata->shift_adj = shift;
+ }
+ }
+ return 0;
+}
+
+int kxti9_update_odr(struct kxti9_data *ti9, int poll_interval)
+{
+ int err = -1;
+ int i;
+ u8 config;
+
+ /* Convert the poll interval into an output data rate configuration
+ * that is as low as possible. The ordering of these checks must be
+ * maintained due to the cascading cut off values - poll intervals are
+ * checked from shortest to longest. At each check, if the next slower
+ * ODR cannot support the current poll interval, we stop searching */
+ for (i = 0; i < ARRAY_SIZE(kxti9_odr_table); i++) {
+ config = kxti9_odr_table[i].mask;
+ if (poll_interval < kxti9_odr_table[i].cutoff)
+ break;
+ }
+
+ if (atomic_read(&ti9->enabled)) {
+ err = kxti9_i2c_write(ti9, DATA_CTRL, &config, 1);
+ if (err < 0)
+ return err;
+ /*
+ * Latch on input_dev - indicates that kxti9_input_init passed
+ * and this workqueue is available
+ */
+ if (ti9->input_dev) {
+ cancel_delayed_work_sync(&ti9->input_work);
+ schedule_delayed_work(&ti9->input_work,
+ msecs_to_jiffies(poll_interval));
+ }
+ }
+ ti9->resume[RES_DATA_CTRL] = config;
+
+ return 0;
+}
+
+static int kxti9_hw_init(struct kxti9_data *ti9)
+{
+ int err = -1;
+ u8 buf[7];
+
+ buf[0] = PC1_OFF;
+ err = kxti9_i2c_write(ti9, CTRL_REG1, buf, 1);
+ if (err < 0)
+ return err;
+ err = kxti9_i2c_write(ti9, DATA_CTRL, &ti9->resume[RES_DATA_CTRL], 1);
+ if (err < 0)
+ return err;
+ err = kxti9_i2c_write(ti9, CTRL_REG3, &ti9->resume[RES_CTRL_REG3], 1);
+ if (err < 0)
+ return err;
+ err = kxti9_i2c_write(ti9, TILT_TIMER, &ti9->resume[RES_TILT_TIMER], 1);
+ if (err < 0)
+ return err;
+ err = kxti9_i2c_write(ti9, WUF_TIMER, &ti9->resume[RES_WUF_TIMER], 1);
+ if (err < 0)
+ return err;
+ err = kxti9_i2c_write(ti9, WUF_THRESH, &ti9->resume[RES_WUF_THRESH], 1);
+ if (err < 0)
+ return err;
+ buf[0] = ti9->resume[RES_TDT_TIMER];
+ buf[1] = ti9->resume[RES_TDT_H_THRESH];
+ buf[2] = ti9->resume[RES_TDT_L_THRESH];
+ buf[3] = ti9->resume[RES_TAP_TIMER];
+ buf[4] = ti9->resume[RES_TOTAL_TIMER];
+ buf[5] = ti9->resume[RES_LAT_TIMER];
+ buf[6] = ti9->resume[RES_WIN_TIMER];
+ err = kxti9_i2c_write(ti9, TDT_TIMER, buf, 7);
+ if (err < 0)
+ return err;
+ err = kxti9_i2c_write(ti9, INT_CTRL1, &ti9->resume[RES_INT_CTRL1], 1);
+ if (err < 0)
+ return err;
+ buf[0] = (ti9->resume[RES_CTRL_REG1] | PC1_ON);
+ err = kxti9_i2c_write(ti9, CTRL_REG1, buf, 1);
+ if (err < 0)
+ return err;
+ ti9->resume[RES_CTRL_REG1] = buf[0];
+ ti9->hw_initialized = 1;
+
+ return 0;
+}
+
+static void kxti9_device_power_off(struct kxti9_data *ti9)
+{
+ int err;
+ u8 buf = PC1_OFF;
+
+ err = kxti9_i2c_write(ti9, CTRL_REG1, &buf, 1);
+ if (err < 0)
+ dev_err(&ti9->client->dev, "soft power off failed\n");
+#ifdef KXTI9_INT_MODE
+ disable_irq(ti9->irq);
+#endif
+ if (ti9->pdata->power_off)
+ ti9->pdata->power_off();
+ ti9->hw_initialized = 0;
+}
+
+static int kxti9_device_power_on(struct kxti9_data *ti9)
+{
+ int err;
+
+ if (ti9->pdata->power_on) {
+ err = ti9->pdata->power_on();
+ if (err < 0)
+ return err;
+ }
+#ifdef KXTI9_INT_MODE
+ enable_irq(ti9->irq);
+#endif
+ if (!ti9->hw_initialized) {
+ msleep(100);
+ err = kxti9_hw_init(ti9);
+ if (err < 0) {
+ kxti9_device_power_off(ti9);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+#ifdef KXTI9_INT_MODE
+static irqreturn_t kxti9_isr(int irq, void *dev)
+{
+ struct kxti9_data *ti9 = dev;
+
+ disable_irq_nosync(irq);
+ schedule_work(&ti9->irq_work);
+
+ return IRQ_HANDLED;
+}
+#endif
+
+static u8 kxti9_resolve_dir(struct kxti9_data *ti9, u8 dir)
+{
+ switch (dir) {
+ case 0x20: /* -X */
+ if (ti9->pdata->negate_x)
+ dir = 0x10;
+ if (ti9->pdata->axis_map_y == 0)
+ dir >>= 2;
+ if (ti9->pdata->axis_map_z == 0)
+ dir >>= 4;
+ break;
+ case 0x10: /* +X */
+ if (ti9->pdata->negate_x)
+ dir = 0x20;
+ if (ti9->pdata->axis_map_y == 0)
+ dir >>= 2;
+ if (ti9->pdata->axis_map_z == 0)
+ dir >>= 4;
+ break;
+ case 0x08: /* -Y */
+ if (ti9->pdata->negate_y)
+ dir = 0x04;
+ if (ti9->pdata->axis_map_x == 1)
+ dir <<= 2;
+ if (ti9->pdata->axis_map_z == 1)
+ dir >>= 2;
+ break;
+ case 0x04: /* +Y */
+ if (ti9->pdata->negate_y)
+ dir = 0x08;
+ if (ti9->pdata->axis_map_x == 1)
+ dir <<= 2;
+ if (ti9->pdata->axis_map_z == 1)
+ dir >>= 2;
+ break;
+ case 0x02: /* -Z */
+ if (ti9->pdata->negate_z)
+ dir = 0x01;
+ if (ti9->pdata->axis_map_x == 2)
+ dir <<= 4;
+ if (ti9->pdata->axis_map_y == 2)
+ dir <<= 2;
+ break;
+ case 0x01: /* +Z */
+ if (ti9->pdata->negate_z)
+ dir = 0x02;
+ if (ti9->pdata->axis_map_x == 2)
+ dir <<= 4;
+ if (ti9->pdata->axis_map_y == 2)
+ dir <<= 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return dir;
+}
+
+static int kxti9_get_acceleration_data(struct kxti9_data *ti9, int *xyz)
+{
+ int err;
+ /* Data bytes from hardware xL, xH, yL, yH, zL, zH */
+ u8 acc_data[6];
+ /* x,y,z hardware values */
+ int hw_d[3];
+
+ err = kxti9_i2c_read(ti9, XOUT_L, acc_data, 6);
+ if (err < 0)
+ return err;
+
+ hw_d[0] = (int) (((acc_data[1]) << 8) | acc_data[0]);
+ hw_d[1] = (int) (((acc_data[3]) << 8) | acc_data[2]);
+ hw_d[2] = (int) (((acc_data[5]) << 8) | acc_data[4]);
+
+ hw_d[0] = (hw_d[0] & 0x8000) ? ((hw_d[0] | 0xFFFF0000) + 1) : (hw_d[0]);
+ hw_d[1] = (hw_d[1] & 0x8000) ? ((hw_d[1] | 0xFFFF0000) + 1) : (hw_d[1]);
+ hw_d[2] = (hw_d[2] & 0x8000) ? ((hw_d[2] | 0xFFFF0000) + 1) : (hw_d[2]);
+
+ hw_d[0] >>= 4;
+ hw_d[1] >>= 4;
+ hw_d[2] >>= 4;
+
+ xyz[0] = ((ti9->pdata->negate_x) ? (-hw_d[ti9->pdata->axis_map_x])
+ : (hw_d[ti9->pdata->axis_map_x]));
+ xyz[1] = ((ti9->pdata->negate_y) ? (-hw_d[ti9->pdata->axis_map_y])
+ : (hw_d[ti9->pdata->axis_map_y]));
+ xyz[2] = ((ti9->pdata->negate_z) ? (-hw_d[ti9->pdata->axis_map_z])
+ : (hw_d[ti9->pdata->axis_map_z]));
+
+ /*** DEBUG OUTPUT - REMOVE ***/
+ //dev_info(&ti9->client->dev, "x:%d y:%d z:%d\n", xyz[0], xyz[1], xyz[2]);
+ /*** <end> DEBUG OUTPUT - REMOVE ***/
+
+ return err;
+}
+
+static void kxti9_report_values(struct kxti9_data *ti9, int *xyz)
+{
+ input_report_abs(ti9->input_dev, ABS_X, xyz[gs_conf.xyz_axis[ABS_X][0]]*gs_conf.xyz_axis[ABS_X][1]);
+ input_report_abs(ti9->input_dev, ABS_Y, xyz[gs_conf.xyz_axis[ABS_Y][0]]*gs_conf.xyz_axis[ABS_Y][1]);
+ input_report_abs(ti9->input_dev, ABS_Z, xyz[gs_conf.xyz_axis[ABS_Z][0]]*gs_conf.xyz_axis[ABS_Z][1]);
+ input_sync(ti9->input_dev);
+}
+
+#ifdef KXTI9_INT_MODE
+static void kxti9_irq_work_func(struct work_struct *work)
+{
+/*
+ * int_status output:
+ * [INT_SRC_REG2][INT_SRC_REG1][TILT_POS_PRE][TILT_POS_CUR]
+ * INT_SRC_REG1, TILT_POS_PRE, and TILT_POS_CUR directions are translated
+ * based on platform data variables.
+ */
+
+ int err;
+ int int_status = 0;
+ u8 status;
+ u8 buf[2];
+
+ struct kxti9_data *ti9
+ = container_of(work, struct kxti9_data, irq_work);
+
+ err = kxti9_i2c_read(ti9, INT_STATUS_REG, &status, 1);
+ if (err < 0)
+ dev_err(&ti9->client->dev, "read err int source\n");
+ int_status = status << 24;
+ if ((status & TPS) > 0) {
+ err = kxti9_i2c_read(ti9, TILT_POS_CUR, buf, 2);
+ if (err < 0)
+ dev_err(&ti9->client->dev, "read err tilt dir\n");
+ int_status |= kxti9_resolve_dir(ti9, buf[0]);
+ int_status |= kxti9_resolve_dir(ti9, buf[1]) << 8;
+ /*** DEBUG OUTPUT - REMOVE ***/
+ dev_info(&ti9->client->dev, "IRQ TILT [%x]\n",
+ kxti9_resolve_dir(ti9, buf[0]));
+ /*** <end> DEBUG OUTPUT - REMOVE ***/
+ }
+ if (((status & TDTS0) | (status & TDTS1)) > 0) {
+ err = kxti9_i2c_read(ti9, INT_SRC_REG1, buf, 1);
+ if (err < 0)
+ dev_err(&ti9->client->dev, "read err tap dir\n");
+ int_status |= (kxti9_resolve_dir(ti9, buf[0])) << 16;
+ /*** DEBUG OUTPUT - REMOVE ***/
+ dev_info(&ti9->client->dev, "IRQ TAP%d [%x]\n",
+ ((status & TDTS1) ? (2) : (1)), kxti9_resolve_dir(ti9, buf[0]));
+ /*** <end> DEBUG OUTPUT - REMOVE ***/
+ }
+ /*** DEBUG OUTPUT - REMOVE ***/
+ if ((status & 0x02) > 0) {
+ if (((status & TDTS0) | (status & TDTS1)) > 0)
+ dev_info(&ti9->client->dev, "IRQ WUF + TAP\n");
+ else
+ dev_info(&ti9->client->dev, "IRQ WUF\n");
+ }
+ /*** <end> DEBUG OUTPUT - REMOVE ***/
+ if (int_status & 0x2FFF) {
+ input_report_abs(ti9->input_dev, ABS_MISC, int_status);
+ input_sync(ti9->input_dev);
+ }
+ err = kxti9_i2c_read(ti9, INT_REL, buf, 1);
+ if (err < 0)
+ dev_err(&ti9->client->dev,
+ "error clearing interrupt status: %d\n", err);
+
+ enable_irq(ti9->irq);
+}
+#endif
+
+static int kxti9_enable(struct kxti9_data *ti9)
+{
+ int err;
+ int int_status = 0;
+ u8 buf;
+
+ if (!atomic_cmpxchg(&ti9->enabled, 0, 1)) {
+ err = kxti9_device_power_on(ti9);
+ err = kxti9_i2c_read(ti9, INT_REL, &buf, 1);
+ if (err < 0) {
+ dev_err(&ti9->client->dev,
+ "error clearing interrupt: %d\n", err);
+ atomic_set(&ti9->enabled, 0);
+ return err;
+ }
+ if ((ti9->resume[RES_CTRL_REG1] & TPE) > 0) {
+ err = kxti9_i2c_read(ti9, TILT_POS_CUR, &buf, 1);
+ if (err < 0) {
+ dev_err(&ti9->client->dev,
+ "read err current tilt\n");
+ int_status |= kxti9_resolve_dir(ti9, buf);
+ input_report_abs(ti9->input_dev, ABS_MISC, int_status);
+ input_sync(ti9->input_dev);
+ }
+ }
+ schedule_delayed_work(&ti9->input_work,
+ msecs_to_jiffies(ti9->res_interval));
+ }
+
+ return 0;
+}
+
+static int kxti9_disable(struct kxti9_data *ti9)
+{
+ if (atomic_cmpxchg(&ti9->enabled, 1, 0)) {
+ cancel_delayed_work_sync(&ti9->input_work);
+ kxti9_device_power_off(ti9);
+ }
+
+ return 0;
+}
+
+static void kxti9_input_work_func(struct work_struct *work)
+{
+ struct kxti9_data *ti9 = container_of((struct delayed_work *)work,
+ struct kxti9_data, input_work);
+ int xyz[3] = { 0 };
+
+ mutex_lock(&ti9->lock);
+
+ if (kxti9_get_acceleration_data(ti9, xyz) == 0)
+ kxti9_report_values(ti9, xyz);
+
+ schedule_delayed_work(&ti9->input_work,
+ msecs_to_jiffies(ti9->res_interval));
+
+ mutex_unlock(&ti9->lock);
+}
+
+int kxti9_input_open(struct input_dev *input)
+{
+ struct kxti9_data *ti9 = input_get_drvdata(input);
+
+ return kxti9_enable(ti9);
+}
+
+void kxti9_input_close(struct input_dev *dev)
+{
+ struct kxti9_data *ti9 = input_get_drvdata(dev);
+
+ kxti9_disable(ti9);
+}
+
+static int kxti9_input_init(struct kxti9_data *ti9)
+{
+ int err;
+
+ INIT_DELAYED_WORK(&ti9->input_work, kxti9_input_work_func);
+ ti9->input_dev = input_allocate_device();
+ if (!ti9->input_dev) {
+ err = -ENOMEM;
+ dev_err(&ti9->client->dev, "input device allocate failed\n");
+ goto err0;
+ }
+ //ti9->input_dev->open = kxti9_input_open;
+ //ti9->input_dev->close = kxti9_input_close;
+
+ input_set_drvdata(ti9->input_dev, ti9);
+
+ set_bit(EV_ABS, ti9->input_dev->evbit);
+ set_bit(ABS_MISC, ti9->input_dev->absbit);
+
+ input_set_abs_params(ti9->input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
+ input_set_abs_params(ti9->input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
+ input_set_abs_params(ti9->input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
+
+ ti9->input_dev->name = "g-sensor";
+
+ err = input_register_device(ti9->input_dev);
+ if (err) {
+ dev_err(&ti9->client->dev,
+ "unable to register input polled device %s: %d\n",
+ ti9->input_dev->name, err);
+ goto err1;
+ }
+
+ return 0;
+err1:
+ input_free_device(ti9->input_dev);
+err0:
+ return err;
+}
+
+static void kxti9_input_cleanup(struct kxti9_data *ti9)
+{
+ input_unregister_device(ti9->input_dev);
+}
+
+/* sysfs */
+static ssize_t kxti9_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ return sprintf(buf, "%d\n", ti9->res_interval);
+}
+
+static ssize_t kxti9_delay_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ int val = simple_strtoul(buf, NULL, 10);
+
+ ti9->res_interval = max(val, ti9->pdata->min_interval);
+ kxti9_update_odr(ti9, ti9->res_interval);
+
+ return count;
+}
+
+static ssize_t kxti9_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ return sprintf(buf, "%d\n", atomic_read(&ti9->enabled));
+}
+
+static ssize_t kxti9_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ int val = simple_strtoul(buf, NULL, 10);
+ if (val)
+ kxti9_enable(ti9);
+ else
+ kxti9_disable(ti9);
+ return count;
+}
+
+static ssize_t kxti9_tilt_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ u8 tilt;
+
+ if (ti9->resume[RES_CTRL_REG1] & TPE) {
+ kxti9_i2c_read(ti9, TILT_POS_CUR, &tilt, 1);
+ return sprintf(buf, "%d\n", kxti9_resolve_dir(ti9, tilt));
+ } else {
+ return sprintf(buf, "%d\n", 0);
+ }
+}
+
+static ssize_t kxti9_tilt_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ int val = simple_strtoul(buf, NULL, 10);
+ if (val)
+ ti9->resume[RES_CTRL_REG1] |= TPE;
+ else
+ ti9->resume[RES_CTRL_REG1] &= (~TPE);
+ kxti9_i2c_write(ti9, CTRL_REG1, &ti9->resume[RES_CTRL_REG1], 1);
+ return count;
+}
+
+static ssize_t kxti9_wake_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ u8 val = ti9->resume[RES_CTRL_REG1] & WUFE;
+ if (val)
+ return sprintf(buf, "%d\n", 1);
+ else
+ return sprintf(buf, "%d\n", 0);
+}
+
+static ssize_t kxti9_wake_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ int val = simple_strtoul(buf, NULL, 10);
+ if (val)
+ ti9->resume[RES_CTRL_REG1] |= WUFE;
+ else
+ ti9->resume[RES_CTRL_REG1] &= (~WUFE);
+ kxti9_i2c_write(ti9, CTRL_REG1, &ti9->resume[RES_CTRL_REG1], 1);
+ return count;
+}
+
+static ssize_t kxti9_tap_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ u8 val = ti9->resume[RES_CTRL_REG1] & TDTE;
+ if (val)
+ return sprintf(buf, "%d\n", 1);
+ else
+ return sprintf(buf, "%d\n", 0);
+}
+
+static ssize_t kxti9_tap_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ int val = simple_strtoul(buf, NULL, 10);
+ if (val)
+ ti9->resume[RES_CTRL_REG1] |= TDTE;
+ else
+ ti9->resume[RES_CTRL_REG1] &= (~TDTE);
+ kxti9_i2c_write(ti9, CTRL_REG1, &ti9->resume[RES_CTRL_REG1], 1);
+ return count;
+}
+
+static ssize_t kxti9_selftest_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ int val = simple_strtoul(buf, NULL, 10);
+ u8 ctrl = 0x00;
+ if (val)
+ ctrl = 0xCA;
+ kxti9_i2c_write(ti9, 0x3A, &ctrl, 1);
+ return count;
+}
+
+static DEVICE_ATTR(delay, S_IRUGO|S_IWUSR, kxti9_delay_show, kxti9_delay_store);
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, kxti9_enable_show,
+ kxti9_enable_store);
+static DEVICE_ATTR(tilt, S_IRUGO|S_IWUSR, kxti9_tilt_show, kxti9_tilt_store);
+static DEVICE_ATTR(wake, S_IRUGO|S_IWUSR, kxti9_wake_show, kxti9_wake_store);
+static DEVICE_ATTR(tap, S_IRUGO|S_IWUSR, kxti9_tap_show, kxti9_tap_store);
+static DEVICE_ATTR(selftest, S_IWUSR, NULL, kxti9_selftest_store);
+
+static struct attribute *kxti9_attributes[] = {
+ &dev_attr_delay.attr,
+ &dev_attr_enable.attr,
+ &dev_attr_tilt.attr,
+ &dev_attr_wake.attr,
+ &dev_attr_tap.attr,
+ &dev_attr_selftest.attr,
+ NULL
+};
+
+static struct attribute_group kxti9_attribute_group = {
+ .attrs = kxti9_attributes
+};
+/* /sysfs */
+static int __devinit kxti9_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err = -1;
+ struct kxti9_data *ti9 = kzalloc(sizeof(*ti9), GFP_KERNEL);
+ gs_ti9 = ti9;
+ if (ti9 == NULL) {
+ dev_err(&client->dev,
+ "failed to allocate memory for module data\n");
+ err = -ENOMEM;
+ goto err0;
+ }
+ /*
+ if (client->dev.platform_data == NULL) {
+ dev_err(&client->dev, "platform data is NULL; exiting\n");
+ err = -ENODEV;
+ goto err0;
+ }
+ */
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "client not i2c capable\n");
+ err = -ENODEV;
+ goto err0;
+ }
+ mutex_init(&ti9->lock);
+ mutex_lock(&ti9->lock);
+ ti9->client = client;
+ i2c_set_clientdata(client, ti9);
+
+#ifdef KXTI9_INT_MODE
+ INIT_WORK(&ti9->irq_work, kxti9_irq_work_func);
+#endif
+ ti9->pdata = kmalloc(sizeof(*ti9->pdata), GFP_KERNEL);
+ if (ti9->pdata == NULL)
+ goto err1;
+
+ err = sysfs_create_group(&client->dev.kobj, &kxti9_attribute_group);
+ if (err)
+ goto err1;
+
+ //memcpy(ti9->pdata, client->dev.platform_data, sizeof(*ti9->pdata));
+ memcpy(ti9->pdata, &kxti9_pdata, sizeof(*ti9->pdata));
+
+ if (ti9->pdata->init) {
+ err = ti9->pdata->init();
+ if (err < 0)
+ goto err2;
+ }
+
+#ifdef KXTI9_INT_MODE
+ ti9->irq = gpio_to_irq(ti9->pdata->gpio);
+#endif
+
+ memset(ti9->resume, 0, ARRAY_SIZE(ti9->resume));
+ ti9->resume[RES_DATA_CTRL] = ti9->pdata->data_odr_init;
+ ti9->resume[RES_CTRL_REG1] = ti9->pdata->ctrl_reg1_init;
+ ti9->resume[RES_INT_CTRL1] = ti9->pdata->int_ctrl_init;
+ ti9->resume[RES_TILT_TIMER] = ti9->pdata->tilt_timer_init;
+ ti9->resume[RES_CTRL_REG3] = ti9->pdata->engine_odr_init;
+ ti9->resume[RES_WUF_TIMER] = ti9->pdata->wuf_timer_init;
+ ti9->resume[RES_WUF_THRESH] = ti9->pdata->wuf_thresh_init;
+ ti9->resume[RES_TDT_TIMER] = ti9->pdata->tdt_timer_init;
+ ti9->resume[RES_TDT_H_THRESH] = ti9->pdata->tdt_h_thresh_init;
+ ti9->resume[RES_TDT_L_THRESH] = ti9->pdata->tdt_l_thresh_init;
+ ti9->resume[RES_TAP_TIMER] = ti9->pdata->tdt_tap_timer_init;
+ ti9->resume[RES_TOTAL_TIMER] = ti9->pdata->tdt_total_timer_init;
+ ti9->resume[RES_LAT_TIMER] = ti9->pdata->tdt_latency_timer_init;
+ ti9->resume[RES_WIN_TIMER] = ti9->pdata->tdt_window_timer_init;
+ ti9->res_interval = ti9->pdata->poll_interval;
+
+ err = kxti9_device_power_on(ti9);
+ if (err < 0)
+ goto err3;
+ atomic_set(&ti9->enabled, 1);
+
+ err = kxti9_verify(ti9);
+ if (err < 0) {
+ dev_err(&client->dev, "unresolved i2c client\n");
+ goto err4;
+ }
+
+ err = kxti9_update_g_range(ti9, ti9->pdata->g_range);
+ if (err < 0)
+ goto err4;
+
+ err = kxti9_update_odr(ti9, ti9->res_interval);
+ if (err < 0)
+ goto err4;
+
+ err = kxti9_input_init(ti9);
+ if (err < 0)
+ goto err4;
+
+ kxti9_device_power_off(ti9);
+ atomic_set(&ti9->enabled, 0);
+
+#ifdef KXTI9_INT_MODE
+ err = request_irq(ti9->irq, kxti9_isr,
+ IRQF_TRIGGER_RISING | IRQF_DISABLED, "kxti9-irq", ti9);
+ if (err < 0) {
+ pr_err("%s: request irq failed: %d\n", __func__, err);
+ goto err5;
+ }
+ disable_irq_nosync(ti9->irq);
+#endif
+
+ mutex_unlock(&ti9->lock);
+
+ return 0;
+
+#ifdef KXTI9_INT_MODE
+err5:
+#endif
+ kxti9_input_cleanup(ti9);
+err4:
+ kxti9_device_power_off(ti9);
+err3:
+ if (ti9->pdata->exit)
+ ti9->pdata->exit();
+err2:
+ kfree(ti9->pdata);
+ sysfs_remove_group(&client->dev.kobj, &kxti9_attribute_group);
+err1:
+ mutex_unlock(&ti9->lock);
+ kfree(ti9);
+err0:
+ return err;
+}
+
+static int __devexit kxti9_remove(struct i2c_client *client)
+{
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+
+#ifdef KXTI9_INT_MODE
+ free_irq(ti9->irq, ti9);
+ gpio_free(ti9->pdata->gpio);
+#endif
+ kxti9_input_cleanup(ti9);
+ kxti9_device_power_off(ti9);
+ if (ti9->pdata->exit)
+ ti9->pdata->exit();
+ kfree(ti9->pdata);
+ sysfs_remove_group(&client->dev.kobj, &kxti9_attribute_group);
+ kfree(ti9);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int kxti9_resume(struct i2c_client *client)
+{
+ //struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ //return kxti9_enable(ti9);
+ return 0;
+}
+
+static int kxti9_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ //struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ //return kxti9_disable(ti9);
+ return 0;
+}
+
+static void kxti9_shutdown(struct i2c_client *client)
+{
+ struct kxti9_data *ti9 = i2c_get_clientdata(client);
+ if (atomic_read(&ti9->enabled)) {
+ flush_delayed_work_sync(&ti9->input_work);
+ cancel_delayed_work_sync(&ti9->input_work);
+ }
+}
+#endif
+
+static const struct i2c_device_id kxti9_id[] = {
+ {NAME, 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, kxti9_id);
+
+static struct i2c_driver kxti9_driver = {
+ .driver = {
+ .name = NAME,
+ },
+ .probe = kxti9_probe,
+ .remove = __devexit_p(kxti9_remove),
+ .resume = kxti9_resume,
+ .suspend = kxti9_suspend,
+ .shutdown = kxti9_shutdown,
+ .id_table = kxti9_id,
+};
+
+int kxti9_enable_accel(int en)
+{
+ printk(KERN_DEBUG "%s: enable = %d\n", __func__, en);
+ if (en)
+ kxti9_enable(gs_ti9);
+ else
+ kxti9_disable(gs_ti9);
+ return 0;
+}
+
+int kxti9_setDelay(int mdelay)
+{
+ printk(KERN_DEBUG "%s: delay = %d\n", __func__, mdelay);
+ gs_ti9->res_interval = mdelay;
+ return kxti9_update_odr(gs_ti9, gs_ti9->res_interval);
+}
+
+int kxti9_getLSG(int *lsg)
+{
+ int max_count;
+ if (gs_ti9->resume[RES_CTRL_REG1] & RES_12BIT)
+ max_count = 2048;
+ else
+ max_count = 128;
+
+ if ((gs_ti9->resume[RES_CTRL_REG1] & 0x18) == KXTI9_G_2G)
+ *lsg = max_count >> 1;
+ else if ((gs_ti9->resume[RES_CTRL_REG1] & 0x18) == KXTI9_G_4G)
+ *lsg = max_count >> 2;
+ else if ((gs_ti9->resume[RES_CTRL_REG1] & 0x18) == KXTI9_G_8G)
+ *lsg = max_count >> 3;
+
+ printk(KERN_DEBUG "%s: LSG = %d\n", __func__, *lsg);
+ return 0;
+}
+
+struct gsensor_data kxti9_gs_data = {
+ .i2c_addr = KXTI9_I2C_ADDR,
+ .enable = kxti9_enable_accel,
+ .setDelay = kxti9_setDelay,
+ .getLSG = kxti9_getLSG,
+};
+
+static int __init kxti9_init(void)
+{
+ if (get_gsensor_conf(&gs_conf))
+ return -1;
+
+ if (gs_conf.op != 2)
+ return -1;
+
+ printk("G-Sensor kxti9 init\n");
+
+ if (gsensor_register(&kxti9_gs_data))
+ return -1;
+
+ if (gsensor_i2c_register_device() < 0)
+ return -1;
+
+ return i2c_add_driver(&kxti9_driver);
+}
+
+static void __exit kxti9_exit(void)
+{
+ i2c_del_driver(&kxti9_driver);
+}
+
+module_init(kxti9_init);
+module_exit(kxti9_exit);
+
+MODULE_DESCRIPTION("KXTI9 accelerometer driver");
+MODULE_AUTHOR("Chris Hudson <chudson@kionix.com>");
+MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/kxti9_gsensor/kxti9.h b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/kxti9_gsensor/kxti9.h
new file mode 100755
index 00000000..c66c740a
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/TP_DRIVER_NOT_USE/kxti9_gsensor/kxti9.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2009, Kionix, Inc. All Rights Reserved.
+ * Written by Chris Hudson <chudson@kionix.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __KXTI9_H__
+#define __KXTI9_H__
+
+#define KXTI9_I2C_ADDR 0x0F
+/* CONTROL REGISTER 1 BITS */
+#define RES_12BIT 0x40
+#define KXTI9_G_2G 0x00
+#define KXTI9_G_4G 0x08
+#define KXTI9_G_8G 0x10
+#define SHIFT_ADJ_2G 4
+#define SHIFT_ADJ_4G 3
+#define SHIFT_ADJ_8G 2
+#define TPE 0x01 /* tilt position function enable bit */
+#define WUFE 0x02 /* wake-up function enable bit */
+#define TDTE 0x04 /* tap/double-tap function enable bit */
+/* CONTROL REGISTER 3 BITS */
+#define OTP1_6 0x00 /* tilt ODR masks */
+#define OTP6_3 0x20
+#define OTP12_5 0x40
+#define OTP50 0x60
+#define OWUF25 0x00 /* wuf ODR masks */
+#define OWUF50 0x01
+#define OWUF100 0x02
+#define OWUF200 0x03
+#define OTDT50 0x00 /* tdt ODR masks */
+#define OTDT100 0x04
+#define OTDT200 0x08
+#define OTDT400 0x0C
+/* INTERRUPT CONTROL REGISTER 1 BITS */
+#define KXTI9_IEN 0x20 /* interrupt enable */
+#define KXTI9_IEA 0x10 /* interrupt polarity */
+#define KXTI9_IEL 0x08 /* interrupt response */
+#define IEU 0x04 /* alternate unlatched response */
+/* DATA CONTROL REGISTER BITS */
+#define ODR800F 0x06 /* lpf output ODR masks */
+#define ODR400F 0x05
+#define ODR200F 0x04
+#define ODR100F 0x03
+#define ODR50F 0x02
+#define ODR25F 0x01
+#define ODR12_5F 0x00
+
+#ifdef __KERNEL__
+struct kxti9_platform_data {
+ int poll_interval;
+ int min_interval;
+
+ u8 g_range;
+ u8 shift_adj;
+
+ u8 axis_map_x;
+ u8 axis_map_y;
+ u8 axis_map_z;
+
+ u8 negate_x;
+ u8 negate_y;
+ u8 negate_z;
+
+ u8 data_odr_init;
+ u8 ctrl_reg1_init;
+ u8 int_ctrl_init;
+ u8 tilt_timer_init;
+ u8 engine_odr_init;
+ u8 wuf_timer_init;
+ u8 wuf_thresh_init;
+ u8 tdt_timer_init;
+ u8 tdt_h_thresh_init;
+ u8 tdt_l_thresh_init;
+ u8 tdt_tap_timer_init;
+ u8 tdt_total_timer_init;
+ u8 tdt_latency_timer_init;
+ u8 tdt_window_timer_init;
+
+ int (*init)(void);
+ void (*exit)(void);
+ int (*power_on)(void);
+ int (*power_off)(void);
+
+ int gpio;
+};
+#endif /* __KERNEL__ */
+
+#endif /* __KXTI9_H__ */
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/cm3232/Makefile b/ANDROID_3.4.5/drivers/input/sensor/cm3232/Makefile
new file mode 100755
index 00000000..06c28edd
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/cm3232/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_lsensor_cm3232
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := cm3232.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/cm3232/cm3232.c b/ANDROID_3.4.5/drivers/input/sensor/cm3232/cm3232.c
new file mode 100755
index 00000000..207ddd3a
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/cm3232/cm3232.c
@@ -0,0 +1,855 @@
+/*
+ * cm3232.c - Intersil cm3232 ALS & Proximity Driver
+ *
+ * By Intersil Corp
+ * Michael DiGioia
+ *
+ * Based on isl29011.c
+ * by Mike DiGioia <mdigioia@intersil.com>
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/hwmon.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/pm_runtime.h>
+#include <linux/input-polldev.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+//#include <linux/earlysuspend.h>
+
+#include "../sensor.h"
+
+/* Insmod parameters */
+//I2C_CLIENT_INSMOD_1(cm3232);
+#define SENSOR_I2C_NAME "cm3232"
+#define SENSOR_I2C_ADDR 0x10
+#define MODULE_NAME "cm3232"
+
+#define REG_CMD_1 0x00
+#define REG_CMD_2 0x01
+#define REG_DATA_LSB 0x02
+#define REG_DATA_MSB 0x03
+#define ISL_MOD_MASK 0xE0
+#define ISL_MOD_POWERDOWN 0
+#define ISL_MOD_ALS_ONCE 1
+#define ISL_MOD_IR_ONCE 2
+#define ISL_MOD_RESERVED 4
+#define ISL_MOD_ALS_CONT 5
+#define ISL_MOD_IR_CONT 6
+#define IR_CURRENT_MASK 0xC0
+#define IR_FREQ_MASK 0x30
+#define SENSOR_RANGE_MASK 0x03
+#define ISL_RES_MASK 0x0C
+
+
+#undef dbg
+#define dbg(fmt, args...) //printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__ , ## args)
+
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk(KERN_ERR "[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static int no_adc_map = 1;
+static int last_mod;
+
+static struct i2c_client *this_client = NULL;
+
+struct isl_device {
+ struct input_polled_dev* input_poll_dev;
+ struct i2c_client* client;
+ int resolution;
+ int range;
+ int isdbg;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend earlysuspend;
+#endif
+
+};
+
+static struct isl_device* l_sensorconfig = NULL;
+static struct kobject *android_lsensor_kobj = NULL;
+static int l_enable = 0; // 0:don't report data, 1
+
+static DEFINE_MUTEX(mutex);
+
+#if 0
+static int isl_set_mod(struct i2c_client *client, int mod)
+{
+ int ret, val, freq;
+
+ switch (mod) {
+ case ISL_MOD_POWERDOWN:
+ case ISL_MOD_RESERVED:
+ goto setmod;
+ case ISL_MOD_ALS_ONCE:
+ case ISL_MOD_ALS_CONT:
+ freq = 0;
+ break;
+ case ISL_MOD_IR_ONCE:
+ case ISL_MOD_IR_CONT:
+ freq = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* set IR frequency */
+ val = i2c_smbus_read_byte_data(client, REG_CMD_2);
+ if (val < 0)
+ return -EINVAL;
+ val &= ~IR_FREQ_MASK;
+ if (freq)
+ val |= IR_FREQ_MASK;
+ ret = i2c_smbus_write_byte_data(client, REG_CMD_2, val);
+ if (ret < 0)
+ return -EINVAL;
+
+setmod:
+ /* set operation mod */
+ val = i2c_smbus_read_byte_data(client, REG_CMD_1);
+ if (val < 0)
+ return -EINVAL;
+ val &= ~ISL_MOD_MASK;
+ val |= (mod << 5);
+ ret = i2c_smbus_write_byte_data(client, REG_CMD_1, val);
+ if (ret < 0)
+ return -EINVAL;
+
+ if (mod != ISL_MOD_POWERDOWN)
+ last_mod = mod;
+
+ return mod;
+}
+
+static int isl_get_res(struct i2c_client *client)
+{
+ int val;
+
+ printk(KERN_INFO MODULE_NAME ": %s cm3232 get_res call, \n", __func__);
+ val = i2c_smbus_read_word_data(client, 0)>>8 & 0xff;
+
+ if (val < 0)
+ return -EINVAL;
+
+ val &= ISL_RES_MASK;
+ val >>= 2;
+
+ switch (val) {
+ case 0:
+ return 65536;
+ case 1:
+ return 4096;
+ case 2:
+ return 256;
+ case 3:
+ return 16;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int isl_get_range(struct i2c_client* client)
+{
+ switch (i2c_smbus_read_word_data(client, 0)>>8 & 0xff & 0x3) {
+ case 0: return 1000;
+ case 1: return 4000;
+ case 2: return 16000;
+ case 3: return 64000;
+ default: return -EINVAL;
+ }
+}
+#endif
+//Fixme plan to transfer the adc value to the config.xml lux 2013-5-10
+static __u16 uadc[8] = {2, 8, 100, 400, 900, 1000, 1500, 1900};//customize
+static __u16 ulux[9] = {128, 200, 1300, 2000, 3000, 4000, 5000, 6000, 7000};
+static __u16 adc_to_lux(__u16 adc)
+{
+ static long long var = 0;
+ int i = 0; //length of array is 8,9
+ for (i=0; i<8; i++) {
+ if ( adc < uadc[i]){
+ break;
+ }
+ }
+ if ( i<9)
+ {
+ var++;
+ if (var%2)
+ return ulux[i]+0;
+ else
+ return ulux[i]+1;
+ }
+ return ulux[4];
+}
+
+
+
+static int isl_get_lux_data(struct i2c_client* client)
+{
+ //struct isl_device* idev = i2c_get_clientdata(client);
+
+ //__u16 resH = 0, resL = 0;
+ __s16 resH = 0, resL = 0;
+ //int range;
+ resL = i2c_smbus_read_word_data(client, 0x50);
+ //resH = i2c_smbus_read_word_data(client, 0x51)&0xff00;
+ if ((resL < 0) || (resH < 0))
+ {
+ errlog("Error to read lux_data!\n");
+
+ return 3000;//???
+ //return -1;
+ }
+ //Fixme plan to transfer the adc value to the config.xml lux 2013-5-10
+ if (!no_adc_map)
+ resL = adc_to_lux(resL);
+ //printk("<<<< lux %d\n", resL);
+ return resL ;//* idev->range / idev->resolution;
+ return (resH | resL) ;//* idev->range / idev->resolution;
+}
+
+
+static int isl_set_default_config(struct i2c_client *client)
+{
+ //struct isl_device* idev = i2c_get_clientdata(client);
+
+ int ret=0;
+ //ret = _cm3232_I2C_Write_Byte(CM3232_SLAVE_addr, CM3232_ALS_RESET);
+ ret = i2c_smbus_write_byte_data(client, 0, (1 << 6));
+ if (ret < 0)
+ return -EINVAL;
+ //if(ret<0)
+ //return ret;
+ msleep(10);
+
+ //ret = _cm3232_I2C_Write_Byte(CM3232_SLAVE_addr, CM3232_ALS_IT_200ms | CM3232_ALS_HS_HIGH );
+ ret = i2c_smbus_write_byte_data(client, 0, (1 << 2)|(1 << 1));
+ if (ret < 0)
+ return -EINVAL;
+ msleep(10);
+ return 0;
+/* We don't know what it does ... */
+// ret = i2c_smbus_write_byte_data(client, REG_CMD_1, 0xE0);
+// ret = i2c_smbus_write_byte_data(client, REG_CMD_2, 0xC3);
+/* Set default to ALS continuous */
+ ret = i2c_smbus_write_byte_data(client, REG_CMD_1, 0xA0);
+ if (ret < 0)
+ return -EINVAL;
+/* Range: 0~16000, number of clock cycles: 65536 */
+ ret = i2c_smbus_write_byte_data(client, REG_CMD_2, 0x02); // vivienne
+ if (ret < 0)
+ return -EINVAL;
+ //idev->resolution = isl_get_res(client);
+ //idev->range = isl_get_range(client);;
+ dbg("cm3232 set_default_config call, \n");
+
+ return 0;
+}
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int cm3232_detect(struct i2c_client *client/*, int kind,
+ struct i2c_board_info *info*/)
+{
+
+
+ return 0;
+}
+
+int isl_input_open(struct input_dev* input)
+{
+ return 0;
+}
+
+void isl_input_close(struct input_dev* input)
+{
+}
+
+static void isl_input_lux_poll(struct input_polled_dev *dev)
+{
+ struct isl_device* idev = dev->private;
+ struct input_dev* input = idev->input_poll_dev->input;
+ struct i2c_client* client = idev->client;
+ static unsigned int val=0;
+
+ //printk("%s\n", __FUNCTION__);
+ if (l_enable != 0)
+ {
+ mutex_lock(&mutex);
+ //pm_runtime_get_sync(dev);
+ #if 0
+ if(val>0x2000)
+ val=0;
+ val+=100;
+ #endif
+ //printk(KERN_ALERT "by flashchen val is %x",val);
+ input_report_abs(input, ABS_MISC, isl_get_lux_data(client));
+ //input_report_abs(input, ABS_MISC, val);//isl_get_lux_data(client));
+ input_sync(input);
+ //pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ }
+}
+
+static struct i2c_device_id cm3232_id[] = {
+ {"cm3232", 0},
+ {}
+};
+
+#if 0
+static int cm3232_runtime_suspend(struct device *dev)
+{
+
+ dev_dbg(dev, "suspend\n");
+
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+ //isl_set_mod(client, ISL_MOD_POWERDOWN);
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+
+ printk(KERN_INFO MODULE_NAME ": %s cm3232 suspend call, \n", __func__);
+ return 0;
+}
+
+static int cm3232_runtime_resume(struct device *dev)
+{
+
+ dev_dbg(dev, "resume\n");
+
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+ //isl_set_mod(client, last_mod);
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+
+ printk(KERN_INFO MODULE_NAME ": %s cm3232 resume call, \n", __func__);
+ return 0;
+}
+#endif
+MODULE_DEVICE_TABLE(i2c, cm3232_id);
+
+/*static const struct dev_pm_ops cm3232_pm_ops = {
+ .runtime_suspend = cm3232_runtime_suspend,
+ .runtime_resume = cm3232_runtime_resume,
+};
+
+static struct i2c_board_info isl_info = {
+ I2C_BOARD_INFO("cm3232", 0x44),
+};
+
+static struct i2c_driver cm3232_driver = {
+ .driver = {
+ .name = "cm3232",
+ .pm = &cm3232_pm_ops,
+ },
+ .probe = cm3232_probe,
+ .remove = cm3232_remove,
+ .id_table = cm3232_id,
+ .detect = cm3232_detect,
+ //.address_data = &addr_data,
+};*/
+
+static int mmad_open(struct inode *inode, struct file *file)
+{
+ dbg("Open the l-sensor node...\n");
+ return 0;
+}
+
+static int mmad_release(struct inode *inode, struct file *file)
+{
+ dbg("Close the l-sensor node...\n");
+ return 0;
+}
+
+static ssize_t mmad_read(struct file *fl, char __user *buf, size_t cnt, loff_t *lf)
+{
+ int lux_data = 0;
+
+ mutex_lock(&mutex);
+ lux_data = isl_get_lux_data(l_sensorconfig->client);
+ mutex_unlock(&mutex);
+ if (lux_data < 0)
+ {
+ errlog("Failed to read lux data!\n");
+ return -1;
+ }
+ printk(KERN_ALERT "lux_data is %x\n",lux_data);
+ //return 0;
+ copy_to_user(buf, &lux_data, sizeof(lux_data));
+ return sizeof(lux_data);
+}
+
+static long
+mmad_ioctl(/*struct inode *inode,*/ struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ //char rwbuf[5];
+ short enable; //amsr = -1;
+ unsigned int uval;
+
+ dbg("l-sensor ioctr...\n");
+ //memset(rwbuf, 0, sizeof(rwbuf));
+ switch (cmd) {
+ case LIGHT_IOCTL_SET_ENABLE:
+ // enable/disable sensor
+ if (copy_from_user(&enable, argp, sizeof(short)))
+ {
+ printk(KERN_ERR "Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ dbg("enable=%d\n",enable);
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor.\n", enable);
+
+ //l_sensorconfig.sensor_enable = enable;
+ dbg("Should to implement d/e the light sensor!\n");
+ l_enable = enable;
+
+ } else {
+ printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+#define CM3232_DRVID 0
+ uval = CM3232_DRVID ;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("cm3232_driver_id:%d\n",uval);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+static struct file_operations mmad_fops = {
+ .owner = THIS_MODULE,
+ .open = mmad_open,
+ .release = mmad_release,
+ .read = mmad_read,
+ .unlocked_ioctl = mmad_ioctl,
+};
+
+
+static struct miscdevice mmad_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "lsensor_ctrl",
+ .fops = &mmad_fops,
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void cm3232_early_suspend(struct early_suspend *h)
+{
+ struct i2c_client *client = l_sensorconfig->client;
+
+ dbg("start\n");
+ mutex_lock(&mutex);
+ //pm_runtime_get_sync(dev);
+ //isl_set_mod(client, ISL_MOD_POWERDOWN);
+ //pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ dbg("exit\n");
+}
+
+static void cm3232_late_resume(struct early_suspend *h)
+{
+ struct i2c_client *client = l_sensorconfig->client;
+
+ dbg("start\n");
+ mutex_lock(&mutex);
+ //pm_runtime_get_sync(dev);
+ //isl_set_mod(client, last_mod);
+ isl_set_default_config(client);
+ //pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ dbg("exit\n");
+}
+#endif
+static ssize_t adc_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+
+ int i;
+ int size = sizeof(uadc)/sizeof(uadc[0]);
+ printk("<<<%s\n", __FUNCTION__);
+ for (i=0; i<size; i++)
+ {
+ printk(" %5d ", uadc[i]);
+ //sprintf(buf, "%d " &uadc[i]);
+ }
+ printk("\n");
+
+ return sizeof(uadc);
+ //printk(" %s \n", buf);
+}
+
+static ssize_t adc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ __u32 tmp;
+ int index;
+ int n;
+ int size = sizeof(uadc)/sizeof(uadc[0]);
+
+ printk("<<<%s\n", __FUNCTION__);
+ printk("<< %s >>>\n", buf);
+ n = sscanf(buf, "%d:%d", &index, &tmp);
+ printk("<<<<int n %d %d:%d \n", n, index, tmp);
+ if ( n==2 && index>=0 && index<size){
+
+ uadc[index] = tmp;
+ no_adc_map = 0;
+ }
+ else {
+ printk("<<<param error!\n");
+ no_adc_map = 1;
+ }
+ return count;
+}
+static struct device_attribute cm3232_attr[] =
+{
+ __ATTR(adc, 0644, adc_show, adc_store),
+ __ATTR_NULL,
+};
+
+static struct device *sdevice;
+static struct class *sclass;
+static dev_t sdev_no;
+static int device_create_attribute(struct device *dev, struct device_attribute *attr)
+{
+ int err, i;
+ for (i=0; NULL != attr[i].attr.name; i++)
+ {
+ err = device_create_file(dev, &attr[i]); //&attr[i].attr
+ if (err)
+ break;
+ }
+ if (err)
+ {
+ for (; i>=0; i--)
+ device_remove_file(dev, &attr[i]);//&attr[i].attr
+ }
+ return err;
+}
+
+static void device_remove_attribute(struct device *dev, struct device_attribute *attr)
+{
+ int i;
+ for (i=0; attr[i].attr.name != NULL; i++)
+ device_remove_file(dev, &attr[i]); //&attr[i].attr
+}
+
+
+static int get_adc_val(void)
+{
+ int i, varlen, n;
+ __u32 buf[8];
+ char varbuf[50];
+ char *name = "wmt.io.lsensor";
+
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara(name, varbuf, &varlen))
+ {
+ printk("<<<<fail to wmt_syspara %s\n", "wmt.io.lsensor");
+ no_adc_map = 1;
+ return -1;
+ }
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d", &buf[0], &buf[1], &buf[2], &buf[3], &buf[4], &buf[5], \
+ &buf[6], &buf[7]);
+ //printk("<<< n %d \n", n);
+ if (n != 8)
+ {
+ printk("<<<<<%s uboot env wmt.io.lsensor param error!\n", __FUNCTION__);
+ return -1;
+ }
+ for (i=0; i<8; i++)
+ {
+ //printk("<<<< %5d ", buf[i]);
+ uadc[i] = buf[i];
+ }
+ no_adc_map = 0;
+ //printk("\n");
+ return 0;
+}
+
+static int
+cm3232_probe(struct i2c_client *client/*, const struct i2c_device_id *id*/)
+{
+ int res=0;
+ int sret = 0;
+ struct isl_device* idev = kzalloc(sizeof(struct isl_device), GFP_KERNEL);
+ if(!idev)
+ return -ENOMEM;
+
+ l_sensorconfig = idev;
+ //android_lsensor_kobj = kobject_create_and_add("android_lsensor", NULL);
+ /*
+ if (android_lsensor_kobj == NULL) {
+ errlog(
+ "lsensor_sysfs_init:"\
+ "subsystem_register failed\n");
+ res = -ENOMEM;
+ goto err_kobjetc_create;
+ }
+ //res = sysfs_create_group(android_lsensor_kobj, &m_isl_gr);
+ if (res) {
+ //pr_warn("cm3232: device create file failed!!\n");
+ printk(KERN_INFO MODULE_NAME ": %s cm3232 device create file failed\n", __func__);
+ res = -EINVAL;
+ goto err_sysfs_create;
+ }
+ */
+
+/* last mod is ALS continuous */
+ last_mod = 5;
+ //pm_runtime_enable(&client->dev);
+ idev->input_poll_dev = input_allocate_polled_device();
+ if(!idev->input_poll_dev)
+ {
+ res = -ENOMEM;
+ goto err_input_allocate_device;
+ }
+ idev->client = client;
+ idev->input_poll_dev->private = idev;
+ idev->input_poll_dev->poll = isl_input_lux_poll;
+ idev->input_poll_dev->poll_interval = 100;//50;
+ idev->input_poll_dev->input->open = isl_input_open;
+ idev->input_poll_dev->input->close = isl_input_close;
+ idev->input_poll_dev->input->name = "lsensor_lux";
+ idev->input_poll_dev->input->id.bustype = BUS_I2C;
+ idev->input_poll_dev->input->dev.parent = &client->dev;
+ input_set_drvdata(idev->input_poll_dev->input, idev);
+ input_set_capability(idev->input_poll_dev->input, EV_ABS, ABS_MISC);
+ input_set_abs_params(idev->input_poll_dev->input, ABS_MISC, 0, 16000, 0, 0);
+ i2c_set_clientdata(client, idev);
+ /* set default config after set_clientdata */
+ res = isl_set_default_config(client);
+ res = misc_register(&mmad_device);
+ if (res) {
+ errlog("mmad_device register failed\n");
+ goto err_misc_register;
+ }
+ res = input_register_polled_device(idev->input_poll_dev);
+ if(res < 0)
+ goto err_input_register_device;
+ // suspend/resume register
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ idev->earlysuspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ idev->earlysuspend.suspend = cm3232_early_suspend;
+ idev->earlysuspend.resume = cm3232_late_resume;
+ register_early_suspend(&(idev->earlysuspend));
+#endif
+
+ dbg("cm3232 probe succeed!\n");
+ //create class device sysdevice 2013-5-10
+ //get_adc_val();
+ sclass = class_create(THIS_MODULE, "cm3232");
+ if (IS_ERR(sclass))
+ {
+ printk("<<<%s fail to create class!\n", __FUNCTION__);
+ return 0;
+ }
+
+
+ sret = alloc_chrdev_region(&sdev_no, 0, 1, "cm3232_devno");
+ if (sret)
+ {
+ printk("<<<<%s alloc_chrdev_region fail!\n", __FUNCTION__);
+ class_destroy(sclass);
+ return 0;
+ }
+ sdevice = device_create(sclass, NULL, sdev_no, NULL, "cm3232_dev");
+ if (IS_ERR(sdevice))
+ {
+ printk("<<<%s device_create fail!\n", __FUNCTION__);
+ class_destroy(sclass);
+ return 0;
+ }
+ device_create_attribute(sdevice, cm3232_attr);
+
+ return 0;
+err_input_register_device:
+ misc_deregister(&mmad_device);
+ input_free_polled_device(idev->input_poll_dev);
+err_misc_register:
+err_input_allocate_device:
+ //__pm_runtime_disable(&client->dev, false);
+
+ kobject_del(android_lsensor_kobj);
+
+ kfree(idev);
+ return res;
+}
+
+static int cm3232_remove(struct i2c_client *client)
+{
+ struct isl_device* idev = i2c_get_clientdata(client);
+ if (!IS_ERR(sdevice))
+ {
+ device_remove_attribute(sdevice, cm3232_attr);
+ device_destroy(sclass, sdev_no);
+ class_destroy(sclass);
+
+ }
+ //unregister_early_suspend(&(idev->earlysuspend));
+ misc_deregister(&mmad_device);
+ input_unregister_polled_device(idev->input_poll_dev);
+ input_free_polled_device(idev->input_poll_dev);
+ //sysfs_remove_group(android_lsensor_kobj, &m_isl_gr);
+ kobject_del(android_lsensor_kobj);
+ //__pm_runtime_disable(&client->dev, false);
+ kfree(idev);
+ printk(KERN_INFO MODULE_NAME ": %s cm3232 remove call, \n", __func__);
+ return 0;
+}
+//****************add platform_device & platform_driver for suspend &resume 2013-7-2
+static int ls_probe(struct platform_device *pdev){
+ //printk("<<<%s\n", __FUNCTION__);
+ return 0;
+}
+static int ls_remove(struct platform_device *pdev){
+ //printk("<<<%s\n", __FUNCTION__);
+ return 0;
+}
+static int ls_suspend(struct platform_device *pdev, pm_message_t state){
+ printk("<<<%s\n", __FUNCTION__);
+
+ return 0;
+}
+
+static int ls_resume(struct platform_device *pdev){
+ //return 0;
+ int ret = 0;
+ int count = 0;
+ printk("<<<%s\n", __FUNCTION__);
+RETRY:
+ ret = isl_set_default_config(this_client);
+ if (ret < 0){
+ printk("%s isl_set_default_config fail!\n", __FUNCTION__);
+ count++;
+ if (count < 5){
+ mdelay(2);
+ goto RETRY;
+ }
+ else
+ return ret;
+ }
+ return 0;
+
+}
+static void lsdev_release(struct device *dev)
+{
+ return;
+}
+static struct platform_device lsdev = {
+ .name = "lsdevice",
+ .id = -1,
+ .dev = {
+ .release = lsdev_release,
+ },
+};
+static struct platform_driver lsdrv = {
+ .probe = ls_probe,
+ .remove = ls_remove,
+ .suspend = ls_suspend,
+ .resume = ls_resume,
+ .driver = {
+ .name = "lsdevice",
+ },
+};
+//********************************************************************
+
+static int __init sensor_cm3232_init(void)
+{
+ int ret = 0;
+ printk(KERN_INFO MODULE_NAME ": %s cm3232 init call, \n", __func__);
+ /*
+ * Force device to initialize: i2c-15 0x44
+ * If i2c_new_device is not called, even cm3232_detect will not run
+ * TODO: rework to automatically initialize the device
+ */
+ //i2c_new_device(i2c_get_adapter(15), &isl_info);
+ //return i2c_add_driver(&cm3232_driver);
+ if (!(this_client = sensor_i2c_register_device(2, SENSOR_I2C_ADDR, SENSOR_I2C_NAME)))
+ {
+ printk(KERN_EMERG"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+ if (cm3232_detect(this_client))
+ {
+ errlog("Can't find light sensor cm3232!\n");
+ goto detect_fail;
+ }
+ get_adc_val();
+ if(cm3232_probe(this_client))
+ {
+ errlog("Erro for probe!\n");
+ goto detect_fail;
+ }
+
+ ret = platform_device_register(&lsdev);
+ if (ret){
+ printk("<<<platform_device_register fail!\n");
+ return ret;
+ }
+ ret = platform_driver_register(&lsdrv);
+ if (ret){
+ printk("<<<platform_driver_register fail!\n");
+ platform_device_unregister(&lsdev);
+ return ret;
+ }
+ return 0;
+
+detect_fail:
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+}
+
+static void __exit sensor_cm3232_exit(void)
+{
+ printk(KERN_INFO MODULE_NAME ": %s cm3232 exit call \n", __func__);
+ cm3232_remove(this_client);
+ sensor_i2c_unregister_device(this_client);
+ platform_driver_unregister(&lsdrv);
+ platform_device_unregister(&lsdev);
+ //i2c_del_driver(&cm3232_driver);
+}
+
+module_init(sensor_cm3232_init);
+module_exit(sensor_cm3232_exit);
+
+MODULE_AUTHOR("flash");
+MODULE_ALIAS("cm3232 ALS");
+MODULE_DESCRIPTION("Intersil cm3232 ALS Driver");
+MODULE_LICENSE("GPL v2");
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard06_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/dmard06_gsensor/Makefile
new file mode 100755
index 00000000..a5dfa3cb
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard06_gsensor/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_gsensor_dmard06
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := dmard06.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard06_gsensor/dmard06.c b/ANDROID_3.4.5/drivers/input/sensor/dmard06_gsensor/dmard06.c
new file mode 100755
index 00000000..bcb6e5ad
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard06_gsensor/dmard06.c
@@ -0,0 +1,980 @@
+/*
+ * @file drivers/i2c/chips/dmard06.c
+ * @brief DMARD06 g-sensor Linux device driver
+ * @author Domintech Technology Co., Ltd (http://www.domintech.com.tw)
+ * @version 1.0
+ * @date 2011/8/5
+ *
+ * @section LICENSE
+ *
+ * Copyright 2011 Domintech Technology Co., Ltd
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/cdev.h>
+//#include <linux/earlysuspend.h>
+#include <linux/wakelock.h>
+#include <asm/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <mach/hardware.h>
+#include <linux/miscdevice.h>
+
+//////////////////////////////////////////////////////////
+#define AKMIO 0xA1
+
+/* IOCTLs for AKM library */
+#define ECS_IOCTL_INIT _IO(AKMIO, 0x01)
+#define ECS_IOCTL_WRITE _IOW(AKMIO, 0x02, char[5])
+#define ECS_IOCTL_READ _IOWR(AKMIO, 0x03, char[5])
+#define ECS_IOCTL_RESET _IO(AKMIO, 0x04)
+#define ECS_IOCTL_INT_STATUS _IO(AKMIO, 0x05)
+#define ECS_IOCTL_FFD_STATUS _IO(AKMIO, 0x06)
+#define ECS_IOCTL_SET_MODE _IOW(AKMIO, 0x07, short)
+#define ECS_IOCTL_GETDATA _IOR(AKMIO, 0x08, char[RBUFF_SIZE+1])
+#define ECS_IOCTL_GET_NUMFRQ _IOR(AKMIO, 0x09, char[2])
+#define ECS_IOCTL_SET_PERST _IO(AKMIO, 0x0A)
+#define ECS_IOCTL_SET_G0RST _IO(AKMIO, 0x0B)
+#define ECS_IOCTL_SET_YPR _IOW(AKMIO, 0x0C, short[12])
+#define ECS_IOCTL_GET_OPEN_STATUS _IOR(AKMIO, 0x0D, int)
+#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(AKMIO, 0x0E, int)
+#define ECS_IOCTL_GET_CALI_DATA _IOR(AKMIO, 0x0F, char[MAX_CALI_SIZE])
+#define ECS_IOCTL_GET_DELAY _IOR(AKMIO, 0x30, short)
+
+/* IOCTLs for APPs */
+#define ECS_IOCTL_APP_SET_MODE _IOW(AKMIO, 0x10, short)
+#define ECS_IOCTL_APP_SET_MFLAG _IOW(AKMIO, 0x11, short)
+#define ECS_IOCTL_APP_GET_MFLAG _IOW(AKMIO, 0x12, short)
+//#define ECS_IOCTL_APP_SET_AFLAG _IOW(AKMIO, 0x13, short)
+#define ECS_IOCTL_APP_GET_AFLAG _IOR(AKMIO, 0x14, short)
+#define ECS_IOCTL_APP_SET_TFLAG _IOR(AKMIO, 0x15, short)
+#define ECS_IOCTL_APP_GET_TFLAG _IOR(AKMIO, 0x16, short)
+#define ECS_IOCTL_APP_RESET_PEDOMETER _IO(AKMIO, 0x17)
+//#define ECS_IOCTL_APP_SET_DELAY _IOW(AKMIO, 0x18, short)
+#define ECS_IOCTL_APP_GET_DELAY ECS_IOCTL_GET_DELAY
+#define ECS_IOCTL_APP_SET_MVFLAG _IOW(AKMIO, 0x19, short) /* Set raw magnetic vector flag */
+#define ECS_IOCTL_APP_GET_MVFLAG _IOR(AKMIO, 0x1A, short) /* Get raw magnetic vector flag */
+
+#define WMTGSENSOR_IOCTL_MAGIC 0x09
+#define WMT_IOCTL_SENSOR_CAL_OFFSET _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x01, int) //offset calibration
+#define ECS_IOCTL_APP_SET_AFLAG _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x02, short)
+#define ECS_IOCTL_APP_SET_DELAY _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x03, short)
+#define WMT_IOCTL_SENSOR_GET_DRVID _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x04, unsigned int)
+
+
+/* IOCTLs for pedometer */
+#define ECS_IOCTL_SET_STEP_CNT _IOW(AKMIO, 0x20, short)
+//////////////////////////////////////////////////////////////////
+#define SENSOR_DELAY_FASTEST 0
+#define SENSOR_DELAY_GAME 20
+#define SENSOR_DELAY_UI 60
+#define SENSOR_DELAY_NORMAL 200
+
+#define DMARD06_DRVID 3
+
+/////////////////////////////////////////////////////////////////
+
+#undef dbg
+#define dbg(fmt, args...) if (l_sensorconfig.isdbg) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk(KERN_ERR "[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+#define DMARD06_I2C_NAME "dmard06"
+#define DMARD06_I2C_ADDR 0x1c
+
+#define GSENSOR_PROC_NAME "gsensor_config"
+#define GSENSOR_MAJOR 161
+#define GSENSOR_NAME "dmard06"
+#define GSENSOR_DRIVER_NAME "dmard06_drv"
+
+#define GSENDMARD06_UBOOT_NAME "wmt.io.d06sensor"
+
+#define MAX_WR_DMARD06_LEN (1+1)
+
+#define LSG 32
+
+static char const *const ACCELEMETER_CLASS_NAME = "accelemeter";
+static char const *const DMARD06_DEVICE_NAME = "dmard06";
+////////////////////////////////////////////////////////////
+#define ID_REG_ADDR 0x0F
+#define SWRESET_REG_ADDR 0x53
+#define T_REG_ADDR 0x40
+#define XYZ_REG_ADDR 0x41
+#define CTR1_REG_ADDR 0x44
+#define CTR2_REG_ADDR 0x45
+#define CTR3_REG_ADDR 0x46
+#define CTR4_REG_ADDR 0x47
+#define CTR5_REG_ADDR 0x48
+#define STAT_REG_ADDR 0x49
+
+
+
+static int dmard06_init(void);
+static void dmard06_exit(void);
+
+static int dmard06_file_open(struct inode*, struct file*);
+static ssize_t dmard06_file_write(struct file*, const char*, size_t, loff_t*);
+static ssize_t dmard06_file_read(struct file*, char*, size_t, loff_t*);
+static int dmard06_file_close(struct inode*, struct file*);
+
+static int dmard06_i2c_suspend(struct platform_device *pdev, pm_message_t state);
+static int dmard06_i2c_resume(struct platform_device *pdev);
+static int dmard06_i2c_probe(void);
+static int dmard06_i2c_remove(void);
+static void dmard06_i2c_read_xyz(s8 *x, s8 *y, s8 *z);
+static void dmard06_i2c_accel_value(s8 *val);
+static int dmard06_probe(
+ struct platform_device *pdev);
+static int dmard06_remove(struct platform_device *pdev);
+static int dmard06_i2c_xyz_read_reg(u8* index ,u8 *buffer, int length);
+
+
+
+//extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num, int bus_id);
+extern int i2c_api_do_send(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size);
+extern int i2c_api_do_recv(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size);
+
+extern int wmt_setsyspara(char *varname, unsigned char *varval);
+
+/////////////////////////////////////////////////////////////////
+struct work_struct poll_work;
+static struct mutex sense_data_mutex;
+
+
+struct dmard06_config
+{
+ int op;
+ int int_gpio; //0-3
+ int samp;
+ int xyz_axis[3][3]; // (axis,direction)
+ int irq;
+ struct proc_dir_entry* sensor_proc;
+ //int sensorlevel;
+ //int shake_enable; // 1--enable shake, 0--disable shake
+ //int manual_rotation; // 0--landance, 90--vertical
+ struct input_dev *input_dev;
+ //struct work_struct work;
+ struct delayed_work work; // for polling
+ struct workqueue_struct *queue;
+ int isdbg; // 0-- no debug log, 1--show debug log
+ int sensor_samp; //
+ int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor
+ int test_pass;
+ spinlock_t spinlock;
+ int pollcnt; // the counts of polling
+ int offset[3]; // for calibration
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend earlysuspend;
+#endif
+};
+
+static struct dmard06_config l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .samp = 16,
+ .xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },
+ .irq = 6,
+ .int_gpio = 3,
+ .sensor_proc = NULL,
+ //.sensorlevel = SENSOR_GRAVITYGAME_MODE,
+ //.shake_enable = 0, // default enable shake
+ .isdbg = 0,
+ .sensor_samp = 1, // 1 sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ .pollcnt = 0, // Don't report the x,y,z when the driver is loaded until 2~3 seconds
+ .offset = {0, 0, 0},
+};
+
+static struct class* l_dev_class = NULL;
+static struct device *l_clsdevice = NULL;
+
+
+struct raw_data
+{
+ short x;
+ short y;
+ short z;
+};
+
+struct dev_data
+{
+ dev_t devno;
+ struct cdev cdev;
+ struct class *class;
+ struct i2c_client *client;
+};
+
+static struct dev_data dev;
+
+struct file_operations dmard06_fops =
+{
+ .owner = THIS_MODULE,
+ .read = dmard06_file_read,
+ .write = dmard06_file_write,
+ .open = dmard06_file_open,
+ .release = dmard06_file_close,
+};
+
+static int dmard06_file_open(struct inode *inode, struct file *filp)
+{
+ dbg("open...\n");
+
+ return 0;
+}
+
+static ssize_t dmard06_file_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
+{
+ dbg("write...\n");
+
+ return 0;
+}
+
+unsigned int sample_rate_2_memsec(unsigned int rate)
+{
+ return (1000/rate);
+}
+
+static int dmard06_packet_rptValue(int x, int y, int z)
+{
+ return ((0xFF&z) | ((0xFF&y)<<8) | ((0xFF&x)<<16));
+}
+
+
+static void dmard06_work_func(struct work_struct *work)
+{
+ u8 buffer[3];
+ //buffer[0] = 0x41;
+ u8 index = 0x41;
+ s8 x,y,z;
+ int xyz,tx,ty,tz;
+
+ mutex_lock(&sense_data_mutex);
+ //read data
+ dmard06_i2c_xyz_read_reg(&index, buffer, 3);
+ mutex_unlock(&sense_data_mutex);
+ // check whether it's valid
+ // report the data
+ x = (s8)buffer[0];
+ y = (s8)buffer[1];
+ z = (s8)buffer[2];
+ dmard06_i2c_accel_value(&x);
+ dmard06_i2c_accel_value(&y);
+ dmard06_i2c_accel_value(&z);
+ tx = x*l_sensorconfig.xyz_axis[0][1]+l_sensorconfig.offset[0];
+ ty = y*l_sensorconfig.xyz_axis[1][1]+l_sensorconfig.offset[1];
+ tz = z*l_sensorconfig.xyz_axis[2][1]+l_sensorconfig.offset[2];
+ xyz = dmard06_packet_rptValue(tx, ty, tz);
+ input_report_abs(l_sensorconfig.input_dev, ABS_X, xyz);
+
+ //input_report_abs(l_sensorconfig.input_dev, l_sensorconfig.xyz_axis[0][0],
+ // x*l_sensorconfig.xyz_axis[0][1]+l_sensorconfig.offset[0]);
+ //input_report_abs(l_sensorconfig.input_dev, l_sensorconfig.xyz_axis[1][0],
+ // y*l_sensorconfig.xyz_axis[1][1]+l_sensorconfig.offset[1]);
+ //input_report_abs(l_sensorconfig.input_dev, l_sensorconfig.xyz_axis[2][0],
+ //z*l_sensorconfig.xyz_axis[2][1]+l_sensorconfig.offset[2]);
+ input_sync(l_sensorconfig.input_dev);
+ dbg("x=%2x(tx=%2x),y=%2x(ty=%2x),z=%2x(tz=%2x),xyz=%x",
+ (char)x, (char)tx, (char)y, (char)ty, (char)z, (char)tz, xyz);
+
+ // for next polling
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+ //klog("%d=%d,%d=%d,%d=%d\n", l_sensorconfig.xyz_axis[0][0], x*l_sensorconfig.xyz_axis[0][1],
+ // l_sensorconfig.xyz_axis[1][0], y*l_sensorconfig.xyz_axis[1][1],
+ // l_sensorconfig.xyz_axis[2][0], z*l_sensorconfig.xyz_axis[2][1]);
+ //klog("the polling period:%d\n", msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+
+}
+
+
+static ssize_t dmard06_file_read(struct file *filp, char *buf, size_t count, loff_t *f_pos)
+{
+ int ret;
+ s8 x, y, z;
+ struct raw_data rdata;
+
+ dbg("read...\n");
+ mutex_lock(&sense_data_mutex);
+ dmard06_i2c_read_xyz(&x, &y, &z);
+ rdata.x = x;
+ rdata.y = y;
+ rdata.z = z;
+
+ ret = copy_to_user(buf, &rdata, count);
+ mutex_unlock(&sense_data_mutex);
+
+ return count;
+}
+
+static int dmard06_file_close(struct inode *inode, struct file *filp)
+{
+ dbg("close...\n");
+
+ return 0;
+}
+
+static void dmard06_platform_release(struct device *device)
+{
+ return;
+}
+
+
+static struct platform_device dmard06_device = {
+ .name = GSENSOR_NAME,
+ .id = 0,
+ .dev = {
+ .release = dmard06_platform_release,
+ },
+};
+
+static struct platform_driver dmard06_driver = {
+ .probe = dmard06_probe,
+ .remove = dmard06_remove,
+ .suspend = dmard06_i2c_suspend,
+ .resume = dmard06_i2c_resume,
+ .driver = {
+ .name = GSENSOR_NAME,
+ },
+};
+
+static int dmard06_i2c_xyz_write_reg(u8* index ,u8 *buffer, int length)
+{
+ /*int ret = 0;
+ u8 buf[MAX_WR_DMARD06_LEN];
+ struct i2c_msg msg[1];
+
+ buf[0] = *index;
+ memcpy(buf+1, buffer, length);
+ msg[0].addr = DMARD06_I2C_ADDR;
+ msg[0].flags = 0 ;
+ msg[0].flags &= ~(I2C_M_RD);
+ msg[0].len = length+1;
+ msg[0].buf = buf;
+ if ((ret = wmt_i2c_xfer_continue_if_4(msg,1,0)) <= 0)
+ {
+ errlog("write error!\n");
+ }
+ return ret;*/
+ return i2c_api_do_send(0, DMARD06_I2C_ADDR, index, buffer, length);
+}
+
+static int dmard06_i2c_xyz_read_reg(u8* index ,u8 *buffer, int length)
+{
+ /*int ret = 0;
+
+ struct i2c_msg msg[] =
+ {
+ {.addr = DMARD06_I2C_ADDR, .flags = 0, .len = 1, .buf = index,},
+ {.addr = DMARD06_I2C_ADDR, .flags = I2C_M_RD, .len = length, .buf = buffer,},
+ };
+ ret = wmt_i2c_xfer_continue_if_4(msg, 2,0);
+ if (ret <= 0)
+ {
+ errlog("read error!\n");
+ }
+ return ret;*/
+ return i2c_api_do_recv(0, DMARD06_I2C_ADDR, index, buffer, length);
+}
+
+static void dmard06_i2c_read_xyz(s8 *x, s8 *y, s8 *z)
+{
+
+ u8 buffer[3];
+ //buffer[0] = 0x41;
+ u8 index = 0x41;
+
+ dmard06_i2c_xyz_read_reg(&index, buffer, 3);
+ *x = (s8)buffer[0];
+ *y = (s8)buffer[1];
+ *z = (s8)buffer[2];
+ dmard06_i2c_accel_value(x);
+ dmard06_i2c_accel_value(y);
+ dmard06_i2c_accel_value(z);
+ if (ABS_X == l_sensorconfig.xyz_axis[0][0])
+ {
+ *x = l_sensorconfig.xyz_axis[0][1]*(*x);
+ *y = l_sensorconfig.xyz_axis[1][1]*(*y);
+ } else {
+ *x = l_sensorconfig.xyz_axis[0][1]*(*y);
+ *y = l_sensorconfig.xyz_axis[1][1]*(*x);
+ }
+ *z = l_sensorconfig.xyz_axis[2][1]*(*z);
+
+ dbg("dmrd06:x=%x,y=%x,z=%x\n", *x, *y, *z);
+}
+
+static void dmard06_i2c_accel_value(s8 *val)
+{
+ *val >>= 1;
+}
+
+static int dmard06_CalOffset(int side)
+{
+ u8 buffer[3];
+ //buffer[0] = 0x41;
+ u8 index = 0x41;
+ s8 x,y,z;
+
+ //mutex_lock(&sense_data_mutex);
+ //read data
+ dmard06_i2c_xyz_read_reg(&index, buffer, 3);
+ //mutex_unlock(&sense_data_mutex);
+ // check whether it's valid
+ // report the data
+ x = (s8)buffer[0];
+ y = (s8)buffer[1];
+ z = (s8)buffer[2];
+ dmard06_i2c_accel_value(&x);
+ dmard06_i2c_accel_value(&y);
+ dmard06_i2c_accel_value(&z);
+ l_sensorconfig.offset[0] = 0 - x*l_sensorconfig.xyz_axis[0][1];
+ l_sensorconfig.offset[1] = 0 - y*l_sensorconfig.xyz_axis[1][1];
+ l_sensorconfig.offset[2] = LSG - z*l_sensorconfig.xyz_axis[2][1];
+ return 0;
+
+}
+
+static int dmard06_i2c_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ dbg("...\n");
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+
+ return 0;
+}
+
+static int is_dmard06(void)
+{
+ int err = 0;
+ u8 cAddress = 0, cData = 0;
+ char buf[4];
+
+ cAddress = 0x53;
+ //i2c_master_send( client, (char*)&cAddress, 1);
+ //i2c_master_recv( client, (char*)&cData, 1);
+ if (dmard06_i2c_xyz_read_reg(&cAddress, &cData,1) <= 0)
+ {
+ errlog("Error to read SW_RESET register!\n");
+ }
+ dbg("i2c Read 0x53 = %x \n", cData);
+
+ cAddress = 0x0f;
+ //i2c_master_send( client, (char*)&cAddress, 1);
+ //i2c_master_recv( client, (char*)&cData, 1);
+ if (dmard06_i2c_xyz_read_reg(&cAddress, &cData,1) <= 0)
+ {
+ errlog("Can't find dmard06!\n");
+ return -1;
+ }
+ dbg("i2c Read 0x0f = %d \n", cData);
+
+ if(( cData&0x00FF) == 0x0006)
+ {
+ klog("Find DMARD06!\n");
+ }
+ else
+ {
+ errlog("ID isn't 0x06.(0x%x) !\n",cData);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int dmard06_i2c_remove(void)
+{
+
+ return 0;
+}
+
+static int dmard06_i2c_resume(struct platform_device *pdev)
+{
+ dbg("...\n");
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+
+
+ return 0;
+}
+
+static int sensor_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+
+ int inputval = -1;
+ int enable, sample = -1;
+ char tembuf[8];
+ unsigned int amsr = 0;
+ int test = 0;
+
+ mutex_lock(&sense_data_mutex);
+ memset(tembuf, 0, sizeof(tembuf));
+ // get sensor level and set sensor level
+ if (sscanf(buffer, "isdbg=%d\n", &l_sensorconfig.isdbg))
+ {
+ // only set the dbg flag
+ } else if (sscanf(buffer, "samp=%d\n", &sample))
+ {
+ if (sample > 0)
+ {
+ if (sample != l_sensorconfig.sensor_samp)
+ {
+ }
+ //printk(KERN_ALERT "sensor samp=%d(amsr:%d) has been set.\n", sample, amsr);
+ } else {
+ printk(KERN_ALERT "Wrong sample argumnet of sensor.\n");
+ }
+ } else if (sscanf(buffer, "enable=%d\n", &enable))
+ {
+ if ((enable < 0) || (enable > 1))
+ {
+ printk(KERN_ERR "The argument to enable/disable g-sensor should be 0 or 1 !!!\n");
+ } else if (enable != l_sensorconfig.sensor_enable)
+ {
+ //mma_enable_disable(enable);
+ l_sensorconfig.sensor_enable = enable;
+ }
+ } else if (sscanf(buffer, "sensor_test=%d\n", &test))
+ { // for test begin
+ l_sensorconfig.test_pass = 0;
+ } else if (sscanf(buffer, "sensor_testend=%d\n", &test))
+ { // Don nothing only to be compatible the before testing program
+ }
+ mutex_unlock(&sense_data_mutex);
+ return count;
+}
+
+static int sensor_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "test_pass=%d\nisdbg=%d\nrate=%d\nenable=%d\n",
+ l_sensorconfig.test_pass,
+ l_sensorconfig.isdbg,
+ l_sensorconfig.sensor_samp,
+ l_sensorconfig.sensor_enable
+ );
+ return len;
+}
+
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static int get_axisset(void* param)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.d06sensor", varbuf, &varlen)) {
+ printk(KERN_DEBUG "Can't get gsensor config in u-boot!!!!\n");
+ return -1;
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &l_sensorconfig.op,
+ &l_sensorconfig.int_gpio,
+ &l_sensorconfig.samp,
+ &(l_sensorconfig.xyz_axis[0][0]),
+ &(l_sensorconfig.xyz_axis[0][1]),
+ &(l_sensorconfig.xyz_axis[1][0]),
+ &(l_sensorconfig.xyz_axis[1][1]),
+ &(l_sensorconfig.xyz_axis[2][0]),
+ &(l_sensorconfig.xyz_axis[2][1]),
+ &l_sensorconfig.offset[0],
+ &l_sensorconfig.offset[1],
+ &l_sensorconfig.offset[2]);
+ if (n != 12) {
+ printk(KERN_ERR "gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+ l_sensorconfig.sensor_samp = l_sensorconfig.samp;
+
+ dbg("get the sensor config: %d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ l_sensorconfig.xyz_axis[0][0],
+ l_sensorconfig.xyz_axis[0][1],
+ l_sensorconfig.xyz_axis[1][0],
+ l_sensorconfig.xyz_axis[1][1],
+ l_sensorconfig.xyz_axis[2][0],
+ l_sensorconfig.xyz_axis[2][1]
+ );
+ }
+ return 0;
+}
+
+// To contol the g-sensor for UI
+static int mmad_open(struct inode *inode, struct file *file)
+{
+ dbg("Open the g-sensor node...\n");
+ return 0;
+}
+
+static int mmad_release(struct inode *inode, struct file *file)
+{
+ dbg("Close the g-sensor node...\n");
+ return 0;
+}
+
+
+static int
+mmad_ioctl(/*struct inode *inode,*/ struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ char rwbuf[5];
+ short delay, enable, amsr = -1;
+ unsigned int sample;
+ int ret = 0;
+ int side;
+ char varbuff[80];
+ unsigned int uval = 0;
+
+ dbg("g-sensor ioctr...\n");
+ memset(rwbuf, 0, sizeof(rwbuf));
+ mutex_lock(&sense_data_mutex);
+ switch (cmd) {
+ case ECS_IOCTL_APP_SET_DELAY:
+ // set the rate of g-sensor
+ if (copy_from_user(&delay, argp, sizeof(short)))
+ {
+ printk(KERN_ALERT "Can't get set delay!!!\n");
+ ret = -EFAULT;
+ goto errioctl;
+ }
+ klog("set delay=%d \n", delay);
+ //klog("before change sensor sample:%d...\n", l_sensorconfig.sensor_samp);
+ if ((delay >=0) && (delay < 20))
+ {
+ delay = 20;
+ } else if (delay > 200)
+ {
+ delay = 200;
+ }
+ if (delay > 0)
+ {
+ l_sensorconfig.sensor_samp = 1000/delay;
+ } else {
+ errlog("error delay argument(delay=%d)!!!\n",delay);
+ ret = -EFAULT;
+ goto errioctl;
+ }
+ break;
+ case ECS_IOCTL_APP_SET_AFLAG:
+ // enable/disable sensor
+ if (copy_from_user(&enable, argp, sizeof(short)))
+ {
+ printk(KERN_ERR "Can't get enable flag!!!\n");
+ ret = -EFAULT;
+ goto errioctl;
+ }
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor.\n", enable);
+
+ if (enable != l_sensorconfig.sensor_enable)
+ {
+ //mma_enable_disable(enable);
+ /*if (enable != 0)
+ {
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+ } else {
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ flush_workqueue(l_sensorconfig.queue);
+ }*/
+ l_sensorconfig.sensor_enable = enable;
+
+ }
+ } else {
+ printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__);
+ ret = -EFAULT;
+ goto errioctl;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ uval = DMARD06_DRVID;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ ret = -EFAULT;
+ goto errioctl;
+ }
+ dbg("dmard06_driver_id:%d\n",uval);
+ break;
+ case WMT_IOCTL_SENSOR_CAL_OFFSET:
+ klog("-->WMT_IOCTL_SENSOR_CAL_OFFSET\n");
+ if(copy_from_user(&side, (int*)argp, sizeof(int)))
+ {
+ ret = -EFAULT;
+ goto errioctl;
+ }
+ dbg("side=%d\n",side);
+ if (dmard06_CalOffset(side) != 0)
+ {
+ ret = -EFAULT;
+ goto errioctl;
+ }
+ // save the param
+ sprintf(varbuff, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ 10,//l_sensorconfig.samp,
+ (l_sensorconfig.xyz_axis[0][0]),
+ (l_sensorconfig.xyz_axis[0][1]),
+ (l_sensorconfig.xyz_axis[1][0]),
+ (l_sensorconfig.xyz_axis[1][1]),
+ (l_sensorconfig.xyz_axis[2][0]),
+ (l_sensorconfig.xyz_axis[2][1]),
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+ wmt_setsyspara(GSENDMARD06_UBOOT_NAME, varbuff);
+ ret = 0;
+ break;
+ default:
+ break;
+ }
+
+
+ /*switch (cmd) {
+ case ECS_IOCTL_READ:
+ if (copy_to_user(argp, &rwbuf, sizeof(rwbuf)))
+ return -EFAULT;
+ break;
+ default:
+ break;
+ }*/
+errioctl:
+ mutex_unlock(&sense_data_mutex);
+ return ret;
+}
+
+
+static struct file_operations mmad_fops = {
+ .owner = THIS_MODULE,
+ .open = mmad_open,
+ .release = mmad_release,
+ .unlocked_ioctl = mmad_ioctl,
+};
+
+
+static struct miscdevice mmad_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "sensor_ctrl",
+ .fops = &mmad_fops,
+};
+
+static int dmard06_probe(
+ struct platform_device *pdev)
+{
+ int err = 0;
+
+ //register ctrl dev
+ err = misc_register(&mmad_device);
+ if (err != 0)
+ {
+ errlog("Can't register mma_device!\n");
+ return -1;
+ }
+ // register rd/wr proc
+ l_sensorconfig.sensor_proc = create_proc_entry(GSENSOR_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ l_sensorconfig.sensor_proc->write_proc = sensor_writeproc;
+ l_sensorconfig.sensor_proc->read_proc = sensor_readproc;
+ }
+ // init work queue
+ l_sensorconfig.queue = create_singlethread_workqueue("sensor-data-report");
+ //INIT_WORK(&l_sensorconfig.work, mma_work_func);
+ INIT_DELAYED_WORK(&l_sensorconfig.work, dmard06_work_func);
+ mutex_init(&sense_data_mutex);
+ l_sensorconfig.input_dev = input_allocate_device();
+ if (!l_sensorconfig.input_dev) {
+ err = -ENOMEM;
+ errlog("Failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+ //set_bit(EV_KEY, l_sensorconfig.input_dev->evbit);
+ //set_bit(EV_ABS, l_sensorconfig.input_dev->evbit);
+ l_sensorconfig.input_dev->evbit[0] = BIT(EV_ABS) | BIT_MASK(EV_KEY);
+ //set_bit(KEY_NEXTSONG, l_sensorconfig.input_dev->keybit);
+
+ /* yaw */
+ //input_set_abs_params(l_sensorconfig.input_dev, ABS_RX, 0, 360*100, 0, 0);
+ /* pitch */
+ //input_set_abs_params(l_sensorconfig.input_dev, ABS_RY, -180*100, 180*100, 0, 0);
+ /* roll */
+ //input_set_abs_params(l_sensorconfig.input_dev, ABS_RZ, -90*100, 90*100, 0, 0);
+ /* x-axis acceleration */
+ input_set_abs_params(l_sensorconfig.input_dev, ABS_X, -128, 128, 0, 0);
+ /* y-axis acceleration */
+ input_set_abs_params(l_sensorconfig.input_dev, ABS_Y, -128, 128, 0, 0);
+ /* z-axis acceleration */
+ input_set_abs_params(l_sensorconfig.input_dev, ABS_Z, -128, 128, 0, 0);
+
+ l_sensorconfig.input_dev->name = "g-sensor";
+
+ err = input_register_device(l_sensorconfig.input_dev);
+
+ if (err) {
+ errlog("Unable to register input device: %s\n",
+ l_sensorconfig.input_dev->name);
+ goto exit_input_register_device_failed;
+ }
+
+ return 0;
+exit_input_register_device_failed:
+ input_free_device(l_sensorconfig.input_dev);
+exit_input_dev_alloc_failed:
+ // release proc
+ remove_proc_entry(GSENSOR_PROC_NAME, NULL);
+ l_sensorconfig.sensor_proc = NULL;
+ // unregister the ctrl dev
+ misc_deregister(&mmad_device);
+ return err;
+}
+
+static int dmard06_remove(struct platform_device *pdev)
+{
+ if (NULL != l_sensorconfig.queue)
+ {
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ flush_workqueue(l_sensorconfig.queue);
+ destroy_workqueue(l_sensorconfig.queue);
+ l_sensorconfig.queue = NULL;
+ }
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ remove_proc_entry(GSENSOR_PROC_NAME, NULL);
+ l_sensorconfig.sensor_proc = NULL;
+ }
+ misc_deregister(&mmad_device);
+ return 0;
+}
+#if 0
+static void dmard06_early_suspend(struct early_suspend *h)
+{
+ dbg("start\n");
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ dbg("exit\n");
+}
+
+static void dmard06_late_resume(struct early_suspend *h)
+{
+ dbg("start\n");
+ // init
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+ dbg("exit\n");
+}
+#endif
+
+static int __init dmard06_init(void)
+{
+ int ret = 0;
+
+ // detech the device
+ if (is_dmard06() != 0)
+ {
+ return -1;
+ }
+ // parse g-sensor u-boot arg
+ ret = get_axisset(NULL);
+ if (ret < 0)
+ {
+ printk("<<<<<%s user choose to no sensor chip!\n", __func__);
+ return ret;
+ }
+ /*if ((ret != 0) || !l_sensorconfig.op)
+ return -EINVAL;
+ */
+
+ // Create device node
+ if (register_chrdev (GSENSOR_MAJOR, GSENSOR_NAME, &dmard06_fops)) {
+ printk (KERN_ERR "unable to get major %d\n", GSENSOR_MAJOR);
+ return -EIO;
+ }
+
+ l_dev_class = class_create(THIS_MODULE, GSENSOR_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create gsensor device !!\n");
+ return ret;
+ }
+ l_clsdevice = device_create(l_dev_class, NULL, MKDEV(GSENSOR_MAJOR, 0), NULL, GSENSOR_NAME);
+ if (IS_ERR(l_clsdevice)){
+ ret = PTR_ERR(l_clsdevice);
+ printk(KERN_ERR "Failed to create device %s !!!",GSENSOR_NAME);
+ return ret;
+ }
+ INIT_WORK(&poll_work, dmard06_work_func);
+
+
+ if((ret = platform_device_register(&dmard06_device)))
+ {
+ printk(KERN_ERR "%s Can't register mma7660 platform devcie!!!\n", __FUNCTION__);
+ return ret;
+ }
+ if ((ret = platform_driver_register(&dmard06_driver)) != 0)
+ {
+ printk(KERN_ERR "%s Can't register mma7660 platform driver!!!\n", __FUNCTION__);
+ return ret;
+ }
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ l_sensorconfig.earlysuspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ l_sensorconfig.earlysuspend.suspend = dmard06_early_suspend;
+ l_sensorconfig.earlysuspend.resume = dmard06_late_resume;
+ register_early_suspend(&l_sensorconfig.earlysuspend);
+#endif
+
+ klog("dmard06 g-sensor driver load!\n");
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+
+ return 0;
+}
+
+static void __exit dmard06_exit(void)
+{
+ //unregister_early_suspend(&l_sensorconfig.earlysuspend);
+ platform_driver_unregister(&dmard06_driver);
+ platform_device_unregister(&dmard06_device);
+ device_destroy(l_dev_class, MKDEV(GSENSOR_MAJOR, 0));
+ unregister_chrdev(GSENSOR_MAJOR, GSENSOR_NAME);
+ class_destroy(l_dev_class);
+
+}
+
+MODULE_AUTHOR("DMT_RD");
+MODULE_DESCRIPTION("DMARD06 g-sensor Driver");
+MODULE_LICENSE("GPL");
+
+module_init(dmard06_init);
+module_exit(dmard06_exit);
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/Makefile
new file mode 100755
index 00000000..82f27563
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_gsensor_dmard08
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := dmard08.o cyclequeue.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/cyclequeue.c b/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/cyclequeue.c
new file mode 100755
index 00000000..4d6b97cd
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/cyclequeue.c
@@ -0,0 +1,68 @@
+#include <linux/mutex.h>
+
+
+#include "cyclequeue.h"
+
+static struct que_data que[QUEUE_LEN];
+static unsigned int head = -1; // point to the first valaid queue data
+static unsigned int tail = 0; // point to the next to the last valaid queue data
+static DEFINE_MUTEX(que_mutex);
+
+// Whether queue is full
+// return 1--full,0 -- no full
+int clque_is_full(void)
+{
+ int ret = 0;
+
+ mutex_lock(&que_mutex);
+ ret = ((tail+1)%QUEUE_LEN) == head ? 1 : 0;
+ mutex_unlock(&que_mutex);
+ return ret;
+}
+
+// Whether queue is empty
+// return 1--empty,0--no empty
+int clque_is_empty(void)
+{
+ int ret = 0;
+
+ mutex_lock(&que_mutex);
+ ret = (tail == head) ? 1: 0;
+ mutex_unlock(&que_mutex);
+ return ret;
+}
+
+// add to queue
+// return:0--successful,-1--queue is full
+int clque_in(struct que_data* data)
+{
+ /*if (clque_is_full())
+ {
+ return -1;
+ }*/
+ mutex_lock(&que_mutex);
+ que[tail].data[0] = data->data[0];
+ que[tail].data[1] = data->data[1];
+ que[tail].data[2] = data->data[2];
+ tail = (tail+1)%QUEUE_LEN;
+ mutex_unlock(&que_mutex);
+ return 0;
+}
+
+// out to queue
+// return:0--successful,-1--queue is empty
+int clque_out(struct que_data* data)
+{
+ /*if (clque_is_empty())
+ {
+ return -1;
+ }*/
+ mutex_lock(&que_mutex);
+ data->data[0]= que[head].data[0];
+ data->data[1]= que[head].data[1];
+ data->data[2]= que[head].data[2];
+ head = (head+1)%QUEUE_LEN;
+ mutex_unlock(&que_mutex);
+ return 0;
+}
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/cyclequeue.h b/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/cyclequeue.h
new file mode 100755
index 00000000..52b9996f
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/cyclequeue.h
@@ -0,0 +1,18 @@
+#ifndef __CYCLEQUEUE_163704111637_H
+#define __CYCLEQUEUE_163704111637_H
+
+#define DATA_TYPE short
+#define QUEUE_LEN 16
+
+struct que_data {
+ DATA_TYPE data[3];
+};
+
+extern int clque_in(struct que_data* data);
+extern int clque_out(struct que_data* data);
+extern int clque_is_full(void);
+extern int clque_is_empty(void);
+#endif
+
+
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/dmard08.c b/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/dmard08.c
new file mode 100755
index 00000000..3cbe2ac7
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/dmard08.c
@@ -0,0 +1,1019 @@
+/*
+ * @file drivers/i2c/dmard08.c
+ * @brief DMARD08 g-sensor Linux device driver
+ * @author Domintech Technology Co., Ltd (http://www.domintech.com.tw)
+ * @version 1.22
+ * @date 2011/12/01
+ *
+ * @section LICENSE
+ *
+ * Copyright 2011 Domintech Technology Co., Ltd
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ */
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/cdev.h>
+//#include <linux/earlysuspend.h>
+#include <linux/wakelock.h>
+#include <asm/uaccess.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/serio.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include <linux/clk.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <mach/hardware.h>
+#include <asm/io.h>
+#include <linux/miscdevice.h>
+#include <mach/gpio.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+// ****Add by Steve Huang*********2011-11-18********
+#include <linux/syscalls.h>
+#include "../sensor.h"
+//#include "cyclequeue.h"
+// ************************************************
+
+#define GSENSOR_I2C_NAME "dmard08"
+#define GSENSOR_I2C_ADDR 0x1c
+
+#define SENSOR_DATA_SIZE 3
+
+static struct i2c_client *this_client = NULL;
+static struct mutex sense_data_mutex;
+static struct class* l_dev_class = NULL;
+
+static struct wmt_gsensor_data l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .samp = 5,
+ .xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },
+ .sensor_proc = NULL,
+ .isdbg = 0,
+ .sensor_samp = 10, // 1 sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ .offset={0,0,0},
+};
+
+
+// ****Add by Steve Huang*********2011-11-18********
+/*void gsensor_write_offset_to_file(void);
+void gsensor_read_offset_from_file(void);
+char OffsetFileName[] = "/data/misc/dmt/offset.txt";*/
+//**************************************************
+
+
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+
+/*static int dmard08_i2c_suspend(struct i2c_client *client, pm_message_t mesg);
+static int dmard08_i2c_resume(struct i2c_client *client);*/
+//static int __devinit dmard08_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
+//static int __devexit dmard08_i2c_remove(struct i2c_client *client);
+void dmard08_i2c_read_xyz(struct i2c_client *client, s16 *xyz);
+static inline void dmard08_i2c_correct_accel_sign(s16 *val); //check output is correct
+void dmard08_i2c_merge_register_values(struct i2c_client *client, s16 *val, u8 msb, u8 lsb); //merge the register values
+
+struct raw_data {
+ short x;
+ short y;
+ short z;
+};
+
+struct raw_data rdata;
+//static struct raw_data offset;
+
+struct dev_data
+{
+ dev_t devno;
+ struct cdev cdev;
+ struct class *class;
+ struct i2c_client *client;
+};
+//static struct dev_data dev;
+
+
+unsigned int sample_rate_2_memsec(unsigned int rate)
+{
+ return (1000/rate);
+}
+
+
+/*void gsensor_read_accel_avg(int num_avg, raw_data *avg_p) // marked by eason check again!!
+{
+ long xyz_acc[SENSOR_DATA_SIZE];
+ s16 xyz[SENSOR_DATA_SIZE];
+ int i, j;
+
+ //initialize the accumulation buffer
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ xyz_acc[i] = 0;
+
+ for(i = 0; i < num_avg; i++)
+ {
+ device_i2c_read_xyz(l_sensorconfig.client, (s16 *)&xyz);
+ for(j = 0; j < SENSOR_DATA_SIZE; j++)
+ xyz_acc[j] += xyz[j];
+ }
+
+ // calculate averages
+ for(i = 0; i < SENSOR_DATA_SIZE; i++)
+ avg_p->v[i] = (s16) (xyz_acc[i] / num_avg);
+}*/
+
+/*void gsensor_calibrate(int side) //marked by eason check again
+{
+ raw_data avg;
+ int avg_num = 16;
+
+ //IN_FUNC_MSG;
+ // get acceleration average reading
+ gsensor_read_accel_avg(avg_num, &avg);
+ // calculate and set the offset
+ gsensor_calculate_offset(side, avg);
+}*/
+
+/*void ce_on(void) //marked by eason check again
+{
+ int gppdat;
+ gppdat = __raw_readl(S3C64XX_GPPDAT);
+ gppdat |= (1 << 0);
+
+ __raw_writel(gppdat,S3C64XX_GPPDAT);
+}
+
+void ce_off(void)
+{
+ int gppdat;
+ gppdat = __raw_readl(S3C64XX_GPPDAT);
+ gppdat &= ~(1 << 0);
+
+ __raw_writel(gppdat,S3C64XX_GPPDAT);
+}
+
+void config_ce_pin(void)
+{
+ unsigned int value;
+ //D08's CE (pin#12) is connected to S3C64XX AP processor's port P0
+ //Below codes set port P0 as digital output
+ value = readl(S3C64XX_GPPCON);
+ value &= ~ (0x3);
+ value |= 1 ; //Output =01 , Input = 00 , Ext. Interrupt = 10
+ writel(value, S3C64XX_GPPCON); //save S3C64XX_GPPCON change
+}
+
+void gsensor_reset(void)
+{
+ ce_off();
+ msleep(300);
+ ce_on();
+}*/
+
+/*void gsensor_set_offset(int val[3]) //marked by eason check again
+{
+ int i;
+ IN_FUNC_MSG;
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ offset.v[i] = (s16) val[i];
+}*/
+
+/*
+static const struct i2c_device_id dmard08_i2c_ids[] =
+{
+ {GSENSOR_I2C_NAME, 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, dmard08_i2c_ids);
+
+
+static struct i2c_driver dmard08_i2c_driver =
+{
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = GSENSOR_I2C_NAME,
+ },
+ .class = I2C_CLASS_HWMON,
+ .probe = dmard08_i2c_probe,
+ .remove = __devexit_p(dmard08_i2c_remove),
+ //.suspend = dmard08_i2c_suspend,
+ //.resume = dmard08_i2c_resume,
+ .id_table = dmard08_i2c_ids,
+};
+*/
+
+static int dmard08_i2c_xyz_read_reg(struct i2c_client *client,u8 *buffer, int length) //OK
+{
+
+ struct i2c_msg msg[] =
+ {
+ {.addr = client->addr, .flags = 0, .len = 1, .buf = buffer,},
+ {.addr = client->addr, .flags = I2C_M_RD, .len = length, .buf = buffer,},
+ };
+ return i2c_transfer(client->adapter, msg, 2);
+}
+
+static int dmard08_i2c_xyz_write_reg(struct i2c_client *client,u8 *buffer, int length) //write reg OK
+{
+ struct i2c_msg msg[] =
+ {
+ {.addr = client->addr, .flags = 0, .len = length, .buf = buffer,},
+ };
+ return i2c_transfer(client->adapter, msg, 1);
+}
+
+//static void dmard08_i2c_read_xyz(struct i2c_client, s16 *x, s16 *y, s16 *z) //add by eason
+void dmard08_i2c_read_xyz(struct i2c_client *client, s16 *xyz_p)
+{
+// s16 xTmp,yTmp,zTmp; //added by eason
+ s16 xyzTmp[SENSOR_DATA_SIZE];
+ int i;
+/*get xyz high/low bytes, 0x02~0x07*/
+ u8 buffer[6];
+ buffer[0] = 0x2;
+ mutex_lock(&sense_data_mutex);
+ dmard08_i2c_xyz_read_reg(client, buffer, 6);
+ mutex_unlock(&sense_data_mutex);
+
+ //merge to 11-bits value
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ dmard08_i2c_merge_register_values(client, (xyzTmp + i), buffer[2*i], buffer[2*i + 1]);
+ }
+ //transfer to the default layout
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ {
+ xyz_p[i] = xyzTmp[i]; // add by eason
+/* xyz_p[i] = 0;
+ for(j = 0; j < 3; j++)
+ xyz_p[i] += sensorlayout[i][j] * xyzTmp[j]; */
+ }
+ dbg("%x,%x,%x,",xyz_p[0], xyz_p[1], xyz_p[2]);
+ //printk("@DMT@ dmard08_i2c_read_xyz: X-axis: %d ,Y-axis: %d ,Z-axis: %d\n", xyz_p[0], xyz_p[1], xyz_p[2]);
+}
+
+void dmard08_i2c_merge_register_values(struct i2c_client *client, s16 *val, u8 msb, u8 lsb)
+{
+
+ *val = (((u16)msb) << 3) | (u16)lsb;
+ dmard08_i2c_correct_accel_sign(val);
+}
+
+static inline void dmard08_i2c_correct_accel_sign(s16 *val)
+{
+
+ *val<<= (sizeof(s16) * BITS_PER_BYTE - 11);
+ *val>>= (sizeof(s16) * BITS_PER_BYTE - 11);
+}
+
+/*
+static int dmard08_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+ dbg("...\n");
+ return 0;
+}
+*/
+
+//static int __devinit dmard08_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id)
+static int __devinit dmard08_hw_init(struct i2c_client *client/*,const struct i2c_device_id *id*/)
+{
+ char cAddress = 0 , cData = 0;
+ u8 buffer[2];
+
+ //for(i = 0; i < SENSOR_DATA_SIZE; ++i) //marked by eason check again
+ // offset.v[i] = 0;
+
+
+ if(!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ {
+ dbg("I2C_FUNC_I2C not support\n");
+ return -1;
+ }
+ //config_ce_pin(); //how used?
+ //gsensor_reset(); //how used?
+ /* check SW RESET */
+ cAddress = 0x08;
+ i2c_master_send( client, (char*)&cAddress, 1);
+ i2c_master_recv( client, (char*)&cData, 1);
+ dbg( "i2c Read 0x08 = %d \n", cData);
+ if( cData == 0x00)
+ {
+ cAddress = 0x09;
+ i2c_master_send( client, (char*)&cAddress, 1);
+ i2c_master_recv( client, (char*)&cData, 1);
+ dbg( "i2c Read 0x09 = %d \n", cData);
+ if( cData == 0x00)
+ {
+ cAddress = 0x0a;
+ i2c_master_send( client, (char*)&cAddress, 1);
+ i2c_master_recv( client, (char*)&cData, 1);
+ dbg( "i2c Read 0x0a = %d \n", cData);
+ if( cData == 0x88)
+ {
+ cAddress = 0x0b;
+ i2c_master_send( client, (char*)&cAddress, 1);
+ i2c_master_recv( client, (char*)&cData, 1);
+ dbg( "i2c Read 0x0b = %d \n", cData);
+ if( cData == 0x08)
+ {
+ dbg( "DMT_DEVICE_NAME registered I2C driver!\n");
+ l_sensorconfig.client = client;
+ }
+ else
+ {
+ dbg( "err : i2c Read 0x0B = %d!\n",cData);
+ l_sensorconfig.client = NULL;
+ return -1;
+ }
+ }
+ else
+ {
+ dbg( "err : i2c Read 0x0A = %d!\n",cData);
+ l_sensorconfig.client = NULL;
+ return -1;
+ }
+ }
+ else
+ {
+ dbg( "err : i2c Read 0x09 = %d!\n",cData);
+ l_sensorconfig.client = NULL;
+ return -1;
+ }
+ }
+ else
+ {
+ dbg( "err : i2c Read 0x08 = %d!\n",cData);
+ l_sensorconfig.client = NULL;
+
+ return -1;
+ }
+
+ /* set sampling period if samp = 1, set the sampling frequency = 684
+ otherwise set the sample frequency = 342 (default) added by eason 2012/3/7*/
+ if (l_sensorconfig.samp == 1) {
+ buffer[0] = 0x08;
+ buffer[1] = 0x04;
+ dmard08_i2c_xyz_write_reg(client, buffer, 2);
+ }
+
+ /*check sensorlayout[i][j] //eason
+ for(i = 0; i < 3; ++i)
+ {
+ for(j = 0; j < 3; j++)
+ printk("%d",sensorlayout[i][j]);
+ printk("\n");
+ } */
+
+ return 0;
+}
+
+static int __devexit dmard08_i2c_remove(struct i2c_client *client) //OK
+{
+ dbg("...\n");
+
+ return 0;
+}
+
+/*
+static int dmard08_i2c_resume(struct i2c_client *client) //OK
+{
+ dbg("...\n");
+
+ return 0;
+}
+*/
+static int get_axisset(void)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.dm08sensor", varbuf, &varlen)) {
+ errlog("Can't get gsensor config in u-boot!!!!\n");
+ return -1;
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &l_sensorconfig.op,
+ &l_sensorconfig.int_gpio,
+ &l_sensorconfig.samp,
+ &(l_sensorconfig.xyz_axis[0][0]),
+ &(l_sensorconfig.xyz_axis[0][1]),
+ &(l_sensorconfig.xyz_axis[1][0]),
+ &(l_sensorconfig.xyz_axis[1][1]),
+ &(l_sensorconfig.xyz_axis[2][0]),
+ &(l_sensorconfig.xyz_axis[2][1]),
+ &(l_sensorconfig.offset[0]),
+ &(l_sensorconfig.offset[1]),
+ &(l_sensorconfig.offset[2])
+ );
+ if (n != 12) {
+ errlog("gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+ l_sensorconfig.sensor_samp = l_sensorconfig.samp;
+
+ dbg("get the sensor config: %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ l_sensorconfig.xyz_axis[0][0],
+ l_sensorconfig.xyz_axis[0][1],
+ l_sensorconfig.xyz_axis[1][0],
+ l_sensorconfig.xyz_axis[1][1],
+ l_sensorconfig.xyz_axis[2][0],
+ l_sensorconfig.xyz_axis[2][1],
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+ }
+ return 0;
+}
+
+static void dmard08_platform_release(struct device *device)
+{
+ dbg("...\n");
+ return;
+}
+
+
+static struct platform_device dmard08_device = {
+ .name = GSENSOR_I2C_NAME,
+ .id = 0,
+ .dev = {
+ .release = dmard08_platform_release,
+ },
+};
+
+static int dmard08_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ dbg("...\n");
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+
+ return 0;
+}
+
+
+static int dmard08_open(struct inode *node, struct file *fle)
+{
+ dbg("open...\n");
+ return 0;
+}
+
+/* release command for dmard08 device file */
+static int dmard08_close(struct inode *node, struct file *fle)
+{
+ dbg("close...\n");
+ return 0;
+}
+
+/* ioctl command for dmard08 device file */
+static long dmard08_ioctl(/*struct inode *inode,*/ struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int err = 0;
+ //unsigned char data[6];
+ short delay = 0;
+ short enable = 0;
+ unsigned int uval = 0;
+
+ if (WMT_IOCTL_SENSOR_CAL_OFFSET == cmd)
+ {
+ return 0;// now do nothing
+ }
+
+ /* cmd mapping */
+ mutex_lock(&sense_data_mutex);
+ switch(cmd)
+ {
+
+ case ECS_IOCTL_APP_SET_DELAY:
+ // set the rate of g-sensor
+ dbg("ECS_IOCTL_APP_SET_DELAY\n");
+ if (copy_from_user(&delay,(short*)arg, sizeof(short)))
+ {
+ errlog("Can't get set delay!!!\n");
+ err = -EFAULT;
+ goto errioctl;
+ }
+ klog("set delay=%d \n", delay);
+ //klog("before change sensor sample:%d...\n", l_sensorconfig.sensor_samp);
+ if ((delay >=0) && (delay < 20))
+ {
+ delay = 20;
+ } else if (delay > 200)
+ {
+ delay = 200;
+ }
+ if (delay > 0)
+ {
+ l_sensorconfig.sensor_samp = 1000/delay;
+ } else {
+ errlog("error delay argument(delay=%d)!!!\n",delay);
+ err = -EFAULT;
+ goto errioctl;
+ }
+ break;
+ case ECS_IOCTL_APP_SET_AFLAG:
+ dbg("ECS_IOCTL_APP_SET_AFLAG\n");
+ // enable/disable sensor
+ if (copy_from_user(&enable, (short*)arg, sizeof(short)))
+ {
+ errlog("Can't get enable flag!!!\n");
+ err = -EFAULT;
+ goto errioctl;
+ }
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor.\n", enable);
+
+ if (enable != l_sensorconfig.sensor_enable)
+ {
+ // do sth ???
+ //mma_enable_disable(enable);
+ /*if (enable != 0)
+ {
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+ } else {
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ flush_workqueue(l_sensorconfig.queue);
+ }*/
+ l_sensorconfig.sensor_enable = enable;
+
+ }
+ } else {
+ errlog("Wrong enable argument!!!\n");
+ err = -EFAULT;
+ goto errioctl;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ uval = DMARD08_DRVID;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("dmard08_driver_id:%d\n",uval);
+ break;
+ default:
+ break;
+ }
+errioctl:
+ mutex_unlock(&sense_data_mutex);
+ return err;
+}
+
+/*
+static ssize_t dmard08_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
+{
+ struct que_data data;
+ short xyz_temp[3];
+
+ // read data from cycle queue
+ while (clque_is_empty()) msleep(10);
+ clque_out(&data);
+ xyz_temp[0] = data.data[0];
+ xyz_temp[1] = data.data[1];
+ xyz_temp[2] = data.data[2];
+
+
+ if(copy_to_user(buf, &xyz_temp, sizeof(xyz_temp)))
+ return -EFAULT;
+ dbg("x=%x,y=%x,z=%x\n",xyz_temp[0], xyz_temp[1], xyz_temp[2]);
+ return sizeof(xyz_temp);
+}
+*/
+/*
+static ssize_t dmard08_write(struct file *file, const char __user *buf, size_t count, loff_t *offset)
+{
+ dbg("write...\n");
+ return 0;
+}
+*/
+
+static const struct file_operations d08_fops = {
+ .owner = THIS_MODULE,
+ .open = dmard08_open,
+ .release = dmard08_close,
+ //.read = dmard08_read,
+ //.wirte = dmard08_write,
+ .unlocked_ioctl = dmard08_ioctl,
+};
+
+static struct miscdevice d08_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = GSENSOR_DEV_NODE,
+ .fops = &d08_fops,
+};
+
+
+static int dmard08_resume(struct platform_device *pdev)
+{
+ char buffer[2];
+ dbg("...\n");
+
+ if (l_sensorconfig.samp == 1) {
+ buffer[0] = 0x08;
+ buffer[1] = 0x04;
+ dmard08_i2c_xyz_write_reg(l_sensorconfig.client, buffer, 2);
+ }
+
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+ return 0;
+}
+
+static int sensor_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+
+ //int inputval = -1;
+ int enable, sample = -1;
+ char tembuf[8];
+ //unsigned int amsr = 0;
+ int test = 0;
+
+ mutex_lock(&sense_data_mutex);
+ memset(tembuf, 0, sizeof(tembuf));
+ // get sensor level and set sensor level
+ if (sscanf(buffer, "isdbg=%d\n", &l_sensorconfig.isdbg))
+ {
+ // only set the dbg flag
+ } else if (sscanf(buffer, "samp=%d\n", &sample))
+ {
+ if (sample > 0)
+ {
+ if (sample != l_sensorconfig.sensor_samp)
+ {
+ // should do sth
+ }
+ //printk(KERN_ALERT "sensor samp=%d(amsr:%d) has been set.\n", sample, amsr);
+ } else {
+ klog("Wrong sample argumnet of sensor.\n");
+ }
+ } else if (sscanf(buffer, "enable=%d\n", &enable))
+ {
+ if ((enable < 0) || (enable > 1))
+ {
+ klog("The argument to enable/disable g-sensor should be 0 or 1 !!!\n");
+ } else if (enable != l_sensorconfig.sensor_enable)
+ {
+ //mma_enable_disable(enable);
+ l_sensorconfig.sensor_enable = enable;
+ }
+ } else if (sscanf(buffer, "sensor_test=%d\n", &test))
+ { // for test begin
+ l_sensorconfig.test_pass = 0;
+ } else if (sscanf(buffer, "sensor_testend=%d\n", &test))
+ { // Don nothing only to be compatible the before testing program
+ }
+ mutex_unlock(&sense_data_mutex);
+ return count;
+}
+
+static int sensor_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "test_pass=%d\nisdbg=%d\nrate=%d\nenable=%d\n",
+ l_sensorconfig.test_pass,
+ l_sensorconfig.isdbg,
+ l_sensorconfig.sensor_samp,
+ l_sensorconfig.sensor_enable
+ );
+ return len;
+}
+
+static void read_work_func(struct work_struct *work)
+{
+ s16 xyz[SENSOR_DATA_SIZE];
+ s16 txyz[SENSOR_DATA_SIZE];
+
+ if (! l_sensorconfig.sensor_enable)
+ {
+ // no report data
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+ return;
+ }
+ // read data to one cycle que
+ //dbg("read...\n");
+ dmard08_i2c_read_xyz(l_sensorconfig.client, (s16 *)xyz);
+
+ // x
+ txyz[0] = xyz[l_sensorconfig.xyz_axis[0][0]]*l_sensorconfig.xyz_axis[0][1]+l_sensorconfig.offset[0];
+ // y
+ txyz[1] = xyz[l_sensorconfig.xyz_axis[1][0]]*l_sensorconfig.xyz_axis[1][1]+l_sensorconfig.offset[1];
+ // z
+ txyz[2] = xyz[l_sensorconfig.xyz_axis[2][0]]*l_sensorconfig.xyz_axis[2][1]+l_sensorconfig.offset[2];
+
+ input_report_abs(l_sensorconfig.input_dev, ABS_X, txyz[0]);
+ input_report_abs(l_sensorconfig.input_dev, ABS_Y, txyz[1]);
+ input_report_abs(l_sensorconfig.input_dev, ABS_Z, txyz[2]);
+ input_sync(l_sensorconfig.input_dev);
+ l_sensorconfig.test_pass = 1; // for testing
+ // read next
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+}
+
+
+static int dmard08_probe(struct platform_device *pdev)
+{
+ int err = 0;
+
+ //register ctrl dev
+ err = misc_register(&d08_device);
+ if (err !=0) {
+ errlog("Can't register d08_device!\n");
+ return -1;
+ }
+ // register rd/wr proc
+ l_sensorconfig.sensor_proc = create_proc_entry(GSENSOR_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ l_sensorconfig.sensor_proc->write_proc = sensor_writeproc;
+ l_sensorconfig.sensor_proc->read_proc = sensor_readproc;
+ }
+ // init work queue
+ l_sensorconfig.queue = create_singlethread_workqueue("sensor-report");
+ INIT_DELAYED_WORK(&l_sensorconfig.work, read_work_func);
+ mutex_init(&sense_data_mutex);
+ // init input device
+ l_sensorconfig.input_dev = input_allocate_device();
+ if (!l_sensorconfig.input_dev) {
+ err = -ENOMEM;
+ errlog("Failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+ l_sensorconfig.input_dev->evbit[0] = BIT(EV_ABS) | BIT_MASK(EV_KEY);
+ /* x-axis acceleration */
+ input_set_abs_params(l_sensorconfig.input_dev, ABS_X, -1024, 1024, 0, 0);
+ /* y-axis acceleration */
+ input_set_abs_params(l_sensorconfig.input_dev, ABS_Y, -1024, 1024, 0, 0);
+ /* z-axis acceleration */
+ input_set_abs_params(l_sensorconfig.input_dev, ABS_Z, -1024, 1024, 0, 0);
+
+ l_sensorconfig.input_dev->name = GSENSOR_INPUT_NAME;
+
+ err = input_register_device(l_sensorconfig.input_dev);
+
+ if (err) {
+ errlog("Unable to register input device: %s\n",
+ l_sensorconfig.input_dev->name);
+ goto exit_input_register_device_failed;
+ }
+
+ return 0;
+exit_input_register_device_failed:
+ // free inut
+ input_free_device(l_sensorconfig.input_dev);
+exit_input_dev_alloc_failed:
+ // free queue
+ destroy_workqueue(l_sensorconfig.queue);
+ l_sensorconfig.queue = NULL;
+ // free proc
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ remove_proc_entry(GSENSOR_PROC_NAME, NULL);
+ l_sensorconfig.sensor_proc = NULL;
+ }
+ // free work
+ // unregister ctrl dev
+ misc_deregister(&d08_device);
+ return err;
+}
+
+static int dmard08_remove(struct platform_device *pdev)
+{
+ if (NULL != l_sensorconfig.queue)
+ {
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ flush_workqueue(l_sensorconfig.queue);
+ destroy_workqueue(l_sensorconfig.queue);
+ l_sensorconfig.queue = NULL;
+ }
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ remove_proc_entry(GSENSOR_PROC_NAME, NULL);
+ l_sensorconfig.sensor_proc = NULL;
+ }
+ misc_deregister(&d08_device);
+ input_unregister_device(l_sensorconfig.input_dev);
+ return 0;
+}
+
+
+static struct platform_driver dmard08_driver = {
+ .probe = dmard08_probe,
+ .remove = dmard08_remove,
+ .suspend = dmard08_suspend,
+ .resume = dmard08_resume,
+ .driver = {
+ .name = GSENSOR_I2C_NAME,
+ },
+};
+
+#if 0
+static void dmard08_early_suspend(struct early_suspend *h)
+{
+ dbg("start\n");
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ dbg("exit\n");
+}
+
+static void dmard08_late_resume(struct early_suspend *h)
+{
+ dbg("start\n");
+ // init
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+ dbg("exit\n");
+}
+#endif
+
+static int __init dmard08_init(void) //OK
+{
+ int ret = 0;
+
+ // parse g-sensor u-boot arg
+ ret = get_axisset();
+ if (ret < 0)
+ {
+ printk("<<<<<%s user choose to no sensor chip!\n", __func__);
+ return ret;
+ }
+ /*if ((ret != 0) || !l_sensorconfig.op)
+ {
+ dbg("Can't load gsensor dmar08 driver for error u-boot arg!\n");
+ return -EINVAL;
+ }*/
+ if (!(this_client = sensor_i2c_register_device(0, GSENSOR_I2C_ADDR, GSENSOR_I2C_NAME)))
+ {
+ printk(KERN_EMERG"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+ // find the device
+ /*if(i2c_add_driver(&dmard08_i2c_driver) != 0)
+ {
+ ret = -1;
+ dbg("Can't find gsensor dmard08!\n");
+ goto err_i2c_add_driver;
+ }*/
+ if(dmard08_hw_init(this_client))
+ {
+ ret = -1;
+ dbg("Can't find gsensor dmard08!\n");
+ goto err_i2c_add_driver;
+ }
+
+
+ // create the platform device
+ l_dev_class = class_create(THIS_MODULE, GSENSOR_I2C_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create gsensor device !!\n");
+ return ret;
+ }
+ if((ret = platform_device_register(&dmard08_device)))
+ {
+ klog("Can't register mc3230 platform devcie!!!\n");
+ return ret;
+ }
+ if ((ret = platform_driver_register(&dmard08_driver)) != 0)
+ {
+ errlog("Can't register mc3230 platform driver!!!\n");
+ return ret;
+ }
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ l_sensorconfig.earlysuspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ l_sensorconfig.earlysuspend.suspend = dmard08_early_suspend;
+ l_sensorconfig.earlysuspend.resume = dmard08_late_resume;
+ register_early_suspend(&l_sensorconfig.earlysuspend);
+#endif
+
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+
+ return 0;
+
+err_i2c_add_driver:
+ sensor_i2c_unregister_device(this_client);
+ return ret;
+}
+
+static void __exit dmard08_exit(void) //OK
+{
+ platform_driver_unregister(&dmard08_driver);
+ platform_device_unregister(&dmard08_device);
+ class_destroy(l_dev_class);
+ sensor_i2c_unregister_device(this_client);
+}
+
+//*********************************************************************************************************
+// 2011-11-30
+// Add by Steve Huang
+// function definition
+/*
+void gsensor_write_offset_to_file(void)
+{
+ char data[18];
+ unsigned int orgfs;
+ long lfile=-1;
+
+ //sprintf(data,"%5d %5d %5d",offset.u.x,offset.u.y,offset.u.z); //marked by eason check again
+
+ orgfs = get_fs();
+// Set segment descriptor associated to kernel space
+ set_fs(KERNEL_DS);
+
+ lfile=sys_open(OffsetFileName,O_WRONLY|O_CREAT, 0777);
+ if (lfile < 0)
+ {
+ printk("sys_open %s error!!. %ld\n",OffsetFileName,lfile);
+ }
+ else
+ {
+ sys_write(lfile, data,18);
+ sys_close(lfile);
+ }
+ set_fs(orgfs);
+
+ return;
+}
+
+void gsensor_read_offset_from_file(void)
+{
+ unsigned int orgfs;
+ char data[18];
+ long lfile=-1;
+ orgfs = get_fs();
+// Set segment descriptor associated to kernel space
+ set_fs(KERNEL_DS);
+
+ lfile=sys_open(OffsetFileName, O_RDONLY, 0);
+ if (lfile < 0)
+ {
+ printk("sys_open %s error!!. %ld\n",OffsetFileName,lfile);
+ if(lfile==-2)
+ {
+ lfile=sys_open(OffsetFileName,O_WRONLY|O_CREAT, 0777);
+ if(lfile >=0)
+ {
+ strcpy(data,"00000 00000 00000");
+ printk("sys_open %s OK!!. %ld\n",OffsetFileName,lfile);
+ sys_write(lfile,data,18);
+ sys_read(lfile, data, 18);
+ sys_close(lfile);
+ }
+ else
+ printk("sys_open %s error!!. %ld\n",OffsetFileName,lfile);
+ }
+
+ }
+ else
+ {
+ sys_read(lfile, data, 18);
+ sys_close(lfile);
+ }
+ //sscanf(data,"%hd %hd %hd",&offset.u.x,&offset.u.y,&offset.u.z); //marked by eason check again
+ set_fs(orgfs);
+
+}
+*/
+//*********************************************************************************************************
+MODULE_AUTHOR("DMT_RD");
+MODULE_DESCRIPTION("DMARD08 g-sensor Driver");
+MODULE_LICENSE("GPL");
+
+module_init(dmard08_init);
+module_exit(dmard08_exit);
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/dmard08.h b/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/dmard08.h
new file mode 100755
index 00000000..e6a6c935
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard08_gsensor/dmard08.h
@@ -0,0 +1,75 @@
+/*
+ * @file include/linux/dmard08.h
+ * @brief DMT g-sensor Linux device driver
+ * @author Domintech Technology Co., Ltd (http://www.domintech.com.tw)
+ * @version 1.2
+ * @date 2011/11/14
+ *
+ * @section LICENSE
+ *
+ * Copyright 2011 Domintech Technology Co., Ltd
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ */
+#ifndef DMARD08_H
+#define DMARD08_H
+
+#define GSENSOR_I2C_NAME "dmard08"
+#define GSENSOR_I2C_ADDR 0x1c
+/*
+#define DEVICE_I2C_NAME "dmard08"
+
+//#define DMT_DEBUG_DATA 1
+#define DMT_DEBUG_DATA 0
+
+#if DMT_DEBUG_DATA
+#define IN_FUNC_MSG printk(KERN_INFO "@DMT@ In %s\n", __func__)
+#define PRINT_X_Y_Z(x, y, z) printk(KERN_INFO "@DMT@ X/Y/Z axis: %04d , %04d , %04d\n", (x), (y), (z))
+#define PRINT_OFFSET(x, y, z) printk(KERN_INFO "@offset@ X/Y/Z axis: %04d , %04d , %04d\n",offset.x,offset.y,offset.z);
+#else
+#define IN_FUNC_MSG
+#define PRINT_X_Y_Z(x, y, z)
+#define PRINT_OFFSET(x, y, z)
+#endif
+*/
+
+//g-senor layout configuration, choose one of the following configuration
+#define CONFIG_GSEN_LAYOUT_PAT_1
+//#define CONFIG_GSEN_LAYOUT_PAT_2
+//#define CONFIG_GSEN_LAYOUT_PAT_3
+//#define CONFIG_GSEN_LAYOUT_PAT_4
+//#define CONFIG_GSEN_LAYOUT_PAT_5
+//#define CONFIG_GSEN_LAYOUT_PAT_6
+//#define CONFIG_GSEN_LAYOUT_PAT_7
+//#define CONFIG_GSEN_LAYOUT_PAT_8
+
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_NEGATIVE 1
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_POSITIVE 2
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Y_NEGATIVE 3
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Y_POSITIVE 4
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_X_NEGATIVE 5
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_X_POSITIVE 6
+
+#define DEFAULT_SENSITIVITY 256
+#define IOCTL_MAGIC 0x09
+#define SENSOR_DATA_SIZE 3
+
+#define SENSOR_RESET _IO(IOCTL_MAGIC, 0)
+#define SENSOR_CALIBRATION _IOWR(IOCTL_MAGIC, 1, int[SENSOR_DATA_SIZE])
+#define SENSOR_GET_OFFSET _IOR(IOCTL_MAGIC, 2, int[SENSOR_DATA_SIZE])
+#define SENSOR_SET_OFFSET _IOWR(IOCTL_MAGIC, 3, int[SENSOR_DATA_SIZE])
+#define SENSOR_READ_ACCEL_XYZ _IOR(IOCTL_MAGIC, 4, int[SENSOR_DATA_SIZE])
+
+#define SENSOR_MAXNR 4
+
+#endif
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard09_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/dmard09_gsensor/Makefile
new file mode 100755
index 00000000..d9242020
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard09_gsensor/Makefile
@@ -0,0 +1,35 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_gsensor_dmard09
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := dmt09.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard09_gsensor/dmt09.c b/ANDROID_3.4.5/drivers/input/sensor/dmard09_gsensor/dmt09.c
new file mode 100755
index 00000000..90b03aa3
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard09_gsensor/dmt09.c
@@ -0,0 +1,1685 @@
+/*
+ * @file drivers/misc/dmt09.c
+ * @brief DMT g-sensor Linux device driver
+ * @author Domintech Technology Co., Ltd (http://www.domintech.com.tw)
+ * @version 1.06
+ * @date 2013/08/14
+ * @section LICENSE
+ *
+ * Copyright 2012 Domintech Technology Co., Ltd
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "dmt09.h"
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/wakelock.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/clk.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+
+#include "../sensor.h"
+
+//////////////////////////////////////////////////////////
+static struct wmt_gsensor_data l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .samp = 5,
+ .xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },
+ .sensor_proc = NULL,
+ .isdbg = 0,
+ .sensor_samp = 10, // 1 sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ .offset={0,0,0},
+};
+
+static struct class* l_dev_class = NULL;
+static void update_var(void);
+
+////////////////////////////////////////////////////////////
+
+
+static unsigned int interval;
+static int D09_write_offset_to_file(struct i2c_client *client);
+void D09_read_offset_from_file(struct i2c_client *client);
+#define DMT_BROADCAST_APK_ENABLE
+char D09_OffsetFileName[] = "/data/misc/gsensor_offset.txt";//"/system/vendor/dmt/gsensor_offset.txt";// /* FILE offset.txt */
+char DmtXXFileName[] = "/data/misc/dmt_sensor.txt";//"/system/vendor/dmt/dmt_sensor.txt";//
+static int create_devidfile(void);
+static struct dmt_data *s_dmt;
+static int device_init(void);
+static void device_exit(void);
+
+static int device_open(struct inode*, struct file*);
+static long device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+static int device_close(struct inode*, struct file*);
+
+static int dmard09_suspend(struct platform_device *pdev, pm_message_t state);
+static int dmard09_resume(struct platform_device *pdev);
+
+/*static int device_i2c_suspend(struct i2c_client *client, pm_message_t mesg);
+static int device_i2c_resume(struct i2c_client *client);
+static int __devinit device_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
+static int __devexit device_i2c_remove(struct i2c_client *client);*/
+static int D09_i2c_read_xyz(struct i2c_client *client, int *xyz);
+static int device_i2c_rxdata(struct i2c_client *client, unsigned char *rxDat, int length);
+static int device_i2c_txdata(struct i2c_client *client, unsigned char *txData, int length);
+
+static int dmt_get_filter(struct i2c_client *client);
+static int dmt_set_filter(struct i2c_client *client,int);
+static int dmt_get_position(struct i2c_client *client);
+static int dmt_set_position(struct i2c_client *client,int);
+static int DMT_GetOpenStatus(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ GSE_LOG("start active=%d\n",dmt->active.counter);
+ wait_event_interruptible(dmt->open_wq, (atomic_read(&dmt->active) != 0));
+ return 0;
+}
+
+static int DMT_GetCloseStatus(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ GSE_LOG("start active=%d\n",dmt->active.counter);
+ wait_event_interruptible(dmt->open_wq, (atomic_read(&dmt->active) <= 0));
+ return 0;
+}
+
+static void DMT_sysfs_update_active_status(struct dmt_data *dmt , int en){
+ unsigned long dmt_delay;
+ if(en){
+ dmt_delay=msecs_to_jiffies(atomic_read(&dmt->delay));
+ if(dmt_delay<1)
+ dmt_delay=1;
+
+ GSE_LOG("schedule_delayed_work start with delay time=%lu\n",dmt_delay);
+ schedule_delayed_work(&dmt->delaywork,dmt_delay);
+ }
+ else
+ cancel_delayed_work_sync(&dmt->delaywork);
+}
+
+static bool get_value_as_int(char const *buf, size_t size, int *value){
+ long tmp;
+ if (size == 0)
+ return false;
+ /* maybe text format value */
+ if ((buf[0] == '0') && (size > 1)) {
+ if ((buf[1] == 'x') || (buf[1] == 'X')) {
+ /* hexadecimal format */
+ if (0 != strict_strtol(buf, 16, &tmp))
+ return false;
+ } else {
+ /* octal format */
+ if (0 != strict_strtol(buf, 8, &tmp))
+ return false;
+ }
+ } else {
+ /* decimal format */
+ if (0 != strict_strtol(buf, 10, &tmp))
+ return false;
+ }
+
+ if (tmp > INT_MAX)
+ return false;
+
+ *value = tmp;
+ return true;
+}
+static bool get_value_as_int64(char const *buf, size_t size, long long *value)
+{
+ long long tmp;
+ if (size == 0)
+ return false;
+ /* maybe text format value */
+ if ((buf[0] == '0') && (size > 1)) {
+ if ((buf[1] == 'x') || (buf[1] == 'X')) {
+ /* hexadecimal format */
+ if (0 != strict_strtoll(buf, 16, &tmp))
+ return false;
+ } else {
+ /* octal format */
+ if (0 != strict_strtoll(buf, 8, &tmp))
+ return false;
+ }
+ } else {
+ /* decimal format */
+ if (0 != strict_strtoll(buf, 10, &tmp))
+ return false;
+ }
+
+ if (tmp > LLONG_MAX)
+ return false;
+
+ *value = tmp;
+ return true;
+}
+/* sysfs enable show & store */
+static ssize_t dmt_sysfs_enable_show(
+ struct dmt_data *dmt, char *buf, int pos)
+{
+ char str[2][16]={"ACC enable OFF","ACC enable ON"};
+ int flag;
+ flag=atomic_read(&dmt->enable);
+ return sprintf(buf, "%s\n", str[flag]);
+}
+
+static ssize_t dmt_sysfs_enable_store(
+ struct dmt_data *dmt, char const *buf, size_t count, int pos)
+{
+ int en = 0;
+ if (NULL == buf)
+ return -EINVAL;
+ //GSE_LOG("buf=%x %x\n", buf[0], buf[1]);
+ if (0 == count)
+ return 0;
+
+ if (false == get_value_as_int(buf, count, &en))
+ return -EINVAL;
+
+ en = en ? 1 : 0;
+
+ atomic_set(&dmt->enable,en);
+ DMT_sysfs_update_active_status(dmt , en);
+ return count;
+}
+
+static ssize_t dmt_enable_show(struct device *dev, struct device_attribute *attr, char *buf){
+ return dmt_sysfs_enable_show( dev_get_drvdata(dev), buf, ACC_DATA_FLAG);
+}
+
+static ssize_t dmt_enable_store( struct device *dev, struct device_attribute *attr, char const *buf, size_t count){
+ return dmt_sysfs_enable_store( dev_get_drvdata(dev), buf, count, ACC_DATA_FLAG);
+}
+
+/* sysfs delay show & store*/
+static ssize_t dmt_sysfs_delay_show( struct dmt_data *dmt, char *buf, int pos){
+ return sprintf(buf, "%d\n", atomic_read(&dmt->delay));
+}
+
+static ssize_t dmt_sysfs_delay_store( struct dmt_data *dmt, char const *buf, size_t count, int pos){
+ long long val = 0;
+
+ if (NULL == buf)
+ return -EINVAL;
+
+ if (0 == count)
+ return 0;
+
+ if (false == get_value_as_int64(buf, count, &val))
+ return -EINVAL;
+
+ atomic_set(&dmt->delay, (unsigned int) val);
+ GSE_LOG("Driver attribute set delay =%lld\n", val);
+
+ return count;
+}
+
+static ssize_t dmt_delay_show( struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return dmt_sysfs_delay_show( dev_get_drvdata(dev), buf, ACC_DATA_FLAG);
+}
+
+static ssize_t dmt_delay_store( struct device *dev,
+ struct device_attribute *attr,
+ char const *buf,
+ size_t count)
+{
+ return dmt_sysfs_delay_store( dev_get_drvdata(dev), buf, count, ACC_DATA_FLAG);
+}
+/* sysfs position show & store */
+static ssize_t dmt_position_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+
+ return sprintf(buf, "%d\n", dmt_get_position(dmt->client));
+}
+
+static ssize_t dmt_position_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ unsigned long position;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &position);
+ if (ret < 0)
+ return count;
+
+ dmt_set_position(dmt->client, position);
+ return count;
+}
+/* sysfs offset show & store */
+static ssize_t dmt_offset_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ return sprintf(buf, "( %d %d %d )\n", dmt->offset.u.x, dmt->offset.u.y, dmt->offset.u.z);
+}
+
+static ssize_t dmt_offset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ sscanf(buf, "%d %d %d", (int *)&dmt->offset.v[0], (int *)&dmt->offset.v[1], (int *)&dmt->offset.v[2]);
+ D09_write_offset_to_file(dmt->client);
+ update_var();
+ return count;
+}
+/* sysfs filter show & store */
+static ssize_t dmt_filter_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+
+ return sprintf(buf, "%d\n", dmt_get_filter(dmt->client));
+}
+
+static ssize_t dmt_filter_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ unsigned long filter;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &filter);
+ if (ret < 0)
+ return count;
+
+ dmt_set_filter(dmt->client, filter);
+ return count;
+}
+
+/* sysfs data show */
+static ssize_t dmt_acc_private_data_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ raw_data accel;
+
+ mutex_lock(&dmt->data_mutex);
+ accel = dmt->last;
+ mutex_unlock(&dmt->data_mutex);
+
+ return sprintf(buf, "( %d %d %d )\n", dmt->last.v[0], dmt->last.v[1], dmt->last.v[2]);
+}
+/* sysfs id show */
+static ssize_t dmt_id_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ char str[8]={GSENSOR_ID};
+ return sprintf(buf, "%s\n", str);
+}
+/* sysfs debug_suspend show & store */
+#ifdef DMT_DEBUG_DATA
+static ssize_t dmt_debug_suspend_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ int suspend = dmt->suspend;
+
+ mutex_lock(&dmt->suspend_mutex);
+ suspend = sprintf(buf, "%d\n", dmt->suspend);
+ mutex_unlock(&dmt->suspend_mutex);
+ return suspend;
+}
+
+static ssize_t dmt_debug_suspend_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ unsigned long suspend;
+ pm_message_t msg;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &suspend);
+ if (ret < 0)
+ return count;
+
+ memset(&msg, 0, sizeof(pm_message_t));
+
+ mutex_lock(&dmt->suspend_mutex);
+
+ if (suspend) {
+ dmard09_suspend(dmt->pdevice, msg);
+ dmt->suspend = 1;
+ } else {
+ dmard09_resume(dmt->pdevice);
+ dmt->suspend = 0;
+ }
+
+ mutex_unlock(&dmt->suspend_mutex);
+
+ return count;
+}
+/* sysfs reg_read show & store */
+static ssize_t dmt_reg_read_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct dmt_data *dmt = dev_get_drvdata(dev);
+ int err;
+ unsigned char i2c[1];
+
+ i2c[0] = (unsigned char)atomic_read(&dmt->addr);
+ err = device_i2c_rxdata(dmt->client, i2c, 1);
+ if (err < 0)
+ return err;
+
+ return sprintf(buf, "0x%02X\n", i2c[0]);
+}
+
+static ssize_t dmt_reg_read_store(struct device *dev,
+ struct device_attribute *attr,
+ char const *buf,
+ size_t count)
+{
+ struct dmt_data *dmt = dev_get_drvdata(dev);
+ int addr = 0;
+
+ if (NULL == buf)
+ return -EINVAL;
+
+ if (0 == count)
+ return 0;
+
+ if (false == get_value_as_int(buf, count, &addr))
+ return -EINVAL;
+
+ if (addr < 0 || 128 < addr)
+ return -EINVAL;
+
+ atomic_set(&dmt->addr, addr);
+
+ return 1;
+}
+#endif /* DEBUG */
+/*********************************************************************
+ *
+ * SysFS attribute functions
+ *
+ * directory : /sys/class/accelemeter/dmardXX/
+ * files :
+ * - enable_acc [rw] [t] : enable flag for accelerometer
+ * - delay_acc [rw] [t] : delay in nanosecond for accelerometer
+ * - position [rw] [t] : chip mounting position
+ * - offset [rw] [t] : offset
+ * - data [r] [t] : raw data
+ * - id [r] [t] : chip id
+ *
+ * debug :
+ * - debug_suspend [w] [t] : suspend test
+ * - reg_read [rw] [t] : Read register
+ * - reg_write [rw] [t] : Weite register
+ *
+ * [rw]= read/write
+ * [r] = read only
+ * [w] = write only
+ * [b] = binary format
+ * [t] = text format
+ */
+
+static struct device_attribute DMT_attributes[] = {
+ __ATTR(enable_acc, 0660, dmt_enable_show, dmt_enable_store),
+ __ATTR(delay_acc, 0660, dmt_delay_show, dmt_delay_store),
+ __ATTR(position, 0660, dmt_position_show, dmt_position_store),
+ __ATTR(offset, 0660, dmt_offset_show, dmt_offset_store),
+ __ATTR(filter, 0660, dmt_filter_show, dmt_filter_store),
+ __ATTR(data, 0660, dmt_acc_private_data_show, NULL),
+ __ATTR(id, 0660, dmt_id_show, NULL),
+#ifdef DMT_DEBUG_DATA
+ __ATTR(debug_suspend, 0660, dmt_debug_suspend_show,dmt_debug_suspend_store),
+ __ATTR(reg_read, 0660, dmt_reg_read_show, dmt_reg_read_store),
+ __ATTR(reg_write, 0660, NULL, NULL),
+#endif // DEBUG
+ __ATTR_NULL,
+};
+
+static char const *const ACCELEMETER_CLASS_NAME = "accelemeter";
+static char const *const GSENSOR_DEVICE_NAME = SENSOR_I2C_NAME;
+static char const *const device_link_name = "i2c";
+static dev_t const dmt_device_dev_t = MKDEV(MISC_MAJOR, MISC_DYNAMIC_MINOR);
+
+// dmt sysfs functions
+static int create_device_attributes(struct device *dev, struct device_attribute *attrs){
+ int i;
+ int err = 0;
+ for (i = 0 ; NULL != attrs[i].attr.name ; ++i) {
+ err = device_create_file(dev, &attrs[i]);
+ if (0 != err)
+ break;
+ }
+
+ if (0 != err) {
+ for (; i >= 0 ; --i)
+ device_remove_file(dev, &attrs[i]);
+ }
+ return err;
+}
+
+static void remove_device_attributes(
+ struct device *dev,
+ struct device_attribute *attrs)
+{
+ int i;
+
+ for (i = 0 ; NULL != attrs[i].attr.name ; ++i)
+ device_remove_file(dev, &attrs[i]);
+}
+
+static int create_sysfs_interfaces(struct dmt_data *dmt)
+{
+ int err;
+
+ if (NULL == dmt)
+ return -EINVAL;
+
+ err = 0;
+ dmt->class = class_create(THIS_MODULE, ACCELEMETER_CLASS_NAME);
+ if (IS_ERR(dmt->class)) {
+ err = PTR_ERR(dmt->class);
+ goto exit_class_create_failed;
+ }
+
+ dmt->class_dev = device_create(
+ dmt->class,
+ NULL,
+ dmt_device_dev_t,
+ dmt,
+ GSENSOR_DEVICE_NAME);
+ if (IS_ERR(dmt->class_dev)) {
+ err = PTR_ERR(dmt->class_dev);
+ goto exit_class_device_create_failed;
+ }
+
+ err = sysfs_create_link(
+ &dmt->class_dev->kobj,
+ &dmt->client->dev.kobj,
+ device_link_name);
+ if (0 > err)
+ goto exit_sysfs_create_link_failed;
+
+ err = create_device_attributes(
+ dmt->class_dev,
+ DMT_attributes);
+ if (0 > err)
+ goto exit_device_attributes_create_failed;
+#if 0
+ err = create_device_binary_attributes(
+ &dmt->class_dev->kobj,
+ dmt_bin_attributes);
+ if (0 > err)
+ goto exit_device_binary_attributes_create_failed;
+#endif
+
+ return err;
+
+#if 0
+exit_device_binary_attributes_create_failed:
+ remove_device_attributes(dmt->class_dev, dmt_attributes);
+#endif
+exit_device_attributes_create_failed:
+ sysfs_remove_link(&dmt->class_dev->kobj, device_link_name);
+exit_sysfs_create_link_failed:
+ device_destroy(dmt->class, dmt_device_dev_t);
+exit_class_device_create_failed:
+ dmt->class_dev = NULL;
+ class_destroy(dmt->class);
+exit_class_create_failed:
+ dmt->class = NULL;
+ return err;
+}
+
+static void remove_sysfs_interfaces(struct dmt_data *dmt){
+ if (NULL == dmt)
+ return;
+
+ if (NULL != dmt->class_dev) {
+
+ remove_device_attributes(
+ dmt->class_dev,
+ DMT_attributes);
+ sysfs_remove_link(
+ &dmt->class_dev->kobj,
+ device_link_name);
+ dmt->class_dev = NULL;
+ }
+ if (NULL != dmt->class) {
+ device_destroy(
+ dmt->class,
+ dmt_device_dev_t);
+ class_destroy(dmt->class);
+ dmt->class = NULL;
+ }
+}
+
+int D09_input_init(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ int err = 0;
+ dmt->input = input_allocate_device();
+ if (!dmt->input){
+ GSE_ERR("input device allocate ERROR !!\n");
+ return -ENOMEM;
+ }
+ else
+ GSE_LOG("input device allocate Success !!\n");
+ /* Setup input device */
+ //dmt->input->name = SENSOR_I2C_NAME;
+ set_bit(EV_ABS, dmt->input->evbit);
+ /* Accelerometer [-78.5, 78.5]m/s2 in Q16 */
+ input_set_abs_params(dmt->input, ABS_X, ABSMIN, ABSMAX, 0, 0);
+ input_set_abs_params(dmt->input, ABS_Y, ABSMIN, ABSMAX, 0, 0);
+ input_set_abs_params(dmt->input, ABS_Z, ABSMIN, ABSMAX, 0, 0);
+ /* Set InputDevice Name */
+ dmt->input->name = INPUT_NAME_ACC;
+ /* Register */
+ err = input_register_device(dmt->input);
+ if (err) {
+ GSE_ERR("input_register_device ERROR !!\n");
+ input_free_device(dmt->input);
+ return err;
+ }
+ GSE_LOG("input_register_device SUCCESS %d !! \n",err);
+
+ return err;
+}
+
+int D09_calibrate(struct i2c_client *client)
+{
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ raw_data avg;
+ int i, j;
+ long xyz_acc[SENSOR_DATA_SIZE];
+ int xyz[SENSOR_DATA_SIZE];
+ /* initialize the offset value */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ dmt->offset.v[i] = 0;
+ /* initialize the accumulation buffer */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ xyz_acc[i] = 0;
+
+ for(i = 0; i < AVG_NUM; i++) {
+ D09_i2c_read_xyz(client, (int *)&xyz);
+ for(j = 0; j < SENSOR_DATA_SIZE; ++j)
+ xyz_acc[j] += xyz[j];
+ }
+ /* calculate averages */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ avg.v[i] = xyz_acc[i] / AVG_NUM;
+
+ if(avg.v[2] < 0){
+ dmt->offset.u.x = avg.v[0] ;
+ dmt->offset.u.y = avg.v[1] ;
+ dmt->offset.u.z = avg.v[2] + DEFAULT_SENSITIVITY;
+ return CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_POSITIVE;
+ }
+ else{
+ dmt->offset.u.x = avg.v[0] ;
+ dmt->offset.u.y = avg.v[1] ;
+ dmt->offset.u.z = avg.v[2] - DEFAULT_SENSITIVITY;
+ return CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_NEGATIVE;
+ }
+ return 0;
+}
+
+int dmard09_init(struct i2c_client *client){
+
+ //struct dmt_data *dmt = i2c_get_clientdata(client);
+ unsigned char buffer[7];
+ /* 1. Active Mode */
+ buffer[0] = REG_ACTR;
+ buffer[1] = MODE_ACTIVE;
+ device_i2c_txdata(client, buffer, 2);
+ /* 2. check D09 who am I */
+ buffer[0] = REG_DC;
+ device_i2c_rxdata(client, buffer, 1);
+ if (buffer[0] == VALUE_WHO_AM_I)
+ {
+ printk(KERN_INFO GSE_TAG"D09 WHO_AM_I_VALUE = %d \n", buffer[0]);
+ GSE_LOG("D09 registered I2C driver!\n");
+ }
+ else
+ {
+ GSE_ERR("gsensor I2C err = %d!\n", buffer[0]);
+ return -1;
+ }
+ /* 3. Set Data conversion rate*/
+ buffer[0] = REG_CNT_L1;
+ buffer[1] = VALUE_ODR_100;
+ buffer[2] = VALUE_CNT_L2;
+ device_i2c_txdata(client, buffer, 3);
+ /* 4. open hardware filter */
+ buffer[0] = REG_ODF;
+ buffer[1] = ODF_Ave_4;
+ buffer[2] = 0x00;
+ device_i2c_txdata(client, buffer, 3);
+ /* 5. check hardware filter again */
+ buffer[0] = REG_ODF; //0x07 smooth filter 1/8 Bandwidth */
+ device_i2c_rxdata(client, buffer, 2);
+ printk(KERN_INFO GSE_TAG" REG_ODF = %x , %x\n", buffer[0] , buffer[1]);
+
+ return 0;
+}
+
+void D09_set_offset(struct i2c_client *client, int val[3]){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ int i;
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ dmt->offset.v[i] = val[i];
+}
+
+struct file_operations sensor_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = device_ioctl,
+ .open = device_open,
+ .release = device_close,
+};
+
+static struct miscdevice dmt_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = SENSOR_I2C_NAME,
+ .fops = &sensor_fops,
+};
+
+static int sensor_close_dev(struct i2c_client *client){
+ char buffer[3];
+ buffer[0] = REG_ACTR;
+ device_i2c_rxdata(client, buffer, 2);
+ buffer[1] = buffer[0] & 0xFE; //Mask off last bit (POWER DOWN MODE)
+ //buffer[1] = MODE_POWERDOWN;
+ device_i2c_txdata(client,buffer, 2);
+ return 0;
+}
+
+static void dmard09_shutdown(struct platform_device *pdev)
+{
+ flush_delayed_work_sync(&s_dmt->delaywork);
+ DMT_sysfs_update_active_status(s_dmt , 0);
+}
+
+
+//static int device_i2c_suspend(struct i2c_client *client, pm_message_t mesg){
+static int dmard09_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct dmt_data *dmt = i2c_get_clientdata(s_dmt->client);
+ flush_delayed_work_sync(&dmt->delaywork);
+ DMT_sysfs_update_active_status(dmt , 0);
+ return sensor_close_dev(dmt->client);
+}
+
+//static int device_i2c_resume(struct i2c_client *client){
+static int dmard09_resume(struct platform_device *pdev)
+{
+ struct dmt_data *dmt = i2c_get_clientdata(s_dmt->client);
+ int en = 1;
+ GSE_FUN();
+ printk("dmt->enable=%d",dmt->enable);
+ dmard09_init(dmt->client);
+ atomic_set(&dmt->enable,en);
+ DMT_sysfs_update_active_status(dmt , en);
+ return 0;
+}
+/*
+static int __devexit device_i2c_remove(struct i2c_client *client){
+ return 0;
+}
+
+static const struct i2c_device_id device_i2c_ids[] = {
+ { SENSOR_I2C_NAME, 0},
+ { }
+};
+
+static struct i2c_driver device_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_I2C_NAME,
+ },
+ .class = I2C_CLASS_HWMON,
+ .id_table = device_i2c_ids,
+ .probe = device_i2c_probe,
+ .remove = __devexit_p(device_i2c_remove),
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ .suspend = device_i2c_suspend,
+ .resume = device_i2c_resume,
+#endif
+};
+*/
+static int device_open(struct inode *inode, struct file *filp){
+ return 0;
+}
+
+static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg){
+ //struct i2c_client *client = (struct i2c_client *)file->private_data;
+ //struct dmt_data *dmt = (struct dmt_data*)i2c_get_clientdata(client);
+
+ int err = 0, ret = 0, i;
+ int intBuf[SENSOR_DATA_SIZE], xyz[SENSOR_DATA_SIZE];
+ /* check type */
+ if (_IOC_TYPE(cmd) != IOCTL_MAGIC) return -ENOTTY;
+
+ /* check user space pointer is valid */
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
+ if (err) return -EFAULT;
+
+ switch(cmd) {
+ case SENSOR_RESET:
+ ret = dmard09_init(s_dmt->client);
+ return ret;
+
+ case SENSOR_CALIBRATION:
+ /* get orientation info */
+ //if(copy_from_user(&intBuf, (int*)arg, sizeof(intBuf))) return -EFAULT;
+ D09_calibrate(s_dmt->client);
+ GSE_LOG("Sensor_calibration:%d %d %d\n", s_dmt->offset.u.x, s_dmt->offset.u.y, s_dmt->offset.u.z);
+ /* save file */
+ D09_write_offset_to_file(s_dmt->client);
+ update_var();
+
+ /* return the offset */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ intBuf[i] = s_dmt->offset.v[i];
+
+ ret = copy_to_user((int *)arg, &intBuf, sizeof(intBuf));
+ return ret;
+
+ case SENSOR_GET_OFFSET:
+ /* get data from file */
+ D09_read_offset_from_file(s_dmt->client);
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ intBuf[i] = s_dmt->offset.v[i];
+
+ ret = copy_to_user((int *)arg, &intBuf, sizeof(intBuf));
+ return ret;
+
+ case SENSOR_SET_OFFSET:
+ ret = copy_from_user(&intBuf, (int *)arg, sizeof(intBuf));
+ D09_set_offset(s_dmt->client , intBuf);
+ /* write into file */
+ D09_write_offset_to_file(s_dmt->client);
+ update_var();
+ return ret;
+
+ case SENSOR_READ_ACCEL_XYZ:
+ D09_i2c_read_xyz(s_dmt->client, (int *)&xyz);
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ intBuf[i] = xyz[i] - s_dmt->offset.v[i];
+
+ ret = copy_to_user((int*)arg, &intBuf, sizeof(intBuf));
+ return ret;
+
+ case SENSOR_SETYPR:
+ if(copy_from_user(&intBuf, (int*)arg, sizeof(intBuf))) {
+ GSE_LOG("%s: -EFAULT\n",__func__);
+ return -EFAULT;
+ }
+ input_report_abs(s_dmt->input, ABS_X, intBuf[0]);
+ input_report_abs(s_dmt->input, ABS_Y, intBuf[1]);
+ input_report_abs(s_dmt->input, ABS_Z, intBuf[2]);
+ input_sync(s_dmt->input);
+ GSE_LOG("SENSOR_SETYPR OK! x=%d,y=%d,z=%d\n",intBuf[0],intBuf[1],intBuf[2]);
+ return ret;
+
+ case SENSOR_GET_OPEN_STATUS:
+ GSE_LOG("Going into DMT_GetOpenStatus()\n");
+ ret = DMT_GetOpenStatus(s_dmt->client);
+ return ret;
+
+ case SENSOR_GET_CLOSE_STATUS:
+ GSE_LOG("Going into DMT_GetCloseStatus()\n");
+ ret = DMT_GetCloseStatus(s_dmt->client);
+ return ret;
+
+ case SENSOR_GET_DELAY:
+ ret = copy_to_user((int*)arg, &interval, sizeof(interval));
+ return ret;
+
+ default: /* redundant, as cmd was checked against MAXNR */
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+static int device_close(struct inode *inode, struct file *filp){
+ return 0;
+}
+
+/***** I2C I/O function ***********************************************/
+static int device_i2c_rxdata( struct i2c_client *client, unsigned char *rxData, int length){
+ struct i2c_msg msgs[] = {
+ {.addr = client->addr, .flags = 0, .len = 1, .buf = rxData,},
+ {.addr = client->addr, .flags = I2C_M_RD, .len = length, .buf = rxData,},
+ };
+ //unsigned char addr = rxData[0];
+ if (i2c_transfer(client->adapter, msgs, 2) < 0) {
+ dev_err(&client->dev, "%s: transfer failed.", __func__);
+ return -EIO;
+ }
+ //DMT_DATA(&client->dev, "RxData: len=%02x, addr=%02x, data=%02x\n",
+ //length, addr, rxData[0]);
+
+ return 0;
+}
+
+static int device_i2c_txdata( struct i2c_client *client, unsigned char *txData, int length){
+ struct i2c_msg msg[] = {
+ {.addr = client->addr, .flags = 0, .len = length, .buf = txData,},
+ };
+
+ if (i2c_transfer(client->adapter, msg, 1) < 0) {
+ dev_err(&client->dev, "%s: transfer failed.", __func__);
+ return -EIO;
+ }
+ //DMT_DATA(&client->dev, "TxData: len=%02x, addr=%02x data=%02x\n",
+ //length, txData[0], txData[1]);
+ return 0;
+}
+
+static int D09_i2c_read_xyz(struct i2c_client *client, int *xyz_p){
+
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ u8 buffer[11];
+ s16 xyzTmp[SENSOR_DATA_SIZE];
+ int pos = dmt->position;
+ int i, j , k;
+ /* get xyz high/low bytes, 0x0A */
+ buffer[0] = REG_STAT;
+ /* Read acceleration data */
+ if (device_i2c_rxdata(client, buffer, 8)!= 0)
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ {
+ xyz_p[i] = 0;
+ xyzTmp[i] = 0;
+ }
+ else
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ xyz_p[i] = 0;
+ xyzTmp[i] = 0;
+ /* merge xyz high/low bytes & 1g = 128 becomes 1g = 1024 */
+ mutex_lock(&dmt->data_mutex);
+ xyzTmp[i] =(((int16_t)((buffer[2*(i+1)+1] << 8)) | buffer[2*(i+1)] ) >> 3) << 5;
+ mutex_unlock(&dmt->data_mutex);
+ }
+#ifdef SW_FILTER
+ if( dmt->aveflag >= dmt->filter){
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ dmt->sum[i] = dmt->sum[i] - dmt->bufferave[i][dmt->pointer] + xyzTmp[i];
+ }
+ /* transfer to the default layout */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ for(j = 0; j < SENSOR_DATA_SIZE; j++)
+ xyz_p[i] += (int)(dmt->sum[j]/dmt->filter * dmt_position_map[pos][i][j]);
+ }
+ }
+ else{
+ /* init dmt->sum */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ dmt->sum[i] = xyzTmp[i];
+#endif
+ /* transfer to the default layout */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ for(j = 0; j < SENSOR_DATA_SIZE; j++){
+ xyz_p[i] += (int)(xyzTmp[j] * dmt_position_map[pos][i][j]);
+ //GSE_LOG("%04d, %04d,%d \n", xyz_p[i], xyzTmp[j], dmt_position_map[pos][i][j]);
+ }
+ }
+ //GSE_LOG("xyz_p: %04d , %04d , %04d\n", xyz_p[0], xyz_p[1], xyz_p[2]);
+#ifdef SW_FILTER
+ dmt->aveflag++;
+ }
+ /* init dmt->sum */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ dmt->sum[i] = 0;
+ }
+ dmt->pointer++;
+ dmt->pointer %= dmt->filter;
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ dmt->bufferave[i][dmt->pointer] = xyzTmp[i];
+ }
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ for(k = 0; k < dmt->filter; ++k){
+ dmt->sum[i] += dmt->bufferave[i][k];
+ }
+ }
+#endif
+ return 0;
+}
+
+static void DMT_work_func(struct work_struct *delaywork){
+ struct dmt_data *dmt = container_of(delaywork, struct dmt_data, delaywork.work);
+ int i;
+ //static bool firsttime=true;
+ raw_data xyz;
+ unsigned long dmt_delay = msecs_to_jiffies(atomic_read(&dmt->delay));
+
+
+ D09_i2c_read_xyz(dmt->client, (int *)&xyz.v);
+ /* dmt->last = RawData - Offset */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ dmt->last.v[i] = xyz.v[i] - dmt->offset.v[i];
+ //GSE_LOG("@DMTRaw @ X/Y/Z axis: %04d , %04d , %04d\n", xyz.v[0], xyz.v[1], xyz.v[2]);
+ //GSE_LOG("@Offset @ X/Y/Z axis: %04d , %04d , %04d\n", dmt->offset.u.x, dmt->offset.u.y, dmt->offset.u.z);
+ //GSE_LOG("@Raw-Offset@ X/Y/Z axis: %04d , %04d , %04d ,dmt_delay=%d\n", dmt->last.u.x, dmt->last.u.y, dmt->last.u.z, atomic_read(&dmt->delay));
+
+#ifdef STABLE_VALUE_FUNCTION
+ if(abs(dmt->last.v[0])< RANGE_XYZ){ dmt->last.v[0] = 0;}
+ if(abs(dmt->last.v[1])< RANGE_XYZ){ dmt->last.v[1] = 0;}
+ if(abs(dmt->last.v[2])< RANGE_XYZ){ dmt->last.v[2] = 0;}
+#endif
+
+
+ input_report_abs(dmt->input, ABS_X, -dmt->last.v[l_sensorconfig.xyz_axis[0][0]]*l_sensorconfig.xyz_axis[0][1]);//dmt->last.v[0]);
+ input_report_abs(dmt->input, ABS_Y, -dmt->last.v[l_sensorconfig.xyz_axis[1][0]]*l_sensorconfig.xyz_axis[1][1]);//dmt->last.v[1]);
+ input_report_abs(dmt->input, ABS_Z, -dmt->last.v[l_sensorconfig.xyz_axis[2][0]]*l_sensorconfig.xyz_axis[2][1]);//dmt->last.v[2]);
+ input_sync(dmt->input);
+
+ if(dmt_delay < 1)
+ dmt_delay = 1;
+ schedule_delayed_work(&dmt->delaywork, dmt_delay);
+}
+
+static int mma09_open(struct inode *node, struct file *fle)
+{
+ GSE_LOG("open...\n");
+ return 0;
+}
+
+static int mma09_close(struct inode *node, struct file *fle)
+{
+ GSE_LOG("close...\n");
+ return 0;
+}
+
+static long mma09_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int err = 0;
+ //unsigned char data[6];
+ void __user *argp = (void __user *)arg;
+ short delay, enable;
+ unsigned int uval = 0;
+
+
+ /* cmd mapping */
+ switch(cmd)
+ {
+ case ECS_IOCTL_APP_SET_DELAY:
+ // set the rate of g-sensor
+ if (copy_from_user(&delay, argp, sizeof(short)))
+ {
+ printk(KERN_ALERT "Can't get set delay!!!\n");
+ return -EFAULT;
+ }
+ klog("Get delay=%d\n", delay);
+
+ if ((delay >=0) && (delay < 20))
+ {
+ delay = 20;
+ } else if (delay > 200)
+ {
+ delay = 200;
+ }
+ l_sensorconfig.sensor_samp = 1000/delay;
+ atomic_set(&s_dmt->delay, 1000/delay);
+ break;
+ case ECS_IOCTL_APP_SET_AFLAG:
+ // enable/disable sensor
+ if (copy_from_user(&enable, argp, sizeof(short)))
+ {
+ printk(KERN_ERR "Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ klog("enable=%d\n",enable);
+ if ((enable >=0) && (enable <=1))
+ {
+ //KMSGINF("driver: disable/enable(%d) gsensor.\n", enable);
+
+ l_sensorconfig.sensor_enable = enable;
+ atomic_set(&s_dmt->enable,enable);
+ DMT_sysfs_update_active_status(s_dmt , enable);
+
+ } else {
+ printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ uval = DMARD09_DRVID;//;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ GSE_LOG("dmard09_driver_id:%d\n",uval);
+ break;
+ case WMT_IOCTL_SENOR_GET_RESOLUTION:
+ uval = (10<<8) | 1;
+ if (copy_to_user((unsigned int *)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ printk("<<<<<<<resolution:0x%x\n",uval);
+ default:
+ err = -1;
+ break;
+ }
+
+ return err;
+}
+
+static const struct file_operations d09_fops = {
+ .owner = THIS_MODULE,
+ .open = mma09_open,
+ .release = mma09_close,
+ .unlocked_ioctl = mma09_ioctl,
+};
+
+
+static struct miscdevice d09_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = GSENSOR_DEV_NODE,
+ .fops = &d09_fops,
+};
+
+static int sensor_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+
+ //int inputval = -1;
+ int enable, sample = -1;
+ char tembuf[8];
+ //unsigned int amsr = 0;
+ int test = 0;
+
+ //mutex_lock(&sense_data_mutex);
+ memset(tembuf, 0, sizeof(tembuf));
+ // get sensor level and set sensor level
+ if (sscanf(buffer, "isdbg=%d\n", &l_sensorconfig.isdbg))
+ {
+ // only set the dbg flag
+ } else if (sscanf(buffer, "samp=%d\n", &sample))
+ {
+ if (sample > 0)
+ {
+ if (sample != l_sensorconfig.sensor_samp)
+ {
+ // should do sth
+ }
+ //printk(KERN_ALERT "sensor samp=%d(amsr:%d) has been set.\n", sample, amsr);
+ } else {
+ klog("Wrong sample argumnet of sensor.\n");
+ }
+ } else if (sscanf(buffer, "enable=%d\n", &enable))
+ {
+ if ((enable < 0) || (enable > 1))
+ {
+ klog("The argument to enable/disable g-sensor should be 0 or 1 !!!\n");
+ } else if (enable != l_sensorconfig.sensor_enable)
+ {
+ //mma_enable_disable(enable);
+ l_sensorconfig.sensor_enable = enable;
+ }
+ } else if (sscanf(buffer, "sensor_test=%d\n", &test))
+ { // for test begin
+ l_sensorconfig.test_pass = 0;
+ atomic_set(&s_dmt->enable,1);
+ DMT_sysfs_update_active_status(s_dmt , 1);
+ } else if (sscanf(buffer, "sensor_testend=%d\n", &test))
+ { // Don nothing only to be compatible the before testing program
+ atomic_set(&s_dmt->enable,0);
+ DMT_sysfs_update_active_status(s_dmt , 0);
+ }
+ //mutex_unlock(&sense_data_mutex);
+ return count;
+}
+
+static int sensor_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "test_pass=%d\nisdbg=%d\nrate=%d\nenable=%d\n",
+ l_sensorconfig.test_pass,
+ l_sensorconfig.isdbg,
+ l_sensorconfig.sensor_samp,
+ l_sensorconfig.sensor_enable
+ );
+ return len;
+}
+
+
+//static int __devinit device_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id){
+static int __devinit dmard09_probe(struct platform_device *pdev)
+{
+ int i, k, ret = 0;
+ //struct dmt_data *s_dmt = i2c_get_clientdata(client);
+ //struct dmt_data *s_dmt;
+ GSE_FUN();
+/*
+ if(!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)){
+ GSE_ERR("check_functionality failed.\n");
+ ret = -ENODEV;
+ goto exit0;
+ }
+
+ // Allocate memory for driver data
+ s_dmt = kzalloc(sizeof(struct dmt_data), GFP_KERNEL);
+ memset(s_dmt, 0, sizeof(struct dmt_data));
+ if (s_dmt == NULL) {
+ GSE_ERR("alloc data failed.\n");
+ ret = -ENOMEM;
+ goto exit1;
+ }
+*/
+ /*for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ s_dmt->offset.v[i] = 0;*/
+#ifdef SW_FILTER
+ s_dmt->pointer = 0;
+ s_dmt->aveflag = 0;
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ s_dmt->sum[i] = 0;
+ for(k = 0; k < SENSOR_DATA_AVG; ++k){
+ s_dmt->bufferave[i][k] = 0;
+ }
+ }
+ s_dmt->filter = SENSOR_DATA_AVG;
+ GSE_LOG("D09_DEFAULT_FILTER: %d\n", s_dmt->filter);
+#endif
+ /* I2C initialization */
+ //s_dmt->client = client;
+
+ /* set client data */
+ i2c_set_clientdata(s_dmt->client, s_dmt);
+ /*ret = dmard09_init(client);
+ if (ret < 0)
+ goto exit2;
+ */
+ /* input */
+ ret = D09_input_init(s_dmt->client);
+ if (ret){
+ GSE_ERR("D09_input_init fail, error code= %d\n",ret);
+ goto exit3;
+ }
+
+ /* initialize variables in dmt_data */
+ mutex_init(&s_dmt->data_mutex);
+ mutex_init(&s_dmt->enable_mutex);
+#ifdef DMT_DEBUG_DATA
+ mutex_init(&s_dmt->suspend_mutex);
+#endif
+ init_waitqueue_head(&s_dmt->open_wq);
+ atomic_set(&s_dmt->active, 0);
+ atomic_set(&s_dmt->enable, 0);
+ atomic_set(&s_dmt->delay, 0);
+ atomic_set(&s_dmt->addr, 0);
+ /* DMT Acceleration Sensor Mounting Position on Board */
+ s_dmt->position = D09_DEFAULT_POSITION;
+ GSE_LOG("D09_DEFAULT_POSITION: %d\n", s_dmt->position);
+ //s_dmt->position = (CONFIG_INPUT_DMT_ACCELEROMETER_POSITION);
+ //GSE_LOG("CONFIG_INPUT_DMT_ACCELEROMETER_POSITION: %d\n", s_dmt->position);
+ /* Misc device */
+ if (misc_register(&dmt_device) < 0){
+ GSE_ERR("dmt_dev register failed");
+ goto exit4;
+ }
+
+ /* Setup sysfs */
+ if (create_sysfs_interfaces(s_dmt) < 0){
+ GSE_ERR("create sysfs failed.");
+ goto exit5;
+ }
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ s_dmt->early_suspend.suspend = device_i2c_suspend;
+ s_dmt->early_suspend.resume = device_i2c_resume;
+ register_early_suspend(&s_dmt->early_suspend);
+#endif
+ /* Setup driver interface */
+ INIT_DELAYED_WORK(&s_dmt->delaywork, DMT_work_func);
+ GSE_LOG("DMT: INIT_DELAYED_WORK\n");
+
+ //register ctrl dev
+ ret = misc_register(&d09_device);
+ if (ret !=0) {
+ errlog("Can't register d09_device!\n");
+ return -1;
+ }
+ // register rd/wr proc
+ l_sensorconfig.sensor_proc = create_proc_entry(GSENSOR_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ l_sensorconfig.sensor_proc->write_proc = sensor_writeproc;
+ l_sensorconfig.sensor_proc->read_proc = sensor_readproc;
+ }
+
+ //create offset file after factory reset
+ D09_read_offset_from_file(s_dmt->client);
+
+ return 0;
+
+exit5:
+ misc_deregister(&dmt_device);
+exit4:
+ input_unregister_device(s_dmt->input);
+exit3:
+ kfree(s_dmt);
+/*exit2:
+exit1:
+exit0:*/
+ return ret;
+}
+/*
+static struct i2c_board_info dmard09_board_info={
+ .type = SENSOR_I2C_NAME,
+ .addr = SENSOR_I2C_ADDR,
+};
+*/
+//static struct i2c_client *client;
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static int get_axisset(void)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.dm09sensor", varbuf, &varlen)) {
+ errlog("Can't get gsensor config in u-boot!!!!\n");
+ return -1;
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &l_sensorconfig.op,
+ &l_sensorconfig.int_gpio,
+ &l_sensorconfig.samp,
+ &(l_sensorconfig.xyz_axis[0][0]),
+ &(l_sensorconfig.xyz_axis[0][1]),
+ &(l_sensorconfig.xyz_axis[1][0]),
+ &(l_sensorconfig.xyz_axis[1][1]),
+ &(l_sensorconfig.xyz_axis[2][0]),
+ &(l_sensorconfig.xyz_axis[2][1]),
+ &(l_sensorconfig.offset[0]),
+ &(l_sensorconfig.offset[1]),
+ &(l_sensorconfig.offset[2])
+ );
+ if (n != 12) {
+ errlog("gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+ l_sensorconfig.sensor_samp = l_sensorconfig.samp;
+
+ dbg("get the sensor config: %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ l_sensorconfig.xyz_axis[0][0],
+ l_sensorconfig.xyz_axis[0][1],
+ l_sensorconfig.xyz_axis[1][0],
+ l_sensorconfig.xyz_axis[1][1],
+ l_sensorconfig.xyz_axis[2][0],
+ l_sensorconfig.xyz_axis[2][1],
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+ }
+ return 0;
+}
+
+static void dmard09_platform_release(struct device *device)
+{
+ GSE_LOG("...\n");
+ return;
+}
+
+static int __devexit dmard09_remove(struct platform_device *pdev)
+{
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ remove_proc_entry(GSENSOR_PROC_NAME, NULL);
+ l_sensorconfig.sensor_proc = NULL;
+ }
+ //misc_deregister(&d09_device);
+ return 0;
+}
+
+
+static struct platform_device dmard09_device = {
+ .name = SENSOR_I2C_NAME,
+ .id = 0,
+ .dev = {
+ .release = dmard09_platform_release,
+ },
+};
+
+static struct platform_driver dmard09_driver = {
+ .probe = dmard09_probe,
+ .remove = dmard09_remove,
+ .shutdown = dmard09_shutdown,
+ .suspend = dmard09_suspend,
+ .resume = dmard09_resume,
+ .driver = {
+ .name = SENSOR_I2C_NAME,
+ },
+};
+
+
+static int __init device_init(void){
+ //struct device *device;
+ struct i2c_client *this_client;
+ int ret = 0;
+
+ // parse g-sensor u-boot arg
+ ret = get_axisset();
+ if (ret < 0)
+ {
+ printk("<<<<<%s user choose to no sensor chip!\n", __func__);
+ return ret;
+ }
+ GSE_LOG("D09 gsensor driver: initialize.\n");
+
+ if (!(this_client = sensor_i2c_register_device(0, DEVICE_I2C_ADDR, SENSOR_I2C_NAME)))
+ {
+ printk(KERN_ERR"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+
+ if (dmard09_init(this_client))
+ {
+ GSE_ERR("Failed to init dmard09!\n");
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+ }
+
+ /* Allocate memory for driver data */
+ s_dmt = kzalloc(sizeof(struct dmt_data), GFP_KERNEL);
+ //memset(s_dmt, 0, sizeof(struct dmt_data));
+ if (s_dmt == NULL) {
+ GSE_ERR("alloc data failed.\n");
+ return -ENOMEM;
+ }
+
+ s_dmt->client = this_client;
+ s_dmt->pdevice = &dmard09_device;
+ s_dmt->offset.u.x = l_sensorconfig.offset[0];
+ s_dmt->offset.u.y = l_sensorconfig.offset[1];
+ s_dmt->offset.u.z = l_sensorconfig.offset[2];
+
+
+ // create the platform device
+ l_dev_class = class_create(THIS_MODULE, SENSOR_I2C_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create gsensor device !!\n");
+ return ret;
+ }
+ if((ret = platform_device_register(&dmard09_device)))
+ {
+ GSE_ERR("Can't register dmard09 platform devcie!!!\n");
+ return ret;
+ }
+ if ((ret = platform_driver_register(&dmard09_driver)) != 0)
+ {
+ GSE_ERR("Can't register dmard09 platform driver!!!\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __exit device_exit(void){
+ //i2c_unregister_device(client);
+ //i2c_del_driver(&device_i2c_driver);
+ GSE_LOG("D09 gsensor driver: release.\n");
+
+ flush_delayed_work_sync(&s_dmt->delaywork);
+ cancel_delayed_work_sync(&s_dmt->delaywork);
+
+ input_unregister_device(s_dmt->input);
+ input_free_device(s_dmt->input);
+ misc_deregister(&dmt_device);
+ misc_deregister(&d09_device);
+ platform_driver_unregister(&dmard09_driver);
+ platform_device_unregister(&dmard09_device);
+ sensor_i2c_unregister_device(s_dmt->client);
+ class_destroy(l_dev_class);
+
+ remove_sysfs_interfaces(s_dmt);
+ kfree(s_dmt);
+}
+
+static int dmt_get_filter(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ return dmt->filter;
+}
+
+static int dmt_set_filter(struct i2c_client *client, int filter){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ if (!((filter >= 1) && (filter <= 32)))
+ return -1;
+ dmt->filter = filter;
+ return 0;
+}
+
+static int dmt_get_position(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ return dmt->position;
+}
+
+static int dmt_set_position(struct i2c_client *client, int position){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ if (!((position >= 0) && (position <= 7)))
+ return -1;
+ dmt->position = position;
+ return 0;
+}
+
+extern int wmt_setsyspara(char *varname, char *varval);
+static void update_var(void)
+{
+ char varbuf[64];
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+
+ sprintf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ l_sensorconfig.xyz_axis[0][0],
+ l_sensorconfig.xyz_axis[0][1],
+ l_sensorconfig.xyz_axis[1][0],
+ l_sensorconfig.xyz_axis[1][1],
+ l_sensorconfig.xyz_axis[2][0],
+ l_sensorconfig.xyz_axis[2][1],
+ s_dmt->offset.u.x,
+ s_dmt->offset.u.y,
+ s_dmt->offset.u.z
+ );
+
+ wmt_setsyspara("wmt.io.dm09sensor",varbuf);
+}
+
+static int D09_write_offset_to_file(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ char r_buf[18] = {0};
+ char w_buf[18] = {0};
+ //unsigned int orgfs;
+ struct file *fp;
+ mm_segment_t fs;
+ ssize_t ret;
+ //int8_t i;
+
+ sprintf(w_buf,"%5d %5d %5d", dmt->offset.u.x, dmt->offset.u.y, dmt->offset.u.z);
+ /* Set segment descriptor associated to kernel space */
+ fp = filp_open(D09_OffsetFileName, O_RDWR | O_CREAT, 0777);
+ if(IS_ERR(fp)){
+ GSE_ERR("filp_open %s error!!.:%d\n",D09_OffsetFileName,fp);
+ return -1;
+ }
+ else{
+ fs = get_fs();
+ //set_fs(KERNEL_DS);
+ set_fs(get_ds());
+ GSE_LOG("filp_open %s SUCCESS!!.\n",D09_OffsetFileName);
+ //fp->f_op->write(fp,data,18, &fp->f_pos);
+ //filp_close(fp,NULL);
+ ret = fp->f_op->write(fp,w_buf,18,&fp->f_pos);
+ if(ret != 18)
+ {
+ printk(KERN_ERR "%s: write error!\n", __func__);
+ filp_close(fp,NULL);
+ return -EIO;
+ }
+ //fp->f_pos=0x00;
+ ret = fp->f_op->read(fp,r_buf, 18,&fp->f_pos);
+ if(ret < 0)
+ {
+ printk(KERN_ERR "%s: read error!\n", __func__);
+ filp_close(fp,NULL);
+ return -EIO;
+ }
+ set_fs(fs);
+
+ //
+ //printk(KERN_INFO "%s: read ret=%d!", __func__, ret);
+ /* for(i=0; i<18 ;i++)
+ {
+ if(r_buf[i] != w_buf[i])
+ {
+ printk(KERN_ERR "%s: read back error, r_buf[%x](0x%x) != w_buf[%x](0x%x)\n",
+ __func__, i, r_buf[i], i, w_buf[i]);
+ filp_close(fp,NULL);
+ return -EIO;
+ }
+ }
+ */
+
+ }
+ filp_close(fp,NULL);
+ return 0;
+}
+
+void D09_read_offset_from_file(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ unsigned int orgfs;
+ char data[18];
+ struct file *fp;
+ int ux,uy,uz;
+ orgfs = get_fs();
+ /* Set segment descriptor associated to kernel space */
+ set_fs(KERNEL_DS);
+
+ fp = filp_open(D09_OffsetFileName, O_RDWR , 0);
+ GSE_FUN();
+ if(IS_ERR(fp)){
+ GSE_ERR("Sorry,file open ERROR !\n");
+ if(l_sensorconfig.op){ //first time
+ l_sensorconfig.op=0;
+#if AUTO_CALIBRATION
+ /* get acceleration average reading */
+ D09_calibrate(client);
+ update_var();
+ D09_write_offset_to_file(client);
+#endif
+#ifdef DMT_BROADCAST_APK_ENABLE
+ create_devidfile();
+ return;
+#endif
+ }
+ D09_write_offset_to_file(client);
+ }
+ else{
+ GSE_LOG("filp_open %s SUCCESS!!.\n",D09_OffsetFileName);
+ fp->f_op->read(fp,data,18, &fp->f_pos);
+ GSE_LOG("filp_read result %s\n",data);
+ sscanf(data,"%d %d %d",&ux,&uy,&uz);
+ dmt->offset.u.x=ux;
+ dmt->offset.u.y=uy;
+ dmt->offset.u.z=uz;
+ }
+ set_fs(orgfs);
+}
+static int create_devidfile(void)
+{
+ char data[18];
+ unsigned int orgfs;
+ struct file *fp;
+
+ sprintf(data,"%5d %5d %5d",0,0,0);
+ orgfs = get_fs();
+ /* Set segment descriptor associated to kernel space */
+ set_fs(KERNEL_DS);
+ GSE_FUN();
+ fp = filp_open(DmtXXFileName, O_RDWR | O_CREAT, 0777);
+ if(IS_ERR(fp)){
+ GSE_ERR("Sorry,file open ERROR !\n");
+ return -1;
+ }
+ fp->f_op->write(fp,data,18, &fp->f_pos);
+ set_fs(orgfs);
+ filp_close(fp,NULL);
+ return 0;
+}
+//*********************************************************************************************************
+MODULE_AUTHOR("DMT_RD");
+MODULE_DESCRIPTION("DMT Gsensor Driver");
+MODULE_LICENSE("GPL");
+
+module_init(device_init);
+module_exit(device_exit);
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard09_gsensor/dmt09.h b/ANDROID_3.4.5/drivers/input/sensor/dmard09_gsensor/dmt09.h
new file mode 100755
index 00000000..d30e606a
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard09_gsensor/dmt09.h
@@ -0,0 +1,183 @@
+/* @version 1.03
+ * Copyright 2011 Domintech Technology Co., Ltd
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef DMT09_H
+#define DMT09_H
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include <linux/syscalls.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+//#include <linux/earlysuspend.h>
+#define AUTO_CALIBRATION 0
+#define SW_FILTER /* Enable or Disable Software filter */
+#define SENSOR_DATA_AVG 4//8 /* AVG sensor data */
+
+#define STABLE_VALUE_FUNCTION
+#define RANGE_XYZ 40
+
+//#define DMT_DEBUG_DATA
+#define GSE_TAG "[DMT_Gsensor]"
+#ifdef DMT_DEBUG_DATA
+#define GSE_ERR(fmt, args...) printk(KERN_ERR GSE_TAG"%s %d : "fmt, __FUNCTION__, __LINE__, ##args)
+#define GSE_LOG(fmt, args...) printk(KERN_INFO GSE_TAG fmt, ##args)
+#define GSE_FUN(f) printk(KERN_INFO GSE_TAG" %s: %s: %i\n", __FILE__, __func__, __LINE__)
+#define DMT_DATA(dev, ...) dev_dbg((dev), ##__VA_ARGS__)
+#else
+#define GSE_ERR(fmt, args...)
+#define GSE_LOG(fmt, args...)
+#define GSE_FUN(f)
+#define DMT_DATA(dev, format, ...)
+#endif
+
+#define GSENSOR_ID "DMARD09"
+#define INPUT_NAME_ACC "g-sensor"//"DMT_accel"//"g-sensor"// /* Input Device Name */
+#define SENSOR_I2C_NAME "dmard09"//"dmt"// /* Device name for DMARD09 misc. device */
+#define DEVICE_I2C_ADDR 0x1d
+#define REG_ACTR 0x00
+#define REG_STAT 0x0A
+#define REG_DX 0x0C
+#define REG_DY 0x0E
+#define REG_DZ 0x10
+#define REG_DT 0x12
+#define REG_INL 0x16
+#define REG_DC 0x18
+#define REG_CNT_L1 0x1B
+#define REG_CNT_L2 0x1C
+#define REG_CNT_L3 0x1D
+#define REG_INC 0x1E
+#define REG_ODF 0x20
+#define REG_THR1 0x62
+#define REG_THR2 0x64
+
+#define MODE_ACTIVE 0x61 /* active */
+#define MODE_POWERDOWN 0x60 /* powerdown */
+
+#define VALUE_WHO_AM_I 0x95 /* D09 WMI */
+#define VALUE_ODR_200 0x9C /* conversion rate 200Hz */
+#define VALUE_ODR_100 0x98 /* conversion rate 100Hz */
+#define VALUE_ODR_50 0x94 /* conversion rate 50Hz */
+#define VALUE_ODR_20 0x90 /* conversion rate 20Hz */
+#define VALUE_ODR_10 0x8C /* conversion rate 10Hz */
+#define VALUE_ODR_5 0x88 /* conversion rate 5Hz */
+#define VALUE_ODR_1 0x84 /* conversion rate 1Hz */
+#define VALUE_ODR_0_5 0x80 /* conversion rate 0.5Hz */
+#define VALUE_CNT_L2 0xE4 /* Disable IEN */
+/* Optional Digital Filter [Low Byte and High Byte Order] */
+#define ODF_NoFilter 0x00 /* No filter */
+#define ODF_Ave_4 0x03 /* smooth filter 1/4 Bandwidth */
+#define ODF_Ave_8 0x07 /* smooth filter 1/8 Bandwidth */
+#define ODF_Ave_16 0x0f /* smooth filter 1/16 Bandwidth */
+
+
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_NEGATIVE 1
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_POSITIVE 2
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Y_NEGATIVE 3
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Y_POSITIVE 4
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_X_NEGATIVE 5
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_X_POSITIVE 6
+
+#define AVG_NUM 16
+#define SENSOR_DATA_SIZE 3
+#define DEFAULT_SENSITIVITY 1024
+
+#define IOCTL_MAGIC 0x09
+#define SENSOR_RESET _IO(IOCTL_MAGIC, 0)
+#define SENSOR_CALIBRATION _IOWR(IOCTL_MAGIC, 1, int[SENSOR_DATA_SIZE])
+#define SENSOR_GET_OFFSET _IOR(IOCTL_MAGIC, 2, int[SENSOR_DATA_SIZE])
+#define SENSOR_SET_OFFSET _IOWR(IOCTL_MAGIC, 3, int[SENSOR_DATA_SIZE])
+#define SENSOR_READ_ACCEL_XYZ _IOR(IOCTL_MAGIC, 4, int[SENSOR_DATA_SIZE])
+#define SENSOR_SETYPR _IOW(IOCTL_MAGIC, 5, int[SENSOR_DATA_SIZE])
+#define SENSOR_GET_OPEN_STATUS _IO(IOCTL_MAGIC, 6)
+#define SENSOR_GET_CLOSE_STATUS _IO(IOCTL_MAGIC, 7)
+#define SENSOR_GET_DELAY _IOR(IOCTL_MAGIC, 8, unsigned int*)
+#define SENSOR_MAXNR 8
+/* Default sensorlayout parameters */
+#define D09_DEFAULT_POSITION 6
+
+/* Transformation matrix for chip mounting position */
+static const int dmt_position_map[][3][3] = {
+ { { 1, 0, 0}, { 0,-1, 0}, { 0, 0,-1}, }, /* top/upper-left */
+ { { 0, 1, 0}, { 1, 0, 0}, { 0, 0,-1}, }, /* top/lower-left */
+ { {-1, 0, 0}, { 0, 1, 0}, { 0, 0,-1}, }, /* top/lower-right */
+ { { 0,-1, 0}, {-1, 0, 0}, { 0, 0,-1}, }, /* top/upper-right */
+ { {-1, 0, 0}, { 0,-1, 0}, { 0, 0, 1}, }, /* bottom/upper-right*/
+ { { 0,-1, 0}, {-1, 0, 0}, { 0, 0, 1}, }, /* bottom/upper-left */
+ { { 1, 0, 0}, { 0, 1, 0}, { 0, 0, 1}, }, /* bottom/lower-right*/
+ { { 0, 1,0}, { 1, 0, 0}, { 0, 0, 1}, }, /* bottom/lower-left */
+};
+
+typedef union {
+ struct {
+ int x;
+ int y;
+ int z;
+ } u;
+ int v[SENSOR_DATA_SIZE];
+} raw_data;
+
+struct dmt_data {
+ struct platform_device *pdevice;
+ struct device *class_dev;
+ struct class *class;
+ struct input_dev *input;
+ struct i2c_client *client;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ struct delayed_work delaywork;
+ struct work_struct work;
+ struct mutex data_mutex;
+ struct mutex enable_mutex; /* for suspend */
+ raw_data last; /* RawData */
+ raw_data offset; /* Offset */
+#ifdef SW_FILTER
+ int sum[SENSOR_DATA_SIZE]; /* SW_FILTER sum */
+ int bufferave[3][32];
+ s8 aveflag; /* FULL bufferave[][] */
+ s8 pointer; /* last update data */
+#endif
+ wait_queue_head_t open_wq;
+ atomic_t active;
+ atomic_t delay;
+ atomic_t enable;
+ int filter;
+ int position; /* must int type ,for Kconfig setup */
+ atomic_t addr;
+#ifdef DMT_DEBUG_DATA
+ struct mutex suspend_mutex;
+ int suspend;
+#endif
+};
+
+#define ACC_DATA_FLAG 0
+#define MAG_DATA_FLAG 1
+#define ORI_DATA_FLAG 2
+#define DMT_NUM_SENSORS 3
+
+/* ABS axes parameter range [um/s^2] (for input event) */
+#define GRAVITY_EARTH 9806550
+#define ABSMAX (GRAVITY_EARTH * 2)
+#define ABSMIN (-GRAVITY_EARTH * 2)
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard10_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/dmard10_gsensor/Makefile
new file mode 100755
index 00000000..3241f881
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard10_gsensor/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_gsensor_dmard10
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := dmt10.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard10_gsensor/dmt10.c b/ANDROID_3.4.5/drivers/input/sensor/dmard10_gsensor/dmt10.c
new file mode 100755
index 00000000..9810ea3a
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard10_gsensor/dmt10.c
@@ -0,0 +1,1702 @@
+/*
+ * @file drivers/misc/dmt10.c
+ * @brief DMT g-sensor Linux device driver
+ * @author Domintech Technology Co., Ltd (http://www.domintech.com.tw)
+ * @version 1.06
+ * @date 2013/08/14
+ * @section LICENSE
+ *
+ * Copyright 2012 Domintech Technology Co., Ltd
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "dmt10.h"
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/wakelock.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/clk.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/string.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+
+#include "../sensor.h"
+
+//////////////////////////////////////////////////////////
+static struct wmt_gsensor_data l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .samp = 5,
+ .xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },
+ .sensor_proc = NULL,
+ .isdbg = 0,
+ .sensor_samp = 10, // 1 sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ .offset={0,0,0},
+};
+
+static struct class* l_dev_class = NULL;
+static void update_var(void);
+
+////////////////////////////////////////////////////////////
+
+
+static unsigned int interval;
+static int D10_write_offset_to_file(struct i2c_client *client);
+void D10_read_offset_from_file(struct i2c_client *client);
+#define DMT_BROADCAST_APK_ENABLE
+char D10_OffsetFileName[] = "/data/misc/gsensor_offset.txt"; /* FILE offset.txt */
+char DmtXXFileName[] = "/data/misc/dmt_sensor.txt";
+static int create_devidfile(void);
+static struct dmt_data *s_dmt;
+static int device_init(void);
+static void device_exit(void);
+
+static int device_open(struct inode*, struct file*);
+static long device_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+static int device_close(struct inode*, struct file*);
+
+static int dmard10_suspend(struct platform_device *pdev, pm_message_t state);
+static int dmard10_resume(struct platform_device *pdev);
+
+/*static int device_i2c_suspend(struct i2c_client *client, pm_message_t mesg);
+static int device_i2c_resume(struct i2c_client *client);
+static int __devinit device_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
+static int __devexit device_i2c_remove(struct i2c_client *client);*/
+static int D10_i2c_read_xyz(struct i2c_client *client, int *xyz);
+static int device_i2c_rxdata(struct i2c_client *client, unsigned char *rxDat, int length);
+static int device_i2c_txdata(struct i2c_client *client, unsigned char *txData, int length);
+
+static int dmt_get_filter(struct i2c_client *client);
+static int dmt_set_filter(struct i2c_client *client,int);
+static int dmt_get_position(struct i2c_client *client);
+static int dmt_set_position(struct i2c_client *client,int);
+static int DMT_GetOpenStatus(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ GSE_LOG("start active=%d\n",dmt->active.counter);
+ wait_event_interruptible(dmt->open_wq, (atomic_read(&dmt->active) != 0));
+ return 0;
+}
+
+static int DMT_GetCloseStatus(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ GSE_LOG("start active=%d\n",dmt->active.counter);
+ wait_event_interruptible(dmt->open_wq, (atomic_read(&dmt->active) <= 0));
+ return 0;
+}
+
+static void DMT_sysfs_update_active_status(struct dmt_data *dmt , int en){
+ unsigned long dmt_delay;
+ if(en){
+ dmt_delay=msecs_to_jiffies(atomic_read(&dmt->delay));
+ if(dmt_delay<1)
+ dmt_delay=1;
+
+ GSE_LOG("schedule_delayed_work start with delay time=%lu\n",dmt_delay);
+ schedule_delayed_work(&dmt->delaywork,dmt_delay);
+ }
+ else
+ cancel_delayed_work_sync(&dmt->delaywork);
+}
+
+static bool get_value_as_int(char const *buf, size_t size, int *value){
+ long tmp;
+ if (size == 0)
+ return false;
+ /* maybe text format value */
+ if ((buf[0] == '0') && (size > 1)) {
+ if ((buf[1] == 'x') || (buf[1] == 'X')) {
+ /* hexadecimal format */
+ if (0 != strict_strtol(buf, 16, &tmp))
+ return false;
+ } else {
+ /* octal format */
+ if (0 != strict_strtol(buf, 8, &tmp))
+ return false;
+ }
+ } else {
+ /* decimal format */
+ if (0 != strict_strtol(buf, 10, &tmp))
+ return false;
+ }
+
+ if (tmp > INT_MAX)
+ return false;
+
+ *value = tmp;
+ return true;
+}
+static bool get_value_as_int64(char const *buf, size_t size, long long *value)
+{
+ long long tmp;
+ if (size == 0)
+ return false;
+ /* maybe text format value */
+ if ((buf[0] == '0') && (size > 1)) {
+ if ((buf[1] == 'x') || (buf[1] == 'X')) {
+ /* hexadecimal format */
+ if (0 != strict_strtoll(buf, 16, &tmp))
+ return false;
+ } else {
+ /* octal format */
+ if (0 != strict_strtoll(buf, 8, &tmp))
+ return false;
+ }
+ } else {
+ /* decimal format */
+ if (0 != strict_strtoll(buf, 10, &tmp))
+ return false;
+ }
+
+ if (tmp > LLONG_MAX)
+ return false;
+
+ *value = tmp;
+ return true;
+}
+/* sysfs enable show & store */
+static ssize_t dmt_sysfs_enable_show(
+ struct dmt_data *dmt, char *buf, int pos)
+{
+ char str[2][16]={"ACC enable OFF","ACC enable ON"};
+ int flag;
+ flag=atomic_read(&dmt->enable);
+ return sprintf(buf, "%s\n", str[flag]);
+}
+
+static ssize_t dmt_sysfs_enable_store(
+ struct dmt_data *dmt, char const *buf, size_t count, int pos)
+{
+ int en = 0;
+ if (NULL == buf)
+ return -EINVAL;
+ //GSE_LOG("buf=%x %x\n", buf[0], buf[1]);
+ if (0 == count)
+ return 0;
+
+ if (false == get_value_as_int(buf, count, &en))
+ return -EINVAL;
+
+ en = en ? 1 : 0;
+
+ atomic_set(&dmt->enable,en);
+ DMT_sysfs_update_active_status(dmt , en);
+ return count;
+}
+
+static ssize_t dmt_enable_show(struct device *dev, struct device_attribute *attr, char *buf){
+ return dmt_sysfs_enable_show( dev_get_drvdata(dev), buf, ACC_DATA_FLAG);
+}
+
+static ssize_t dmt_enable_store( struct device *dev, struct device_attribute *attr, char const *buf, size_t count){
+ return dmt_sysfs_enable_store( dev_get_drvdata(dev), buf, count, ACC_DATA_FLAG);
+}
+
+/* sysfs delay show & store*/
+static ssize_t dmt_sysfs_delay_show( struct dmt_data *dmt, char *buf, int pos){
+ return sprintf(buf, "%d\n", atomic_read(&dmt->delay));
+}
+
+static ssize_t dmt_sysfs_delay_store( struct dmt_data *dmt, char const *buf, size_t count, int pos){
+ long long val = 0;
+
+ if (NULL == buf)
+ return -EINVAL;
+
+ if (0 == count)
+ return 0;
+
+ if (false == get_value_as_int64(buf, count, &val))
+ return -EINVAL;
+
+ atomic_set(&dmt->delay, (unsigned int) val);
+ GSE_LOG("Driver attribute set delay =%lld\n", val);
+
+ return count;
+}
+
+static ssize_t dmt_delay_show( struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return dmt_sysfs_delay_show( dev_get_drvdata(dev), buf, ACC_DATA_FLAG);
+}
+
+static ssize_t dmt_delay_store( struct device *dev,
+ struct device_attribute *attr,
+ char const *buf,
+ size_t count)
+{
+ return dmt_sysfs_delay_store( dev_get_drvdata(dev), buf, count, ACC_DATA_FLAG);
+}
+/* sysfs position show & store */
+static ssize_t dmt_position_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+
+ return sprintf(buf, "%d\n", dmt_get_position(dmt->client));
+}
+
+static ssize_t dmt_position_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ unsigned long position;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &position);
+ if (ret < 0)
+ return count;
+
+ dmt_set_position(dmt->client, position);
+ return count;
+}
+/* sysfs offset show & store */
+static ssize_t dmt_offset_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ return sprintf(buf, "( %d %d %d )\n", dmt->offset.u.x, dmt->offset.u.y, dmt->offset.u.z);
+}
+
+static ssize_t dmt_offset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ sscanf(buf, "%d %d %d", (int *)&dmt->offset.v[0], (int *)&dmt->offset.v[1], (int *)&dmt->offset.v[2]);
+ D10_write_offset_to_file(dmt->client);
+ update_var();
+ return count;
+}
+/* sysfs filter show & store */
+static ssize_t dmt_filter_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+
+ return sprintf(buf, "%d\n", dmt_get_filter(dmt->client));
+}
+
+static ssize_t dmt_filter_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ unsigned long filter;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &filter);
+ if (ret < 0)
+ return count;
+
+ dmt_set_filter(dmt->client, filter);
+ return count;
+}
+
+/* sysfs data show */
+static ssize_t dmt_acc_private_data_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ raw_data accel;
+
+ mutex_lock(&dmt->data_mutex);
+ accel = dmt->last;
+ mutex_unlock(&dmt->data_mutex);
+
+ return sprintf(buf, "( %d %d %d )\n", dmt->last.v[0], dmt->last.v[1], dmt->last.v[2]);
+}
+/* sysfs id show */
+static ssize_t dmt_id_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ char str[8]={GSENSOR_ID};
+ return sprintf(buf, "%s\n", str);
+}
+/* sysfs debug_suspend show & store */
+#ifdef DMT_DEBUG_DATA
+static ssize_t dmt_debug_suspend_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ int suspend = dmt->suspend;
+
+ mutex_lock(&dmt->suspend_mutex);
+ suspend = sprintf(buf, "%d\n", dmt->suspend);
+ mutex_unlock(&dmt->suspend_mutex);
+ return suspend;
+}
+
+static ssize_t dmt_debug_suspend_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct input_dev *input = to_input_dev(dev);
+ struct dmt_data *dmt = input_get_drvdata(input);
+ unsigned long suspend;
+ pm_message_t msg;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &suspend);
+ if (ret < 0)
+ return count;
+
+ memset(&msg, 0, sizeof(pm_message_t));
+
+ mutex_lock(&dmt->suspend_mutex);
+
+ if (suspend) {
+ dmard10_suspend(dmt->pdevice, msg);
+ dmt->suspend = 1;
+ } else {
+ dmard10_resume(dmt->pdevice);
+ dmt->suspend = 0;
+ }
+
+ mutex_unlock(&dmt->suspend_mutex);
+
+ return count;
+}
+/* sysfs reg_read show & store */
+static ssize_t dmt_reg_read_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct dmt_data *dmt = dev_get_drvdata(dev);
+ int err;
+ unsigned char i2c[1];
+
+ i2c[0] = (unsigned char)atomic_read(&dmt->addr);
+ err = device_i2c_rxdata(dmt->client, i2c, 1);
+ if (err < 0)
+ return err;
+
+ return sprintf(buf, "0x%02X\n", i2c[0]);
+}
+
+static ssize_t dmt_reg_read_store(struct device *dev,
+ struct device_attribute *attr,
+ char const *buf,
+ size_t count)
+{
+ struct dmt_data *dmt = dev_get_drvdata(dev);
+ int addr = 0;
+
+ if (NULL == buf)
+ return -EINVAL;
+
+ if (0 == count)
+ return 0;
+
+ if (false == get_value_as_int(buf, count, &addr))
+ return -EINVAL;
+
+ if (addr < 0 || 128 < addr)
+ return -EINVAL;
+
+ atomic_set(&dmt->addr, addr);
+
+ return 1;
+}
+#endif /* DEBUG */
+/*********************************************************************
+ *
+ * SysFS attribute functions
+ *
+ * directory : /sys/class/accelemeter/dmardXX/
+ * files :
+ * - enable_acc [rw] [t] : enable flag for accelerometer
+ * - delay_acc [rw] [t] : delay in nanosecond for accelerometer
+ * - position [rw] [t] : chip mounting position
+ * - offset [rw] [t] : offset
+ * - data [r] [t] : raw data
+ * - id [r] [t] : chip id
+ *
+ * debug :
+ * - debug_suspend [w] [t] : suspend test
+ * - reg_read [rw] [t] : Read register
+ * - reg_write [rw] [t] : Weite register
+ *
+ * [rw]= read/write
+ * [r] = read only
+ * [w] = write only
+ * [b] = binary format
+ * [t] = text format
+ */
+
+static struct device_attribute DMT_attributes[] = {
+ __ATTR(enable_acc, 0660, dmt_enable_show, dmt_enable_store),
+ __ATTR(delay_acc, 0660, dmt_delay_show, dmt_delay_store),
+ __ATTR(position, 0660, dmt_position_show, dmt_position_store),
+ __ATTR(offset, 0660, dmt_offset_show, dmt_offset_store),
+ __ATTR(filter, 0660, dmt_filter_show, dmt_filter_store),
+ __ATTR(data, 0660, dmt_acc_private_data_show, NULL),
+ __ATTR(id, 0660, dmt_id_show, NULL),
+#ifdef DMT_DEBUG_DATA
+ __ATTR(debug_suspend, 0660, dmt_debug_suspend_show,dmt_debug_suspend_store),
+ __ATTR(reg_read, 0660, dmt_reg_read_show, dmt_reg_read_store),
+ __ATTR(reg_write, 0660, NULL, NULL),
+#endif // DEBUG
+ __ATTR_NULL,
+};
+
+static char const *const ACCELEMETER_CLASS_NAME = "accelemeter";
+static char const *const GSENSOR_DEVICE_NAME = SENSOR_I2C_NAME;
+static char const *const device_link_name = "i2c";
+static dev_t const dmt_device_dev_t = MKDEV(MISC_MAJOR, MISC_DYNAMIC_MINOR);
+
+// dmt sysfs functions
+static int create_device_attributes(struct device *dev, struct device_attribute *attrs){
+ int i;
+ int err = 0;
+ for (i = 0 ; NULL != attrs[i].attr.name ; ++i) {
+ err = device_create_file(dev, &attrs[i]);
+ if (0 != err)
+ break;
+ }
+
+ if (0 != err) {
+ for (; i >= 0 ; --i)
+ device_remove_file(dev, &attrs[i]);
+ }
+ return err;
+}
+
+static void remove_device_attributes(
+ struct device *dev,
+ struct device_attribute *attrs)
+{
+ int i;
+
+ for (i = 0 ; NULL != attrs[i].attr.name ; ++i)
+ device_remove_file(dev, &attrs[i]);
+}
+
+static int create_sysfs_interfaces(struct dmt_data *dmt)
+{
+ int err;
+
+ if (NULL == dmt)
+ return -EINVAL;
+
+ err = 0;
+ dmt->class = class_create(THIS_MODULE, ACCELEMETER_CLASS_NAME);
+ if (IS_ERR(dmt->class)) {
+ err = PTR_ERR(dmt->class);
+ goto exit_class_create_failed;
+ }
+
+ dmt->class_dev = device_create(
+ dmt->class,
+ NULL,
+ dmt_device_dev_t,
+ dmt,
+ GSENSOR_DEVICE_NAME);
+ if (IS_ERR(dmt->class_dev)) {
+ err = PTR_ERR(dmt->class_dev);
+ goto exit_class_device_create_failed;
+ }
+
+ err = sysfs_create_link(
+ &dmt->class_dev->kobj,
+ &dmt->client->dev.kobj,
+ device_link_name);
+ if (0 > err)
+ goto exit_sysfs_create_link_failed;
+
+ err = create_device_attributes(
+ dmt->class_dev,
+ DMT_attributes);
+ if (0 > err)
+ goto exit_device_attributes_create_failed;
+#if 0
+ err = create_device_binary_attributes(
+ &dmt->class_dev->kobj,
+ dmt_bin_attributes);
+ if (0 > err)
+ goto exit_device_binary_attributes_create_failed;
+#endif
+
+ return err;
+
+#if 0
+exit_device_binary_attributes_create_failed:
+ remove_device_attributes(dmt->class_dev, dmt_attributes);
+#endif
+exit_device_attributes_create_failed:
+ sysfs_remove_link(&dmt->class_dev->kobj, device_link_name);
+exit_sysfs_create_link_failed:
+ device_destroy(dmt->class, dmt_device_dev_t);
+exit_class_device_create_failed:
+ dmt->class_dev = NULL;
+ class_destroy(dmt->class);
+exit_class_create_failed:
+ dmt->class = NULL;
+ return err;
+}
+
+static void remove_sysfs_interfaces(struct dmt_data *dmt){
+ if (NULL == dmt)
+ return;
+
+ if (NULL != dmt->class_dev) {
+
+ remove_device_attributes(
+ dmt->class_dev,
+ DMT_attributes);
+ sysfs_remove_link(
+ &dmt->class_dev->kobj,
+ device_link_name);
+ dmt->class_dev = NULL;
+ }
+ if (NULL != dmt->class) {
+ device_destroy(
+ dmt->class,
+ dmt_device_dev_t);
+ class_destroy(dmt->class);
+ dmt->class = NULL;
+ }
+}
+
+int D10_input_init(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ int err = 0;
+ dmt->input = input_allocate_device();
+ if (!dmt->input){
+ GSE_ERR("input device allocate ERROR !!\n");
+ return -ENOMEM;
+ }
+ else
+ GSE_LOG("input device allocate Success !!\n");
+ /* Setup input device */
+ //dmt->input->name = SENSOR_I2C_NAME;
+ set_bit(EV_ABS, dmt->input->evbit);
+ /* Accelerometer [-78.5, 78.5]m/s2 in Q16 */
+ input_set_abs_params(dmt->input, ABS_X, ABSMIN, ABSMAX, 0, 0);
+ input_set_abs_params(dmt->input, ABS_Y, ABSMIN, ABSMAX, 0, 0);
+ input_set_abs_params(dmt->input, ABS_Z, ABSMIN, ABSMAX, 0, 0);
+ /* Set InputDevice Name */
+ dmt->input->name = INPUT_NAME_ACC;
+ /* Register */
+ err = input_register_device(dmt->input);
+ if (err) {
+ GSE_ERR("input_register_device ERROR !!\n");
+ input_free_device(dmt->input);
+ return err;
+ }
+ GSE_LOG("input_register_device SUCCESS %d !! \n",err);
+
+ return err;
+}
+
+int D10_calibrate(struct i2c_client *client)
+{
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ raw_data avg;
+ int i, j;
+ long xyz_acc[SENSOR_DATA_SIZE];
+ int xyz[SENSOR_DATA_SIZE];
+ /* initialize the offset value */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ dmt->offset.v[i] = 0;
+ /* initialize the accumulation buffer */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ xyz_acc[i] = 0;
+
+ for(i = 0; i < AVG_NUM; i++) {
+ D10_i2c_read_xyz(client, (int *)&xyz);
+ for(j = 0; j < SENSOR_DATA_SIZE; ++j)
+ xyz_acc[j] += xyz[j];
+ }
+ /* calculate averages */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ avg.v[i] = xyz_acc[i] / AVG_NUM;
+
+ if(avg.v[2] < 0){
+ dmt->offset.u.x = avg.v[0] ;
+ dmt->offset.u.y = avg.v[1] ;
+ dmt->offset.u.z = avg.v[2] + DEFAULT_SENSITIVITY;
+ return CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_POSITIVE;
+ }
+ else{
+ dmt->offset.u.x = avg.v[0] ;
+ dmt->offset.u.y = avg.v[1] ;
+ dmt->offset.u.z = avg.v[2] - DEFAULT_SENSITIVITY;
+ return CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_NEGATIVE;
+ }
+ return 0;
+}
+
+int dmard10_init(struct i2c_client *client){
+ unsigned char buffer[7], buffer2[2];
+ /* 1. check D10 , VALUE_STADR = 0x55 , VALUE_STAINT = 0xAA */
+ buffer[0] = REG_STADR;
+ buffer2[0] = REG_STAINT;
+
+ device_i2c_rxdata(client, buffer, 2);
+ device_i2c_rxdata(client, buffer2, 2);
+
+ if( buffer[0] == VALUE_STADR || buffer2[0] == VALUE_STAINT){
+ GSE_LOG(" REG_STADR_VALUE = %d , REG_STAINT_VALUE = %d\n", buffer[0], buffer2[0]);
+ }
+ else{
+ GSE_LOG(" REG_STADR_VALUE = %d , REG_STAINT_VALUE = %d \n", buffer[0], buffer2[0]);
+ return -1;
+ }
+ /* 2. Powerdown reset */
+ buffer[0] = REG_PD;
+ buffer[1] = VALUE_PD_RST;
+ device_i2c_txdata(client, buffer, 2);
+ /* 3. ACTR => Standby mode => Download OTP to parameter reg => Standby mode => Reset data path => Standby mode */
+ buffer[0] = REG_ACTR;
+ buffer[1] = MODE_Standby;
+ buffer[2] = MODE_ReadOTP;
+ buffer[3] = MODE_Standby;
+ buffer[4] = MODE_ResetDataPath;
+ buffer[5] = MODE_Standby;
+ device_i2c_txdata(client, buffer, 6);
+ /* 4. OSCA_EN = 1 ,TSTO = b'000(INT1 = normal, TEST0 = normal) */
+ buffer[0] = REG_MISC2;
+ buffer[1] = VALUE_MISC2_OSCA_EN;
+ device_i2c_txdata(client, buffer, 2);
+ /* 5. AFEN = 1(AFE will powerdown after ADC) */
+ buffer[0] = REG_AFEM;
+ buffer[1] = VALUE_AFEM_AFEN_Normal;
+ buffer[2] = VALUE_CKSEL_ODR_100_204;
+ buffer[3] = VALUE_INTC;
+ buffer[4] = VALUE_TAPNS_Ave_4;
+ buffer[5] = 0x00; // DLYC, no delay timing
+ buffer[6] = 0x07; // INTD=1 (push-pull), INTA=1 (active high), AUTOT=1 (enable T)
+ device_i2c_txdata(client, buffer, 7);
+ /* 6. write TCGYZ & TCGX */
+ buffer[0] = REG_WDAL; // REG:0x01
+ buffer[1] = 0x00; // set TC of Y,Z gain value
+ buffer[2] = 0x00; // set TC of X gain value
+ buffer[3] = 0x03; // Temperature coefficient of X,Y,Z gain
+ device_i2c_txdata(client, buffer, 4);
+
+ buffer[0] = REG_ACTR; // REG:0x00
+ buffer[1] = MODE_Standby; // Standby
+ buffer[2] = MODE_WriteOTPBuf; // WriteOTPBuf
+ buffer[3] = MODE_Standby; // Standby
+ device_i2c_txdata(client, buffer, 4);
+ //buffer[0] = REG_TCGYZ;
+ //device_i2c_rxdata(client, buffer, 2);
+ //GSE_LOG(" TCGYZ = %d, TCGX = %d \n", buffer[0], buffer[1]);
+
+ /* 7. Activation mode */
+ buffer[0] = REG_ACTR;
+ buffer[1] = MODE_Active;
+ device_i2c_txdata(client, buffer, 2);
+ return 0;
+}
+
+void D10_set_offset(struct i2c_client *client, int val[3]){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ int i;
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ dmt->offset.v[i] = val[i];
+}
+
+struct file_operations sensor_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = device_ioctl,
+ .open = device_open,
+ .release = device_close,
+};
+
+static struct miscdevice dmt_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = SENSOR_I2C_NAME,
+ .fops = &sensor_fops,
+};
+
+static int sensor_close_dev(struct i2c_client *client){
+ char buffer[3];
+ GSE_FUN();
+ buffer[0] = REG_AFEM;
+ buffer[1] = 0x0f;
+ device_i2c_txdata(client,buffer, 2);
+ buffer[0] = REG_ACTR;
+ buffer[1] = MODE_Standby;
+ buffer[2] = MODE_Off;
+ device_i2c_txdata(client,buffer, 3);
+ return 0;
+}
+
+static void dmard10_shutdown(struct platform_device *pdev)
+{
+ flush_delayed_work_sync(&s_dmt->delaywork);
+ DMT_sysfs_update_active_status(s_dmt , 0);
+}
+
+
+//static int device_i2c_suspend(struct i2c_client *client, pm_message_t mesg){
+static int dmard10_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct dmt_data *dmt = i2c_get_clientdata(s_dmt->client);
+ flush_delayed_work_sync(&dmt->delaywork);
+ DMT_sysfs_update_active_status(dmt , 0);
+ return sensor_close_dev(dmt->client);
+}
+
+//static int device_i2c_resume(struct i2c_client *client){
+static int dmard10_resume(struct platform_device *pdev)
+{
+ struct dmt_data *dmt = i2c_get_clientdata(s_dmt->client);
+ int en = 1;
+ GSE_FUN();
+ printk("dmt->enable=%d",dmt->enable);
+ dmard10_init(dmt->client);
+ atomic_set(&dmt->enable,en);
+ DMT_sysfs_update_active_status(dmt , en);
+ return 0;
+}
+/*
+static int __devexit device_i2c_remove(struct i2c_client *client){
+ return 0;
+}
+
+static const struct i2c_device_id device_i2c_ids[] = {
+ { SENSOR_I2C_NAME, 0},
+ { }
+};
+
+static struct i2c_driver device_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_I2C_NAME,
+ },
+ .class = I2C_CLASS_HWMON,
+ .id_table = device_i2c_ids,
+ .probe = device_i2c_probe,
+ .remove = __devexit_p(device_i2c_remove),
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ .suspend = device_i2c_suspend,
+ .resume = device_i2c_resume,
+#endif
+};
+*/
+static int device_open(struct inode *inode, struct file *filp){
+ return 0;
+}
+
+static long device_ioctl(struct file *file, unsigned int cmd, unsigned long arg){
+ //struct i2c_client *client = (struct i2c_client *)file->private_data;
+ //struct dmt_data *dmt = (struct dmt_data*)i2c_get_clientdata(client);
+
+ int err = 0, ret = 0, i;
+ int intBuf[SENSOR_DATA_SIZE], xyz[SENSOR_DATA_SIZE];
+ /* check type */
+ if (_IOC_TYPE(cmd) != IOCTL_MAGIC) return -ENOTTY;
+
+ /* check user space pointer is valid */
+ if (_IOC_DIR(cmd) & _IOC_READ)
+ err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
+ else if (_IOC_DIR(cmd) & _IOC_WRITE)
+ err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
+ if (err) return -EFAULT;
+
+ switch(cmd) {
+ case SENSOR_RESET:
+ ret = dmard10_init(s_dmt->client);
+ return ret;
+
+ case SENSOR_CALIBRATION:
+ /* get orientation info */
+ //if(copy_from_user(&intBuf, (int*)arg, sizeof(intBuf))) return -EFAULT;
+ D10_calibrate(s_dmt->client);
+ GSE_LOG("Sensor_calibration:%d %d %d\n", s_dmt->offset.u.x, s_dmt->offset.u.y, s_dmt->offset.u.z);
+ /* save file */
+ D10_write_offset_to_file(s_dmt->client);
+ update_var();
+
+ /* return the offset */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ intBuf[i] = s_dmt->offset.v[i];
+
+ ret = copy_to_user((int *)arg, &intBuf, sizeof(intBuf));
+ return ret;
+
+ case SENSOR_GET_OFFSET:
+ /* get data from file */
+ D10_read_offset_from_file(s_dmt->client);
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ intBuf[i] = s_dmt->offset.v[i];
+
+ ret = copy_to_user((int *)arg, &intBuf, sizeof(intBuf));
+ return ret;
+
+ case SENSOR_SET_OFFSET:
+ ret = copy_from_user(&intBuf, (int *)arg, sizeof(intBuf));
+ D10_set_offset(s_dmt->client , intBuf);
+ /* write into file */
+ D10_write_offset_to_file(s_dmt->client);
+ update_var();
+ return ret;
+
+ case SENSOR_READ_ACCEL_XYZ:
+ D10_i2c_read_xyz(s_dmt->client, (int *)&xyz);
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ intBuf[i] = xyz[i] - s_dmt->offset.v[i];
+
+ ret = copy_to_user((int*)arg, &intBuf, sizeof(intBuf));
+ return ret;
+
+ case SENSOR_SETYPR:
+ if(copy_from_user(&intBuf, (int*)arg, sizeof(intBuf))) {
+ GSE_LOG("%s: -EFAULT\n",__func__);
+ return -EFAULT;
+ }
+ input_report_abs(s_dmt->input, ABS_X, intBuf[0]);
+ input_report_abs(s_dmt->input, ABS_Y, intBuf[1]);
+ input_report_abs(s_dmt->input, ABS_Z, intBuf[2]);
+ input_sync(s_dmt->input);
+ GSE_LOG("SENSOR_SETYPR OK! x=%d,y=%d,z=%d\n",intBuf[0],intBuf[1],intBuf[2]);
+ return ret;
+
+ case SENSOR_GET_OPEN_STATUS:
+ GSE_LOG("Going into DMT_GetOpenStatus()\n");
+ ret = DMT_GetOpenStatus(s_dmt->client);
+ return ret;
+
+ case SENSOR_GET_CLOSE_STATUS:
+ GSE_LOG("Going into DMT_GetCloseStatus()\n");
+ ret = DMT_GetCloseStatus(s_dmt->client);
+ return ret;
+
+ case SENSOR_GET_DELAY:
+ ret = copy_to_user((int*)arg, &interval, sizeof(interval));
+ return ret;
+
+ default: /* redundant, as cmd was checked against MAXNR */
+ return -ENOTTY;
+ }
+
+ return 0;
+}
+
+static int device_close(struct inode *inode, struct file *filp){
+ return 0;
+}
+
+/***** I2C I/O function ***********************************************/
+static int device_i2c_rxdata( struct i2c_client *client, unsigned char *rxData, int length){
+ struct i2c_msg msgs[] = {
+ {.addr = client->addr, .flags = 0, .len = 1, .buf = rxData,},
+ {.addr = client->addr, .flags = I2C_M_RD, .len = length, .buf = rxData,},
+ };
+ //unsigned char addr = rxData[0];
+ if (i2c_transfer(client->adapter, msgs, 2) < 0) {
+ dev_err(&client->dev, "%s: transfer failed.", __func__);
+ return -EIO;
+ }
+ //DMT_DATA(&client->dev, "RxData: len=%02x, addr=%02x, data=%02x\n",
+ //length, addr, rxData[0]);
+
+ return 0;
+}
+
+static int device_i2c_txdata( struct i2c_client *client, unsigned char *txData, int length){
+ struct i2c_msg msg[] = {
+ {.addr = client->addr, .flags = 0, .len = length, .buf = txData,},
+ };
+
+ if (i2c_transfer(client->adapter, msg, 1) < 0) {
+ dev_err(&client->dev, "%s: transfer failed.", __func__);
+ return -EIO;
+ }
+ //DMT_DATA(&client->dev, "TxData: len=%02x, addr=%02x data=%02x\n",
+ //length, txData[0], txData[1]);
+ return 0;
+}
+
+static int D10_i2c_read_xyz(struct i2c_client *client, int *xyz_p){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ u8 buffer[11];
+ s16 xyzTmp[SENSOR_DATA_SIZE];
+ int pos = dmt->position;
+ int i, j , k;
+ /* get xyz high/low bytes, 0x12 */
+ buffer[0] = REG_STADR;
+ /* Read acceleration data */
+ if (device_i2c_rxdata(client, buffer, 10)!= 0)
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ xyz_p[i] = 0;
+ else
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ xyz_p[i] = 0;
+ /* merge xyz high/low bytes & 1g = 128 becomes 1g = 1024 */
+ mutex_lock(&dmt->data_mutex);
+ xyzTmp[i] = ((int16_t)((buffer[2*(i+1)+1] << 8)) | buffer[2*(i+1)] ) << 3;
+ mutex_unlock(&dmt->data_mutex);
+ }
+#ifdef SW_FILTER
+ if( dmt->aveflag >= dmt->filter){
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ dmt->sum[i] = dmt->sum[i] - dmt->bufferave[i][dmt->pointer] + xyzTmp[i];
+ }
+ /* transfer to the default layout */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ for(j = 0; j < SENSOR_DATA_SIZE; j++)
+ xyz_p[i] += (int)(dmt->sum[j]/dmt->filter * dmt_position_map[pos][i][j]);
+ }
+ }
+ else{
+ /* init dmt->sum */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ dmt->sum[i] = xyzTmp[i];
+#endif
+ /* transfer to the default layout */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ for(j = 0; j < SENSOR_DATA_SIZE; j++){
+ xyz_p[i] += (int)(xyzTmp[j] * dmt_position_map[pos][i][j]);
+ //GSE_LOG("%04d, %04d,%d \n", xyz_p[i], xyzTmp[j], dmt_position_map[pos][i][j]);
+ }
+ }
+ //GSE_LOG("xyz_p: %04d , %04d , %04d\n", xyz_p[0], xyz_p[1], xyz_p[2]);
+#ifdef SW_FILTER
+ dmt->aveflag++;
+ }
+ /* init dmt->sum */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ dmt->sum[i] = 0;
+ }
+ dmt->pointer++;
+ dmt->pointer %= dmt->filter;
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ dmt->bufferave[i][dmt->pointer] = xyzTmp[i];
+ }
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ for(k = 0; k < dmt->filter; ++k){
+ dmt->sum[i] += dmt->bufferave[i][k];
+ }
+ }
+#endif
+ return 0;
+}
+
+static void DMT_work_func(struct work_struct *delaywork){
+ struct dmt_data *dmt = container_of(delaywork, struct dmt_data, delaywork.work);
+ int i;
+ //static bool firsttime=true;
+ raw_data xyz;
+ unsigned long dmt_delay = msecs_to_jiffies(atomic_read(&dmt->delay));
+
+
+ D10_i2c_read_xyz(dmt->client, (int *)&xyz.v);
+ /* dmt->last = RawData - Offset */
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ dmt->last.v[i] = xyz.v[i] - dmt->offset.v[i];
+ //GSE_LOG("@DMTRaw @ X/Y/Z axis: %04d , %04d , %04d\n", xyz.v[0], xyz.v[1], xyz.v[2]);
+ //GSE_LOG("@Offset @ X/Y/Z axis: %04d , %04d , %04d\n", dmt->offset.u.x, dmt->offset.u.y, dmt->offset.u.z);
+ //GSE_LOG("@Raw-Offset@ X/Y/Z axis: %04d , %04d , %04d ,dmt_delay=%d\n", dmt->last.u.x, dmt->last.u.y, dmt->last.u.z, atomic_read(&dmt->delay));
+
+
+ input_report_abs(dmt->input, ABS_X, dmt->last.v[l_sensorconfig.xyz_axis[0][0]]*l_sensorconfig.xyz_axis[0][1]);//dmt->last.v[0]);
+ input_report_abs(dmt->input, ABS_Y, dmt->last.v[l_sensorconfig.xyz_axis[1][0]]*l_sensorconfig.xyz_axis[1][1]);//dmt->last.v[1]);
+ input_report_abs(dmt->input, ABS_Z, dmt->last.v[l_sensorconfig.xyz_axis[2][0]]*l_sensorconfig.xyz_axis[2][1]);//dmt->last.v[2]);
+ input_sync(dmt->input);
+
+ if(dmt_delay < 1)
+ dmt_delay = 1;
+ schedule_delayed_work(&dmt->delaywork, dmt_delay);
+}
+
+static int mma10_open(struct inode *node, struct file *fle)
+{
+ GSE_LOG("open...\n");
+ return 0;
+}
+
+static int mma10_close(struct inode *node, struct file *fle)
+{
+ GSE_LOG("close...\n");
+ return 0;
+}
+
+static long mma10_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int err = 0;
+ //unsigned char data[6];
+ void __user *argp = (void __user *)arg;
+ short delay, enable;
+ unsigned int uval = 0;
+
+
+ /* cmd mapping */
+ switch(cmd)
+ {
+ case ECS_IOCTL_APP_SET_DELAY:
+ // set the rate of g-sensor
+ if (copy_from_user(&delay, argp, sizeof(short)))
+ {
+ printk(KERN_ALERT "Can't get set delay!!!\n");
+ return -EFAULT;
+ }
+ klog("Get delay=%d\n", delay);
+
+ if ((delay >=0) && (delay < 20))
+ {
+ delay = 20;
+ } else if (delay > 200)
+ {
+ delay = 200;
+ }
+ l_sensorconfig.sensor_samp = 1000/delay;
+ atomic_set(&s_dmt->delay, 1000/delay);
+ break;
+ case ECS_IOCTL_APP_SET_AFLAG:
+ // enable/disable sensor
+ if (copy_from_user(&enable, argp, sizeof(short)))
+ {
+ printk(KERN_ERR "Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ klog("enable=%d\n",enable);
+ if ((enable >=0) && (enable <=1))
+ {
+ //KMSGINF("driver: disable/enable(%d) gsensor.\n", enable);
+
+ l_sensorconfig.sensor_enable = enable;
+ atomic_set(&s_dmt->enable,enable);
+ DMT_sysfs_update_active_status(s_dmt , enable);
+
+ } else {
+ printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ uval = DMARD10_DRVID;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ GSE_LOG("dmard10_driver_id:%d\n",uval);
+ break;
+ case WMT_IOCTL_SENOR_GET_RESOLUTION:
+ uval = (10<<8) | 1;
+ if (copy_to_user((unsigned int *)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ printk("<<<<<<<resolution:0x%x\n",uval);
+ default:
+ err = -1;
+ break;
+ }
+
+ return err;
+}
+
+static const struct file_operations d10_fops = {
+ .owner = THIS_MODULE,
+ .open = mma10_open,
+ .release = mma10_close,
+ .unlocked_ioctl = mma10_ioctl,
+};
+
+
+static struct miscdevice d10_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = GSENSOR_DEV_NODE,
+ .fops = &d10_fops,
+};
+
+static int sensor_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+
+ //int inputval = -1;
+ int enable, sample = -1;
+ char tembuf[8];
+ //unsigned int amsr = 0;
+ int test = 0;
+
+ //mutex_lock(&sense_data_mutex);
+ memset(tembuf, 0, sizeof(tembuf));
+ // get sensor level and set sensor level
+ if (sscanf(buffer, "isdbg=%d\n", &l_sensorconfig.isdbg))
+ {
+ // only set the dbg flag
+ } else if (sscanf(buffer, "samp=%d\n", &sample))
+ {
+ if (sample > 0)
+ {
+ if (sample != l_sensorconfig.sensor_samp)
+ {
+ // should do sth
+ }
+ //printk(KERN_ALERT "sensor samp=%d(amsr:%d) has been set.\n", sample, amsr);
+ } else {
+ klog("Wrong sample argumnet of sensor.\n");
+ }
+ } else if (sscanf(buffer, "enable=%d\n", &enable))
+ {
+ if ((enable < 0) || (enable > 1))
+ {
+ klog("The argument to enable/disable g-sensor should be 0 or 1 !!!\n");
+ } else if (enable != l_sensorconfig.sensor_enable)
+ {
+ //mma_enable_disable(enable);
+ l_sensorconfig.sensor_enable = enable;
+ }
+ } else if (sscanf(buffer, "sensor_test=%d\n", &test))
+ { // for test begin
+ l_sensorconfig.test_pass = 0;
+ atomic_set(&s_dmt->enable,1);
+ DMT_sysfs_update_active_status(s_dmt , 1);
+ } else if (sscanf(buffer, "sensor_testend=%d\n", &test))
+ { // Don nothing only to be compatible the before testing program
+ atomic_set(&s_dmt->enable,0);
+ DMT_sysfs_update_active_status(s_dmt , 0);
+ }
+ //mutex_unlock(&sense_data_mutex);
+ return count;
+}
+
+static int sensor_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "test_pass=%d\nisdbg=%d\nrate=%d\nenable=%d\n",
+ l_sensorconfig.test_pass,
+ l_sensorconfig.isdbg,
+ l_sensorconfig.sensor_samp,
+ l_sensorconfig.sensor_enable
+ );
+ return len;
+}
+
+
+//static int __devinit device_i2c_probe(struct i2c_client *client,const struct i2c_device_id *id){
+static int __devinit dmard10_probe(struct platform_device *pdev)
+{
+ int i, k, ret = 0;
+ //struct dmt_data *s_dmt = i2c_get_clientdata(client);
+ //struct dmt_data *s_dmt;
+ GSE_FUN();
+/*
+ if(!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)){
+ GSE_ERR("check_functionality failed.\n");
+ ret = -ENODEV;
+ goto exit0;
+ }
+
+ // Allocate memory for driver data
+ s_dmt = kzalloc(sizeof(struct dmt_data), GFP_KERNEL);
+ memset(s_dmt, 0, sizeof(struct dmt_data));
+ if (s_dmt == NULL) {
+ GSE_ERR("alloc data failed.\n");
+ ret = -ENOMEM;
+ goto exit1;
+ }
+*/
+ /*for(i = 0; i < SENSOR_DATA_SIZE; ++i)
+ s_dmt->offset.v[i] = 0;*/
+#ifdef SW_FILTER
+ s_dmt->pointer = 0;
+ s_dmt->aveflag = 0;
+ for(i = 0; i < SENSOR_DATA_SIZE; ++i){
+ s_dmt->sum[i] = 0;
+ for(k = 0; k < SENSOR_DATA_AVG; ++k){
+ s_dmt->bufferave[i][k] = 0;
+ }
+ }
+ s_dmt->filter = SENSOR_DATA_AVG;
+ GSE_LOG("D10_DEFAULT_FILTER: %d\n", s_dmt->filter);
+#endif
+ /* I2C initialization */
+ //s_dmt->client = client;
+
+ /* set client data */
+ i2c_set_clientdata(s_dmt->client, s_dmt);
+ /*ret = dmard10_init(client);
+ if (ret < 0)
+ goto exit2;
+ */
+ /* input */
+ ret = D10_input_init(s_dmt->client);
+ if (ret){
+ GSE_ERR("D10_input_init fail, error code= %d\n",ret);
+ goto exit3;
+ }
+
+ /* initialize variables in dmt_data */
+ mutex_init(&s_dmt->data_mutex);
+ mutex_init(&s_dmt->enable_mutex);
+#ifdef DMT_DEBUG_DATA
+ mutex_init(&s_dmt->suspend_mutex);
+#endif
+ init_waitqueue_head(&s_dmt->open_wq);
+ atomic_set(&s_dmt->active, 0);
+ atomic_set(&s_dmt->enable, 0);
+ atomic_set(&s_dmt->delay, 0);
+ atomic_set(&s_dmt->addr, 0);
+ /* DMT Acceleration Sensor Mounting Position on Board */
+ s_dmt->position = D10_DEFAULT_POSITION;
+ GSE_LOG("D10_DEFAULT_POSITION: %d\n", s_dmt->position);
+ //s_dmt->position = (CONFIG_INPUT_DMT_ACCELEROMETER_POSITION);
+ //GSE_LOG("CONFIG_INPUT_DMT_ACCELEROMETER_POSITION: %d\n", s_dmt->position);
+ /* Misc device */
+ if (misc_register(&dmt_device) < 0){
+ GSE_ERR("dmt_dev register failed");
+ goto exit4;
+ }
+
+ /* Setup sysfs */
+ if (create_sysfs_interfaces(s_dmt) < 0){
+ GSE_ERR("create sysfs failed.");
+ goto exit5;
+ }
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ s_dmt->early_suspend.suspend = device_i2c_suspend;
+ s_dmt->early_suspend.resume = device_i2c_resume;
+ register_early_suspend(&s_dmt->early_suspend);
+#endif
+ /* Setup driver interface */
+ INIT_DELAYED_WORK(&s_dmt->delaywork, DMT_work_func);
+ GSE_LOG("DMT: INIT_DELAYED_WORK\n");
+
+ //register ctrl dev
+ ret = misc_register(&d10_device);
+ if (ret !=0) {
+ errlog("Can't register d10_device!\n");
+ return -1;
+ }
+ // register rd/wr proc
+ l_sensorconfig.sensor_proc = create_proc_entry(GSENSOR_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ l_sensorconfig.sensor_proc->write_proc = sensor_writeproc;
+ l_sensorconfig.sensor_proc->read_proc = sensor_readproc;
+ }
+
+ //create offset file after factory reset
+ D10_read_offset_from_file(s_dmt->client);
+
+ return 0;
+
+exit5:
+ misc_deregister(&dmt_device);
+exit4:
+ input_unregister_device(s_dmt->input);
+exit3:
+ kfree(s_dmt);
+/*exit2:
+exit1:
+exit0:*/
+ return ret;
+}
+/*
+static struct i2c_board_info dmard10_board_info={
+ .type = SENSOR_I2C_NAME,
+ .addr = SENSOR_I2C_ADDR,
+};
+*/
+//static struct i2c_client *client;
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static int get_axisset(void)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.dm10sensor", varbuf, &varlen)) {
+ errlog("Can't get gsensor config in u-boot!!!!\n");
+ return -1; //open it for no env just,not insmod such module 2014-6-30
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &l_sensorconfig.op,
+ &l_sensorconfig.int_gpio,
+ &l_sensorconfig.samp,
+ &(l_sensorconfig.xyz_axis[0][0]),
+ &(l_sensorconfig.xyz_axis[0][1]),
+ &(l_sensorconfig.xyz_axis[1][0]),
+ &(l_sensorconfig.xyz_axis[1][1]),
+ &(l_sensorconfig.xyz_axis[2][0]),
+ &(l_sensorconfig.xyz_axis[2][1]),
+ &(l_sensorconfig.offset[0]),
+ &(l_sensorconfig.offset[1]),
+ &(l_sensorconfig.offset[2])
+ );
+ if (n != 12) {
+ errlog("gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+ l_sensorconfig.sensor_samp = l_sensorconfig.samp;
+
+ dbg("get the sensor config: %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ l_sensorconfig.xyz_axis[0][0],
+ l_sensorconfig.xyz_axis[0][1],
+ l_sensorconfig.xyz_axis[1][0],
+ l_sensorconfig.xyz_axis[1][1],
+ l_sensorconfig.xyz_axis[2][0],
+ l_sensorconfig.xyz_axis[2][1],
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+ }
+ return 0;
+}
+
+static void dmard10_platform_release(struct device *device)
+{
+ GSE_LOG("...\n");
+ return;
+}
+
+static int __devexit dmard10_remove(struct platform_device *pdev)
+{
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ remove_proc_entry(GSENSOR_PROC_NAME, NULL);
+ l_sensorconfig.sensor_proc = NULL;
+ }
+ //misc_deregister(&d10_device);
+ return 0;
+}
+
+
+static struct platform_device dmard10_device = {
+ .name = SENSOR_I2C_NAME,
+ .id = 0,
+ .dev = {
+ .release = dmard10_platform_release,
+ },
+};
+
+static struct platform_driver dmard10_driver = {
+ .probe = dmard10_probe,
+ .remove = dmard10_remove,
+ .shutdown = dmard10_shutdown,
+ .suspend = dmard10_suspend,
+ .resume = dmard10_resume,
+ .driver = {
+ .name = SENSOR_I2C_NAME,
+ },
+};
+
+
+static int __init device_init(void){
+ //struct device *device;
+ struct i2c_client *this_client;
+ int ret = 0;
+
+ // parse g-sensor u-boot arg
+ ret = get_axisset();
+ if (ret < 0)
+ {
+ printk("<<<<<%s user choose to no sensor chip!\n", __func__);
+ return ret;
+ }
+ GSE_LOG("D10 gsensor driver: initialize.\n");
+
+ if (!(this_client = sensor_i2c_register_device(0, SENSOR_I2C_ADDR, SENSOR_I2C_NAME)))
+ {
+ printk(KERN_ERR"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+
+ if (dmard10_init(this_client))
+ {
+ GSE_ERR("Failed to init dmard10!\n");
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+ }
+
+ /* Allocate memory for driver data */
+ s_dmt = kzalloc(sizeof(struct dmt_data), GFP_KERNEL);
+ //memset(s_dmt, 0, sizeof(struct dmt_data));
+ if (s_dmt == NULL) {
+ GSE_ERR("alloc data failed.\n");
+ return -ENOMEM;
+ }
+
+ s_dmt->client = this_client;
+ s_dmt->pdevice = &dmard10_device;
+ s_dmt->offset.u.x = l_sensorconfig.offset[0];
+ s_dmt->offset.u.y = l_sensorconfig.offset[1];
+ s_dmt->offset.u.z = l_sensorconfig.offset[2];
+
+
+ // create the platform device
+ l_dev_class = class_create(THIS_MODULE, SENSOR_I2C_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create gsensor device !!\n");
+ return ret;
+ }
+ if((ret = platform_device_register(&dmard10_device)))
+ {
+ GSE_ERR("Can't register dmard10 platform devcie!!!\n");
+ return ret;
+ }
+ if ((ret = platform_driver_register(&dmard10_driver)) != 0)
+ {
+ GSE_ERR("Can't register dmard10 platform driver!!!\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __exit device_exit(void){
+ //i2c_unregister_device(client);
+ //i2c_del_driver(&device_i2c_driver);
+ GSE_LOG("D10 gsensor driver: release.\n");
+
+ flush_delayed_work_sync(&s_dmt->delaywork);
+ cancel_delayed_work_sync(&s_dmt->delaywork);
+
+ input_unregister_device(s_dmt->input);
+ input_free_device(s_dmt->input);
+ misc_deregister(&dmt_device);
+ misc_deregister(&d10_device);
+ platform_driver_unregister(&dmard10_driver);
+ platform_device_unregister(&dmard10_device);
+ sensor_i2c_unregister_device(s_dmt->client);
+ class_destroy(l_dev_class);
+
+ remove_sysfs_interfaces(s_dmt);
+ kfree(s_dmt);
+}
+
+static int dmt_get_filter(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ return dmt->filter;
+}
+
+static int dmt_set_filter(struct i2c_client *client, int filter){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ if (!((filter >= 1) && (filter <= 32)))
+ return -1;
+ dmt->filter = filter;
+ return 0;
+}
+
+static int dmt_get_position(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ return dmt->position;
+}
+
+static int dmt_set_position(struct i2c_client *client, int position){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ if (!((position >= 0) && (position <= 7)))
+ return -1;
+ dmt->position = position;
+ return 0;
+}
+
+extern int wmt_setsyspara(char *varname, char *varval);
+static void update_var(void)
+{
+ char varbuf[64];
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+
+ sprintf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ l_sensorconfig.xyz_axis[0][0],
+ l_sensorconfig.xyz_axis[0][1],
+ l_sensorconfig.xyz_axis[1][0],
+ l_sensorconfig.xyz_axis[1][1],
+ l_sensorconfig.xyz_axis[2][0],
+ l_sensorconfig.xyz_axis[2][1],
+ s_dmt->offset.u.x,
+ s_dmt->offset.u.y,
+ s_dmt->offset.u.z
+ );
+
+ wmt_setsyspara("wmt.io.dm10sensor",varbuf);
+}
+
+static int D10_write_offset_to_file(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ char r_buf[18] = {0};
+ char w_buf[18] = {0};
+ //unsigned int orgfs;
+ struct file *fp;
+ mm_segment_t fs;
+ ssize_t ret;
+ //int8_t i;
+
+ sprintf(w_buf,"%5d %5d %5d", dmt->offset.u.x, dmt->offset.u.y, dmt->offset.u.z);
+ /* Set segment descriptor associated to kernel space */
+ fp = filp_open(D10_OffsetFileName, O_RDWR | O_CREAT, 0777);
+ if(IS_ERR(fp)){
+ GSE_ERR("filp_open %s error!!.\n",D10_OffsetFileName);
+ return -1;
+ }
+ else{
+ fs = get_fs();
+ //set_fs(KERNEL_DS);
+ set_fs(get_ds());
+ GSE_LOG("filp_open %s SUCCESS!!.\n",D10_OffsetFileName);
+ //fp->f_op->write(fp,data,18, &fp->f_pos);
+ //filp_close(fp,NULL);
+ ret = fp->f_op->write(fp,w_buf,18,&fp->f_pos);
+ if(ret != 18)
+ {
+ printk(KERN_ERR "%s: write error!\n", __func__);
+ filp_close(fp,NULL);
+ return -EIO;
+ }
+ //fp->f_pos=0x00;
+ ret = fp->f_op->read(fp,r_buf, 18,&fp->f_pos);
+ if(ret < 0)
+ {
+ printk(KERN_ERR "%s: read error!\n", __func__);
+ filp_close(fp,NULL);
+ return -EIO;
+ }
+ set_fs(fs);
+
+ //
+ //printk(KERN_INFO "%s: read ret=%d!", __func__, ret);
+ /* for(i=0; i<18 ;i++)
+ {
+ if(r_buf[i] != w_buf[i])
+ {
+ printk(KERN_ERR "%s: read back error, r_buf[%x](0x%x) != w_buf[%x](0x%x)\n",
+ __func__, i, r_buf[i], i, w_buf[i]);
+ filp_close(fp,NULL);
+ return -EIO;
+ }
+ }
+ */
+
+ }
+ filp_close(fp,NULL);
+ return 0;
+}
+
+void D10_read_offset_from_file(struct i2c_client *client){
+ struct dmt_data *dmt = i2c_get_clientdata(client);
+ unsigned int orgfs;
+ char data[18];
+ struct file *fp;
+ int ux,uy,uz;
+ orgfs = get_fs();
+ /* Set segment descriptor associated to kernel space */
+ set_fs(KERNEL_DS);
+
+ fp = filp_open(D10_OffsetFileName, O_RDWR , 0);
+ GSE_FUN();
+ if(IS_ERR(fp)){
+ GSE_ERR("Sorry,file open ERROR !\n");
+ if(l_sensorconfig.op){ //first time
+ l_sensorconfig.op=0;
+#if AUTO_CALIBRATION
+ /* get acceleration average reading */
+ D10_calibrate(client);
+ update_var();
+ D10_write_offset_to_file(client);
+#endif
+#ifdef DMT_BROADCAST_APK_ENABLE
+ create_devidfile();
+ return;
+#endif
+ }
+ D10_write_offset_to_file(client);
+ }
+ else{
+ GSE_LOG("filp_open %s SUCCESS!!.\n",D10_OffsetFileName);
+ fp->f_op->read(fp,data,18, &fp->f_pos);
+ GSE_LOG("filp_read result %s\n",data);
+ sscanf(data,"%d %d %d",&ux,&uy,&uz);
+ dmt->offset.u.x=ux;
+ dmt->offset.u.y=uy;
+ dmt->offset.u.z=uz;
+ }
+ set_fs(orgfs);
+}
+static int create_devidfile(void)
+{
+ char data[18];
+ unsigned int orgfs;
+ struct file *fp;
+
+ sprintf(data,"%5d %5d %5d",0,0,0);
+ orgfs = get_fs();
+ /* Set segment descriptor associated to kernel space */
+ set_fs(KERNEL_DS);
+ GSE_FUN();
+ fp = filp_open(DmtXXFileName, O_RDWR | O_CREAT, 0777);
+ if(IS_ERR(fp)){
+ GSE_ERR("Sorry,file open ERROR !\n");
+ return -1;
+ }
+ fp->f_op->write(fp,data,18, &fp->f_pos);
+ set_fs(orgfs);
+ filp_close(fp,NULL);
+ return 0;
+}
+//*********************************************************************************************************
+MODULE_AUTHOR("DMT_RD");
+MODULE_DESCRIPTION("DMT Gsensor Driver");
+MODULE_LICENSE("GPL");
+
+module_init(device_init);
+module_exit(device_exit);
diff --git a/ANDROID_3.4.5/drivers/input/sensor/dmard10_gsensor/dmt10.h b/ANDROID_3.4.5/drivers/input/sensor/dmard10_gsensor/dmt10.h
new file mode 100755
index 00000000..f77b07e3
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/dmard10_gsensor/dmt10.h
@@ -0,0 +1,192 @@
+/* @version 1.03
+ * Copyright 2011 Domintech Technology Co., Ltd
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef DMT10_H
+#define DMT10_H
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include <linux/syscalls.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+//#include <linux/earlysuspend.h>
+#define AUTO_CALIBRATION 0
+#define SW_FILTER /* Enable or Disable Software filter */
+#define SENSOR_DATA_AVG 8 /* AVG sensor data */
+
+//#define DMT_DEBUG_DATA
+#define GSE_TAG "[DMT_Gsensor]"
+#ifdef DMT_DEBUG_DATA
+#define GSE_ERR(fmt, args...) printk(KERN_ERR GSE_TAG"%s %d : "fmt, __FUNCTION__, __LINE__, ##args)
+#define GSE_LOG(fmt, args...) printk(KERN_INFO GSE_TAG fmt, ##args)
+#define GSE_FUN(f) printk(KERN_INFO GSE_TAG" %s: %s: %i\n", __FILE__, __func__, __LINE__)
+#define DMT_DATA(dev, ...) dev_dbg((dev), ##__VA_ARGS__)
+#else
+#define GSE_ERR(fmt, args...)
+#define GSE_LOG(fmt, args...)
+#define GSE_FUN(f)
+#define DMT_DATA(dev, format, ...)
+#endif
+
+#define GSENSOR_ID "DMARD10"
+#define INPUT_NAME_ACC "g-sensor"//"DMT_accel"//"g-sensor"// /* Input Device Name */
+#define SENSOR_I2C_NAME "dmard10"//"dmt"// /* Device name for DMARD10 misc. device */
+#define SENSOR_I2C_ADDR 0x18
+#define REG_ACTR 0x00
+#define REG_WDAL 0x01
+#define REG_TAPNS 0x0f
+#define REG_MISC2 0x1f
+#define REG_AFEM 0x0c
+#define REG_CKSEL 0x0d
+#define REG_INTC 0x0e
+#define REG_STADR 0x12
+#define REG_STAINT 0x1C
+#define REG_PD 0x21
+#define REG_TCGYZ 0x26
+#define REG_X_OUT 0x41
+
+#define MODE_Off 0x00
+#define MODE_ResetAtOff 0x01
+#define MODE_Standby 0x02
+#define MODE_ResetAtStandby 0x03
+#define MODE_Active 0x06
+#define MODE_Trigger 0x0a
+#define MODE_ReadOTP 0x12
+#define MODE_WriteOTP 0x22
+#define MODE_WriteOTPBuf 0x42
+#define MODE_ResetDataPath 0x82
+
+#define VALUE_STADR 0x55
+#define VALUE_STAINT 0xAA
+#define VALUE_AFEM_AFEN_Normal 0x8f// AFEN set 1 , ATM[2:0]=b'000(normal),EN_Z/Y/X/T=1
+#define VALUE_AFEM_Normal 0x0f// AFEN set 0 , ATM[2:0]=b'000(normal),EN_Z/Y/X/T=1
+#define VALUE_INTC 0x00// INTC[6:5]=b'00
+#define VALUE_INTC_Interrupt_En 0x20// INTC[6:5]=b'01 (Data ready interrupt enable, active high at INT0)
+#define VALUE_CKSEL_ODR_0_204 0x04// ODR[3:0]=b'0000 (0.78125Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_1_204 0x14// ODR[3:0]=b'0001 (1.5625Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_3_204 0x24// ODR[3:0]=b'0010 (3.125Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_6_204 0x34// ODR[3:0]=b'0011 (6.25Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_12_204 0x44// ODR[3:0]=b'0100 (12.5Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_25_204 0x54// ODR[3:0]=b'0101 (25Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_50_204 0x64// ODR[3:0]=b'0110 (50Hz), CCK[3:0]=b'0100 (204.8kHZ)
+#define VALUE_CKSEL_ODR_100_204 0x74// ODR[3:0]=b'0111 (100Hz), CCK[3:0]=b'0100 (204.8kHZ)
+
+#define VALUE_TAPNS_NoFilter 0x00 // TAP1/TAP2 NO FILTER
+#define VALUE_TAPNS_Ave_2 0x11 // TAP1/TAP2 Average 2
+#define VALUE_TAPNS_Ave_4 0x22 // TAP1/TAP2 Average 4
+#define VALUE_TAPNS_Ave_8 0x33 // TAP1/TAP2 Average 8
+#define VALUE_TAPNS_Ave_16 0x44 // TAP1/TAP2 Average 16
+#define VALUE_TAPNS_Ave_32 0x55 // TAP1/TAP2 Average 32
+#define VALUE_MISC2_OSCA_EN 0x08
+#define VALUE_PD_RST 0x52
+
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_NEGATIVE 1
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Z_POSITIVE 2
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Y_NEGATIVE 3
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_Y_POSITIVE 4
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_X_NEGATIVE 5
+#define CONFIG_GSEN_CALIBRATION_GRAVITY_ON_X_POSITIVE 6
+
+#define AVG_NUM 16
+#define SENSOR_DATA_SIZE 3
+#define DEFAULT_SENSITIVITY 1024
+
+#define IOCTL_MAGIC 0x09
+#define SENSOR_RESET _IO(IOCTL_MAGIC, 0)
+#define SENSOR_CALIBRATION _IOWR(IOCTL_MAGIC, 1, int[SENSOR_DATA_SIZE])
+#define SENSOR_GET_OFFSET _IOR(IOCTL_MAGIC, 2, int[SENSOR_DATA_SIZE])
+#define SENSOR_SET_OFFSET _IOWR(IOCTL_MAGIC, 3, int[SENSOR_DATA_SIZE])
+#define SENSOR_READ_ACCEL_XYZ _IOR(IOCTL_MAGIC, 4, int[SENSOR_DATA_SIZE])
+#define SENSOR_SETYPR _IOW(IOCTL_MAGIC, 5, int[SENSOR_DATA_SIZE])
+#define SENSOR_GET_OPEN_STATUS _IO(IOCTL_MAGIC, 6)
+#define SENSOR_GET_CLOSE_STATUS _IO(IOCTL_MAGIC, 7)
+#define SENSOR_GET_DELAY _IOR(IOCTL_MAGIC, 8, unsigned int*)
+#define SENSOR_MAXNR 8
+/* Default sensorlayout parameters */
+#define D10_DEFAULT_POSITION 6
+
+/* Transformation matrix for chip mounting position */
+static const int dmt_position_map[][3][3] = {
+ { { 1, 0, 0}, { 0,-1, 0}, { 0, 0,-1}, }, /* top/upper-left */
+ { { 0, 1, 0}, { 1, 0, 0}, { 0, 0,-1}, }, /* top/lower-left */
+ { {-1, 0, 0}, { 0, 1, 0}, { 0, 0,-1}, }, /* top/lower-right */
+ { { 0,-1, 0}, {-1, 0, 0}, { 0, 0,-1}, }, /* top/upper-right */
+ { {-1, 0, 0}, { 0,-1, 0}, { 0, 0, 1}, }, /* bottom/upper-right*/
+ { { 0,-1, 0}, {-1, 0, 0}, { 0, 0, 1}, }, /* bottom/upper-left */
+ { { 1, 0, 0}, { 0, 1, 0}, { 0, 0, 1}, }, /* bottom/lower-right*/
+ { { 0, 1,0}, { 1, 0, 0}, { 0, 0, 1}, }, /* bottom/lower-left */
+};
+
+typedef union {
+ struct {
+ int x;
+ int y;
+ int z;
+ } u;
+ int v[SENSOR_DATA_SIZE];
+} raw_data;
+
+struct dmt_data {
+ struct platform_device *pdevice;
+ struct device *class_dev;
+ struct class *class;
+ struct input_dev *input;
+ struct i2c_client *client;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ struct delayed_work delaywork;
+ struct work_struct work;
+ struct mutex data_mutex;
+ struct mutex enable_mutex; /* for suspend */
+ raw_data last; /* RawData */
+ raw_data offset; /* Offset */
+#ifdef SW_FILTER
+ int sum[SENSOR_DATA_SIZE]; /* SW_FILTER sum */
+ int bufferave[3][32];
+ s8 aveflag; /* FULL bufferave[][] */
+ s8 pointer; /* last update data */
+#endif
+ wait_queue_head_t open_wq;
+ atomic_t active;
+ atomic_t delay;
+ atomic_t enable;
+ int filter;
+ int position; /* must int type ,for Kconfig setup */
+ atomic_t addr;
+#ifdef DMT_DEBUG_DATA
+ struct mutex suspend_mutex;
+ int suspend;
+#endif
+};
+
+#define ACC_DATA_FLAG 0
+#define MAG_DATA_FLAG 1
+#define ORI_DATA_FLAG 2
+#define DMT_NUM_SENSORS 3
+
+/* ABS axes parameter range [um/s^2] (for input event) */
+#define GRAVITY_EARTH 9806550
+#define ABSMAX (GRAVITY_EARTH * 2)
+#define ABSMIN (-GRAVITY_EARTH * 2)
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/sensor/isl29023_lsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/isl29023_lsensor/Makefile
new file mode 100755
index 00000000..ac959091
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/isl29023_lsensor/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_lsensor_isl29023
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := isl29023.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/isl29023_lsensor/isl29023.c b/ANDROID_3.4.5/drivers/input/sensor/isl29023_lsensor/isl29023.c
new file mode 100755
index 00000000..3366e92a
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/isl29023_lsensor/isl29023.c
@@ -0,0 +1,1164 @@
+/*
+ * isl29023.c - Intersil ISL29023 ALS & Proximity Driver
+ *
+ * By Intersil Corp
+ * Michael DiGioia
+ *
+ * Based on isl29011.c
+ * by Mike DiGioia <mdigioia@intersil.com>
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/hwmon.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/pm_runtime.h>
+#include <linux/input-polldev.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+//#include <linux/earlysuspend.h>
+#include <linux/platform_device.h>
+#include "../sensor.h"
+
+/* Insmod parameters */
+//I2C_CLIENT_INSMOD_1(isl29023);
+
+#define MODULE_NAME "isl29023"
+
+#define SENSOR_I2C_NAME "isl29023"
+#define SENSOR_I2C_ADDR 0x44
+
+#undef dbg
+#define dbg(fmt, args...)
+
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk(KERN_ERR "[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+/* ICS932S401 registers */
+#define ISL29023_REG_VENDOR_REV 0x06
+#define ISL29023_VENDOR 1
+#define ISL29023_VENDOR_MASK 0x0F
+#define ISL29023_REV 4
+#define ISL29023_REV_SHIFT 4
+#define ISL29023_REG_DEVICE 0x44
+#define ISL29023_DEVICE 44
+
+
+#define REG_CMD_1 0x00
+#define REG_CMD_2 0x01
+#define REG_DATA_LSB 0x02
+#define REG_DATA_MSB 0x03
+#define ISL_MOD_MASK 0xE0
+#define ISL_MOD_POWERDOWN 0
+#define ISL_MOD_ALS_ONCE 1
+#define ISL_MOD_IR_ONCE 2
+#define ISL_MOD_RESERVED 4
+#define ISL_MOD_ALS_CONT 5
+#define ISL_MOD_IR_CONT 6
+#define IR_CURRENT_MASK 0xC0
+#define IR_FREQ_MASK 0x30
+#define SENSOR_RANGE_MASK 0x03
+#define ISL_RES_MASK 0x0C
+
+static int last_mod;
+
+static struct i2c_client *this_client = NULL;
+struct isl_device {
+ struct input_polled_dev* input_poll_dev;
+ struct i2c_client* client;
+ int resolution;
+ int range;
+ int isdbg;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend earlysuspend;
+#endif
+
+};
+
+static struct isl_device* l_sensorconfig = NULL;
+static struct kobject *android_lsensor_kobj = NULL;
+static int l_enable = 1; // 0:don't report data
+
+static DEFINE_MUTEX(mutex);
+
+static int isl_set_range(struct i2c_client *client, int range)
+{
+ int ret_val;
+
+ ret_val = i2c_smbus_read_byte_data(client, REG_CMD_2);
+ if (ret_val < 0)
+ return -EINVAL;
+ ret_val &= ~SENSOR_RANGE_MASK; /*reset the bit */
+ ret_val |= range;
+ ret_val = i2c_smbus_write_byte_data(client, REG_CMD_2, ret_val);
+
+ printk(KERN_INFO MODULE_NAME ": %s isl29023 set_range call, \n", __func__);
+ if (ret_val < 0)
+ return ret_val;
+ return range;
+}
+
+static int isl_set_mod(struct i2c_client *client, int mod)
+{
+ int ret, val, freq;
+
+ switch (mod) {
+ case ISL_MOD_POWERDOWN:
+ case ISL_MOD_RESERVED:
+ goto setmod;
+ case ISL_MOD_ALS_ONCE:
+ case ISL_MOD_ALS_CONT:
+ freq = 0;
+ break;
+ case ISL_MOD_IR_ONCE:
+ case ISL_MOD_IR_CONT:
+ freq = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* set IR frequency */
+ val = i2c_smbus_read_byte_data(client, REG_CMD_2);
+ if (val < 0)
+ return -EINVAL;
+ val &= ~IR_FREQ_MASK;
+ if (freq)
+ val |= IR_FREQ_MASK;
+ ret = i2c_smbus_write_byte_data(client, REG_CMD_2, val);
+ if (ret < 0)
+ return -EINVAL;
+
+setmod:
+ /* set operation mod */
+ val = i2c_smbus_read_byte_data(client, REG_CMD_1);
+ if (val < 0)
+ return -EINVAL;
+ val &= ~ISL_MOD_MASK;
+ val |= (mod << 5);
+ ret = i2c_smbus_write_byte_data(client, REG_CMD_1, val);
+ if (ret < 0)
+ return -EINVAL;
+
+ if (mod != ISL_MOD_POWERDOWN)
+ last_mod = mod;
+
+ return mod;
+}
+
+static int isl_get_res(struct i2c_client *client)
+{
+ int val;
+
+ printk(KERN_INFO MODULE_NAME ": %s isl29023 get_res call, \n", __func__);
+ val = i2c_smbus_read_word_data(client, 0)>>8 & 0xff;
+
+ if (val < 0)
+ return -EINVAL;
+
+ val &= ISL_RES_MASK;
+ val >>= 2;
+
+ switch (val) {
+ case 0:
+ return 65536;
+ case 1:
+ return 4096;
+ case 2:
+ return 256;
+ case 3:
+ return 16;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int isl_get_mod(struct i2c_client *client)
+{
+ int val;
+
+ val = i2c_smbus_read_byte_data(client, REG_CMD_1);
+ if (val < 0)
+ return -EINVAL;
+ return val >> 5;
+}
+
+static int isl_get_range(struct i2c_client* client)
+{
+ switch (i2c_smbus_read_word_data(client, 0)>>8 & 0xff & 0x3) {
+ case 0: return 1000;
+ case 1: return 4000;
+ case 2: return 16000;
+ case 3: return 64000;
+ default: return -EINVAL;
+ }
+}
+
+static ssize_t
+isl_sensing_range_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int val;
+
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+ val = i2c_smbus_read_byte_data(client, REG_CMD_2);
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+
+ dev_dbg(dev, "%s: range: 0x%.2x\n", __func__, val);
+
+ if (val < 0)
+ return val;
+ return sprintf(buf, "%d000\n", 1 << (2 * (val & 3)));
+}
+
+static ssize_t
+ir_current_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int val;
+
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+ val = i2c_smbus_read_byte_data(client, REG_CMD_2);
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+
+ dev_dbg(dev, "%s: IR current: 0x%.2x\n", __func__, val);
+
+ if (val < 0)
+ return -EINVAL;
+ val >>= 6;
+
+ switch (val) {
+ case 0:
+ val = 100;
+ break;
+ case 1:
+ val = 50;
+ break;
+ case 2:
+ val = 25;
+ break;
+ case 3:
+ val = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (val)
+ val = sprintf(buf, "%d\n", val);
+ else
+ val = sprintf(buf, "%s\n", "12.5");
+ return val;
+}
+
+static ssize_t
+isl_sensing_mod_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+// struct i2c_client *client = to_i2c_client(dev);
+
+ dev_dbg(dev, "%s: mod: 0x%.2x\n", __func__, last_mod);
+
+ switch (last_mod) {
+ case ISL_MOD_POWERDOWN:
+ return sprintf(buf, "%s\n", "0-Power-down");
+ case ISL_MOD_ALS_ONCE:
+ return sprintf(buf, "%s\n", "1-ALS once");
+ case ISL_MOD_IR_ONCE:
+ return sprintf(buf, "%s\n", "2-IR once");
+ case ISL_MOD_RESERVED:
+ return sprintf(buf, "%s\n", "4-Reserved");
+ case ISL_MOD_ALS_CONT:
+ return sprintf(buf, "%s\n", "5-ALS continuous");
+ case ISL_MOD_IR_CONT:
+ return sprintf(buf, "%s\n", "6-IR continuous");
+ default:
+ return -EINVAL;
+ }
+}
+
+static ssize_t
+isl_output_data_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int ret_val, mod;
+ unsigned long int output = 0;
+ int temp;
+
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+
+ temp = i2c_smbus_read_byte_data(client, REG_DATA_MSB);
+ if (temp < 0)
+ goto err_exit;
+ ret_val = i2c_smbus_read_byte_data(client, REG_DATA_LSB);
+ if (ret_val < 0)
+ goto err_exit;
+ ret_val |= temp << 8;
+
+ dev_dbg(dev, "%s: Data: %04x\n", __func__, ret_val);
+
+ mod = isl_get_mod(client);
+ switch (last_mod) {
+ case ISL_MOD_ALS_CONT:
+ case ISL_MOD_ALS_ONCE:
+ case ISL_MOD_IR_ONCE:
+ case ISL_MOD_IR_CONT:
+ output = ret_val;
+ break;
+ default:
+ goto err_exit;
+ }
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ return sprintf(buf, "%ld\n", output);
+
+err_exit:
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ return -EINVAL;
+}
+
+static int isl_get_lux_data(struct i2c_client* client)
+{
+ struct isl_device* idev = i2c_get_clientdata(client);
+
+ __u16 resH, resL;
+ //int range;
+ resL = i2c_smbus_read_word_data(client, 1)>>8;
+ resH = i2c_smbus_read_word_data(client, 2)&0xff00;
+ if ((resL < 0) || (resH < 0))
+ {
+ errlog("Error to read lux_data!\n");
+ return -1;
+ }
+ return (resH | resL) * idev->range / idev->resolution;
+}
+static ssize_t
+isl_lux_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ __u16 resH, resL;// L1, L2, H1, H2, thresL, thresH;
+ char cmd2;
+ int res, data, tmp, range, resolution;
+
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+
+// cmd2 = i2c_smbus_read_word_data(client, 0)>>8 & 0xff; // 01h
+ resL = i2c_smbus_read_word_data(client, 1)>>8; // 02h
+ resH = i2c_smbus_read_word_data(client, 2)&0xff00; // 03h
+// L1 = i2c_smbus_read_word_data(client, 3)>>8; // 04h
+// L2 = i2c_smbus_read_word_data(client, 4)&0xff00; // 05h
+// H1 = i2c_smbus_read_word_data(client, 5)>>8; // 06h
+// H2 = i2c_smbus_read_word_data(client, 6)&0xff00; // 07h
+
+ res = resH | resL;
+// thresL = L2 | L1;
+// thresH = H2 | H1;
+
+ cmd2 = i2c_smbus_read_word_data(client, 0)>>8 & 0xff;
+ resolution = isl_get_res(client); //resolution
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ tmp = cmd2 & 0x3; //range
+ switch (tmp) {
+ case 0:
+ range = 1000;
+ break;
+ case 1:
+ range = 4000;
+ break;
+ case 2:
+ range = 16000;
+ break;
+ case 3:
+ range = 64000;
+ break;
+ default:
+ return -EINVAL;
+ }
+ data = res * range / resolution;
+
+// printk("Data = 0x%04x [%d]\n", data, data);
+// printk("CMD2 = 0x%x\n", cmd2);
+// printk("Threshold Low = 0x%04x\n", thresL);
+// printk("Threshold High = 0x%04x\n", thresH);
+
+ return sprintf(buf, "%u\n", data);
+}
+
+static ssize_t
+isl_cmd2_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long cmd2;
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+ cmd2 = i2c_smbus_read_word_data(client, 0)>>8 & 0xff;
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ dbg(" cmd2: 0x%02x\n", cmd2);
+ switch (cmd2) {
+ case 0:
+ return sprintf(buf, "%s\n", "[cmd2 = 0] n = 16, range = 1000");
+ case 1:
+ return sprintf(buf, "%s\n", "[cmd2 = 1] n = 16, range = 4000");
+ case 2:
+ return sprintf(buf, "%s\n", "[cmd2 = 2] n = 16, range = 16000");
+ case 3:
+ return sprintf(buf, "%s\n", "[cmd2 = 3] n = 16, range = 64000");
+
+ case 4:
+ return sprintf(buf, "%s\n", "[cmd2 = 4] n = 12, range = 1000");
+ case 5:
+ return sprintf(buf, "%s\n", "[cmd2 = 5] n = 12, range = 4000");
+ case 6:
+ return sprintf(buf, "%s\n", "[cmd2 = 6] n = 12, range = 16000");
+ case 7:
+ return sprintf(buf, "%s\n", "[cmd2 = 7] n = 12, range = 64000");
+
+ case 8:
+ return sprintf(buf, "%s\n", "[cmd2 = 8] n = 8, range = 1000");
+ case 9:
+ return sprintf(buf, "%s\n", "[cmd2 = 9] n = 8, range = 4000");
+ case 10:
+ return sprintf(buf, "%s\n", "[cmd2 = 10] n = 8, range = 16000");
+ case 11:
+ return sprintf(buf, "%s\n", "[cmd2 = 11] n = 8, range = 64000");
+
+ case 12:
+ return sprintf(buf, "%s\n", "[cmd2 = 12] n = 4, range = 1000");
+ case 13:
+ return sprintf(buf, "%s\n", "[cmd2 = 13] n = 4, range = 4000");
+ case 14:
+ return sprintf(buf, "%s\n", "[cmd2 = 14] n = 4, range = 16000");
+ case 15:
+ return sprintf(buf, "%s\n", "[cmd2 = 15] n = 4, range = 64000");
+
+ default:
+ return -EINVAL;
+ }
+}
+
+
+static ssize_t
+isl_sensing_range_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned int ret_val;
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+
+ switch (val) {
+ case 1000:
+ val = 0;
+ break;
+ case 4000:
+ val = 1;
+ break;
+ case 16000:
+ val = 2;
+ break;
+ case 64000:
+ val = 3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+ ret_val = isl_set_range(client, val);
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+
+ if (ret_val < 0)
+ return ret_val;
+ return count;
+}
+
+static ssize_t
+ir_current_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned int ret_val;
+ unsigned long val;
+
+ if (!strncmp(buf, "12.5", 4))
+ val = 3;
+ else {
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+ switch (val) {
+ case 100:
+ val = 0;
+ break;
+ case 50:
+ val = 1;
+ break;
+ case 25:
+ val = 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+
+ ret_val = i2c_smbus_read_byte_data(client, REG_CMD_2);
+ if (ret_val < 0)
+ goto err_exit;
+
+ ret_val &= ~IR_CURRENT_MASK; /*reset the bit before setting them */
+ ret_val |= (val << 6);
+
+ ret_val = i2c_smbus_write_byte_data(client, REG_CMD_2, ret_val);
+ if (ret_val < 0)
+ goto err_exit;
+
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+
+ return count;
+
+err_exit:
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ return -EINVAL;
+}
+
+static ssize_t
+isl_sensing_mod_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int ret_val;
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+ if (val > 7)
+ return -EINVAL;
+
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+ ret_val = isl_set_mod(client, val);
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+
+ if (ret_val < 0)
+ return ret_val;
+ return count;
+}
+
+static ssize_t
+isl_cmd2_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct isl_device* idev = i2c_get_clientdata(client);
+ int res;
+ unsigned long val;
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+ if (val > 15 || val < 0)
+ return -EINVAL;
+
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+ res = i2c_smbus_write_byte_data(client, REG_CMD_2, val);
+ if (res < 0)
+ printk("Warning - write failed\n");
+
+ idev->resolution = isl_get_res(client);
+ idev->range = isl_get_range(client);
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+
+ return count;
+}
+
+static DEVICE_ATTR(range, S_IRUGO | S_IWUSR,
+ isl_sensing_range_show, isl_sensing_range_store);
+static DEVICE_ATTR(mod, S_IRUGO | S_IWUSR,
+ isl_sensing_mod_show, isl_sensing_mod_store);
+static DEVICE_ATTR(ir_current, S_IRUGO | S_IWUSR,
+ ir_current_show, ir_current_store);
+static DEVICE_ATTR(output, S_IRUGO, isl_output_data_show, NULL);
+static DEVICE_ATTR(cmd2, S_IRUGO | S_IWUSR,
+ isl_cmd2_show, isl_cmd2_store);
+static DEVICE_ATTR(lux, S_IRUGO,
+ isl_lux_show, NULL);
+
+static struct attribute *mid_att_isl[] = {
+ &dev_attr_range.attr,
+ &dev_attr_mod.attr,
+ &dev_attr_ir_current.attr,
+ &dev_attr_output.attr,
+ &dev_attr_lux.attr,
+ &dev_attr_cmd2.attr,
+ NULL
+};
+
+static struct attribute_group m_isl_gr = {
+ .name = "isl29023",
+ .attrs = mid_att_isl
+};
+
+static int isl_set_default_config(struct i2c_client *client)
+{
+ struct isl_device* idev = i2c_get_clientdata(client);
+
+ int ret=0;
+/* We don't know what it does ... */
+// ret = i2c_smbus_write_byte_data(client, REG_CMD_1, 0xE0);
+// ret = i2c_smbus_write_byte_data(client, REG_CMD_2, 0xC3);
+/* Set default to ALS continuous */
+ ret = i2c_smbus_write_byte_data(client, REG_CMD_1, 0xA0);
+ if (ret < 0)
+ return -EINVAL;
+/* Range: 0~16000, number of clock cycles: 65536 */
+ ret = i2c_smbus_write_byte_data(client, REG_CMD_2, 0x02); // vivienne
+ if (ret < 0)
+ return -EINVAL;
+ idev->resolution = isl_get_res(client);
+ idev->range = isl_get_range(client);;
+ dbg("isl29023 set_default_config call, \n");
+
+ return 0;
+}
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int isl29023_detect(struct i2c_client *client/*, int kind,
+ struct i2c_board_info *info*/)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ int vendor, device, revision;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+ //printk(KERN_INFO MODULE_NAME ": %s isl29023 detact call, kind:%d type:%s addr:%x \n", __func__, kind, info->type, info->addr);
+
+ /* if (kind <= 0)*/ {
+
+
+ vendor = i2c_smbus_read_word_data(client,
+ ISL29023_REG_VENDOR_REV);
+ dbg("read vendor=%d(0x%x)\n", vendor,vendor);
+ if (0x0FFFF == vendor)
+ {
+ dbg("find isl29023!\n");
+ return 0;
+ } else {
+ return -ENODEV;
+ }
+ vendor >>= 8;
+ revision = vendor >> ISL29023_REV_SHIFT;
+ vendor &= ISL29023_VENDOR_MASK;
+ if (vendor != ISL29023_VENDOR)
+ {
+ dbg("real_vendor=0x%x,tvendor=0x%x\n",vendor,ISL29023_VENDOR);
+ return -ENODEV;
+ }
+
+ device = i2c_smbus_read_word_data(client,
+ ISL29023_REG_DEVICE);
+ dbg("device=%x\n", device);
+ device >>= 8;
+ if (device != ISL29023_DEVICE)
+ {
+ dbg("real_device=0x%x, tdevice=0x%x\n", device, ISL29023_DEVICE);
+ return -ENODEV;
+ }
+
+ if (revision != ISL29023_REV)
+ {
+ dbg("Unknown revision %d\n",
+ revision);
+ }
+ } /*else
+ dev_dbg(&adapter->dev, "detection forced\n");*/
+
+ // strlcpy(info->type, "isl29023", I2C_NAME_SIZE);
+
+ return 0;
+}
+
+int isl_input_open(struct input_dev* input)
+{
+ return 0;
+}
+
+void isl_input_close(struct input_dev* input)
+{
+}
+
+static void isl_input_lux_poll(struct input_polled_dev *dev)
+{
+ struct isl_device* idev = dev->private;
+ struct input_dev* input = idev->input_poll_dev->input;
+ struct i2c_client* client = idev->client;
+
+ if (l_enable != 0)
+ {
+ mutex_lock(&mutex);
+ //pm_runtime_get_sync(dev);
+ input_report_abs(input, ABS_MISC, isl_get_lux_data(client));
+ input_sync(input);
+ //pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ }
+}
+
+static struct i2c_device_id isl29023_id[] = {
+ {"isl29023", 0},
+ {}
+};
+
+static int isl29023_runtime_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ dev_dbg(dev, "suspend\n");
+
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+ isl_set_mod(client, ISL_MOD_POWERDOWN);
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+
+ printk(KERN_INFO MODULE_NAME ": %s isl29023 suspend call, \n", __func__);
+ return 0;
+}
+
+static int isl29023_runtime_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ dev_dbg(dev, "resume\n");
+
+ mutex_lock(&mutex);
+ pm_runtime_get_sync(dev);
+ isl_set_mod(client, last_mod);
+ pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+
+ printk(KERN_INFO MODULE_NAME ": %s isl29023 resume call, \n", __func__);
+ return 0;
+}
+
+MODULE_DEVICE_TABLE(i2c, isl29023_id);
+
+/*static const struct dev_pm_ops isl29023_pm_ops = {
+ .runtime_suspend = isl29023_runtime_suspend,
+ .runtime_resume = isl29023_runtime_resume,
+};
+
+static struct i2c_board_info isl_info = {
+ I2C_BOARD_INFO("isl29023", 0x44),
+};
+
+static struct i2c_driver isl29023_driver = {
+ .driver = {
+ .name = "isl29023",
+ .pm = &isl29023_pm_ops,
+ },
+ .probe = isl29023_probe,
+ .remove = isl29023_remove,
+ .id_table = isl29023_id,
+ .detect = isl29023_detect,
+ //.address_data = &addr_data,
+};*/
+
+static int mmad_open(struct inode *inode, struct file *file)
+{
+ dbg("Open the l-sensor node...\n");
+ return 0;
+}
+
+static int mmad_release(struct inode *inode, struct file *file)
+{
+ dbg("Close the l-sensor node...\n");
+ return 0;
+}
+
+static ssize_t mmad_read(struct file *fl, char __user *buf, size_t cnt, loff_t *lf)
+{
+ int lux_data = 0;
+
+ mutex_lock(&mutex);
+ lux_data = isl_get_lux_data(l_sensorconfig->client);
+ mutex_unlock(&mutex);
+ if (lux_data < 0)
+ {
+ errlog("Failed to read lux data!\n");
+ return -1;
+ }
+ copy_to_user(buf, &lux_data, sizeof(lux_data));
+ return sizeof(lux_data);
+}
+
+static long
+mmad_ioctl(/*struct inode *inode,*/ struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ //char rwbuf[5];
+ short enable; //amsr = -1;
+ unsigned int uval;
+
+ dbg("l-sensor ioctr...\n");
+ //memset(rwbuf, 0, sizeof(rwbuf));
+ switch (cmd) {
+ case LIGHT_IOCTL_SET_ENABLE:
+ // enable/disable sensor
+ if (copy_from_user(&enable, argp, sizeof(short)))
+ {
+ printk(KERN_ERR "Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ dbg("enable=%d\n",enable);
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor.\n", enable);
+
+ //l_sensorconfig.sensor_enable = enable;
+ dbg("Should to implement d/e the light sensor!\n");
+ l_enable = enable;
+
+ } else {
+ printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ uval = ISL29023_DRVID;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("Isl29023_driver_id:%d\n",uval);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+static struct file_operations mmad_fops = {
+ .owner = THIS_MODULE,
+ .open = mmad_open,
+ .release = mmad_release,
+ .read = mmad_read,
+ .unlocked_ioctl = mmad_ioctl,
+};
+
+
+static struct miscdevice mmad_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "lsensor_ctrl",
+ .fops = &mmad_fops,
+};
+
+static void isl29023_early_suspend(struct early_suspend *h)
+{
+ struct i2c_client *client = l_sensorconfig->client;
+
+ dbg("start\n");
+ mutex_lock(&mutex);
+ //pm_runtime_get_sync(dev);
+ isl_set_mod(client, ISL_MOD_POWERDOWN);
+ //pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ dbg("exit\n");
+}
+
+static void isl29023_late_resume(struct early_suspend *h)
+{
+ struct i2c_client *client = l_sensorconfig->client;
+
+ dbg("start\n");
+ mutex_lock(&mutex);
+ //pm_runtime_get_sync(dev);
+ isl_set_mod(client, last_mod);
+ isl_set_default_config(client);
+ //pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ dbg("exit\n");
+}
+
+
+static int
+isl29023_probe(struct i2c_client *client/*, const struct i2c_device_id *id*/)
+{
+ int res=0;
+
+ struct isl_device* idev = kzalloc(sizeof(struct isl_device), GFP_KERNEL);
+ if(!idev)
+ return -ENOMEM;
+
+ l_sensorconfig = idev;
+ android_lsensor_kobj = kobject_create_and_add("android_lsensor", NULL);
+ if (android_lsensor_kobj == NULL) {
+ errlog(
+ "lsensor_sysfs_init:"\
+ "subsystem_register failed\n");
+ res = -ENOMEM;
+ goto err_kobjetc_create;
+ }
+ res = sysfs_create_group(android_lsensor_kobj, &m_isl_gr);
+ if (res) {
+ //pr_warn("isl29023: device create file failed!!\n");
+ printk(KERN_INFO MODULE_NAME ": %s isl29023 device create file failed\n", __func__);
+ res = -EINVAL;
+ goto err_sysfs_create;
+ }
+
+/* last mod is ALS continuous */
+ last_mod = 5;
+ //pm_runtime_enable(&client->dev);
+ idev->input_poll_dev = input_allocate_polled_device();
+ if(!idev->input_poll_dev)
+ {
+ res = -ENOMEM;
+ goto err_input_allocate_device;
+ }
+ idev->client = client;
+ idev->input_poll_dev->private = idev;
+ idev->input_poll_dev->poll = isl_input_lux_poll;
+ idev->input_poll_dev->poll_interval = 100;//50;
+ idev->input_poll_dev->input->open = isl_input_open;
+ idev->input_poll_dev->input->close = isl_input_close;
+ idev->input_poll_dev->input->name = "lsensor_lux";
+ idev->input_poll_dev->input->id.bustype = BUS_I2C;
+ idev->input_poll_dev->input->dev.parent = &client->dev;
+ input_set_drvdata(idev->input_poll_dev->input, idev);
+ input_set_capability(idev->input_poll_dev->input, EV_ABS, ABS_MISC);
+ input_set_abs_params(idev->input_poll_dev->input, ABS_MISC, 0, 16000, 0, 0);
+ i2c_set_clientdata(client, idev);
+ /* set default config after set_clientdata */
+ res = isl_set_default_config(client);
+ res = misc_register(&mmad_device);
+ if (res) {
+ errlog("mmad_device register failed\n");
+ goto err_misc_register;
+ }
+ res = input_register_polled_device(idev->input_poll_dev);
+ if(res < 0)
+ goto err_input_register_device;
+ // suspend/resume register
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ idev->earlysuspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ idev->earlysuspend.suspend = isl29023_early_suspend;
+ idev->earlysuspend.resume = isl29023_late_resume;
+ register_early_suspend(&(idev->earlysuspend));
+#endif
+
+ dbg("isl29023 probe succeed!\n");
+ return 0;
+err_input_register_device:
+ misc_deregister(&mmad_device);
+ input_free_polled_device(idev->input_poll_dev);
+err_misc_register:
+err_input_allocate_device:
+ //__pm_runtime_disable(&client->dev, false);
+err_sysfs_create:
+ kobject_del(android_lsensor_kobj);
+err_kobjetc_create:
+ kfree(idev);
+ return res;
+}
+
+static int isl29023_remove(struct i2c_client *client)
+{
+ struct isl_device* idev = i2c_get_clientdata(client);
+
+ //unregister_early_suspend(&(idev->earlysuspend));
+ misc_deregister(&mmad_device);
+ input_unregister_polled_device(idev->input_poll_dev);
+ input_free_polled_device(idev->input_poll_dev);
+ sysfs_remove_group(android_lsensor_kobj, &m_isl_gr);
+ kobject_del(android_lsensor_kobj);
+ //__pm_runtime_disable(&client->dev, false);
+ kfree(idev);
+ printk(KERN_INFO MODULE_NAME ": %s isl29023 remove call, \n", __func__);
+ return 0;
+}
+
+//****************add platform_device & platform_driver for suspend &resume 2013-7-2
+static int ls_probe(struct platform_device *pdev){
+ //printk("<<<%s\n", __FUNCTION__);
+ return 0;
+}
+static int ls_remove(struct platform_device *pdev){
+ //printk("<<<%s\n", __FUNCTION__);
+ return 0;
+}
+static int ls_suspend(struct platform_device *pdev, pm_message_t state){
+ printk("<<<%s\n", __FUNCTION__);
+ struct i2c_client *client = l_sensorconfig->client;
+
+ mutex_lock(&mutex);
+
+ isl_set_mod(client, ISL_MOD_POWERDOWN);
+
+ mutex_unlock(&mutex);
+
+
+ return 0;
+}
+
+static int ls_resume(struct platform_device *pdev){
+ //return 0;
+ int ret = 0;
+ int count = 0;
+ printk("<<<%s\n", __FUNCTION__);
+ struct i2c_client *client = l_sensorconfig->client;
+
+
+
+
+RETRY:
+ mutex_lock(&mutex);
+ //pm_runtime_get_sync(dev);
+ isl_set_mod(client, last_mod);
+ ret = isl_set_default_config(client);
+ //pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ if (ret < 0){
+ printk("%s isl_set_default_config fail!\n", __FUNCTION__);
+ count++;
+ if (count < 5){
+ mdelay(2);
+ goto RETRY;
+ }
+ else
+ return ret;
+ }
+ return 0;
+
+}
+static void lsdev_release(struct device *dev)
+{
+ return;
+}
+static struct platform_device lsdev = {
+ .name = "lsdevice",
+ .id = -1,
+ .dev = {
+ .release = lsdev_release,
+ },
+};
+static struct platform_driver lsdrv = {
+ .probe = ls_probe,
+ .remove = ls_remove,
+ .suspend = ls_suspend,
+ .resume = ls_resume,
+ .driver = {
+ .name = "lsdevice",
+ },
+};
+//********************************************************************
+
+static int __init sensor_isl29023_init(void)
+{
+ printk(KERN_INFO MODULE_NAME ": %s isl29023 init call, \n", __func__);
+ /*
+ * Force device to initialize: i2c-15 0x44
+ * If i2c_new_device is not called, even isl29023_detect will not run
+ * TODO: rework to automatically initialize the device
+ */
+ //i2c_new_device(i2c_get_adapter(15), &isl_info);
+ //return i2c_add_driver(&isl29023_driver);
+ if (!(this_client = sensor_i2c_register_device(2, SENSOR_I2C_ADDR, SENSOR_I2C_NAME)))
+ {
+ printk(KERN_EMERG"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+ if (isl29023_detect(this_client))
+ {
+ errlog("Can't find light sensor isl29023!\n");
+ goto detect_fail;
+ }
+ if(isl29023_probe(this_client))
+ {
+ errlog("Erro for probe!\n");
+ goto detect_fail;
+ }
+ int ret = 0;
+ ret = platform_device_register(&lsdev);
+ if (ret){
+ printk("<<<platform_device_register fail!\n");
+ return ret;
+ }
+ ret = platform_driver_register(&lsdrv);
+ if (ret){
+ printk("<<<platform_driver_register fail!\n");
+ platform_device_unregister(&lsdev);
+ return ret;
+ }
+
+ return 0;
+
+detect_fail:
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+}
+
+static void __exit sensor_isl29023_exit(void)
+{
+ printk(KERN_INFO MODULE_NAME ": %s isl29023 exit call \n", __func__);
+ isl29023_remove(this_client);
+ sensor_i2c_unregister_device(this_client);
+ platform_driver_unregister(&lsdrv);
+ platform_device_unregister(&lsdev);
+ //i2c_del_driver(&isl29023_driver);
+}
+
+module_init(sensor_isl29023_init);
+module_exit(sensor_isl29023_exit);
+
+MODULE_AUTHOR("mdigioia");
+MODULE_ALIAS("isl29023 ALS");
+MODULE_DESCRIPTION("Intersil isl29023 ALS Driver");
+MODULE_LICENSE("GPL v2");
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/kionix_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/kionix_gsensor/Makefile
new file mode 100755
index 00000000..774b6c9c
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/kionix_gsensor/Makefile
@@ -0,0 +1,35 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_gsensor_kionix_accel
+
+$(MY_MODULE_NAME)-objs := kionix_accel.o
+obj-m := $(MY_MODULE_NAME).o
+
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/kionix_gsensor/kionix_accel.c b/ANDROID_3.4.5/drivers/input/sensor/kionix_gsensor/kionix_accel.c
new file mode 100755
index 00000000..ddb5bbcb
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/kionix_gsensor/kionix_accel.c
@@ -0,0 +1,2427 @@
+/* drivers/input/misc/kionix_accel.c - Kionix accelerometer driver
+ *
+ * Copyright (C) 2012 Kionix, Inc.
+ * Written by Kuching Tan <kuchingtan@kionix.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+//#include <linux/input/kionix_accel.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <linux/platform_device.h>
+#include "kionix_accel.h"
+#include "../sensor.h"
+
+
+
+/* Debug Message Flags */
+#define KIONIX_KMSG_ERR 1 /* Print kernel debug message for error */
+#define KIONIX_KMSG_INF 1 /* Print kernel debug message for info */
+
+#if KIONIX_KMSG_ERR
+#define KMSGERR(format, ...) \
+ dev_err(format, ## __VA_ARGS__)
+ //printk(format, ## __VA_ARGS__)
+#else
+#define KMSGERR(format, ...)
+#endif
+
+#if KIONIX_KMSG_INF
+#define KMSGINF(format, ...) \
+ dev_info(format, ## __VA_ARGS__)
+ //printk(format, ## __VA_ARGS__)
+#else
+#define KMSGINF(format, ...)
+#endif
+
+
+/******************************************************************************
+ * Accelerometer WHO_AM_I return value
+ *****************************************************************************/
+#define KIONIX_ACCEL_WHO_AM_I_KXTE9 0x00
+#define KIONIX_ACCEL_WHO_AM_I_KXTF9 0x01
+#define KIONIX_ACCEL_WHO_AM_I_KXTI9_1001 0x04
+#define KIONIX_ACCEL_WHO_AM_I_KXTIK_1004 0x05
+#define KIONIX_ACCEL_WHO_AM_I_KXTJ9_1005 0x07
+#define KIONIX_ACCEL_WHO_AM_I_KXTJ9_1007 0x08
+#define KIONIX_ACCEL_WHO_AM_I_KXCJ9_1008 0x0A
+#define KIONIX_ACCEL_WHO_AM_I_KXTJ2_1009 0x09
+#define KIONIX_ACCEL_WHO_AM_I_KXCJK_1013 0x11
+
+/******************************************************************************
+ * Accelerometer Grouping
+ *****************************************************************************/
+#define KIONIX_ACCEL_GRP1 1 /* KXTE9 */
+#define KIONIX_ACCEL_GRP2 2 /* KXTF9/I9-1001/J9-1005 */
+#define KIONIX_ACCEL_GRP3 3 /* KXTIK-1004 */
+#define KIONIX_ACCEL_GRP4 4 /* KXTJ9-1007/KXCJ9-1008 */
+#define KIONIX_ACCEL_GRP5 5 /* KXTJ2-1009 */
+#define KIONIX_ACCEL_GRP6 6 /* KXCJK-1013 */
+
+/******************************************************************************
+ * Registers for Accelerometer Group 1 & 2 & 3
+ *****************************************************************************/
+#define ACCEL_WHO_AM_I 0x0F
+
+/*****************************************************************************/
+/* Registers for Accelerometer Group 1 */
+/*****************************************************************************/
+/* Output Registers */
+#define ACCEL_GRP1_XOUT 0x12
+/* Control Registers */
+#define ACCEL_GRP1_CTRL_REG1 0x1B
+/* CTRL_REG1 */
+#define ACCEL_GRP1_PC1_OFF 0x7F
+#define ACCEL_GRP1_PC1_ON (1 << 7)
+#define ACCEL_GRP1_ODR40 (3 << 3)
+#define ACCEL_GRP1_ODR10 (2 << 3)
+#define ACCEL_GRP1_ODR3 (1 << 3)
+#define ACCEL_GRP1_ODR1 (0 << 3)
+#define ACCEL_GRP1_ODR_MASK (3 << 3)
+
+/*****************************************************************************/
+/* Registers for Accelerometer Group 2 & 3 */
+/*****************************************************************************/
+/* Output Registers */
+#define ACCEL_GRP2_XOUT_L 0x06
+/* Control Registers */
+#define ACCEL_GRP2_INT_REL 0x1A
+#define ACCEL_GRP2_CTRL_REG1 0x1B
+#define ACCEL_GRP2_INT_CTRL1 0x1E
+#define ACCEL_GRP2_DATA_CTRL 0x21
+/* CTRL_REG1 */
+#define ACCEL_GRP2_PC1_OFF 0x7F
+#define ACCEL_GRP2_PC1_ON (1 << 7)
+#define ACCEL_GRP2_DRDYE (1 << 5)
+#define ACCEL_GRP2_G_8G (2 << 3)
+#define ACCEL_GRP2_G_4G (1 << 3)
+#define ACCEL_GRP2_G_2G (0 << 3)
+#define ACCEL_GRP2_G_MASK (3 << 3)
+#define ACCEL_GRP2_RES_8BIT (0 << 6)
+#define ACCEL_GRP2_RES_12BIT (1 << 6)
+#define ACCEL_GRP2_RES_MASK (1 << 6)
+/* INT_CTRL1 */
+#define ACCEL_GRP2_IEA (1 << 4)
+#define ACCEL_GRP2_IEN (1 << 5)
+/* DATA_CTRL_REG */
+#define ACCEL_GRP2_ODR12_5 0x00
+#define ACCEL_GRP2_ODR25 0x01
+#define ACCEL_GRP2_ODR50 0x02
+#define ACCEL_GRP2_ODR100 0x03
+#define ACCEL_GRP2_ODR200 0x04
+#define ACCEL_GRP2_ODR400 0x05
+#define ACCEL_GRP2_ODR800 0x06
+/*****************************************************************************/
+
+
+/*****************************************************************************/
+/* Registers for Accelerometer Group 4 & 5 & 6 */
+/*****************************************************************************/
+/* Output Registers */
+#define ACCEL_GRP4_XOUT_L 0x06
+/* Control Registers */
+#define ACCEL_GRP4_INT_REL 0x1A
+#define ACCEL_GRP4_CTRL_REG1 0x1B
+#define ACCEL_GRP4_INT_CTRL1 0x1E
+#define ACCEL_GRP4_DATA_CTRL 0x21
+/* CTRL_REG1 */
+#define ACCEL_GRP4_PC1_OFF 0x7F
+#define ACCEL_GRP4_PC1_ON (1 << 7)
+#define ACCEL_GRP4_DRDYE (1 << 5)
+#define ACCEL_GRP4_G_8G (2 << 3)
+#define ACCEL_GRP4_G_4G (1 << 3)
+#define ACCEL_GRP4_G_2G (0 << 3)
+#define ACCEL_GRP4_G_MASK (3 << 3)
+#define ACCEL_GRP4_RES_8BIT (0 << 6)
+#define ACCEL_GRP4_RES_12BIT (1 << 6)
+#define ACCEL_GRP4_RES_MASK (1 << 6)
+/* INT_CTRL1 */
+#define ACCEL_GRP4_IEA (1 << 4)
+#define ACCEL_GRP4_IEN (1 << 5)
+/* DATA_CTRL_REG */
+#define ACCEL_GRP4_ODR0_781 0x08
+#define ACCEL_GRP4_ODR1_563 0x09
+#define ACCEL_GRP4_ODR3_125 0x0A
+#define ACCEL_GRP4_ODR6_25 0x0B
+#define ACCEL_GRP4_ODR12_5 0x00
+#define ACCEL_GRP4_ODR25 0x01
+#define ACCEL_GRP4_ODR50 0x02
+#define ACCEL_GRP4_ODR100 0x03
+#define ACCEL_GRP4_ODR200 0x04
+#define ACCEL_GRP4_ODR400 0x05
+#define ACCEL_GRP4_ODR800 0x06
+#define ACCEL_GRP4_ODR1600 0x07
+/*****************************************************************************/
+
+/* Input Event Constants */
+#define ACCEL_G_MAX 8096
+#define ACCEL_FUZZ 3
+#define ACCEL_FLAT 3
+/* I2C Retry Constants */
+#define KIONIX_I2C_RETRY_COUNT 10 /* Number of times to retry i2c */
+#define KIONIX_I2C_RETRY_TIMEOUT 1 /* Timeout between retry (miliseconds) */
+
+/* Earlysuspend Contants */
+#define KIONIX_ACCEL_EARLYSUSPEND_TIMEOUT 5000 /* Timeout (miliseconds) */
+
+/*
+ * The following table lists the maximum appropriate poll interval for each
+ * available output data rate (ODR).
+ */
+static const struct {
+ unsigned int cutoff;
+ u8 mask;
+} kionix_accel_grp1_odr_table[] = {
+ { 100, ACCEL_GRP1_ODR40 },
+ { 334, ACCEL_GRP1_ODR10 },
+ { 1000, ACCEL_GRP1_ODR3 },
+ { 0, ACCEL_GRP1_ODR1 },
+};
+
+static const struct {
+ unsigned int cutoff;
+ u8 mask;
+} kionix_accel_grp2_odr_table[] = {
+ { 3, ACCEL_GRP2_ODR800 },
+ { 5, ACCEL_GRP2_ODR400 },
+ { 10, ACCEL_GRP2_ODR200 },
+ { 20, ACCEL_GRP2_ODR100 },
+ { 40, ACCEL_GRP2_ODR50 },
+ { 80, ACCEL_GRP2_ODR25 },
+ { 0, ACCEL_GRP2_ODR12_5},
+};
+
+static const struct {
+ unsigned int cutoff;
+ u8 mask;
+} kionix_accel_grp4_odr_table[] = {
+ { 2, ACCEL_GRP4_ODR1600 },
+ { 3, ACCEL_GRP4_ODR800 },
+ { 5, ACCEL_GRP4_ODR400 },
+ { 10, ACCEL_GRP4_ODR200 },
+ { 20, ACCEL_GRP4_ODR100 },
+ { 40, ACCEL_GRP4_ODR50 },
+ { 80, ACCEL_GRP4_ODR25 },
+ { 160, ACCEL_GRP4_ODR12_5},
+ { 320, ACCEL_GRP4_ODR6_25},
+ { 640, ACCEL_GRP4_ODR3_125},
+ { 1280, ACCEL_GRP4_ODR1_563},
+ { 0, ACCEL_GRP4_ODR0_781},
+};
+
+enum {
+ accel_grp1_ctrl_reg1 = 0,
+ accel_grp1_regs_count,
+};
+
+enum {
+ accel_grp2_ctrl_reg1 = 0,
+ accel_grp2_data_ctrl,
+ accel_grp2_int_ctrl,
+ accel_grp2_regs_count,
+};
+
+enum {
+ accel_grp4_ctrl_reg1 = 0,
+ accel_grp4_data_ctrl,
+ accel_grp4_int_ctrl,
+ accel_grp4_regs_count,
+};
+
+#define GSENSOR_PROC_NAME "gsensor_config"
+#define GSENSOR_MAJOR 161
+static struct i2c_client *this_client = NULL;
+static struct platform_device *this_pdev;
+static struct kionix_accel_platform_data kionix_accel_pdata = {
+ .min_interval = 5,
+ .poll_interval = 200,
+ .accel_direction = 7,
+ .accel_irq_use_drdy = 0,
+ .accel_res = KIONIX_ACCEL_RES_12BIT,
+ .accel_g_range = KIONIX_ACCEL_G_4G,
+};
+/*
+struct kionix_config
+{
+ int op;
+ int int_gpio; //0-3
+ int xyz_axis[3][2]; // (axis,direction)
+ int rxyz_axis[3][2];
+ int irq;
+ struct proc_dir_entry* sensor_proc;
+ int sensorlevel;
+ int shake_enable; // 1--enable shake, 0--disable shake
+ int manual_rotation; // 0--landance, 90--vertical
+ struct input_dev *input_dev;
+ //struct work_struct work;
+ struct delayed_work work; // for polling
+ struct workqueue_struct *queue;
+ int isdbg; // 0-- no debug log, 1--show debug log
+ int sensor_samp; // 1,2,4,8,16,32,64,120
+ int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor
+ int test_pass;
+ spinlock_t spinlock;
+ int pollcnt; // the counts of polling
+ int offset[3];
+};
+
+static struct kionix_config l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },
+ .irq = 6,
+ .int_gpio = 3,
+ .sensor_proc = NULL,
+ //.sensorlevel = SENSOR_GRAVITYGAME_MODE,
+ .shake_enable = 0, // default enable shake
+ .isdbg = 0,
+ .sensor_samp = 10, // 4sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ .pollcnt = 0, // Don't report the x,y,z when the driver is loaded until 2~3 seconds
+ .offset = {0,0,0},
+};
+*/
+
+struct kionix_accel_driver {
+ struct i2c_client *client;
+ struct kionix_accel_platform_data accel_pdata;
+ struct input_dev *input_dev;
+ struct delayed_work accel_work;
+ struct workqueue_struct *accel_workqueue;
+ wait_queue_head_t wqh_suspend;
+
+ int accel_data[3];
+ int accel_cali[3];
+ u8 axis_map_x;
+ u8 axis_map_y;
+ u8 axis_map_z;
+ bool negate_x;
+ bool negate_y;
+ bool negate_z;
+ u8 shift;
+
+ unsigned int poll_interval;
+ unsigned int poll_delay;
+ unsigned int accel_group;
+ u8 *accel_registers;
+
+ atomic_t accel_suspended;
+ atomic_t accel_suspend_continue;
+ atomic_t accel_enabled;
+ atomic_t accel_input_event;
+ atomic_t accel_enable_resume;
+ struct mutex mutex_earlysuspend;
+ struct mutex mutex_resume;
+ struct mutex mutex_subinput;
+ rwlock_t rwlock_accel_data;
+
+ bool accel_drdy;
+
+ /* Function callback */
+ void (*kionix_accel_report_accel_data)(struct kionix_accel_driver *acceld);
+ int (*kionix_accel_update_odr)(struct kionix_accel_driver *acceld, unsigned int poll_interval);
+ int (*kionix_accel_power_on_init)(struct kionix_accel_driver *acceld);
+ int (*kionix_accel_operate)(struct kionix_accel_driver *acceld);
+ int (*kionix_accel_standby)(struct kionix_accel_driver *acceld);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+};
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static void kionix_accel_update_direction(struct kionix_accel_driver *acceld);
+static int get_axisset(struct kionix_accel_driver *acceld)
+{
+ char varbuf[64];
+ int n;
+ int ubootvar[3][3];
+ int varlen;
+ int err;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.kionixgsensor", varbuf, &varlen)) {
+ printk(KERN_DEBUG "Can't get gsensor config in u-boot!!!!\n");
+ return -1;
+ kionix_accel_update_direction(acceld);//return -1;
+ } else {
+ sscanf(varbuf, "%d:%d:%d:%d:%d:%d",
+ &ubootvar[0][0],
+ &ubootvar[0][1],
+ &ubootvar[1][0],
+ &ubootvar[1][1],
+ &ubootvar[2][0],
+ &ubootvar[2][1]);
+
+ acceld->axis_map_x = ubootvar[0][0];
+ acceld->negate_x = ubootvar[0][1]<0?1:0;
+ acceld->axis_map_y = ubootvar[1][0];
+ acceld->negate_y = ubootvar[1][1]<0?1:0;
+ acceld->axis_map_z = ubootvar[2][0];
+ acceld->negate_z = ubootvar[2][1]<0?1:0;
+ /*kionix_accel_pdata.accel_direction = direction;
+ printk(KERN_ERR"accel_direction is %d,g_range is %d,res is %d\n",kionix_accel_pdata.accel_direction,kionix_accel_pdata.accel_g_range,kionix_accel_pdata.accel_res);*/
+
+ }
+ return 0;
+}
+
+static int kionix_i2c_read(struct i2c_client *client, u8 addr, u8 *data, int len)
+{
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = client->flags,
+ .len = 1,
+ .buf = &addr,
+ },
+ {
+ .addr = client->addr,
+ .flags = client->flags | I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+
+ return i2c_transfer(client->adapter, msgs, 2);
+}
+
+static int kionix_i2c_write(struct i2c_client *client, u8 addr, u8 *data, int len)
+{
+ char wrData[12] = {0};
+ /*
+ struct i2c_msg msgs =
+ {.addr = client->addr, .flags = 0, .len = len+1, .buf = wrData,};
+*/
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = client->flags,
+ .len = len+1,
+ .buf = wrData,
+ },
+ };
+
+ if (!client || (!data))
+ {
+ printk("%s NULL client!\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ wrData[0] = addr;
+ strncpy(&wrData[1], data, len);
+
+ if (i2c_transfer(client->adapter, &msgs, 1) < 0) {
+ printk( "%s: transfer failed.", __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int kionix_i2c_writebyte(struct i2c_client *client, u8 addr, u8 data)
+{
+ char wrData[2] = {0};
+ /*
+ struct i2c_msg msgs =
+ {.addr = client->addr, .flags = 0, .len = len+1, .buf = wrData,};
+*/
+ struct i2c_msg msgs[] = {
+ {
+ .addr = client->addr,
+ .flags = client->flags,
+ .len = 2,
+ .buf = &wrData[0],
+ },
+ };
+
+ if (!client)
+ {
+ printk("%s NULL client!\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ wrData[0] = addr;
+ //strncpy(&wrData[1], data, len);
+ wrData[1] = data;
+
+ if (i2c_transfer(client->adapter, &msgs, 1) < 0) {
+ printk( "%s: transfer failed.", __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int kionix_strtok(const char *buf, size_t count, char **token, const int token_nr)
+{
+ char *buf2 = (char *)kzalloc((count + 1) * sizeof(char), GFP_KERNEL);
+ char **token2 = token;
+ unsigned int num_ptr = 0, num_nr = 0, num_neg = 0;
+ int i = 0, start = 0, end = (int)count;
+
+ strcpy(buf2, buf);
+
+ /* We need to breakup the string into separate chunks in order for kstrtoint
+ * or strict_strtol to parse them without returning an error. Stop when the end of
+ * the string is reached or when enough value is read from the string */
+ while((start < end) && (i < token_nr)) {
+ /* We found a negative sign */
+ if(*(buf2 + start) == '-') {
+ /* Previous char(s) are numeric, so we store their value first before proceed */
+ if(num_nr > 0) {
+ /* If there is a pending negative sign, we adjust the variables to account for it */
+ if(num_neg) {
+ num_ptr--;
+ num_nr++;
+ }
+ *token2 = (char *)kzalloc((num_nr + 2) * sizeof(char), GFP_KERNEL);
+ strncpy(*token2, (const char *)(buf2 + num_ptr), (size_t) num_nr);
+ *(*token2+num_nr) = '\n';
+ i++;
+ token2++;
+ /* Reset */
+ num_ptr = num_nr = 0;
+ }
+ /* This indicates that there is a pending negative sign in the string */
+ num_neg = 1;
+ }
+ /* We found a numeric */
+ else if((*(buf2 + start) >= '0') && (*(buf2 + start) <= '9')) {
+ /* If the previous char(s) are not numeric, set num_ptr to current char */
+ if(num_nr < 1)
+ num_ptr = start;
+ num_nr++;
+ }
+ /* We found an unwanted character */
+ else {
+ /* Previous char(s) are numeric, so we store their value first before proceed */
+ if(num_nr > 0) {
+ if(num_neg) {
+ num_ptr--;
+ num_nr++;
+ }
+ *token2 = (char *)kzalloc((num_nr + 2) * sizeof(char), GFP_KERNEL);
+ strncpy(*token2, (const char *)(buf2 + num_ptr), (size_t) num_nr);
+ *(*token2+num_nr) = '\n';
+ i++;
+ token2++;
+ }
+ /* Reset all the variables to start afresh */
+ num_ptr = num_nr = num_neg = 0;
+ }
+ start++;
+ }
+
+ kfree(buf2);
+
+ return (i == token_nr) ? token_nr : -1;
+}
+
+static int kionix_accel_grp1_power_on_init(struct kionix_accel_driver *acceld)
+{
+ int err;
+
+ if(atomic_read(&acceld->accel_enabled) > 0) {
+ err = i2c_smbus_write_byte_data(acceld->client,
+ ACCEL_GRP1_CTRL_REG1, acceld->accel_registers[accel_grp1_ctrl_reg1] | ACCEL_GRP1_PC1_ON);
+ if (err < 0)
+ return err;
+ }
+ else {
+ err = i2c_smbus_write_byte_data(acceld->client,
+ ACCEL_GRP1_CTRL_REG1, acceld->accel_registers[accel_grp1_ctrl_reg1]);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int kionix_accel_grp1_operate(struct kionix_accel_driver *acceld)
+{
+ int err;
+
+ err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP1_CTRL_REG1, \
+ acceld->accel_registers[accel_grp2_ctrl_reg1] | ACCEL_GRP1_PC1_ON);
+ if (err < 0)
+ return err;
+
+ queue_delayed_work(acceld->accel_workqueue, &acceld->accel_work, 0);
+
+ return 0;
+}
+
+static int kionix_accel_grp1_standby(struct kionix_accel_driver *acceld)
+{
+ int err;
+
+ cancel_delayed_work_sync(&acceld->accel_work);
+
+ err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP1_CTRL_REG1, 0);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static void kionix_accel_grp1_report_accel_data(struct kionix_accel_driver *acceld)
+{
+ u8 accel_data[3];
+ s16 x, y, z;
+ int err;
+ struct input_dev *input_dev = acceld->input_dev;
+ int loop = KIONIX_I2C_RETRY_COUNT;
+
+ if(atomic_read(&acceld->accel_enabled) > 0) {
+ if(atomic_read(&acceld->accel_enable_resume) > 0)
+ {
+ while(loop) {
+ //mutex_lock(&input_dev->mutex);
+ mutex_lock(&acceld->mutex_subinput);
+ err = kionix_i2c_read(acceld->client, ACCEL_GRP1_XOUT, accel_data, 6);
+ //mutex_unlock(&input_dev->mutex);
+ mutex_unlock(&acceld->mutex_subinput);
+ if(err < 0){
+ loop--;
+ mdelay(KIONIX_I2C_RETRY_TIMEOUT);
+ }
+ else
+ loop = 0;
+ }
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, "%s: read data output error = %d\n", __func__, err);
+ }
+ else {
+ write_lock(&acceld->rwlock_accel_data);
+
+ x = ((s16) le16_to_cpu(((s16)(accel_data[acceld->axis_map_x] >> 2)) - 32)) << 6;
+ y = ((s16) le16_to_cpu(((s16)(accel_data[acceld->axis_map_y] >> 2)) - 32)) << 6;
+ z = ((s16) le16_to_cpu(((s16)(accel_data[acceld->axis_map_z] >> 2)) - 32)) << 6;
+
+ acceld->accel_data[acceld->axis_map_x] = (acceld->negate_x ? -x : x) + acceld->accel_cali[acceld->axis_map_x];
+ acceld->accel_data[acceld->axis_map_y] = (acceld->negate_y ? -y : y) + acceld->accel_cali[acceld->axis_map_y];
+ acceld->accel_data[acceld->axis_map_z] = (acceld->negate_z ? -z : z) + acceld->accel_cali[acceld->axis_map_z];
+
+ if(atomic_read(&acceld->accel_input_event) > 0) {
+ input_report_abs(acceld->input_dev, ABS_X, acceld->accel_data[acceld->axis_map_x]);
+ input_report_abs(acceld->input_dev, ABS_Y, acceld->accel_data[acceld->axis_map_y]);
+ input_report_abs(acceld->input_dev, ABS_Z, acceld->accel_data[acceld->axis_map_z]);
+ input_sync(acceld->input_dev);
+ }
+
+ write_unlock(&acceld->rwlock_accel_data);
+ }
+ }
+ else
+ {
+ atomic_inc(&acceld->accel_enable_resume);
+ }
+ }
+}
+
+static int kionix_accel_grp1_update_odr(struct kionix_accel_driver *acceld, unsigned int poll_interval)
+{
+ int err;
+ int i;
+ u8 odr;
+
+ /* Use the lowest ODR that can support the requested poll interval */
+ for (i = 0; i < ARRAY_SIZE(kionix_accel_grp1_odr_table); i++) {
+ odr = kionix_accel_grp1_odr_table[i].mask;
+ if (poll_interval < kionix_accel_grp1_odr_table[i].cutoff)
+ break;
+ }
+
+ /* Do not need to update CTRL_REG1 register if the ODR is not changed */
+ if((acceld->accel_registers[accel_grp1_ctrl_reg1] & ACCEL_GRP1_ODR_MASK) == odr)
+ return 0;
+ else {
+ acceld->accel_registers[accel_grp1_ctrl_reg1] &= ~ACCEL_GRP1_ODR_MASK;
+ acceld->accel_registers[accel_grp1_ctrl_reg1] |= odr;
+ }
+
+ /* Do not need to update CTRL_REG1 register if the sensor is not currently turn on */
+ if(atomic_read(&acceld->accel_enabled) > 0) {
+ err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP1_CTRL_REG1, \
+ acceld->accel_registers[accel_grp1_ctrl_reg1] | ACCEL_GRP1_PC1_ON);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int kionix_accel_grp2_power_on_init(struct kionix_accel_driver *acceld)
+{
+ int err;
+
+ /* ensure that PC1 is cleared before updating control registers */
+ err = i2c_smbus_write_byte_data(acceld->client,
+ ACCEL_GRP2_CTRL_REG1, 0);
+ if (err < 0)
+ return err;
+
+ err = i2c_smbus_write_byte_data(acceld->client,
+ ACCEL_GRP2_DATA_CTRL, acceld->accel_registers[accel_grp2_data_ctrl]);
+ if (err < 0)
+ return err;
+
+ /* only write INT_CTRL_REG1 if in irq mode */
+ if (acceld->client->irq) {
+ err = i2c_smbus_write_byte_data(acceld->client,
+ ACCEL_GRP2_INT_CTRL1, acceld->accel_registers[accel_grp2_int_ctrl]);
+ if (err < 0)
+ return err;
+ }
+
+ if(atomic_read(&acceld->accel_enabled) > 0) {
+ err = i2c_smbus_write_byte_data(acceld->client,
+ ACCEL_GRP2_CTRL_REG1, acceld->accel_registers[accel_grp2_ctrl_reg1] | ACCEL_GRP2_PC1_ON);
+ if (err < 0)
+ return err;
+ }
+ else {
+ err = i2c_smbus_write_byte_data(acceld->client,
+ ACCEL_GRP2_CTRL_REG1, acceld->accel_registers[accel_grp2_ctrl_reg1]);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int kionix_accel_grp2_operate(struct kionix_accel_driver *acceld)
+{
+ int err;
+
+ err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP2_CTRL_REG1, \
+ acceld->accel_registers[accel_grp2_ctrl_reg1] | ACCEL_GRP2_PC1_ON);
+ if (err < 0)
+ return err;
+
+ if(acceld->accel_drdy == 0)
+ queue_delayed_work(acceld->accel_workqueue, &acceld->accel_work, 0);
+
+ return 0;
+}
+
+static int kionix_accel_grp2_standby(struct kionix_accel_driver *acceld)
+{
+ int err;
+
+ if(acceld->accel_drdy == 0)
+ cancel_delayed_work_sync(&acceld->accel_work);
+
+ err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP2_CTRL_REG1, 0);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static void kionix_accel_grp2_report_accel_data(struct kionix_accel_driver *acceld)
+{
+ struct { union {
+ s16 accel_data_s16[3];
+ s8 accel_data_s8[6];
+ }; } accel_data;
+ s16 x, y, z;
+ int err;
+ struct input_dev *input_dev = acceld->input_dev;
+ int loop;
+
+ /* Only read the output registers if enabled */
+ if(atomic_read(&acceld->accel_enabled) > 0) {
+ if(atomic_read(&acceld->accel_enable_resume) > 0)
+ {
+ loop = KIONIX_I2C_RETRY_COUNT;
+ while(loop) {
+ //mutex_lock(&input_dev->mutex);
+ mutex_lock(&acceld->mutex_subinput);
+ err = kionix_i2c_read(acceld->client, ACCEL_GRP2_XOUT_L, (u8 *)accel_data.accel_data_s16, 6);
+ //mutex_unlock(&input_dev->mutex);
+ mutex_unlock(&acceld->mutex_subinput);
+ if(err < 0){
+ loop--;
+ mdelay(KIONIX_I2C_RETRY_TIMEOUT);
+ }
+ else
+ loop = 0;
+ }
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, "%s: read data output error = %d\n", __func__, err);
+ }
+ else {
+ write_lock(&acceld->rwlock_accel_data);
+
+ x = ((s16) le16_to_cpu(accel_data.accel_data_s16[acceld->axis_map_x])) >> acceld->shift;
+ y = ((s16) le16_to_cpu(accel_data.accel_data_s16[acceld->axis_map_y])) >> acceld->shift;
+ z = ((s16) le16_to_cpu(accel_data.accel_data_s16[acceld->axis_map_z])) >> acceld->shift;
+
+ acceld->accel_data[acceld->axis_map_x] = (acceld->negate_x ? -x : x) + acceld->accel_cali[acceld->axis_map_x];
+ acceld->accel_data[acceld->axis_map_y] = (acceld->negate_y ? -y : y) + acceld->accel_cali[acceld->axis_map_y];
+ acceld->accel_data[acceld->axis_map_z] = (acceld->negate_z ? -z : z) + acceld->accel_cali[acceld->axis_map_z];
+
+ if(atomic_read(&acceld->accel_input_event) > 0) {
+ input_report_abs(acceld->input_dev, ABS_X, acceld->accel_data[acceld->axis_map_x]);
+ input_report_abs(acceld->input_dev, ABS_Y, acceld->accel_data[acceld->axis_map_y]);
+ input_report_abs(acceld->input_dev, ABS_Z, acceld->accel_data[acceld->axis_map_z]);
+ input_sync(acceld->input_dev);
+ }
+
+ write_unlock(&acceld->rwlock_accel_data);
+ }
+ }
+ else
+ {
+ atomic_inc(&acceld->accel_enable_resume);
+ }
+ }
+
+ /* Clear the interrupt if using drdy */
+ if(acceld->accel_drdy == 1) {
+ loop = KIONIX_I2C_RETRY_COUNT;
+ while(loop) {
+ err = i2c_smbus_read_byte_data(acceld->client, ACCEL_GRP2_INT_REL);
+ if(err < 0){
+ loop--;
+ mdelay(KIONIX_I2C_RETRY_TIMEOUT);
+ }
+ else
+ loop = 0;
+ }
+ if (err < 0)
+ KMSGERR(&acceld->client->dev, "%s: clear interrupt error = %d\n", __func__, err);
+ }
+}
+
+static void kionix_accel_grp2_update_g_range(struct kionix_accel_driver *acceld)
+{
+ acceld->accel_registers[accel_grp2_ctrl_reg1] &= ~ACCEL_GRP2_G_MASK;
+
+ switch (acceld->accel_pdata.accel_g_range) {
+ case KIONIX_ACCEL_G_8G:
+ case KIONIX_ACCEL_G_6G:
+ acceld->shift = 2;
+ acceld->accel_registers[accel_grp2_ctrl_reg1] |= ACCEL_GRP2_G_8G;
+ break;
+ case KIONIX_ACCEL_G_4G:
+ acceld->shift = 3;
+ acceld->accel_registers[accel_grp2_ctrl_reg1] |= ACCEL_GRP2_G_4G;
+ break;
+ case KIONIX_ACCEL_G_2G:
+ default:
+ acceld->shift = 4;
+ acceld->accel_registers[accel_grp2_ctrl_reg1] |= ACCEL_GRP2_G_2G;
+ break;
+ }
+
+ return;
+}
+
+static int kionix_accel_grp2_update_odr(struct kionix_accel_driver *acceld, unsigned int poll_interval)
+{
+ int err;
+ int i;
+ u8 odr;
+
+ /* Use the lowest ODR that can support the requested poll interval */
+ for (i = 0; i < ARRAY_SIZE(kionix_accel_grp2_odr_table); i++) {
+ odr = kionix_accel_grp2_odr_table[i].mask;
+ if (poll_interval < kionix_accel_grp2_odr_table[i].cutoff)
+ break;
+ }
+
+ /* Do not need to update DATA_CTRL_REG register if the ODR is not changed */
+ if(acceld->accel_registers[accel_grp2_data_ctrl] == odr)
+ return 0;
+ else
+ acceld->accel_registers[accel_grp2_data_ctrl] = odr;
+
+ /* Do not need to update DATA_CTRL_REG register if the sensor is not currently turn on */
+ if(atomic_read(&acceld->accel_enabled) > 0) {
+ err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP2_CTRL_REG1, 0);
+ if (err < 0)
+ return err;
+
+ err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP2_DATA_CTRL, acceld->accel_registers[accel_grp2_data_ctrl]);
+ if (err < 0)
+ return err;
+
+ err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP2_CTRL_REG1, acceld->accel_registers[accel_grp2_ctrl_reg1] | ACCEL_GRP2_PC1_ON);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int kionix_accel_grp4_power_on_init(struct kionix_accel_driver *acceld)
+{
+ int err;
+ char rxData[2] = {0};
+ /* ensure that PC1 is cleared before updating control registers */
+ /*err = i2c_smbus_write_byte_data(acceld->client,
+ ACCEL_GRP4_CTRL_REG1, 0);*/
+
+ err = kionix_i2c_writebyte(acceld->client,
+ ACCEL_GRP4_CTRL_REG1, 0);
+ /*kionix_i2c_read(acceld->client,ACCEL_GRP4_CTRL_REG1,rxData,1);
+ printk(KERN_ERR"%d ,%s: ACCEL_GRP4_CTRL_REG1 is %d",__LINE__,__FUNCTION__,rxData[0]);*/
+
+ if (err < 0)
+ return err;
+
+ /*err = i2c_smbus_write_byte_data(acceld->client,
+ ACCEL_GRP4_DATA_CTRL, acceld->accel_registers[accel_grp4_data_ctrl]);*/
+
+ err = kionix_i2c_writebyte(acceld->client,
+ ACCEL_GRP4_DATA_CTRL, acceld->accel_registers[accel_grp4_data_ctrl]);
+ /*kionix_i2c_read(acceld->client,ACCEL_GRP4_CTRL_REG1,rxData,1);
+ printk(KERN_ERR"%d,%s: ACCEL_GRP4_CTRL_REG1 now is %d,wanted value is %d",__LINE__,__FUNCTION__,rxData[0],rxData[1]);*/
+
+ if (err < 0)
+ return err;
+
+ /* only write INT_CTRL_REG1 if in irq mode */
+ if (acceld->client->irq) {
+ err = i2c_smbus_write_byte_data(acceld->client,
+ ACCEL_GRP4_INT_CTRL1, acceld->accel_registers[accel_grp4_int_ctrl]);
+ if (err < 0)
+ return err;
+ }
+
+ if(atomic_read(&acceld->accel_enabled) > 0) {
+ /*err = i2c_smbus_write_byte_data(acceld->client,
+ ACCEL_GRP4_CTRL_REG1, acceld->accel_registers[accel_grp4_ctrl_reg1] | ACCEL_GRP4_PC1_ON);*/
+
+ err = kionix_i2c_writebyte(acceld->client,
+ ACCEL_GRP4_CTRL_REG1, acceld->accel_registers[accel_grp4_ctrl_reg1] | ACCEL_GRP4_PC1_ON);
+ /*kionix_i2c_read(acceld->client,ACCEL_GRP4_CTRL_REG1,rxData,1);
+ printk(KERN_ERR"%d,%s: ACCEL_GRP4_CTRL_REG1 now is %d,wanted value is %d",rxData[0],rxData[1]);*/
+
+ if (err < 0)
+ return err;
+ }
+ else {
+ /*err = i2c_smbus_write_byte_data(acceld->client,
+ ACCEL_GRP4_CTRL_REG1, acceld->accel_registers[accel_grp4_ctrl_reg1]);*/
+
+ err = kionix_i2c_writebyte(acceld->client,
+ ACCEL_GRP4_CTRL_REG1, acceld->accel_registers[accel_grp4_ctrl_reg1]);
+ /*kionix_i2c_read(acceld->client,ACCEL_GRP4_CTRL_REG1,rxData,1);
+ printk(KERN_ERR"%d,%s: ACCEL_GRP4_CTRL_REG1 now is %d,wanted value is %d",__LINE__,__FUNCTION__,rxData[0],acceld->accel_registers[accel_grp4_ctrl_reg1]);*/
+
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static int kionix_accel_grp4_operate(struct kionix_accel_driver *acceld)
+{
+ int err;
+
+ /*err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP4_CTRL_REG1, \
+ acceld->accel_registers[accel_grp4_ctrl_reg1] | ACCEL_GRP4_PC1_ON);*/
+
+ err = kionix_i2c_writebyte(acceld->client, ACCEL_GRP4_CTRL_REG1, \
+ acceld->accel_registers[accel_grp4_ctrl_reg1] | ACCEL_GRP4_PC1_ON);
+ if (err < 0)
+ return err;
+
+ if(acceld->accel_drdy == 0)
+ queue_delayed_work(acceld->accel_workqueue, &acceld->accel_work, 0);
+
+ return 0;
+}
+
+static int kionix_accel_grp4_standby(struct kionix_accel_driver *acceld)
+{
+ int err;
+
+ if(acceld->accel_drdy == 0)
+ cancel_delayed_work_sync(&acceld->accel_work);
+
+ //err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP4_CTRL_REG1, 0);
+ err = kionix_i2c_writebyte(acceld->client, ACCEL_GRP4_CTRL_REG1, 0);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static void kionix_accel_grp4_report_accel_data(struct kionix_accel_driver *acceld)
+{
+ struct { union {
+ s16 accel_data_s16[3];
+ s8 accel_data_s8[6];
+ }; } accel_data;
+ s16 x, y, z;
+ int err;
+ struct input_dev *input_dev = acceld->input_dev;
+ int loop;
+
+ /* Only read the output registers if enabled */
+ if(atomic_read(&acceld->accel_enabled) > 0) {
+ if(atomic_read(&acceld->accel_enable_resume) > 0)
+ {
+ loop = KIONIX_I2C_RETRY_COUNT;
+ while(loop) {
+ //mutex_lock(&input_dev->mutex);
+ mutex_lock(&acceld->mutex_subinput);
+ err = kionix_i2c_read(acceld->client, ACCEL_GRP4_XOUT_L, (u8 *)accel_data.accel_data_s16, 6);
+ //mutex_unlock(&input_dev->mutex);
+ mutex_unlock(&acceld->mutex_subinput);
+ if(err < 0){
+ loop--;
+ mdelay(KIONIX_I2C_RETRY_TIMEOUT);
+ }
+ else
+ loop = 0;
+ }
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, "%s: read data output error = %d\n", __func__, err);
+ }
+ else {
+ write_lock(&acceld->rwlock_accel_data);
+
+ x = ((s16) le16_to_cpu(accel_data.accel_data_s16[acceld->axis_map_x])) >> acceld->shift;
+ y = ((s16) le16_to_cpu(accel_data.accel_data_s16[acceld->axis_map_y])) >> acceld->shift;
+ z = ((s16) le16_to_cpu(accel_data.accel_data_s16[acceld->axis_map_z])) >> acceld->shift;
+
+ acceld->accel_data[acceld->axis_map_x] = (acceld->negate_x ? -x : x) + acceld->accel_cali[acceld->axis_map_x];
+ acceld->accel_data[acceld->axis_map_y] = (acceld->negate_y ? -y : y) + acceld->accel_cali[acceld->axis_map_y];
+ acceld->accel_data[acceld->axis_map_z] = (acceld->negate_z ? -z : z) + acceld->accel_cali[acceld->axis_map_z];
+
+ //printk(KERN_ERR"x:%d,y:%d,z:%d",x,y,z);
+
+ if(atomic_read(&acceld->accel_input_event) > 0) {
+ input_report_abs(acceld->input_dev, ABS_X, acceld->accel_data[acceld->axis_map_x]);
+ input_report_abs(acceld->input_dev, ABS_Y, acceld->accel_data[acceld->axis_map_y]);
+ input_report_abs(acceld->input_dev, ABS_Z, acceld->accel_data[acceld->axis_map_z]);
+ input_sync(acceld->input_dev);
+ }
+
+ write_unlock(&acceld->rwlock_accel_data);
+ }
+ }
+ else
+ {
+ atomic_inc(&acceld->accel_enable_resume);
+ }
+ }
+
+ /* Clear the interrupt if using drdy */
+ if(acceld->accel_drdy == 1) {
+ loop = KIONIX_I2C_RETRY_COUNT;
+ while(loop) {
+ err = i2c_smbus_read_byte_data(acceld->client, ACCEL_GRP4_INT_REL);
+ if(err < 0){
+ loop--;
+ mdelay(KIONIX_I2C_RETRY_TIMEOUT);
+ }
+ else
+ loop = 0;
+ }
+ if (err < 0)
+ KMSGERR(&acceld->client->dev, "%s: clear interrupt error = %d\n", __func__, err);
+ }
+}
+
+static void kionix_accel_grp4_update_g_range(struct kionix_accel_driver *acceld)
+{
+ acceld->accel_registers[accel_grp4_ctrl_reg1] &= ~ACCEL_GRP4_G_MASK;
+ //printk(KERN_ERR"kionix_accel_grp4_update_g_range is %d",acceld->accel_pdata.accel_g_range);
+ switch (acceld->accel_pdata.accel_g_range) {
+ case KIONIX_ACCEL_G_8G:
+ case KIONIX_ACCEL_G_6G:
+ //acceld->shift = 2;
+ acceld->accel_registers[accel_grp4_ctrl_reg1] |= ACCEL_GRP4_G_8G;
+ break;
+ case KIONIX_ACCEL_G_4G:
+ //acceld->shift = 4;//3;
+ acceld->accel_registers[accel_grp4_ctrl_reg1] |= ACCEL_GRP4_G_4G;
+ break;
+ case KIONIX_ACCEL_G_2G:
+ default:
+ //acceld->shift = 4;
+ acceld->accel_registers[accel_grp4_ctrl_reg1] |= ACCEL_GRP4_G_2G;
+ break;
+ }
+
+ return;
+}
+
+static int kionix_accel_grp4_update_odr(struct kionix_accel_driver *acceld, unsigned int poll_interval)
+{
+ int err;
+ int i;
+ u8 odr;
+
+ /* Use the lowest ODR that can support the requested poll interval */
+ for (i = 0; i < ARRAY_SIZE(kionix_accel_grp4_odr_table); i++) {
+ odr = kionix_accel_grp4_odr_table[i].mask;
+ if (poll_interval < kionix_accel_grp4_odr_table[i].cutoff)
+ break;
+ }
+
+ /* Do not need to update DATA_CTRL_REG register if the ODR is not changed */
+ if(acceld->accel_registers[accel_grp4_data_ctrl] == odr)
+ return 0;
+ else
+ acceld->accel_registers[accel_grp4_data_ctrl] = odr;
+
+ /* Do not need to update DATA_CTRL_REG register if the sensor is not currently turn on */
+ if(atomic_read(&acceld->accel_enabled) > 0) {
+ //err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP4_CTRL_REG1, 0);
+ err = kionix_i2c_writebyte(acceld->client, ACCEL_GRP4_CTRL_REG1, 0);
+
+
+ if (err < 0)
+ return err;
+
+ //err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP4_DATA_CTRL, acceld->accel_registers[accel_grp4_data_ctrl]);
+ err = kionix_i2c_writebyte(acceld->client, ACCEL_GRP4_DATA_CTRL, acceld->accel_registers[accel_grp4_data_ctrl]);
+ if (err < 0)
+ return err;
+
+ //err = i2c_smbus_write_byte_data(acceld->client, ACCEL_GRP4_CTRL_REG1, acceld->accel_registers[accel_grp4_ctrl_reg1] | ACCEL_GRP4_PC1_ON);
+ err = kionix_i2c_writebyte(acceld->client, ACCEL_GRP4_CTRL_REG1, acceld->accel_registers[accel_grp4_ctrl_reg1] | ACCEL_GRP4_PC1_ON);
+ if (err < 0)
+ return err;
+ //#############
+ err = i2c_smbus_read_byte_data(acceld->client, ACCEL_GRP4_DATA_CTRL);
+ if (err < 0)
+ return err;
+ switch(err) {
+ case ACCEL_GRP4_ODR0_781:
+ dev_info(&acceld->client->dev, "ODR = 0.781 Hz\n");
+ break;
+ case ACCEL_GRP4_ODR1_563:
+ dev_info(&acceld->client->dev, "ODR = 1.563 Hz\n");
+ break;
+ case ACCEL_GRP4_ODR3_125:
+ dev_info(&acceld->client->dev, "ODR = 3.125 Hz\n");
+ break;
+ case ACCEL_GRP4_ODR6_25:
+ dev_info(&acceld->client->dev, "ODR = 6.25 Hz\n");
+ break;
+ case ACCEL_GRP4_ODR12_5:
+ dev_info(&acceld->client->dev, "ODR = 12.5 Hz\n");
+ break;
+ case ACCEL_GRP4_ODR25:
+ dev_info(&acceld->client->dev, "ODR = 25 Hz\n");
+ break;
+ case ACCEL_GRP4_ODR50:
+ dev_info(&acceld->client->dev, "ODR = 50 Hz\n");
+ break;
+ case ACCEL_GRP4_ODR100:
+ dev_info(&acceld->client->dev, "ODR = 100 Hz\n");
+ break;
+ case ACCEL_GRP4_ODR200:
+ dev_info(&acceld->client->dev, "ODR = 200 Hz\n");
+ break;
+ case ACCEL_GRP4_ODR400:
+ dev_info(&acceld->client->dev, "ODR = 400 Hz\n");
+ break;
+ case ACCEL_GRP4_ODR800:
+ dev_info(&acceld->client->dev, "ODR = 800 Hz\n");
+ break;
+ case ACCEL_GRP4_ODR1600:
+ dev_info(&acceld->client->dev, "ODR = 1600 Hz\n");
+ break;
+ default:
+ dev_info(&acceld->client->dev, "Unknown ODR\n");
+ break;
+ }
+ //#############
+ }
+
+ return 0;
+}
+
+static int kionix_accel_power_on(struct kionix_accel_driver *acceld)
+{
+ if (acceld->accel_pdata.power_on)
+ return acceld->accel_pdata.power_on();
+
+ return 0;
+}
+
+static void kionix_accel_power_off(struct kionix_accel_driver *acceld)
+{
+ if (acceld->accel_pdata.power_off)
+ acceld->accel_pdata.power_off();
+}
+
+static irqreturn_t kionix_accel_isr(int irq, void *dev)
+{
+ struct kionix_accel_driver *acceld = dev;
+
+ queue_delayed_work(acceld->accel_workqueue, &acceld->accel_work, 0);
+
+ return IRQ_HANDLED;
+}
+
+static void kionix_accel_work(struct work_struct *work)
+{
+ struct kionix_accel_driver *acceld = container_of((struct delayed_work *)work, struct kionix_accel_driver, accel_work);
+
+ if(acceld->accel_drdy == 0)
+ queue_delayed_work(acceld->accel_workqueue, &acceld->accel_work, acceld->poll_delay);
+
+ acceld->kionix_accel_report_accel_data(acceld);
+}
+
+static void kionix_accel_update_direction(struct kionix_accel_driver *acceld)
+{
+ unsigned int direction = acceld->accel_pdata.accel_direction;
+ unsigned int accel_group = acceld->accel_group;
+
+ write_lock(&acceld->rwlock_accel_data);
+ acceld->axis_map_x = ((direction-1)%2);
+ acceld->axis_map_y = (direction%2);
+ acceld->axis_map_z = 2;
+ acceld->negate_z = ((direction-1)/4);
+ switch(accel_group) {
+ case KIONIX_ACCEL_GRP3:
+ case KIONIX_ACCEL_GRP6:
+ acceld->negate_x = (((direction+2)/2)%2);
+ acceld->negate_y = (((direction+5)/4)%2);
+ break;
+ case KIONIX_ACCEL_GRP5:
+ acceld->axis_map_x = (direction%2);
+ acceld->axis_map_y = ((direction-1)%2);
+ acceld->negate_x = (((direction+1)/2)%2);
+ acceld->negate_y = (((direction/2)+((direction-1)/4))%2);
+ break;
+ default:
+ acceld->negate_x = ((direction/2)%2);
+ acceld->negate_y = (((direction+1)/4)%2);
+ break;
+ }
+ write_unlock(&acceld->rwlock_accel_data);
+ return;
+}
+
+static int kionix_accel_enable(struct kionix_accel_driver *acceld)
+{
+ int err = 0;
+ long remaining;
+
+ mutex_lock(&acceld->mutex_earlysuspend);
+
+ atomic_set(&acceld->accel_suspend_continue, 0);
+
+ /* Make sure that the sensor had successfully resumed before enabling it */
+ if(atomic_read(&acceld->accel_suspended) == 1) {
+ KMSGINF(&acceld->client->dev, "%s: waiting for resume\n", __func__);
+ remaining = wait_event_interruptible_timeout(acceld->wqh_suspend, \
+ atomic_read(&acceld->accel_suspended) == 0, \
+ msecs_to_jiffies(KIONIX_ACCEL_EARLYSUSPEND_TIMEOUT));
+
+ if(atomic_read(&acceld->accel_suspended) == 1) {
+ KMSGERR(&acceld->client->dev, "%s: timeout waiting for resume\n", __func__);
+ err = -ETIME;
+ goto exit;
+ }
+ }
+
+ err = acceld->kionix_accel_operate(acceld);
+
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: kionix_accel_operate returned err = %d\n", __func__, err);
+ goto exit;
+ }
+
+ atomic_inc(&acceld->accel_enabled);
+
+exit:
+ mutex_unlock(&acceld->mutex_earlysuspend);
+
+ return err;
+}
+
+static int kionix_accel_disable(struct kionix_accel_driver *acceld)
+{
+ int err = 0;
+
+ mutex_lock(&acceld->mutex_resume);
+
+ atomic_set(&acceld->accel_suspend_continue, 1);
+
+ if(atomic_read(&acceld->accel_enabled) > 0){
+ if(atomic_dec_and_test(&acceld->accel_enabled)) {
+ if(atomic_read(&acceld->accel_enable_resume) > 0)
+ atomic_set(&acceld->accel_enable_resume, 0);
+ err = acceld->kionix_accel_standby(acceld);
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: kionix_accel_standby returned err = %d\n", __func__, err);
+ goto exit;
+ }
+ wake_up_interruptible(&acceld->wqh_suspend);
+ }
+ }
+
+exit:
+ mutex_unlock(&acceld->mutex_resume);
+
+ return err;
+}
+
+static int kionix_accel_input_open(struct input_dev *input)
+{
+ struct kionix_accel_driver *acceld = input_get_drvdata(input);
+
+ atomic_inc(&acceld->accel_input_event);
+
+ return 0;
+}
+
+static void kionix_accel_input_close(struct input_dev *dev)
+{
+ struct kionix_accel_driver *acceld = input_get_drvdata(dev);
+
+ atomic_dec(&acceld->accel_input_event);
+}
+
+static void __devinit kionix_accel_init_input_device(struct kionix_accel_driver *acceld,
+ struct input_dev *input_dev)
+{
+ __set_bit(EV_ABS, input_dev->evbit);
+ input_set_abs_params(input_dev, ABS_X, -ACCEL_G_MAX, ACCEL_G_MAX, ACCEL_FUZZ, ACCEL_FLAT);
+ input_set_abs_params(input_dev, ABS_Y, -ACCEL_G_MAX, ACCEL_G_MAX, ACCEL_FUZZ, ACCEL_FLAT);
+ input_set_abs_params(input_dev, ABS_Z, -ACCEL_G_MAX, ACCEL_G_MAX, ACCEL_FUZZ, ACCEL_FLAT);
+
+ input_dev->name = "g-sensor";//KIONIX_ACCEL_NAME;
+ input_dev->id.bustype = BUS_I2C;
+ input_dev->dev.parent = &acceld->client->dev;
+}
+
+static int __devinit kionix_accel_setup_input_device(struct kionix_accel_driver *acceld)
+{
+ struct input_dev *input_dev;
+ int err;
+
+ input_dev = input_allocate_device();
+ if (!input_dev) {
+ KMSGERR(&acceld->client->dev, "input_allocate_device failed\n");
+ printk("kionix_accel_probe: Failed to allocate input device\n");
+ return -ENOMEM;
+ }
+
+ acceld->input_dev = input_dev;
+
+ input_dev->open = kionix_accel_input_open;
+ input_dev->close = kionix_accel_input_close;
+ input_set_drvdata(input_dev, acceld);
+
+ kionix_accel_init_input_device(acceld, input_dev);
+
+ err = input_register_device(acceld->input_dev);
+ if (err) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: input_register_device returned err = %d\n", __func__, err);
+ printk("kionix_accel_probe: Failed to register input device\n");
+ input_free_device(acceld->input_dev);
+ return err;
+ }
+
+ return 0;
+}
+
+/* Returns the enable state of device */
+static ssize_t kionix_accel_get_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", atomic_read(&acceld->accel_enabled) > 0 ? 1 : 0);
+}
+
+/* Allow users to enable/disable the device */
+static ssize_t kionix_accel_set_enable(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(client);
+ struct input_dev *input_dev = acceld->input_dev;
+ char *buf2;
+ const int enable_count = 1;
+ unsigned long enable;
+ int err = 0;
+
+ /* Lock the device to prevent races with open/close (and itself) */
+ //mutex_lock(&input_dev->mutex);
+ mutex_lock(&acceld->mutex_subinput);
+ if(kionix_strtok(buf, count, &buf2, enable_count) < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: No enable data being read. " \
+ "No enable data will be updated.\n", __func__);
+ }
+
+ else {
+ /* Removes any leading negative sign */
+ while(*buf2 == '-')
+ buf2++;
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35))
+ err = kstrtouint((const char *)buf2, 10, (unsigned int *)&enable);
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: kstrtouint returned err = %d\n", __func__, err);
+ goto exit;
+ }
+ #else
+ err = strict_strtoul((const char *)buf2, 10, &enable);
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: strict_strtoul returned err = %d\n", __func__, err);
+ goto exit;
+ }
+ #endif
+
+ if(enable)
+ err = kionix_accel_enable(acceld);
+ else
+ err = kionix_accel_disable(acceld);
+ }
+
+exit:
+ //mutex_unlock(&input_dev->mutex);
+ mutex_unlock(&acceld->mutex_subinput);
+ return (err < 0) ? err : count;
+}
+
+/* Returns currently selected poll interval (in ms) */
+static ssize_t kionix_accel_get_delay(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", acceld->poll_interval);
+}
+
+/* Allow users to select a new poll interval (in ms) */
+static ssize_t kionix_accel_set_delay(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(client);
+ struct input_dev *input_dev = acceld->input_dev;
+ char *buf2;
+ const int delay_count = 1;
+ unsigned long interval;
+ int err = 0;
+
+ /* Lock the device to prevent races with open/close (and itself) */
+ //mutex_lock(&input_dev->mutex);
+ mutex_lock(&acceld->mutex_subinput);
+ if(kionix_strtok(buf, count, &buf2, delay_count) < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: No delay data being read. " \
+ "No delay data will be updated.\n", __func__);
+ }
+
+ else {
+ /* Removes any leading negative sign */
+ while(*buf2 == '-')
+ buf2++;
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35))
+ err = kstrtouint((const char *)buf2, 10, (unsigned int *)&interval);
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: kstrtouint returned err = %d\n", __func__, err);
+ goto exit;
+ }
+ #else
+ err = strict_strtoul((const char *)buf2, 10, &interval);
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: strict_strtoul returned err = %d\n", __func__, err);
+ goto exit;
+ }
+ #endif
+
+ if(acceld->accel_drdy == 1)
+ disable_irq(client->irq);
+
+ /*
+ * Set current interval to the greater of the minimum interval or
+ * the requested interval
+ */
+ acceld->poll_interval = max((unsigned int)interval, acceld->accel_pdata.min_interval);
+ acceld->poll_delay = msecs_to_jiffies(acceld->poll_interval);
+
+ err = acceld->kionix_accel_update_odr(acceld, acceld->poll_interval);
+
+ if(acceld->accel_drdy == 1)
+ enable_irq(client->irq);
+ }
+
+exit:
+ //mutex_unlock(&input_dev->mutex);
+ mutex_unlock(&acceld->mutex_subinput);
+
+ return (err < 0) ? err : count;
+}
+
+/* Returns the direction of device */
+static ssize_t kionix_accel_get_direct(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", acceld->accel_pdata.accel_direction);
+}
+
+/* Allow users to change the direction the device */
+static ssize_t kionix_accel_set_direct(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(client);
+ struct input_dev *input_dev = acceld->input_dev;
+ char *buf2;
+ const int direct_count = 1;
+ unsigned long direction;
+ int err = 0;
+
+ /* Lock the device to prevent races with open/close (and itself) */
+ //mutex_lock(&input_dev->mutex);
+ mutex_lock(&acceld->mutex_subinput);
+ if(kionix_strtok(buf, count, &buf2, direct_count) < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: No direction data being read. " \
+ "No direction data will be updated.\n", __func__);
+ }
+
+ else {
+ /* Removes any leading negative sign */
+ while(*buf2 == '-')
+ buf2++;
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35))
+ err = kstrtouint((const char *)buf2, 10, (unsigned int *)&direction);
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: kstrtouint returned err = %d\n", __func__, err);
+ goto exit;
+ }
+ #else
+ err = strict_strtoul((const char *)buf2, 10, &direction);
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: strict_strtoul returned err = %d\n", __func__, err);
+ goto exit;
+ }
+ #endif
+
+ if(direction < 1 || direction > 8)
+ KMSGERR(&acceld->client->dev, "%s: invalid direction = %d\n", __func__, (unsigned int) direction);
+
+ else {
+ acceld->accel_pdata.accel_direction = (u8) direction;
+ kionix_accel_update_direction(acceld);
+ }
+ }
+
+exit:
+ //mutex_unlock(&input_dev->mutex);
+ mutex_unlock(&acceld->mutex_subinput);
+ return (err < 0) ? err : count;
+}
+
+/* Returns the data output of device */
+static ssize_t kionix_accel_get_data(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(client);
+ int x, y, z;
+
+ read_lock(&acceld->rwlock_accel_data);
+
+ x = acceld->accel_data[acceld->axis_map_x];
+ y = acceld->accel_data[acceld->axis_map_y];
+ z = acceld->accel_data[acceld->axis_map_z];
+
+ read_unlock(&acceld->rwlock_accel_data);
+
+ return sprintf(buf, "%d %d %d\n", x, y, z);
+}
+
+/* Returns the calibration value of the device */
+static ssize_t kionix_accel_get_cali(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(client);
+ int calibration[3];
+
+ read_lock(&acceld->rwlock_accel_data);
+
+ calibration[0] = acceld->accel_cali[acceld->axis_map_x];
+ calibration[1] = acceld->accel_cali[acceld->axis_map_y];
+ calibration[2] = acceld->accel_cali[acceld->axis_map_z];
+
+ read_unlock(&acceld->rwlock_accel_data);
+
+ return sprintf(buf, "%d %d %d\n", calibration[0], calibration[1], calibration[2]);
+}
+
+/* Allow users to change the calibration value of the device */
+static ssize_t kionix_accel_set_cali(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(client);
+ struct input_dev *input_dev = acceld->input_dev;
+ const int cali_count = 3; /* How many calibration that we expect to get from the string */
+ char **buf2;
+ long calibration[cali_count];
+ int err = 0, i = 0;
+
+ /* Lock the device to prevent races with open/close (and itself) */
+ //mutex_lock(&input_dev->mutex);
+ mutex_lock(&acceld->mutex_subinput);
+ buf2 = (char **)kzalloc(cali_count * sizeof(char *), GFP_KERNEL);
+
+ if(kionix_strtok(buf, count, buf2, cali_count) < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: Not enough calibration data being read. " \
+ "No calibration data will be updated.\n", __func__);
+ }
+ else {
+ /* Convert string to integers */
+ for(i = 0 ; i < cali_count ; i++) {
+ #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,35))
+ err = kstrtoint((const char *)*(buf2+i), 10, (int *)&calibration[i]);
+ if(err < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: kstrtoint returned err = %d." \
+ "No calibration data will be updated.\n", __func__ , err);
+ goto exit;
+ }
+ #else
+ err = strict_strtol((const char *)*(buf2+i), 10, &calibration[i]);
+ if(err < 0) {
+ KMSGERR(&acceld->client->dev, \
+ "%s: strict_strtol returned err = %d." \
+ "No calibration data will be updated.\n", __func__ , err);
+ goto exit;
+ }
+ #endif
+ }
+
+ write_lock(&acceld->rwlock_accel_data);
+
+ acceld->accel_cali[acceld->axis_map_x] = (int)calibration[0];
+ acceld->accel_cali[acceld->axis_map_y] = (int)calibration[1];
+ acceld->accel_cali[acceld->axis_map_z] = (int)calibration[2];
+
+ write_unlock(&acceld->rwlock_accel_data);
+ }
+
+exit:
+ for(i = 0 ; i < cali_count ; i++)
+ kfree(*(buf2+i));
+
+ kfree(buf2);
+
+ //mutex_unlock(&input_dev->mutex);
+ mutex_unlock(&acceld->mutex_subinput);
+
+ return (err < 0) ? err : count;
+}
+
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, kionix_accel_get_enable, kionix_accel_set_enable);
+static DEVICE_ATTR(delay, S_IRUGO|S_IWUSR, kionix_accel_get_delay, kionix_accel_set_delay);
+static DEVICE_ATTR(direct, S_IRUGO|S_IWUSR, kionix_accel_get_direct, kionix_accel_set_direct);
+static DEVICE_ATTR(data, S_IRUGO, kionix_accel_get_data, NULL);
+static DEVICE_ATTR(cali, S_IRUGO|S_IWUSR, kionix_accel_get_cali, kionix_accel_set_cali);
+
+static struct attribute *kionix_accel_attributes[] = {
+ &dev_attr_enable.attr,
+ &dev_attr_delay.attr,
+ &dev_attr_direct.attr,
+ &dev_attr_data.attr,
+ &dev_attr_cali.attr,
+ NULL
+};
+
+static struct attribute_group kionix_accel_attribute_group = {
+ .attrs = kionix_accel_attributes
+};
+
+static int kionix_chip_id[] ={
+ KIONIX_ACCEL_WHO_AM_I_KXTE9,
+ KIONIX_ACCEL_WHO_AM_I_KXTF9,
+ KIONIX_ACCEL_WHO_AM_I_KXTI9_1001,
+ KIONIX_ACCEL_WHO_AM_I_KXTIK_1004,
+ KIONIX_ACCEL_WHO_AM_I_KXTJ9_1005,
+ KIONIX_ACCEL_WHO_AM_I_KXTJ9_1007,
+ KIONIX_ACCEL_WHO_AM_I_KXCJ9_1008,
+ KIONIX_ACCEL_WHO_AM_I_KXTJ2_1009,
+ KIONIX_ACCEL_WHO_AM_I_KXCJK_1013
+};
+
+static int iskionix()
+{
+ char rxData[2] = {0};
+ int ret = 0;
+ int i = 0;
+
+ ret = kionix_i2c_read(this_client,ACCEL_WHO_AM_I,rxData,1); //maybe should 2 success // -5 ioerror!!
+ printk(KERN_ERR"<<<<%s ret:%d val 0x%x\n", __FUNCTION__, ret, rxData[0]);
+ if (ret <= 0) // 2 ?
+ {
+ return -1;
+ }
+ for(i = 0 ; i < sizeof(kionix_chip_id)/sizeof(kionix_chip_id[0]);i++)
+ if(rxData[0] == kionix_chip_id[i])
+ return 0;
+
+ return -1;
+}
+
+static int __devinit kionix_verify(struct kionix_accel_driver *acceld)
+{
+ int retval = i2c_smbus_read_byte_data(acceld->client, ACCEL_WHO_AM_I);
+
+#if KIONIX_KMSG_INF
+ switch (retval) {
+ case KIONIX_ACCEL_WHO_AM_I_KXTE9:
+ KMSGINF(&acceld->client->dev, "this accelerometer is a KXTE9.\n");
+ break;
+ case KIONIX_ACCEL_WHO_AM_I_KXTF9:
+ KMSGINF(&acceld->client->dev, "this accelerometer is a KXTF9.\n");
+ break;
+ case KIONIX_ACCEL_WHO_AM_I_KXTI9_1001:
+ KMSGINF(&acceld->client->dev, "this accelerometer is a KXTI9-1001.\n");
+ break;
+ case KIONIX_ACCEL_WHO_AM_I_KXTIK_1004:
+ KMSGINF(&acceld->client->dev, "this accelerometer is a KXTIK-1004.\n");
+ break;
+ case KIONIX_ACCEL_WHO_AM_I_KXTJ9_1005:
+ KMSGINF(&acceld->client->dev, "this accelerometer is a KXTJ9-1005.\n");
+ break;
+ case KIONIX_ACCEL_WHO_AM_I_KXTJ9_1007:
+ KMSGINF(&acceld->client->dev, "this accelerometer is a KXTJ9-1007.\n");
+ break;
+ case KIONIX_ACCEL_WHO_AM_I_KXCJ9_1008:
+ KMSGINF(&acceld->client->dev, "this accelerometer is a KXCJ9-1008.\n");
+ break;
+ case KIONIX_ACCEL_WHO_AM_I_KXTJ2_1009:
+ KMSGINF(&acceld->client->dev, "this accelerometer is a KXTJ2-1009.\n");
+ break;
+ case KIONIX_ACCEL_WHO_AM_I_KXCJK_1013:
+ KMSGINF(&acceld->client->dev, "this accelerometer is a KXCJK-1013.\n");
+ break;
+ default:
+ break;
+ }
+#endif
+
+ return retval;
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+void kionix_accel_earlysuspend_suspend(struct early_suspend *h)
+{
+ struct kionix_accel_driver *acceld = container_of(h, struct kionix_accel_driver, early_suspend);
+ long remaining;
+
+ mutex_lock(&acceld->mutex_earlysuspend);
+
+ /* Only continue to suspend if enable did not intervene */
+ if(atomic_read(&acceld->accel_suspend_continue) > 0) {
+ /* Make sure that the sensor had successfully disabled before suspending it */
+ if(atomic_read(&acceld->accel_enabled) > 0) {
+ KMSGINF(&acceld->client->dev, "%s: waiting for disable\n", __func__);
+ remaining = wait_event_interruptible_timeout(acceld->wqh_suspend, \
+ atomic_read(&acceld->accel_enabled) < 1, \
+ msecs_to_jiffies(KIONIX_ACCEL_EARLYSUSPEND_TIMEOUT));
+
+ if(atomic_read(&acceld->accel_enabled) > 0) {
+ KMSGERR(&acceld->client->dev, "%s: timeout waiting for disable\n", __func__);
+ }
+ }
+
+ kionix_accel_power_off(acceld);
+
+ atomic_set(&acceld->accel_suspended, 1);
+ }
+
+ mutex_unlock(&acceld->mutex_earlysuspend);
+
+ return;
+}
+
+void kionix_accel_earlysuspend_resume(struct early_suspend *h)
+{
+ struct kionix_accel_driver *acceld = container_of(h, struct kionix_accel_driver, early_suspend);
+ int err;
+
+ mutex_lock(&acceld->mutex_resume);
+
+ if(atomic_read(&acceld->accel_suspended) == 1) {
+ err = kionix_accel_power_on(acceld);
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, "%s: kionix_accel_power_on returned err = %d\n", __func__, err);
+ goto exit;
+ }
+
+ /* Only needs to reinitialized the registers if Vdd is pulled low during suspend */
+ if(err > 0) {
+ err = acceld->kionix_accel_power_on_init(acceld);
+ if (err) {
+ KMSGERR(&acceld->client->dev, "%s: kionix_accel_power_on_init returned err = %d\n", __func__, err);
+ goto exit;
+ }
+ }
+
+ atomic_set(&acceld->accel_suspended, 0);
+ }
+
+ wake_up_interruptible(&acceld->wqh_suspend);
+
+exit:
+ mutex_unlock(&acceld->mutex_resume);
+
+ return;
+}
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+static int kionix_open(struct inode *inode, struct file *file)
+{
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(this_client);
+ //KMSGINF("Open the g-sensor node...\n");
+ kionix_accel_input_open(acceld->input_dev);
+ return 0;
+}
+
+static int kionix_release(struct inode *inode, struct file *file)
+{
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(this_client);
+ //KMSGINF("Close the g-sensor node...\n");
+ kionix_accel_input_close(acceld->input_dev);
+ return 0;
+}
+
+static long
+kionix_ioctl(/*struct inode *inode,*/ struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ char rwbuf[5];
+ short delay, enable; //amsr = -1;
+ unsigned int uval = 0;
+
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(this_client);
+
+ //KMSGINF("g-sensor ioctr...\n");
+ memset(rwbuf, 0, sizeof(rwbuf));
+ switch (cmd) {
+ case ECS_IOCTL_APP_SET_DELAY:
+ // set the rate of g-sensor
+ if (copy_from_user(&delay, argp, sizeof(short)))
+ {
+ printk(KERN_ALERT "Can't get set delay!!!\n");
+ return -EFAULT;
+ }
+ klog("Get delay=%d\n", delay);
+
+ if ((delay >=0) && (delay < 20))
+ {
+ delay = 20;
+ } else if (delay > 200)
+ {
+ delay = 200;
+ }
+ //l_sensorconfig.sensor_samp = 1000/delay;
+ acceld->poll_interval = 1000/delay;
+ acceld->poll_delay = msecs_to_jiffies(acceld->poll_interval);
+ acceld->kionix_accel_update_odr(acceld, acceld->poll_interval);
+ break;
+ case ECS_IOCTL_APP_SET_AFLAG:
+ // enable/disable sensor
+ if (copy_from_user(&enable, argp, sizeof(short)))
+ {
+ printk(KERN_ERR "Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ klog("enable=%d\n",enable);
+ if ((enable >=0) && (enable <=1))
+ {
+ //KMSGINF("driver: disable/enable(%d) gsensor.\n", enable);
+
+ //l_sensorconfig.sensor_enable = enable;
+ if(enable)
+ kionix_accel_enable(acceld);
+ else
+ kionix_accel_disable(acceld);
+
+ } else {
+ printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ uval = KIONIX_DRVID;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ //KMSGINF("kionix_driver_id:%d\n",uval);
+ break;
+ case WMT_IOCTL_SENOR_GET_RESOLUTION:
+
+ uval = (12<<8) | 8; // 8bit:4g 0xxx xx //mma8452Q
+ if (copy_to_user((unsigned int *)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ printk("<<<<<<<resolution:0x%x\n",uval);
+ default:
+ break;
+ }
+
+
+
+ return 0;
+}
+
+static struct file_operations kionix_fops = {
+ .owner = THIS_MODULE,
+ .open = kionix_open,
+ .release = kionix_release,
+ .unlocked_ioctl = kionix_ioctl,
+};
+
+
+static struct miscdevice kionix_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "sensor_ctrl",
+ .fops = &kionix_fops,
+};
+
+static int sensor_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+ return 0;
+}
+
+static int sensor_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ return 0;
+}
+
+
+
+
+/*static int __devinit kionix_accel_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)*/
+static int kionix_accel_probe(struct platform_device *pdev)
+{
+ const struct kionix_accel_platform_data *accel_pdata = this_client->dev.platform_data;
+ struct kionix_accel_driver *acceld;
+ int err;
+ struct proc_dir_entry *proc_dir, *proc_entry;
+/*
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE_DATA)) {
+ KMSGERR(&client->dev, "client is not i2c capable. Abort.\n");
+ return -ENXIO;
+ }
+*/
+ if (!accel_pdata) {
+ KMSGERR(&this_client->dev, "platform data is NULL. Abort.\n");
+ return -EINVAL;
+ }
+
+ acceld = kzalloc(sizeof(*acceld), GFP_KERNEL);
+ if (acceld == NULL) {
+ KMSGERR(&this_client->dev, \
+ "failed to allocate memory for module data. Abort.\n");
+ return -ENOMEM;
+ }
+
+ acceld->client = this_client;
+ acceld->accel_pdata = *accel_pdata;
+
+ i2c_set_clientdata(this_client, acceld);
+
+ err = kionix_accel_power_on(acceld);
+ if (err < 0)
+ goto err_free_mem;
+
+ if (accel_pdata->init) {
+ err = accel_pdata->init();
+ if (err < 0)
+ goto err_accel_pdata_power_off;
+ }
+
+ err = kionix_verify(acceld);
+ if (err < 0) {
+ KMSGERR(&acceld->client->dev, "%s: kionix_verify returned err = %d. Abort.\n", __func__, err);
+ goto err_accel_pdata_exit;
+ }
+
+ /* Setup group specific configuration and function callback */
+ switch (err) {
+ case KIONIX_ACCEL_WHO_AM_I_KXTE9:
+ acceld->accel_group = KIONIX_ACCEL_GRP1;
+ acceld->accel_registers = kzalloc(sizeof(u8)*accel_grp1_regs_count, GFP_KERNEL);
+ if (acceld->accel_registers == NULL) {
+ KMSGERR(&this_client->dev, \
+ "failed to allocate memory for accel_registers. Abort.\n");
+ goto err_accel_pdata_exit;
+ }
+ acceld->accel_drdy = 0;
+ acceld->kionix_accel_report_accel_data = kionix_accel_grp1_report_accel_data;
+ acceld->kionix_accel_update_odr = kionix_accel_grp1_update_odr;
+ acceld->kionix_accel_power_on_init = kionix_accel_grp1_power_on_init;
+ acceld->kionix_accel_operate = kionix_accel_grp1_operate;
+ acceld->kionix_accel_standby = kionix_accel_grp1_standby;
+ break;
+ case KIONIX_ACCEL_WHO_AM_I_KXTF9:
+ case KIONIX_ACCEL_WHO_AM_I_KXTI9_1001:
+ case KIONIX_ACCEL_WHO_AM_I_KXTIK_1004:
+ case KIONIX_ACCEL_WHO_AM_I_KXTJ9_1005:
+ if(err == KIONIX_ACCEL_WHO_AM_I_KXTIK_1004)
+ acceld->accel_group = KIONIX_ACCEL_GRP3;
+ else
+ acceld->accel_group = KIONIX_ACCEL_GRP2;
+ acceld->accel_registers = kzalloc(sizeof(u8)*accel_grp2_regs_count, GFP_KERNEL);
+ if (acceld->accel_registers == NULL) {
+ KMSGERR(&this_client->dev, \
+ "failed to allocate memory for accel_registers. Abort.\n");
+ goto err_accel_pdata_exit;
+ }
+ switch(acceld->accel_pdata.accel_res) {
+ case KIONIX_ACCEL_RES_6BIT:
+ case KIONIX_ACCEL_RES_8BIT:
+ acceld->accel_registers[accel_grp2_ctrl_reg1] |= ACCEL_GRP2_RES_8BIT;
+ break;
+ case KIONIX_ACCEL_RES_12BIT:
+ default:
+ acceld->accel_registers[accel_grp2_ctrl_reg1] |= ACCEL_GRP2_RES_12BIT;
+ break;
+ }
+ if(acceld->accel_pdata.accel_irq_use_drdy && this_client->irq) {
+ acceld->accel_registers[accel_grp2_int_ctrl] |= ACCEL_GRP2_IEN | ACCEL_GRP2_IEA;
+ acceld->accel_registers[accel_grp2_ctrl_reg1] |= ACCEL_GRP2_DRDYE;
+ acceld->accel_drdy = 1;
+ }
+ else
+ acceld->accel_drdy = 0;
+ kionix_accel_grp2_update_g_range(acceld);
+ acceld->kionix_accel_report_accel_data = kionix_accel_grp2_report_accel_data;
+ acceld->kionix_accel_update_odr = kionix_accel_grp2_update_odr;
+ acceld->kionix_accel_power_on_init = kionix_accel_grp2_power_on_init;
+ acceld->kionix_accel_operate = kionix_accel_grp2_operate;
+ acceld->kionix_accel_standby = kionix_accel_grp2_standby;
+ break;
+ case KIONIX_ACCEL_WHO_AM_I_KXTJ9_1007:
+ case KIONIX_ACCEL_WHO_AM_I_KXCJ9_1008:
+ case KIONIX_ACCEL_WHO_AM_I_KXTJ2_1009:
+ case KIONIX_ACCEL_WHO_AM_I_KXCJK_1013:
+ if(err == KIONIX_ACCEL_WHO_AM_I_KXTJ2_1009)
+ acceld->accel_group = KIONIX_ACCEL_GRP5;
+ else if(err == KIONIX_ACCEL_WHO_AM_I_KXCJK_1013)
+ acceld->accel_group = KIONIX_ACCEL_GRP6;
+ else
+ acceld->accel_group = KIONIX_ACCEL_GRP4;
+ acceld->accel_registers = kzalloc(sizeof(u8)*accel_grp4_regs_count, GFP_KERNEL);
+ if (acceld->accel_registers == NULL) {
+ KMSGERR(&this_client->dev, \
+ "failed to allocate memory for accel_registers. Abort.\n");
+ goto err_accel_pdata_exit;
+ }
+ switch(acceld->accel_pdata.accel_res) {
+ case KIONIX_ACCEL_RES_6BIT:
+ case KIONIX_ACCEL_RES_8BIT:
+ acceld->shift = 0;
+ acceld->accel_registers[accel_grp4_ctrl_reg1] |= ACCEL_GRP4_RES_8BIT;
+ break;
+ case KIONIX_ACCEL_RES_12BIT:
+ acceld->shift = 4;
+ default:
+ acceld->accel_registers[accel_grp4_ctrl_reg1] |= ACCEL_GRP4_RES_12BIT;
+ break;
+ }
+ if(acceld->accel_pdata.accel_irq_use_drdy && this_client->irq) {
+ acceld->accel_registers[accel_grp4_int_ctrl] |= ACCEL_GRP4_IEN | ACCEL_GRP4_IEA;
+ acceld->accel_registers[accel_grp4_ctrl_reg1] |= ACCEL_GRP4_DRDYE;
+ acceld->accel_drdy = 1;
+ }
+ else
+ acceld->accel_drdy = 0;
+ kionix_accel_grp4_update_g_range(acceld);
+ acceld->kionix_accel_report_accel_data = kionix_accel_grp4_report_accel_data;
+ acceld->kionix_accel_update_odr = kionix_accel_grp4_update_odr;
+ acceld->kionix_accel_power_on_init = kionix_accel_grp4_power_on_init;
+ acceld->kionix_accel_operate = kionix_accel_grp4_operate;
+ acceld->kionix_accel_standby = kionix_accel_grp4_standby;
+ break;
+ default:
+ KMSGERR(&acceld->client->dev, \
+ "%s: unsupported device, who am i = %d. Abort.\n", __func__, err);
+ goto err_accel_pdata_exit;
+ }
+
+ err = kionix_accel_setup_input_device(acceld);
+ if (err)
+ goto err_free_accel_registers;
+
+//add
+ /*this_pdev = pdev;
+ l_sensorconfig.input_dev = acceld->input_dev;*/
+
+ err = misc_register(&kionix_device);
+ if (err) {
+ printk(KERN_ERR
+ "kionix_accel_probe: kionix_device register failed\n");
+ goto exit_misc_device_register_failed;
+ }
+
+ //dev_set_drvdata(&pdev->dev, &l_sensorconfig);
+//end add
+
+
+ atomic_set(&acceld->accel_suspended, 0);
+ atomic_set(&acceld->accel_suspend_continue, 1);
+ atomic_set(&acceld->accel_enabled, 0);
+ atomic_set(&acceld->accel_input_event, 0);
+ atomic_set(&acceld->accel_enable_resume, 0);
+
+ mutex_init(&acceld->mutex_earlysuspend);
+ mutex_init(&acceld->mutex_resume);
+
+ mutex_init(&acceld->mutex_subinput);//add 2014-6-12
+
+ rwlock_init(&acceld->rwlock_accel_data);
+
+ acceld->poll_interval = acceld->accel_pdata.poll_interval;
+ acceld->poll_delay = msecs_to_jiffies(acceld->poll_interval);
+ acceld->kionix_accel_update_odr(acceld, acceld->poll_interval);
+ get_axisset(acceld);//kionix_accel_update_direction(acceld);
+
+ proc_dir = proc_mkdir("sensors", NULL);
+ if (proc_dir == NULL)
+ KMSGERR(&this_client->dev, "failed to create /proc/sensors\n");
+ else {
+ proc_entry = create_proc_entry( "accelinfo", 0644, proc_dir);
+ if (proc_entry == NULL)
+ KMSGERR(&this_client->dev, "failed to create /proc/cpu/accelinfo\n");
+ }
+
+/*
+ proc_dir = create_proc_entry(GSENSOR_PROC_NAME, 0666, NULL);//&proc_root
+ if (proc_dir != NULL)
+ {
+ proc_dir->write_proc = sensor_writeproc;
+ proc_dir->read_proc = sensor_readproc;
+ }
+*/
+ acceld->accel_workqueue = create_singlethread_workqueue("Kionix Accel Workqueue");
+ INIT_DELAYED_WORK(&acceld->accel_work, kionix_accel_work);
+ init_waitqueue_head(&acceld->wqh_suspend);
+
+ if (acceld->accel_drdy) {
+ err = request_threaded_irq(this_client->irq, NULL, kionix_accel_isr, \
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT, \
+ KIONIX_ACCEL_IRQ, acceld);
+ if (err) {
+ KMSGERR(&acceld->client->dev, "%s: request_threaded_irq returned err = %d\n", __func__, err);
+ KMSGERR(&acceld->client->dev, "%s: running in software polling mode instead\n", __func__);
+ acceld->accel_drdy = 0;
+ }
+ KMSGINF(&acceld->client->dev, "running in hardware interrupt mode\n");
+ } else {
+ KMSGINF(&acceld->client->dev, "running in software polling mode\n");
+ }
+
+ err = acceld->kionix_accel_power_on_init(acceld);
+ if (err) {
+ KMSGERR(&acceld->client->dev, "%s: kionix_accel_power_on_init returned err = %d. Abort.\n", __func__, err);
+ goto err_free_irq;
+ }
+
+ err = sysfs_create_group(&this_client->dev.kobj, &kionix_accel_attribute_group);
+ if (err) {
+ KMSGERR(&acceld->client->dev, "%s: sysfs_create_group returned err = %d. Abort.\n", __func__, err);
+ goto err_free_irq;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ /* The higher the level, the earlier it resume, and the later it suspend */
+ acceld->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 50;
+ acceld->early_suspend.suspend = kionix_accel_earlysuspend_suspend;
+ acceld->early_suspend.resume = kionix_accel_earlysuspend_resume;
+ register_early_suspend(&acceld->early_suspend);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+
+ // satrt the polling work
+ if(acceld->accel_drdy == 0)
+ queue_delayed_work(acceld->accel_workqueue, &acceld->accel_work, acceld->poll_delay);
+ return 0;
+
+exit_misc_device_register_failed:
+err_free_irq:
+ if (acceld->accel_drdy)
+ free_irq(this_client->irq, acceld);
+ destroy_workqueue(acceld->accel_workqueue);
+ input_unregister_device(acceld->input_dev);
+err_free_accel_registers:
+ kfree(acceld->accel_registers);
+err_accel_pdata_exit:
+ if (accel_pdata->exit)
+ accel_pdata->exit();
+err_accel_pdata_power_off:
+ kionix_accel_power_off(acceld);
+err_free_mem:
+ kfree(acceld);
+exit_input_dev_alloc_failed:
+ return err;
+}
+
+static int kionix_accel_remove(struct platform_device *pdev)
+{
+ struct kionix_accel_driver *acceld = i2c_get_clientdata(this_client);
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&acceld->early_suspend);
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+ if (NULL != acceld->accel_workqueue)
+ {
+ cancel_delayed_work_sync(&acceld->accel_work);
+ flush_workqueue(acceld->accel_workqueue);
+ destroy_workqueue(acceld->accel_workqueue);
+ acceld->accel_workqueue = NULL;
+ }
+ sysfs_remove_group(&this_client->dev.kobj, &kionix_accel_attribute_group);
+ if (acceld->accel_drdy)
+ free_irq(this_client->irq, acceld);
+ //destroy_workqueue(acceld->accel_workqueue);
+ misc_deregister(&kionix_device);
+ input_unregister_device(acceld->input_dev);
+ kfree(acceld->accel_registers);
+ if (acceld->accel_pdata.exit)
+ acceld->accel_pdata.exit();
+ kionix_accel_power_off(acceld);
+ kfree(acceld);
+
+ return 0;
+}
+
+static int __devexit kionix_accel_i2cremove(struct i2c_client *client)
+{
+ return 0;
+}
+
+static const struct i2c_device_id kionix_accel_id[] = {
+ { KIONIX_ACCEL_NAME, 0 },
+ { },
+};
+
+MODULE_DEVICE_TABLE(i2c, kionix_accel_id);
+
+static struct i2c_driver kionix_accel_driver = {
+ .driver = {
+ .name = KIONIX_ACCEL_NAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = kionix_accel_probe,
+ .remove = __devexit_p(kionix_accel_i2cremove),
+ .id_table = kionix_accel_id,
+};
+
+
+static struct platform_device kionix_pdevice = {
+ .name = "kionix",
+ .id = 0,
+ /*.dev = {
+ //.release = mma8452q_platform_release,
+ },*/
+};
+
+//************
+static void kionix_accel_shutdown(struct platform_device *pdev)
+{
+ struct kionix_accel_driver *acceld = NULL;
+ acceld = i2c_get_clientdata(this_client);
+ if (acceld) {
+ printk("<<<<<%s\n", __func__);
+ flush_delayed_work_sync(&acceld->accel_work);
+ cancel_delayed_work_sync(&acceld->accel_work);
+ }
+
+}
+//****add for resume dpm timeout 2014-6-12
+static int kionix_accel_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct kionix_accel_driver *acceld = NULL;
+ acceld = i2c_get_clientdata(this_client);
+ if (acceld) {
+ printk("<<<<<%s\n", __func__);
+ flush_delayed_work_sync(&acceld->accel_work);
+ cancel_delayed_work_sync(&acceld->accel_work);
+ }
+}
+
+int kionix_accel_resume(struct platform_device *pdev)
+{
+ struct kionix_accel_driver *acceld = NULL;
+ acceld = i2c_get_clientdata(this_client);
+ if (acceld) {
+ printk("<<<<<%s\n", __func__);
+ queue_delayed_work(acceld->accel_workqueue, &acceld->accel_work, acceld->poll_delay);
+ }
+}
+//***********************
+static struct platform_driver kionix_driver = {
+ .probe = kionix_accel_probe,
+ .remove = kionix_accel_remove,
+ .shutdown = kionix_accel_shutdown,
+ .suspend = kionix_accel_suspend,
+ .resume = kionix_accel_resume,
+ .driver = {
+ .name = "kionix",
+ },
+};
+
+
+static struct class* l_dev_class = NULL;
+static struct device *l_clsdevice = NULL;
+static int __init kionix_accel_init(void)
+{
+ //return i2c_add_driver(&kionix_accel_driver);
+
+ int ret = 0;
+ struct kionix_accel_driver *acceld;
+
+ acceld = kzalloc(sizeof(*acceld), GFP_KERNEL);
+ if (acceld == NULL) {
+ printk("%s kzalloc fail!\n", __func__);
+ return -ENOMEM;
+ }
+
+ ret = get_axisset(acceld);//
+ if (ret < 0)
+ {
+ printk("%s user choose to no sensor chip!\n", __func__);
+ kfree(acceld);
+ return ret;
+ }
+ kfree(acceld);
+
+ if (!(this_client = sensor_i2c_register_device2(0, KIONIX_ACCEL_I2C_ADDR, KIONIX_ACCEL_NAME,(void*)(&kionix_accel_pdata))))
+ {
+ printk(KERN_EMERG"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+
+
+ if(iskionix())
+ {
+ printk(KERN_ERR "Can't find kionix!!\n");
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+ }
+
+ //ret = get_axisset(NULL);
+
+ printk("kionix g-sensor driver init\n");
+
+ //spin_lock_init(&l_sensorconfig.spinlock);
+ l_dev_class = class_create(THIS_MODULE, KIONIX_ACCEL_NAME);
+ //for S40 module to judge whether insmod is ok
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create gsensor device !!\n");
+ return ret;
+ }
+ l_clsdevice = device_create(l_dev_class, NULL, MKDEV(GSENSOR_MAJOR, 0), NULL, KIONIX_ACCEL_NAME);
+ if (IS_ERR(l_clsdevice)){
+ ret = PTR_ERR(l_clsdevice);
+ printk(KERN_ERR "Failed to create device %s !!!",KIONIX_ACCEL_NAME);
+ return ret;
+ }
+
+ if((ret = platform_device_register(&kionix_pdevice)))
+ {
+ printk(KERN_ERR "%s Can't register kionix platform devcie!!!\n", __FUNCTION__);
+ return ret;
+ }
+ if ((ret = platform_driver_register(&kionix_driver)) != 0)
+ {
+ printk(KERN_ERR "%s Can't register kionix platform driver!!!\n", __FUNCTION__);
+ return ret;
+ }
+
+ return 0;
+
+}
+module_init(kionix_accel_init);
+
+static void __exit kionix_accel_exit(void)
+{
+ //i2c_del_driver(&kionix_accel_driver);
+ platform_driver_unregister(&kionix_driver);
+ platform_device_unregister(&kionix_pdevice);
+
+ device_destroy(l_dev_class, MKDEV(GSENSOR_MAJOR, 0));
+
+ class_destroy(l_dev_class);
+ sensor_i2c_unregister_device(this_client);
+}
+module_exit(kionix_accel_exit);
+
+MODULE_DESCRIPTION("Kionix accelerometer driver");
+MODULE_AUTHOR("Kuching Tan <kuchingtan@kionix.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("3.3.0");
diff --git a/ANDROID_3.4.5/drivers/input/sensor/kionix_gsensor/kionix_accel.h b/ANDROID_3.4.5/drivers/input/sensor/kionix_gsensor/kionix_accel.h
new file mode 100755
index 00000000..b7be9b8f
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/kionix_gsensor/kionix_accel.h
@@ -0,0 +1,85 @@
+/* include/linux/input/kionix_accel.h - Kionix accelerometer driver
+ *
+ * Copyright (C) 2012 Kionix, Inc.
+ * Written by Kuching Tan <kuchingtan@kionix.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __KIONIX_ACCEL_H__
+#define __KIONIX_ACCEL_H__
+
+#define KIONIX_ACCEL_I2C_ADDR 0x0E
+#define KIONIX_ACCEL_NAME "kionix_accel"
+#define KIONIX_ACCEL_IRQ "kionix-irq"
+
+struct kionix_accel_platform_data {
+ /* Although the accelerometer can perform at high ODR,
+ * there is a need to keep the maximum ODR to a lower
+ * value due to power consumption or other concern.
+ * Use this variable to set the minimum allowable
+ * interval for data to be reported from the
+ * accelerometer. Unit is measured in milli-
+ * seconds. Recommended value is 5ms. */
+ unsigned int min_interval;
+ /* Use this variable to set the default interval for
+ * data to be reported from the accelerometer. This
+ * value will be used during driver setup process,
+ * but can be changed by the system during runtime via
+ * sysfs control. Recommended value is 200ms.*/
+ unsigned int poll_interval;
+
+ /* This variable controls the corresponding direction
+ * of the accelerometer that is mounted on the board
+ * of the device. Refer to the porting guide for
+ * details. Valid value is 1 to 8. */
+ u8 accel_direction;
+
+ /* Use this variable to choose whether or not to use
+ * DRDY hardware interrupt mode to trigger a data
+ * report event instead of using software polling.
+ * Note that for those accelerometer model that does
+ * not support DRDY hardware interrupt, the driver
+ * will revert to software polling mode automatically.
+ * Valid value is 0 or 1.*/
+ bool accel_irq_use_drdy;
+
+ /* Use this variable to control the number of
+ * effective bits of the accelerometer output.
+ * Use the macro definition to select the desired
+ * number of effective bits. */
+ #define KIONIX_ACCEL_RES_12BIT 0
+ #define KIONIX_ACCEL_RES_8BIT 1
+ #define KIONIX_ACCEL_RES_6BIT 2
+ u8 accel_res;
+
+ /* Use this variable to control the G range of
+ * the accelerometer output. Use the macro definition
+ * to select the desired G range.*/
+ #define KIONIX_ACCEL_G_2G 0
+ #define KIONIX_ACCEL_G_4G 1
+ #define KIONIX_ACCEL_G_6G 2
+ #define KIONIX_ACCEL_G_8G 3
+ u8 accel_g_range;
+
+ /* Optional callback functions that can be implemented
+ * on per product basis. If these callbacks are defined,
+ * they will be called by the driver. */
+ int (*init)(void);
+ void (*exit)(void);
+ int (*power_on)(void);
+ int (*power_off)(void);
+};
+#endif /* __KIONIX_ACCEL_H__ */
diff --git a/ANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/Makefile
new file mode 100755
index 00000000..23eca917
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_gsensor_kxte9
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := kxte9.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/kxte9.c b/ANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/kxte9.c
new file mode 100755
index 00000000..2f25a4f8
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/kxte9.c
@@ -0,0 +1,1798 @@
+/* drivers/i2c/chips/kxte9.c - KXTE9 accelerometer driver
+ *
+ * Copyright (C) 2010 Kionix, Inc.
+ * Written by Kuching Tan <kuchingtan@kionix.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+//#include <linux/kxte9.h>
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include <mach/hardware.h>
+#include "kxte9.h"
+//#include <linux/earlysuspend.h>
+#include <mach/wmt-i2c-bus.h>
+
+#define NAME "kxte9"
+#define G_MAX 2000
+/* OUTPUT REGISTERS */
+#define CT_RESP 0x0C
+#define WHO_AM_I 0x0F
+#define TILT_POS_CUR 0x10
+#define TILT_POS_PRE 0x11
+#define XOUT 0x12
+#define INT_STATUS_REG 0x16
+#define INT_SRC_REG2 0x17
+#define INT_REL 0x1A
+/* CONTROL REGISTERS */
+#define CTRL_REG1 0x1B
+#define CTRL_REG2 0x1C
+#define CTRL_REG3 0x1D
+#define INT_CTRL1 0x1E
+#define INT_CTRL2 0x1F
+#define TILT_TIMER 0x28
+#define WUF_TIMER 0x29
+#define B2S_TIMER 0x2A
+#define WUF_THRESH 0x5A
+#define B2S_THRESH 0x5B
+/* CTRL_REG1 BITS */
+#define PC1_OFF 0x00
+#define PC1_ON 0x80
+/* INT_SRC_REG2 BITS */
+#define TPS 0x01
+#define WUFS 0x02
+#define B2SS 0x04
+/* Direction Mask */
+/* Used for TILT_POS_CUR, TILT_POS_PRE */
+/* INT_SRC_REG1, CTRL_REG2 */
+#define DIR_LE 0x20
+#define DIR_RI 0x10
+#define DIR_DO 0x08
+#define DIR_UP 0x04
+#define DIR_FD 0x02
+#define DIR_FU 0x01
+/* ODR MASKS */
+#define ODRM 0x18 // CTRL_REG1
+#define OWUFM 0x03 // CTRL_REG3
+#define OB2SM 0x0C // CTRL_REG3
+/* INPUT_ABS CONSTANTS */
+#define FUZZ 32
+#define FLAT 32
+/* RESUME STATE INDICES */
+#define RES_CTRL_REG1 0
+#define RES_CTRL_REG3 1
+#define RES_INT_CTRL1 2
+#define RES_TILT_TIMER 3
+#define RES_WUF_TIMER 4
+#define RES_B2S_TIMER 5
+#define RES_WUF_THRESH 6
+#define RES_B2S_THRESH 7
+#define RES_CURRENT_ODR 8
+#define RESUME_ENTRIES 9
+/* OFFSET and SENSITIVITY */
+//#define OFFSET 32 //6-bit
+#define OFFSET 128 //8-bit
+#define SENS 16
+
+#define IOCTL_BUFFER_SIZE 64
+
+//#define WM3445_A0
+//#define INT_MODE
+
+//////////////////////////////////////////////////////////////////////////
+//#define DEBUG_WMT_GSENSOR
+#ifdef DEBUG_WMT_GSENSOR
+#define kxte9_dbg(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__ , ## args)
+//#define kxte9_dbg(fmt, args...) if (kpadall_isrundbg()) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+#else
+#define kxte9_dbg(fmt, args...)
+#endif
+
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk(KERN_ERR "[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk(KERN_DEBUG "[%s]: " fmt, __FUNCTION__, ## args)
+//////////////////////////////////////////////////////////////////////////
+
+/*
+ * The following table lists the maximum appropriate poll interval for each
+ * available output data rate.
+ */
+struct {
+ unsigned int interval;
+ u8 mask;
+} kxte9_odr_table[] = {
+ {1000, ODR1E},
+ {334, ODR3E},
+ {100, ODR10E},
+ {25, ODR40E},
+ {8, ODR125E},
+};
+
+struct kxte9_data {
+ //struct i2c_client *client;
+ struct kxte9_platform_data *pdata;
+ struct mutex lock;
+ struct delayed_work input_work;
+ struct input_dev *input_dev;
+#ifdef INT_MODE
+ struct work_struct irq_work;
+#endif
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend earlysuspend;
+#endif
+ int hw_initialized;
+ atomic_t enabled;
+ u8 resume[RESUME_ENTRIES];
+ int i2c_xfer_complete;
+ int suspend;
+};
+
+struct gsensor_config
+{
+ int op;
+ int samp;
+ int xyz_axis[3][3]; // (axis,direction)
+ struct proc_dir_entry* sensor_proc;
+ int sensorlevel;
+ unsigned int avg_count;
+ unsigned int kxte9_8bit;
+ int name;
+ int bmp;
+ unsigned int ctraddr;
+ unsigned int ocaddr;
+ unsigned int idaddr;
+ unsigned int peaddr;
+ unsigned int pcaddr;
+ unsigned int itbmp;
+ unsigned int itaddr;
+ unsigned int isbmp;
+ unsigned int isaddr;
+ int irq;
+};
+
+static struct gsensor_config gconf = {
+ .op = 0,
+ .samp = 40,
+ .xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },
+ .sensor_proc = NULL,
+ .avg_count = 4,
+ .kxte9_8bit = 1,
+ .name = 3,
+#ifdef WM3445_A0
+ .bmp = 0x100, /* GPIO 8 */
+ .ctraddr = GPIO_BASE_ADDR + 0x40,
+ .ocaddr = GPIO_BASE_ADDR + 0x80,
+ .idaddr = GPIO_BASE_ADDR + 0x00,
+ .peaddr = GPIO_BASE_ADDR + 0x480,
+ .pcaddr = GPIO_BASE_ADDR + 0x4c0,
+ .itbmp = 0x30000, /* Rising Edge */
+ .itaddr = GPIO_BASE_ADDR + 0x300,
+ .isbmp = 0x100,
+ .isaddr = GPIO_BASE_ADDR + 0x304,
+ .irq = IRQ_GPIO8,
+#else
+ .bmp = 0x8, /* GPIO 3 */
+ .ctraddr = GPIO_BASE_ADDR + 0x40,
+ .ocaddr = GPIO_BASE_ADDR + 0x80,
+ .idaddr = GPIO_BASE_ADDR + 0x00,
+ .peaddr = GPIO_BASE_ADDR + 0x480,
+ .pcaddr = GPIO_BASE_ADDR + 0x4c0,
+ .itbmp = 0x83000000, /* Rising Edge */
+ .itaddr = GPIO_BASE_ADDR + 0x300,
+ .isbmp = 0x8,
+ .isaddr = GPIO_BASE_ADDR + 0x320,
+ .irq = 5,
+#endif
+};
+
+static struct kxte9_platform_data kxte9_pdata = {
+ .min_interval = 1,
+ .poll_interval = 100,
+ .ctrl_reg1_init = ODR10E & ~B2SE & ~WUFE & ~TPE,
+ .engine_odr_init = OB2S1 | OWUF1,
+ .int_ctrl_init = KXTE9_IEA,
+ .tilt_timer_init = 0x00,
+ .wuf_timer_init = 0x00,
+ .wuf_thresh_init = 0x20,
+ .b2s_timer_init = 0x00,
+ .b2s_thresh_init = 0x60,
+};
+
+#ifdef WM3445_A0
+#define SET_GPIO_GSENSOR_INT() {\
+ REG32_VAL(gconf.ctraddr) &= ~gconf.bmp; \
+ REG32_VAL(gconf.ocaddr) &= ~gconf.bmp; \
+ REG32_VAL(gconf.peaddr) |= gconf.bmp; \
+ REG32_VAL(gconf.pcaddr) &= ~gconf.bmp; \
+ REG32_VAL(gconf.itaddr) |= gconf.itbmp; \
+ REG32_VAL(GPIO_BASE_ADDR + 0x308) |= gconf.bmp; \
+ REG32_VAL(gconf.isaddr) |= gconf.isbmp; \
+}
+#define ENABLE_SENSOR_INT(enable) { \
+ if (enable) \
+ {\
+ REG32_VAL(GPIO_BASE_ADDR + 0x308) &= ~gconf.bmp; \
+ } else {\
+ REG32_VAL(GPIO_BASE_ADDR + 0x308) |= gconf.bmp; \
+ }\
+}
+
+#else
+#define SET_GPIO_GSENSOR_INT() {\
+ REG32_VAL(gconf.ctraddr) |= gconf.bmp; \
+ REG32_VAL(gconf.ocaddr) &= ~gconf.bmp; \
+ REG32_VAL(gconf.pcaddr) &= ~gconf.bmp; \
+ REG32_VAL(gconf.itaddr) |= gconf.itbmp; \
+ REG32_VAL(gconf.isaddr) |= gconf.isbmp; \
+}
+#endif
+
+#define X_CONVERT(x) x*gconf.xyz_axis[ABS_X][1]
+#define Y_CONVERT(y) y*gconf.xyz_axis[ABS_Y][1]
+#define Z_CONVERT(z) z*gconf.xyz_axis[ABS_Z][1]
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void kxte9_early_suspend(struct early_suspend *h);
+static void kxte9_late_resume(struct early_suspend *h);
+#endif
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+//extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num, int bus_id);
+extern int i2c_api_do_send(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size);
+extern int i2c_api_do_recv(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size);
+extern unsigned int wmt_read_oscr(void);
+
+static struct kxte9_data *te9 = NULL;
+static atomic_t kxte9_dev_open_count;
+static struct kobject *android_gsensor_kobj = NULL;
+static void kxte9_read_callback(void *data);
+struct i2c_msg *kxte9_msg;
+unsigned char *i2c_read_buf;
+unsigned char *i2c_write_buf;
+static struct timer_list kxte9_timer;
+static unsigned char *x_count;
+static unsigned char *y_count;
+static unsigned char *z_count;
+static unsigned int x_total = 0, y_total = 0, z_total = 0;
+static unsigned int xyz_index = 0;
+
+static int wait_i2c_xfer_complete(void)
+{
+ unsigned int now_time = 0;
+ unsigned int delay_time = 0;
+
+ now_time = wmt_read_oscr();
+ while (!te9->i2c_xfer_complete) {
+ delay_time = wmt_read_oscr() - now_time;
+ if (delay_time > 60000) {//20ms
+ printk(KERN_WARNING "[kxte9] transfer timeout!\n");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void kxte9_read_callback(void *data)
+{
+ int xyz[3];
+
+ if (te9->suspend) {
+ te9->i2c_xfer_complete = 1;
+ return;
+ }
+ if (xyz_index >= gconf.avg_count)
+ xyz_index = 0;
+ x_total -= x_count[xyz_index];
+ y_total -= y_count[xyz_index];
+ z_total -= z_count[xyz_index];
+ if (gconf.kxte9_8bit) {
+ x_count[xyz_index] = i2c_read_buf[0];
+ y_count[xyz_index] = i2c_read_buf[1];
+ z_count[xyz_index] = i2c_read_buf[2];
+ } else {
+ x_count[xyz_index] = i2c_read_buf[0] & ~0x03;
+ y_count[xyz_index] = i2c_read_buf[1] & ~0x03;
+ z_count[xyz_index] = i2c_read_buf[2] & ~0x03;
+ }
+ x_total += x_count[xyz_index];
+ y_total += y_count[xyz_index];
+ z_total += z_count[xyz_index];
+ xyz[ABS_X] = (x_total/gconf.avg_count - OFFSET) << 4;
+ xyz[ABS_Y] = (y_total/gconf.avg_count - OFFSET) << 4;
+ xyz[ABS_Z] = (z_total/gconf.avg_count - OFFSET) << 4;
+ //printk(KERN_DEBUG " [%d] x:%d y:%d z:%d\n", xyz_index, x_count[xyz_index], y_count[xyz_index], z_count[xyz_index]);
+ //printk(KERN_DEBUG " total x:%d y:%d z:%d\n", x_total, y_total, z_total);
+ //printk(KERN_DEBUG " avg x:%d y:%d z:%d\n", x_total/gconf.avg_count, y_total/gconf.avg_count, z_total/gconf.avg_count);
+ //printk(KERN_DEBUG "report x:%d y:%d z:%d\n", xyz[ABS_X], xyz[ABS_Y], xyz[ABS_Z]);
+ xyz_index++;
+ input_report_abs(te9->input_dev, ABS_X, X_CONVERT(xyz[gconf.xyz_axis[ABS_X][0]]));
+ input_report_abs(te9->input_dev, ABS_Y, Y_CONVERT(xyz[gconf.xyz_axis[ABS_Y][0]]));
+ input_report_abs(te9->input_dev, ABS_Z, Z_CONVERT(xyz[gconf.xyz_axis[ABS_Z][0]]));
+ input_sync(te9->input_dev);
+ te9->i2c_xfer_complete = 1;
+ mod_timer(&kxte9_timer, jiffies + msecs_to_jiffies(te9->pdata->poll_interval));
+}
+
+static void kxte9_read_data(u8 addr, int len)
+{
+ i2c_write_buf[0] = addr;
+ kxte9_msg[0].addr = KXTE9_I2C_ADDR;
+ kxte9_msg[0].flags = 0 ;
+ kxte9_msg[0].len = 1;
+ kxte9_msg[0].buf = i2c_write_buf;
+ kxte9_msg[1].addr = KXTE9_I2C_ADDR;
+ kxte9_msg[1].flags = I2C_M_RD;
+ kxte9_msg[1].len = len;
+ kxte9_msg[1].buf = i2c_read_buf;
+ wmt_i2c_transfer(kxte9_msg, 2, 0, kxte9_read_callback, 0);
+}
+
+static int kxte9_i2c_read(u8 addr, u8 *data, int len)
+{
+/*
+ int err;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = KXTE9_I2C_ADDR,
+ .flags = 0 & ~(I2C_M_RD), //te9->client->flags & I2C_M_TEN,
+ .len = 1,
+ .buf = &addr,
+ },
+ {
+ .addr = KXTE9_I2C_ADDR, //te9->client->addr,
+ .flags = (I2C_M_RD), //(te9->client->flags & I2C_M_TEN) | I2C_M_RD,
+ .len = len,
+ .buf = data,
+ },
+ };
+ err = wmt_i2c_xfer_continue_if_4(msgs, 2, 0);
+
+ if(err != 2)
+ errlog("read transfer error\n");
+ else
+ err = 0;
+
+ return err;
+*/
+ int ret;
+ ret = i2c_api_do_recv(0, KXTE9_I2C_ADDR, addr, data, len);
+ if (ret <= 0) {
+ errlog("i2c_api_do_recv error!\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int kxte9_i2c_write(u8 addr, u8 *data, int len)
+{
+/*
+ int err;
+ int i;
+ u8 buf[len + 1];
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = KXTE9_I2C_ADDR, //te9->client->addr,
+ .flags = 0 & ~(I2C_M_RD), //te9->client->flags & I2C_M_TEN,
+ .len = len + 1,
+ .buf = buf,
+ },
+ };
+
+ buf[0] = addr;
+ for (i = 0; i < len; i++)
+ buf[i + 1] = data[i];
+
+ err = wmt_i2c_xfer_continue_if_4(msgs, 1, 0);
+ if(err != 1)
+ errlog("write transfer error\n");
+ else
+ err = 0;
+ return err;
+*/
+ int ret;
+ ret = i2c_api_do_send(0, KXTE9_I2C_ADDR, addr, data, len);
+ if (ret <= 0) {
+ errlog("i2c_api_do_send error!\n");
+ return -1;
+ }
+ return 0;
+
+}
+
+int kxte9_get_bits(u8 reg_addr, u8* bits_value, u8 bits_mask)
+{
+ int err;
+ u8 reg_data;
+
+ err = kxte9_i2c_read(reg_addr, &reg_data, 1);
+ kxte9_dbg("kxte9_i2c_read(%x, 1)=%x, err=%d\n", reg_addr, reg_data, err);
+ if(err < 0)
+ return err;
+
+ *bits_value = reg_data & bits_mask;
+
+ return 1;
+}
+
+int kxte9_get_byte(u8 reg_addr, u8* reg_value)
+{
+ int err;
+ u8 reg_data;
+
+ err = kxte9_i2c_read(reg_addr, &reg_data, 1);
+ kxte9_dbg("kxte9_i2c_read(%x, 1)=%x, err=%d\n", reg_addr, reg_data, err);
+ if(err < 0)
+ return err;
+
+ *reg_value = reg_data;
+
+ return 1;
+}
+
+int kxte9_set_bits(int res_index, u8 reg_addr, u8 bits_value, u8 bits_mask)
+{
+ int err=0, err1=0, retval=0;
+ u8 reg_data = 0x00, reg_bits = 0x00, bits_set = 0x00;
+
+ // Turn off PC1
+ reg_data = te9->resume[RES_CTRL_REG1] & ~PC1_ON;
+
+ err = kxte9_i2c_write(CTRL_REG1, &reg_data, 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", CTRL_REG1, reg_data, err);
+ if(err < 0)
+ goto exit0;
+
+ // Read from device register
+ err = kxte9_i2c_read(reg_addr, &reg_data, 1);
+ kxte9_dbg("kxte9_i2c_read(%x, 1)=%x, err=%d\n", reg_addr, reg_data, err);
+ if(err < 0)
+ goto exit0;
+
+ // Apply mask to device register;
+ reg_bits = reg_data & bits_mask;
+
+ // Update resume state data
+ bits_set = bits_mask & bits_value;
+ te9->resume[res_index] &= ~bits_mask;
+ te9->resume[res_index] |= bits_set;
+
+ // Return 0 if value in device register and value to be written is the same
+ if(reg_bits == bits_set)
+ retval = 0;
+ // Else, return 1
+ else
+ retval = 1;
+
+ // Write to device register
+ err = kxte9_i2c_write(reg_addr, &te9->resume[res_index], 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", reg_addr, te9->resume[res_index], err);
+ if(err < 0)
+ goto exit0;
+
+exit0:
+ // Turn on PC1
+ reg_data = te9->resume[RES_CTRL_REG1] | PC1_ON;
+
+ err1 = kxte9_i2c_write(CTRL_REG1, &reg_data, 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", CTRL_REG1, reg_data, err);
+ if(err1 < 0)
+ return err1;
+
+ if(err < 0)
+ return err;
+
+ return retval;
+}
+
+int kxte9_set_byte(int res_index, u8 reg_addr, u8 reg_value)
+{
+ int err, err1, retval=0;
+ u8 reg_data;
+
+ // Turn off PC1
+ reg_data = te9->resume[RES_CTRL_REG1] & ~PC1_ON;
+
+ err = kxte9_i2c_write(CTRL_REG1, &reg_data, 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", CTRL_REG1, reg_data, err);
+ if(err < 0)
+ goto exit0;
+
+ // Read from device register
+ err = kxte9_i2c_read(reg_addr, &reg_data, 1);
+ kxte9_dbg("kxte9_i2c_read(%x, 1)=%x, err=%d\n", reg_addr, reg_data, err);
+ if(err < 0)
+ goto exit0;
+
+ // Update resume state data
+ te9->resume[res_index] = reg_value;
+
+ // Return 0 if value in device register and value to be written is the same
+ if(reg_data == reg_value)
+ retval = 0;
+ // Else, return 1
+ else
+ retval = 1;
+
+ // Write to device register
+ err = kxte9_i2c_write(reg_addr, &te9->resume[res_index], 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", reg_addr, te9->resume[res_index], err);
+ if(err < 0)
+ goto exit0;
+
+exit0:
+ // Turn on PC1
+ reg_data = te9->resume[RES_CTRL_REG1] | PC1_ON;
+ err1 = kxte9_i2c_write(CTRL_REG1, &reg_data, 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", CTRL_REG1, reg_data, err);
+ if(err1 < 0)
+ return err1;
+
+ if(err < 0)
+ return err;
+
+ return retval;
+}
+
+int kxte9_set_pc1_off(void)
+{
+ u8 reg_data;
+
+ reg_data = te9->resume[RES_CTRL_REG1] & ~PC1_ON;
+
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1)\n", CTRL_REG1, reg_data);
+ return kxte9_i2c_write(CTRL_REG1, &reg_data, 1);
+}
+
+int kxte9_set_pc1_on(void)
+{
+ u8 reg_data;
+
+ reg_data = te9->resume[RES_CTRL_REG1] | PC1_ON;
+
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1)\n", CTRL_REG1, reg_data);
+ return kxte9_i2c_write(CTRL_REG1, &reg_data, 1);
+}
+
+static int kxte9_verify(void)
+{
+ int err;
+ u8 buf;
+
+ err = kxte9_i2c_read(WHO_AM_I, &buf, 1);
+ kxte9_dbg("kxte9_i2c_read(%x, 1)=%x, err=%d\n", WHO_AM_I, buf, err);
+ if(err < 0)
+ errlog( "read err int source\n");
+ if(buf != 0)
+ err = -1;
+ return err;
+}
+
+static int kxte9_hw_init(void)
+{
+ int err;
+ u8 buf = PC1_OFF;
+
+ err = kxte9_i2c_write(CTRL_REG1, &buf, 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", CTRL_REG1, buf, err);
+ if(err < 0)
+ return err;
+ err = kxte9_i2c_write(CTRL_REG3, &te9->resume[RES_CTRL_REG3], 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", CTRL_REG3, te9->resume[RES_CTRL_REG3], err);
+ if(err < 0)
+ return err;
+ err = kxte9_i2c_write(INT_CTRL1, &te9->resume[RES_INT_CTRL1], 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", INT_CTRL1, te9->resume[RES_INT_CTRL1], err);
+ if(err < 0)
+ return err;
+ err = kxte9_i2c_write(TILT_TIMER, &te9->resume[RES_TILT_TIMER], 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", TILT_TIMER, te9->resume[RES_TILT_TIMER], err);
+ if(err < 0)
+ return err;
+ err = kxte9_i2c_write(WUF_TIMER, &te9->resume[RES_WUF_TIMER], 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", WUF_TIMER, te9->resume[RES_WUF_TIMER], err);
+ if(err < 0)
+ return err;
+ err = kxte9_i2c_write(B2S_TIMER, &te9->resume[RES_B2S_TIMER], 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", B2S_TIMER, te9->resume[RES_B2S_TIMER], err);
+ if(err < 0)
+ return err;
+ err = kxte9_i2c_write(WUF_THRESH, &te9->resume[RES_WUF_THRESH], 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", WUF_THRESH, te9->resume[RES_WUF_THRESH], err);
+ if(err < 0)
+ return err;
+ err = kxte9_i2c_write(B2S_THRESH, &te9->resume[RES_B2S_THRESH], 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", B2S_THRESH, te9->resume[RES_B2S_THRESH], err);
+ if(err < 0)
+ return err;
+ buf = te9->resume[RES_CTRL_REG1] | PC1_ON;
+ err = kxte9_i2c_write(CTRL_REG1, &buf, 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", CTRL_REG1, buf, err);
+ if(err < 0)
+ return err;
+
+ te9->resume[RES_CTRL_REG1] = buf;
+ te9->hw_initialized = 1;
+
+ return 0;
+}
+
+static void kxte9_device_power_off(void)
+{
+ int err;
+ u8 buf = PC1_OFF;
+
+ err = kxte9_i2c_write(CTRL_REG1, &buf, 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1), err=%d\n", CTRL_REG1, buf, err);
+ if(err < 0)
+ errlog("soft power off failed\n");
+#ifdef INT_MODE
+ ENABLE_SENSOR_INT(0);
+// disable_irq(gconf.irq);
+#endif
+ te9->hw_initialized = 0;
+}
+
+static int kxte9_device_power_on(void)
+{
+ int err;
+
+ if(!te9->hw_initialized) {
+ //mdelay(110);
+ err = kxte9_hw_init();
+ if(err < 0) {
+ kxte9_device_power_off();
+ return err;
+ }
+ }
+#ifdef INT_MODE
+ ENABLE_SENSOR_INT(1);
+// enable_irq(gconf.irq);
+#endif
+ return 0;
+}
+
+static u8 kxte9_resolve_dir(u8 dir)
+{
+ switch (dir) {
+ case 0x20: /* -X */
+ if (gconf.xyz_axis[ABS_X][1] < 0)
+ dir = 0x10;
+ if (gconf.xyz_axis[ABS_Y][0] == 0)
+ dir >>= 2;
+ if (gconf.xyz_axis[ABS_Z][0] == 0)
+ dir >>= 4;
+ break;
+ case 0x10: /* +X */
+ if (gconf.xyz_axis[ABS_X][1] < 0)
+ dir = 0x20;
+ if (gconf.xyz_axis[ABS_Y][0] == 0)
+ dir >>= 2;
+ if (gconf.xyz_axis[ABS_Z][0] == 0)
+ dir >>= 4;
+ break;
+ case 0x08: /* -Y */
+ if (gconf.xyz_axis[ABS_Y][1] < 0)
+ dir = 0x04;
+ if (gconf.xyz_axis[ABS_X][0] == 1)
+ dir <<= 2;
+ if (gconf.xyz_axis[ABS_Z][0] == 1)
+ dir >>= 2;
+ break;
+ case 0x04: /* +Y */
+ if (gconf.xyz_axis[ABS_Y][1] < 0)
+ dir = 0x08;
+ if (gconf.xyz_axis[ABS_X][0] == 1)
+ dir <<= 2;
+ if (gconf.xyz_axis[ABS_Z][0] == 1)
+ dir >>= 2;
+ break;
+ case 0x02: /* -Z */
+ if (gconf.xyz_axis[ABS_Z][1] < 0)
+ dir = 0x01;
+ if (gconf.xyz_axis[ABS_X][0] == 2)
+ dir <<= 4;
+ if (gconf.xyz_axis[ABS_Y][0] == 2)
+ dir <<= 2;
+ break;
+ case 0x01: /* +Z */
+ if (gconf.xyz_axis[ABS_Z][1] < 0)
+ dir = 0x02;
+ if (gconf.xyz_axis[ABS_X][0] == 2)
+ dir <<= 4;
+ if (gconf.xyz_axis[ABS_Y][0] == 2)
+ dir <<= 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return dir;
+}
+
+#ifdef INT_MODE
+static void kxte9_irq_work_func(struct work_struct *work)
+{
+/*
+ * int_status output:
+ * [INT_SRC_REG1][INT_SRC_REG2][TILT_POS_PRE][TILT_POS_CUR]
+ * INT_SRC_REG2, TILT_POS_PRE, and TILT_POS_CUR directions are translated
+ * based on platform data variables.
+ */
+
+ int err;
+ int i;
+ int int_status = 0;
+ u8 status;
+ u8 b2s_comp;
+ u8 wuf_comp;
+ u8 buf[2];
+
+ err = kxte9_i2c_read(INT_STATUS_REG, &status, 1);
+ kxte9_dbg("kxte9_i2c_read(%x, 1)=%x, err=%d\n", INT_STATUS_REG, status, err);
+ if(err < 0)
+ errlog("read err int source\n");
+ int_status = status << 24;
+ if((status & TPS) > 0) {
+ err = kxte9_i2c_read(TILT_POS_CUR, buf, 2);
+ kxte9_dbg("kxte9_i2c_read(%x, 2)=%x,%x, err=%d\n", TILT_POS_CUR, buf[0], buf[1], err);
+ if(err < 0)
+ errlog("read err tilt dir\n");
+ int_status |= kxte9_resolve_dir(buf[0]);
+ int_status |= (kxte9_resolve_dir(buf[1])) << 8;
+ kxte9_dbg("IRQ TILT [%x]\n", kxte9_resolve_dir(buf[0]));
+ }
+ if((status & WUFS) > 0) {
+ kxte9_dbg("for WUFS\n");
+ err = kxte9_i2c_read(INT_SRC_REG2, buf, 1);
+ kxte9_dbg("kxte9_i2c_read(%x, 1)=%x, err=%d\n", INT_SRC_REG2, buf[0], err);
+ if(err < 0)
+ kxte9_dbg("reading err wuf dir\n");
+ int_status |= (kxte9_resolve_dir(buf[0])) << 16;
+ b2s_comp = (te9->resume[RES_CTRL_REG3] & 0x0C) >> 2;
+ wuf_comp = te9->resume[RES_CTRL_REG3] & 0x03;
+ if(!te9->resume[RES_CURRENT_ODR] &&
+ !(te9->resume[RES_CTRL_REG1] & ODR125E) &&
+ !(b2s_comp & wuf_comp)) {
+ /* set the new poll interval based on wuf odr */
+ for (i = 0; i < ARRAY_SIZE(kxte9_odr_table); i++) {
+ if(kxte9_odr_table[i].mask == wuf_comp << 3) {
+ te9->pdata->poll_interval = kxte9_odr_table[i].interval;
+ break;
+ }
+ }
+ if(te9->input_dev) {
+ cancel_delayed_work_sync(&te9->input_work);
+ schedule_delayed_work(&te9->input_work,
+ msecs_to_jiffies(te9->pdata->poll_interval));
+ }
+ }
+ }
+ if((status & B2SS) > 0) {
+ kxte9_dbg("fro B2SS\n");
+ b2s_comp = (te9->resume[RES_CTRL_REG3] & 0x0C) >> 2;
+ wuf_comp = te9->resume[RES_CTRL_REG3] & 0x03;
+ if(!te9->resume[RES_CURRENT_ODR] &&
+ !(te9->resume[RES_CTRL_REG1] & ODR125E) &&
+ !(b2s_comp & wuf_comp)) {
+ /* set the new poll interval based on b2s odr */
+ for (i = 1; i < ARRAY_SIZE(kxte9_odr_table); i++) {
+ if(kxte9_odr_table[i].mask == b2s_comp << 3) {
+ te9->pdata->poll_interval = kxte9_odr_table[i].interval;
+ break;
+ }
+ }
+ if(te9->input_dev) {
+ cancel_delayed_work_sync(&te9->input_work);
+ schedule_delayed_work(&te9->input_work,
+ msecs_to_jiffies(te9->pdata->poll_interval));
+ }
+ }
+ }
+ input_report_abs(te9->input_dev, ABS_MISC, int_status);
+ input_sync(te9->input_dev);
+ err = kxte9_i2c_read(INT_REL, buf, 1);
+ kxte9_dbg("kxte9_i2c_read(%x, 1)=%x, err=%d\n", INT_REL, buf[0], err);
+ if(err < 0)
+ errlog("error clearing interrupt\n");
+ //enable_irq(gconf.irq);
+}
+
+static irqreturn_t kxte9_isr(int irq, void *dev)
+{
+ unsigned int status = REG32_VAL(gconf.isaddr);
+
+ // clr int status ...??
+ if ((status & gconf.isbmp) != 0)
+ {
+ kxte9_dbg("\n");
+ REG32_VAL(gconf.isaddr) |= gconf.isbmp;
+ udelay(5);
+ // disable int and satrt irq work
+ disable_irq_nosync(irq);
+ schedule_work(&te9->irq_work);
+ return IRQ_HANDLED;
+ }
+ return IRQ_NONE;
+}
+#endif
+
+static int kxte9_update_odr(int poll_interval)
+{
+ int err = -1;
+ int i;
+ u8 config;
+
+ /* Convert the poll interval into an output data rate configuration
+ * that is as low as possible. The ordering of these checks must be
+ * maintained due to the cascading cut off values - poll intervals are
+ * checked from shortest to longest. At each check, if the next lower
+ * ODR cannot support the current poll interval, we stop searching */
+ for (i = 0; i < ARRAY_SIZE(kxte9_odr_table); i++) {
+ config = kxte9_odr_table[i].mask;
+ if(poll_interval >= kxte9_odr_table[i].interval)
+ break;
+ }
+
+ config |= (te9->resume[RES_CTRL_REG1] & ~(ODR40E | ODR125E));
+ te9->resume[RES_CTRL_REG1] = config;
+ if(atomic_read(&te9->enabled)) {
+ err = kxte9_set_byte(RES_CTRL_REG1, CTRL_REG1, config);
+ if(err < 0)
+ return err;
+ }
+ klog("Set new ODR to 0x%02X\n", config);
+ return 0;
+}
+
+static void kxte9_input_work_func(unsigned long unused)
+{
+ //mutex_lock(&te9->lock);
+ if (te9->suspend)
+ return;
+ if (te9->i2c_xfer_complete) {
+ te9->i2c_xfer_complete = 0;
+ kxte9_read_data(XOUT, 3);
+ }
+ //mutex_unlock(&te9->lock);
+}
+
+static int kxte9_enable(void)
+{
+ int err;
+ int int_status = 0;
+ u8 buf;
+
+ if(!atomic_cmpxchg(&te9->enabled, 0, 1)) {
+ err = kxte9_device_power_on();
+ err = kxte9_i2c_read(INT_REL, &buf, 1);
+ kxte9_dbg("kxte9_i2c_read(%x, 1)=%x, err=%d\n", INT_REL, buf, err);
+ if(err < 0) {
+ errlog("error clearing interrupt: %d\n", err);
+ atomic_set(&te9->enabled, 0);
+ return err;
+ }
+ if((te9->resume[RES_CTRL_REG1] & TPS) > 0) {
+ err = kxte9_i2c_read(TILT_POS_CUR, &buf, 1);
+ kxte9_dbg("kxte9_i2c_read(%x, 1)=%x, err=%d\n", TILT_POS_CUR, buf, err);
+ if(err < 0)
+ errlog("kxte9 error reading current tilt\n");
+ int_status |= kxte9_resolve_dir(buf);
+ input_report_abs(te9->input_dev, ABS_MISC, int_status);
+ input_sync(te9->input_dev);
+ }
+ kxte9_msg = kzalloc(2*sizeof(struct i2c_msg), GFP_ATOMIC);
+ i2c_read_buf = kzalloc(3*sizeof(unsigned char), GFP_ATOMIC);
+ i2c_write_buf = kzalloc(sizeof(char), GFP_ATOMIC);
+ setup_timer(&kxte9_timer, kxte9_input_work_func, 0);
+ mod_timer(&kxte9_timer, jiffies + msecs_to_jiffies(te9->pdata->poll_interval));
+ kxte9_dbg("Enabled\n");
+ }
+ return 0;
+}
+
+static int kxte9_disable(void)
+{
+ if(atomic_cmpxchg(&te9->enabled, 1, 0)) {
+ del_timer_sync(&kxte9_timer);
+ wait_i2c_xfer_complete();
+ kfree(kxte9_msg);
+ kfree(i2c_read_buf);
+ kfree(i2c_write_buf);
+#ifdef WM3445_A0
+ ENABLE_SENSOR_INT(1);
+#endif
+ kxte9_device_power_off();
+ kxte9_dbg(" Disabled\n");
+ //#endif
+ }
+ return 0;
+}
+
+int kxte9_input_open(struct input_dev *input)
+{
+ kxte9_dbg("\n");
+ return kxte9_enable();
+}
+
+void kxte9_input_close(struct input_dev *dev)
+{
+ kxte9_dbg("\n");
+ kxte9_disable();
+}
+
+static int kxte9_input_init(void)
+{
+ int err;
+
+ te9->input_dev = input_allocate_device();
+ if(!te9->input_dev) {
+ err = -ENOMEM;
+ errlog("input device allocate failed\n");
+ goto err0;
+ }
+ te9->input_dev->open = kxte9_input_open;
+ te9->input_dev->close = kxte9_input_close;
+
+ input_set_drvdata(te9->input_dev, te9);
+
+ set_bit(EV_ABS, te9->input_dev->evbit);
+ set_bit(ABS_MISC, te9->input_dev->absbit);
+
+ input_set_abs_params(te9->input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
+ input_set_abs_params(te9->input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
+ input_set_abs_params(te9->input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
+
+ te9->input_dev->name = INPUT_NAME_ACC;
+
+ err = input_register_device(te9->input_dev);
+ if(err) {
+ errlog("unable to register input polled device %s: %d\n",
+ te9->input_dev->name, err);
+ goto err1;
+ }
+
+ return 0;
+err1:
+ input_free_device(te9->input_dev);
+err0:
+ return err;
+}
+
+static void kxte9_input_cleanup(void)
+{
+ input_unregister_device(te9->input_dev);
+}
+
+/* sysfs */
+static ssize_t kxte9_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", te9->pdata->poll_interval);
+}
+
+static ssize_t kxte9_delay_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int val = simple_strtoul(buf, NULL, 10);
+ u8 ctrl;
+
+ te9->pdata->poll_interval = max(val, te9->pdata->min_interval);
+ kxte9_update_odr(te9->pdata->poll_interval);
+ ctrl = te9->resume[RES_CTRL_REG1] & 0x18;
+ te9->resume[RES_CURRENT_ODR] = ctrl;
+ /* All ODRs are changed when this method is used. */
+ ctrl = (ctrl >> 1) | (ctrl >> 3);
+ kxte9_i2c_write(CTRL_REG3, &ctrl, 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1)\n", CTRL_REG3, ctrl);
+ te9->resume[RES_CTRL_REG3] = ctrl;
+ return count;
+}
+
+static ssize_t kxte9_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", atomic_read(&te9->enabled));
+}
+
+static ssize_t kxte9_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int val = simple_strtoul(buf, NULL, 10);
+ if(val)
+ kxte9_enable();
+ else
+ kxte9_disable();
+ return count;
+}
+
+static ssize_t kxte9_tilt_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 tilt;
+
+ if(te9->resume[RES_CTRL_REG1] & TPE) {
+ kxte9_i2c_read(TILT_POS_CUR, &tilt, 1);
+ kxte9_dbg("kxte9_i2c_read(%x, 1)=%x\n", TILT_POS_CUR, tilt);
+ return sprintf(buf, "%d\n", kxte9_resolve_dir(tilt));
+ } else {
+ return sprintf(buf, "%d\n", 0);
+ }
+}
+
+static ssize_t kxte9_tilt_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int val = simple_strtoul(buf, NULL, 10);
+ u8 ctrl;
+ if(val)
+ te9->resume[RES_CTRL_REG1] |= TPE;
+ else
+ te9->resume[RES_CTRL_REG1] &= (~TPE);
+ ctrl = te9->resume[RES_CTRL_REG1];
+ kxte9_i2c_write(CTRL_REG1, &ctrl, 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1)\n", CTRL_REG1, ctrl);
+ return count;
+}
+
+static ssize_t kxte9_wake_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u8 val = te9->resume[RES_CTRL_REG1] & WUFE;
+ if(val)
+ return sprintf(buf, "%d\n", 1);
+ else
+ return sprintf(buf, "%d\n", 0);
+}
+
+static ssize_t kxte9_wake_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int val = simple_strtoul(buf, NULL, 10);
+ u8 ctrl;
+ if(val)
+ te9->resume[RES_CTRL_REG1] |= (WUFE | B2SE);
+ else
+ te9->resume[RES_CTRL_REG1] &= (~WUFE & ~B2SE);
+ ctrl = te9->resume[RES_CTRL_REG1];
+ kxte9_i2c_write(CTRL_REG1, &ctrl, 1);
+ kxte9_dbg("kxte9_i2c_write(%x, %x, 1)\n", CTRL_REG1, ctrl);
+ return count;
+}
+
+static ssize_t kxte9_selftest_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int val = simple_strtoul(buf, NULL, 10);
+ u8 ctrl = 0x00;
+ if(val)
+ ctrl = 0xCA;
+ kxte9_i2c_write(0x3A, &ctrl, 1);
+ kxte9_dbg("kxte9_i2c_write(0x3A, %x, 1)\n", ctrl);
+ return count;
+}
+
+static DEVICE_ATTR(delay, S_IRUGO|S_IWUSR, kxte9_delay_show, kxte9_delay_store);
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR, kxte9_enable_show,
+ kxte9_enable_store);
+static DEVICE_ATTR(tilt, S_IRUGO|S_IWUSR, kxte9_tilt_show, kxte9_tilt_store);
+static DEVICE_ATTR(wake, S_IRUGO|S_IWUSR, kxte9_wake_show, kxte9_wake_store);
+static DEVICE_ATTR(selftest, S_IWUSR, NULL, kxte9_selftest_store);
+
+static struct attribute *kxte9_attributes[] = {
+ &dev_attr_delay.attr,
+ &dev_attr_enable.attr,
+ &dev_attr_tilt.attr,
+ &dev_attr_wake.attr,
+ &dev_attr_selftest.attr,
+ NULL
+};
+
+static struct attribute_group kxte9_attribute_group = {
+ .attrs = kxte9_attributes
+};
+/* /sysfs */
+
+static int kxte9_get_count(char *buf, int bufsize)
+{
+ const char ACC_REG_SIZE = 3;
+ int err;
+ /* Data bytes from hardware xL, xH, yL, yH, zL, zH */
+ u8 acc_data[ACC_REG_SIZE];
+ /* x,y,z hardware values */
+ int xyz[3];
+
+ if((!buf)||(bufsize<=(sizeof(xyz)*3)))
+ return -1;
+
+ err = kxte9_i2c_read(XOUT, acc_data, ACC_REG_SIZE);
+ kxte9_dbg("kxte9_i2c_read(%x, %x)=%x,%x,%x, err=%d\n", XOUT, ACC_REG_SIZE,
+ acc_data[0], acc_data[1], acc_data[2], err);
+ if(err < 0)
+ return err;
+
+ sprintf(buf, "%d %d %d", acc_data[0], acc_data[1], acc_data[2]);
+
+ return err;
+}
+
+static int kxte9_get_mg(char *buf, int bufsize)
+{
+ const char ACC_REG_SIZE = 3;
+ int err;
+ /* Data bytes from hardware xL, xH, yL, yH, zL, zH */
+ u8 acc_data[ACC_REG_SIZE];
+ /* x,y,z hardware values */
+ int xyz[3], mg[3];
+
+ if((!buf)||(bufsize<=(sizeof(mg))))
+ return -1;
+
+ err = kxte9_i2c_read(XOUT, acc_data, ACC_REG_SIZE);
+ kxte9_dbg("kxte9_i2c_read(%x, %x)=%x,%x,%x, err=%x\n", XOUT, ACC_REG_SIZE,
+ acc_data[0], acc_data[1], acc_data[2], err);
+ if(err < 0)
+ return err;
+
+ xyz[0] = ((int)(acc_data[0]) - OFFSET) << 4;
+ xyz[1] = ((int)(acc_data[1]) - OFFSET) << 4;
+ xyz[2] = ((int)(acc_data[2]) - OFFSET) << 4;
+
+ mg[0] = X_CONVERT(xyz[gconf.xyz_axis[ABS_X][0]]);
+ mg[1] = Y_CONVERT(xyz[gconf.xyz_axis[ABS_Y][0]]);
+ mg[2] = Z_CONVERT(xyz[gconf.xyz_axis[ABS_Z][0]]);
+
+ sprintf(buf, "%d %d %d",mg[0], mg[1], mg[2]);
+
+ kxte9_dbg(" [%5d] [%5d] [%5d]\n", mg[0], mg[1], mg[2]);
+
+ return err;
+}
+
+static void kxte9_dump_reg(void)
+{
+ u8 regval = 0;
+
+ klog("**********************kxte9 reg val***************\n");
+ // ct_resp
+ kxte9_i2c_read(CT_RESP, &regval, 1);
+ klog("ct_resp:0x%x\n", regval);
+ // who_am_i
+ kxte9_i2c_read(WHO_AM_I, &regval, 1);
+ klog("who_am_i:0x%x\n", regval);
+ // tilt_pos_cur
+ kxte9_i2c_read(TILT_POS_CUR, &regval, 1);
+ klog("tilt_pos_cur:0x%x\n", regval);
+ // int_src_reg1
+ kxte9_i2c_read(INT_STATUS_REG, &regval, 1);
+ klog("int_src_reg1:0x%x\n", regval);
+ // int_src_reg2
+ kxte9_i2c_read(INT_SRC_REG2, &regval, 1);
+ klog("int_src_reg2:0x%x\n", regval);
+ // status_reg
+ kxte9_i2c_read(0x18, &regval, 1);
+ klog("status_reg:0x%x\n", regval);
+ // int_rel
+ kxte9_i2c_read(INT_REL, &regval, 1);
+ klog("int_rel:0x%x\n", regval);
+ // ctrl_reg1
+ kxte9_i2c_read(CTRL_REG1, &regval, 1);
+ klog("ctrl_reg1:0x%x\n", regval);
+ // ctrl_reg2
+ kxte9_i2c_read(CTRL_REG2, &regval, 1);
+ klog("ctrl_reg2:0x%x\n", regval);
+ // ctrl_reg3
+ kxte9_i2c_read(CTRL_REG3, &regval, 1);
+ klog("ctrl_reg3:0x%x\n", regval);
+ // int_ctrl_reg1
+ kxte9_i2c_read(INT_CTRL1, &regval, 1);
+ klog("int_ctrl_reg1:0x%x\n", regval);
+ // int_ctrl_reg2
+ kxte9_i2c_read(0x1F, &regval, 1);
+ klog("int_ctrl_reg2:0x%x\n", regval);
+ // tilt_timer
+ kxte9_i2c_read(TILT_TIMER, &regval, 1);
+ klog("tilt_timer:0x%x\n", regval);
+ // wuf_timer
+ kxte9_i2c_read(WUF_TIMER, &regval, 1);
+ klog("wuf_timer:0x%x\n", regval);
+ // b2s_timer
+ kxte9_i2c_read(B2S_TIMER, &regval, 1);
+ klog("b2s_timer:0x%x\n", regval);
+ // wuf_thresh
+ kxte9_i2c_read(WUF_THRESH, &regval, 1);
+ klog("wuf_thresh:0x%x\n", regval);
+ // b2s_thresh
+ kxte9_i2c_read(B2S_THRESH, &regval, 1);
+ klog("b2s_thresh:0x%x\n", regval);
+ // tilt_angle
+ kxte9_i2c_read(0x5c, &regval, 1);
+ klog("tilt_angle:0x%x\n", regval);
+ // hyst_set
+ kxte9_i2c_read(0x5f, &regval, 1);
+ klog("hyst_set:0x%x\n", regval);
+ klog("**********************************************************");
+}
+
+static int kxte9_open(struct inode *inode, struct file *file)
+{
+ int ret = -1;
+
+ if(kxte9_enable() < 0)
+ return ret;
+
+ atomic_inc(&kxte9_dev_open_count);
+ kxte9_dbg("opened %d times\n",\
+ atomic_read(&kxte9_dev_open_count));
+ kxte9_dump_reg();
+ return 0;
+}
+
+static int kxte9_release(struct inode *inode, struct file *file)
+{
+ int open_count;
+
+ atomic_dec(&kxte9_dev_open_count);
+ open_count = (int)atomic_read(&kxte9_dev_open_count);
+
+ if(open_count == 0)
+ kxte9_disable();
+
+ kxte9_dbg("opened %d times\n",\
+ atomic_read(&kxte9_dev_open_count));
+ return 0;
+}
+
+static int kxte9_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ char buffer[IOCTL_BUFFER_SIZE];
+ void __user *data;
+ u8 reg_buffer = 0x00;
+ const u8 set = 0xFF, unset = 0x00;
+ int retval=0, val_int=0;
+ short val_short=0;
+
+ switch (cmd) {
+ case KXTE9_IOCTL_GET_COUNT:
+ data = (void __user *) arg;
+ if(data == NULL){
+ retval = -EFAULT;
+ goto err_out;
+ }
+ retval = kxte9_get_count(buffer, sizeof(buffer));
+ if(retval < 0)
+ goto err_out;
+
+ if(copy_to_user(data, buffer, sizeof(buffer))) {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ break;
+
+ case KXTE9_IOCTL_GET_MG:
+ data = (void __user *) arg;
+ if(data == NULL){
+ retval = -EFAULT;
+ goto err_out;
+ }
+ retval = kxte9_get_mg(buffer, sizeof(buffer));
+ if(retval < 0)
+ goto err_out;
+
+ if(copy_to_user(data, buffer, sizeof(buffer))) {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ break;
+
+ case KXTE9_IOCTL_ENABLE_OUTPUT:
+ retval = kxte9_set_pc1_on();
+ if(retval < 0)
+ goto err_out;
+ break;
+
+ case KXTE9_IOCTL_DISABLE_OUTPUT:
+ retval = kxte9_set_pc1_off();
+ if(retval < 0)
+ goto err_out;
+ break;
+
+ case KXTE9_IOCTL_GET_ENABLE:
+ data = (void __user *) arg;
+ if(data == NULL){
+ retval = -EFAULT;
+ goto err_out;
+ }
+ retval = kxte9_get_bits(CTRL_REG1, &reg_buffer, PC1_ON);
+ if(retval < 0)
+ goto err_out;
+
+ val_short = (short)reg_buffer;
+
+ if(copy_to_user(data, &val_short, sizeof(val_short))) {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ break;
+
+ case KXTE9_IOCTL_RESET:
+ retval = kxte9_set_bits(RES_CTRL_REG3, CTRL_REG3, set, SRST);
+ if(retval < 0)
+ goto err_out;
+ break;
+
+ case KXTE9_IOCTL_UPDATE_ODR:
+ data = (void __user *) arg;
+ if(data == NULL){
+ retval = -EFAULT;
+ goto err_out;
+ }
+ if(copy_from_user(&val_int, data, sizeof(val_int))) {
+ retval = -EFAULT;
+ goto err_out;
+ }
+
+ mutex_lock(&te9->lock);
+ te9->pdata->poll_interval = max(val_int, te9->pdata->min_interval);
+ mutex_unlock(&te9->lock);
+
+ retval = kxte9_update_odr(te9->pdata->poll_interval);
+ if(retval < 0)
+ goto err_out;
+ break;
+
+ case KXTE9_IOCTL_ENABLE_CTC:
+ retval = kxte9_set_bits(RES_CTRL_REG3, CTRL_REG3, set, CTC);
+ if(retval < 0)
+ goto err_out;
+ break;
+
+ case KXTE9_IOCTL_DISABLE_CTC:
+ retval = kxte9_set_bits(RES_CTRL_REG3, CTRL_REG3, unset, CTC);
+ if(retval < 0)
+ goto err_out;
+ break;
+
+ case KXTE9_IOCTL_GET_CT_RESP:
+ data = (void __user *) arg;
+ if(data == NULL){
+ retval = -EFAULT;
+ goto err_out;
+ }
+ retval = kxte9_get_byte(CT_RESP, &reg_buffer);
+ if(retval < 0)
+ goto err_out;
+
+ buffer[0] = (char)reg_buffer;
+ if(copy_to_user(data, buffer, sizeof(buffer))) {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ break;
+
+ default:
+ retval = -ENOIOCTLCMD;
+ break;
+ }
+
+err_out:
+ return retval;
+}
+
+static struct file_operations kxte9_fops = {
+ .owner = THIS_MODULE,
+ .open = kxte9_open,
+ .release = kxte9_release,
+ //.ioctl = kxte9_ioctl,
+};
+
+static struct miscdevice kxte9_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = NAME_DEV,
+ .fops = &kxte9_fops,
+};
+
+static int kxte9_probe(void)
+{
+ int err = -1;
+
+ te9 = kzalloc(sizeof(*te9), GFP_KERNEL);
+ if(te9 == NULL) {
+ errlog("failed to allocate memory for module data\n");
+ err = -ENOMEM;
+ goto err0;
+ }
+ te9->pdata = &kxte9_pdata;
+ mutex_init(&te9->lock);
+ mutex_lock(&te9->lock);
+
+ x_count = kzalloc(gconf.avg_count, GFP_KERNEL);
+ y_count = kzalloc(gconf.avg_count, GFP_KERNEL);
+ z_count = kzalloc(gconf.avg_count, GFP_KERNEL);
+
+ if ((1000000/gconf.samp)%1000)
+ te9->pdata->poll_interval = 1000/gconf.samp + 1;
+ else
+ te9->pdata->poll_interval = 1000/gconf.samp;
+ printk(KERN_INFO "G-Sensor Time Interval: %d ms\n", te9->pdata->poll_interval);
+
+ android_gsensor_kobj = kobject_create_and_add("kxte9_gsensor", NULL);
+ if (android_gsensor_kobj == NULL) {
+ errlog("gsensor_sysfs_init:subsystem_register failed\n");
+ err = -ENOMEM;
+ goto err0;
+ }
+
+ err = sysfs_create_group(android_gsensor_kobj, &kxte9_attribute_group);
+ if(err)
+ goto err1;
+
+ if(te9->pdata->init) {
+ err = te9->pdata->init();
+ if(err < 0)
+ goto err2;
+ }
+
+ memset(te9->resume, 0, ARRAY_SIZE(te9->resume));
+ te9->resume[RES_CTRL_REG1] = te9->pdata->ctrl_reg1_init;
+ te9->resume[RES_CTRL_REG3] = te9->pdata->engine_odr_init;
+ te9->resume[RES_INT_CTRL1] = te9->pdata->int_ctrl_init;
+ te9->resume[RES_TILT_TIMER] = te9->pdata->tilt_timer_init;
+ te9->resume[RES_WUF_TIMER] = te9->pdata->wuf_timer_init;
+ te9->resume[RES_B2S_TIMER] = te9->pdata->b2s_timer_init;
+ te9->resume[RES_WUF_THRESH] = te9->pdata->wuf_thresh_init;
+ te9->resume[RES_B2S_THRESH] = te9->pdata->b2s_thresh_init;
+ te9->hw_initialized = 0;
+ te9->i2c_xfer_complete = 1;
+
+#ifdef INT_MODE
+ // init gpio
+ SET_GPIO_GSENSOR_INT();
+ INIT_WORK(&te9->irq_work, kxte9_irq_work_func);
+#endif
+
+ err = kxte9_device_power_on();
+ if(err < 0)
+ goto err3;
+ atomic_set(&te9->enabled, 1);
+
+ err = kxte9_verify();
+ if(err < 0) {
+ errlog("kxte9_verify failed\n");
+ goto err4;
+ }
+
+ err = kxte9_update_odr(te9->pdata->poll_interval);
+ if(err < 0) {
+ errlog("update_odr failed\n");
+ goto err4;
+ }
+
+ err = kxte9_input_init();
+ if(err < 0)
+ goto err4;
+
+ err = misc_register(&kxte9_device);
+ if(err) {
+ errlog("misc. device failed to register.\n");
+ goto err5;
+ }
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ te9->earlysuspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ te9->earlysuspend.suspend = kxte9_early_suspend;
+ te9->earlysuspend.resume = kxte9_late_resume;
+ register_early_suspend(&te9->earlysuspend);
+#endif
+
+ atomic_set(&te9->enabled, 0);
+
+#ifdef INT_MODE
+ err = request_irq(gconf.irq, kxte9_isr,
+ IRQF_TRIGGER_RISING | IRQF_DISABLED, "kxte9_irq", te9);
+ if(err < 0) {
+ pr_err("%s: request irq failed: %d\n", __func__, err);
+ goto err6;
+ }
+
+#ifdef WM3445_A0
+ // enable int
+ ENABLE_SENSOR_INT(1);
+#endif
+
+ // enable kxte9
+ /*err = kxte9_enable();
+ if (err < 0) {
+ errlog("kxte9_enable failed.\n");
+ goto err6;
+ }*/
+#endif
+
+ mutex_unlock(&te9->lock);
+ //kxte9_dump_reg();
+
+ return 0;
+
+#ifdef INT_MODE
+err6:
+ misc_deregister(&kxte9_device);
+#endif
+err5:
+ kxte9_input_cleanup();
+err4:
+ kxte9_device_power_off();
+err3:
+ if(te9->pdata->exit)
+ te9->pdata->exit();
+err2:
+ //kfree(te9->pdata);
+ sysfs_remove_group(android_gsensor_kobj, &kxte9_attribute_group);
+err1:
+ kobject_del(android_gsensor_kobj);
+ mutex_unlock(&te9->lock);
+ kfree(te9);
+err0:
+ return err;
+}
+
+static int kxte9_remove(void)
+{
+ cancel_delayed_work_sync(&te9->input_work);
+#ifdef INT_MODE
+ free_irq(gconf.irq, te9);
+#endif
+ kxte9_input_cleanup();
+ misc_deregister(&kxte9_device);
+ kxte9_device_power_off();
+ if(te9->pdata->exit)
+ te9->pdata->exit();
+ kobject_del(android_gsensor_kobj);
+ sysfs_remove_group(android_gsensor_kobj, &kxte9_attribute_group);
+ kfree(te9);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+#if 0
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void kxte9_early_suspend(struct early_suspend *h)
+{
+ kxte9_dbg("start\n");
+ te9->suspend = 1;
+ kxte9_disable();
+ kxte9_dbg("exit\n");
+}
+
+static void kxte9_late_resume(struct early_suspend *h)
+{
+ kxte9_dbg("start\n");
+ te9->suspend = 0;
+ kxte9_enable();
+ kxte9_dbg("exit\n");
+}
+#endif
+#endif
+static int kxte9_resume(struct platform_device *pdev)
+{
+ te9->suspend = 0;
+ kxte9_enable();
+ return 0;
+}
+
+static int kxte9_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ te9->suspend = 1;
+ kxte9_disable();
+ return 0;
+}
+#endif
+
+static void kxte9_platform_release(struct device *device)
+{
+ kxte9_dbg("Do nothing!!!\n");
+ return;
+}
+
+static struct platform_device kxte9_plt_device = {
+ .name = "kxte9",
+ .id = 0,
+ .dev = {
+ .release = kxte9_platform_release,
+ },
+};
+
+static struct platform_driver kxte9_plt_driver = {
+ .probe = NULL, //kxte9_probe,
+ .remove = NULL, //kxte9_remove,
+ .suspend = kxte9_suspend,
+ .resume = kxte9_resume,
+ .driver = {
+ .name = "kxte9",
+ },
+};
+
+/*
+ * Get the configure of sensor from u-boot.
+ * Return: 1--success, 0--error.
+ */
+static int get_axisset(void)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.gsensor", varbuf, &varlen)) {
+ printk(KERN_DEBUG "KXTE9: wmt.io.gsensor not defined!\n");
+ return 0;
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &gconf.op,
+ &gconf.samp,
+ &(gconf.xyz_axis[0][0]),
+ &(gconf.xyz_axis[0][1]),
+ &(gconf.xyz_axis[1][0]),
+ &(gconf.xyz_axis[1][1]),
+ &(gconf.xyz_axis[2][0]),
+ &(gconf.xyz_axis[2][1]),
+ &gconf.avg_count,
+ &gconf.kxte9_8bit);
+
+ if (n != 10) {
+ kxte9_dbg(KERN_ERR "KXTE9: wmt.io.gsensor format is incorrect!\n");
+ return 0;
+ }
+ }
+ if (gconf.op != 1)
+ return 0;
+ printk(KERN_INFO "KXTE9 G-Sensor driver init\n");
+ kxte9_dbg("AVG Count: %d, KXTE9 8bit: %d\n",
+ gconf.avg_count,
+ gconf.kxte9_8bit);
+ if (gconf.samp > 100) {
+ printk(KERN_ERR "Sample Rate can't be greater than 100 !\n");
+ gconf.samp = 100;
+ }
+ if (gconf.avg_count == 0)
+ gconf.avg_count = 1;
+ if (gconf.kxte9_8bit > 1)
+ gconf.kxte9_8bit = 1;
+ kxte9_dbg("wmt.io.gsensor = %d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ gconf.op,
+ gconf.samp,
+ gconf.xyz_axis[0][0],
+ gconf.xyz_axis[0][1],
+ gconf.xyz_axis[1][0],
+ gconf.xyz_axis[1][1],
+ gconf.xyz_axis[2][0],
+ gconf.xyz_axis[2][1],
+ gconf.avg_count,
+ gconf.kxte9_8bit);
+ return 1;
+}
+
+static int get_gpioset(void)
+{
+ char varbuf[96];
+ int n;
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.gpt.gsensor", varbuf, &varlen)) {
+ printk(KERN_DEBUG "Can't get gsensor's gpio config from u-boot! -> Use default config\n");
+ return 0;
+ } else {
+ n = sscanf(varbuf, "%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x",
+ &gconf.name,
+ &gconf.bmp,
+ &(gconf.ctraddr),
+ &(gconf.ocaddr),
+ &(gconf.idaddr),
+ &(gconf.peaddr),
+ &(gconf.pcaddr),
+ &(gconf.itbmp),
+ &(gconf.itaddr),
+ &(gconf.isbmp),
+ &(gconf.isaddr),
+ &(gconf.irq));
+ if (n != 12) {
+ printk(KERN_ERR "wmt.gpt.gsensor format is incorrect in u-boot!!!\n");
+ return 0;
+ }
+
+ gconf.ctraddr += WMT_MMAP_OFFSET;
+ gconf.ocaddr += WMT_MMAP_OFFSET;
+ gconf.idaddr += WMT_MMAP_OFFSET;
+ gconf.peaddr += WMT_MMAP_OFFSET;
+ gconf.pcaddr += WMT_MMAP_OFFSET;
+ gconf.itaddr += WMT_MMAP_OFFSET;
+ gconf.isaddr += WMT_MMAP_OFFSET;
+ }
+ return 1;
+}
+
+static int __init kxte9_init(void)
+{
+ int ret = 0;
+
+ // parsing u-boot arg
+ ret = get_axisset(); // get gsensor config from u-boot
+ if (!ret)
+ return -EINVAL;
+
+ get_gpioset();
+
+ // initail
+ if ((ret = kxte9_probe()) != 0) {
+ errlog(" Error for kxte9_probe !!!\n");
+ return ret;
+ }
+ atomic_set(&kxte9_dev_open_count, 0);
+
+ if ((ret = platform_device_register(&kxte9_plt_device)) != 0) {
+ errlog("Can't register kxte9_plt_device platform devcie!!!\n");
+ return ret;
+ }
+ if ((ret = platform_driver_register(&kxte9_plt_driver)) != 0) {
+ errlog("Can't register kxte9_plt_driver platform driver!!!\n");
+ return ret;
+ }
+ klog("gsensor_kxte9 driver is loaded successfully!\n");
+ return ret;
+}
+
+static void __exit kxte9_exit(void)
+{
+ platform_driver_unregister(&kxte9_plt_driver);
+ platform_device_unregister(&kxte9_plt_device);
+ atomic_set(&kxte9_dev_open_count, 0);
+ kxte9_remove();
+}
+
+module_init(kxte9_init);
+module_exit(kxte9_exit);
+
+MODULE_DESCRIPTION("KXTE9 accelerometer driver");
+MODULE_AUTHOR("Kuching Tan <kuchingtan@kionix.com>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(VERSION_DEV);
diff --git a/ANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/kxte9.h b/ANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/kxte9.h
new file mode 100755
index 00000000..6b5141e5
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/kxte9.h
@@ -0,0 +1,116 @@
+/* include/linux/kxte9.h - KXTE9 accelerometer driver
+ *
+ * Copyright (C) 2010 Kionix, Inc.
+ * Written by Kuching Tan <kuchingtan@kionix.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __KXTE9_H__
+#define __KXTE9_H__
+
+#define KXTE9_I2C_ADDR 0x0F
+/* CONTROL REGISTER 1 BITS */
+#define TPE 0x01 /* tilt position function enable bit */
+#define WUFE 0x02 /* wake-up function enable bit */
+#define B2SE 0x04 /* back-to-sleep function enable bit */
+#define ODR125E 0x20 /* 125Hz ODR mode */
+#define ODR40E 0x18 /* initial ODR masks */
+#define ODR10E 0x10
+#define ODR3E 0x08
+#define ODR1E 0x00
+/* CONTROL REGISTER 3 BITS */
+#define SRST 0x80 /* software reset */
+#define CTC 0x10 /* communication-test function */
+#define OB2S40 0x0C /* back-to-sleep ODR masks */
+#define OB2S10 0x08
+#define OB2S3 0x04
+#define OB2S1 0x00
+#define OWUF40 0x03 /* wake-up ODR masks */
+#define OWUF10 0x02
+#define OWUF3 0x01
+#define OWUF1 0x00
+/* INTERRUPT CONTROL REGISTER 1 BITS */
+#define KXTE9_IEN 0x10 /* interrupt enable */
+#define KXTE9_IEA 0x08 /* interrupt polarity */
+#define KXTE9_IEL 0x04 /* interrupt response */
+
+/* Device Meta Data */
+#define DESC_DEV "KXTE9 3-axis Accelerometer" // Device Description
+#define VERSION_DEV "1.1.7"
+#define VER_MAJOR_DEV 1
+#define VER_MINOR_DEV 1
+#define VER_MAINT_DEV 7
+#define MAX_G_DEV (2.0f) // Maximum G Level
+#define MAX_SENS_DEV (1024.0f) // Maximum Sensitivity
+#define PWR_DEV (0.03f) // Typical Current
+
+/* Input Device Name */
+//#define INPUT_NAME_ACC "kxte9_accel"
+#define INPUT_NAME_ACC "g-sensor"
+
+/* Device name for kxte9 misc. device */
+#define NAME_DEV "kxte9"
+#define DIR_DEV "/dev/kxte9"
+
+/* IOCTLs for kxte9 misc. device library */
+#define KXTE9IO 0x92
+#define KXTE9_IOCTL_GET_COUNT _IOR(KXTE9IO, 0x01, int)
+#define KXTE9_IOCTL_GET_MG _IOR(KXTE9IO, 0x02, int)
+#define KXTE9_IOCTL_ENABLE_OUTPUT _IO(KXTE9IO, 0x03)
+#define KXTE9_IOCTL_DISABLE_OUTPUT _IO(KXTE9IO, 0x04)
+#define KXTE9_IOCTL_GET_ENABLE _IOR(KXTE9IO, 0x05, int)
+#define KXTE9_IOCTL_RESET _IO(KXTE9IO, 0x06)
+#define KXTE9_IOCTL_UPDATE_ODR _IOW(KXTE9IO, 0x07, int)
+#define KXTE9_IOCTL_ENABLE_CTC _IO(KXTE9IO, 0x08)
+#define KXTE9_IOCTL_DISABLE_CTC _IO(KXTE9IO, 0x09)
+#define KXTE9_IOCTL_GET_CT_RESP _IOR(KXTE9IO, 0x0A, int)
+
+
+#ifdef __KERNEL__
+struct kxte9_platform_data {
+ int poll_interval;
+ int min_interval;
+ /* the desired g-range, in milli-g (always 2000 for kxte9) */
+ u8 g_range;
+ /* used to compensate for alternate device placement within the host */
+/*
+ u8 axis_map_x;
+ u8 axis_map_y;
+ u8 axis_map_z;
+ u8 negate_x;
+ u8 negate_y;
+ u8 negate_z;
+*/
+ /* initial configuration values, set during board configuration */
+ u8 ctrl_reg1_init;
+ u8 engine_odr_init;
+ u8 int_ctrl_init;
+ u8 tilt_timer_init;
+ u8 wuf_timer_init;
+ u8 b2s_timer_init;
+ u8 wuf_thresh_init;
+ u8 b2s_thresh_init;
+
+ int (*init)(void);
+ void (*exit)(void);
+//NelsonTmp{
+// int gpio;
+//}
+};
+#endif /* __KERNEL__ */
+
+#endif /* __KXTE9_H__ */
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/readme.txt b/ANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/readme.txt
new file mode 100755
index 00000000..e4653a08
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/kxte9_gsensor/readme.txt
@@ -0,0 +1,47 @@
+The back of WM3445 MID
+ ______________
+| +z |
+| \ @ |
+| \ |
+| ---- +y |
+| | |
+| | |
+| +x |
+|______________|
+(KXTE9-2050 Accelerometer)
+
+wmt.io.gsensor
+Configure G-Sensor for Enable/Disable,X,Y,Z axis mapping and sampling rate. If driver not detect this variable, then G-sensor driver won¡¦t be loaded.
+<op>:<freq>:<axis-X>:<X-dir>:<axis-Y>:<Y-dir>:<axis-Z>:<Z-dir>:<avg-count>:<8bit>
+<op>:= Operation mode for the g-sensor
+0 : KXTE9-2050 G-Sensor is disabled.
+1 : KXTE9-2050 G-Sensor is enabled.
+<freq>:= G-Sensor sampling rate. The valid values are 1,3,10,and 40.
+<axis-X>:= G-Sensor axis-x will map to which axis of device.
+0 : X
+1 : Y
+2 : Z
+<X-dir>:= If G-Sensor axis-x direction is the same as device.
+1 : Positive direction
+-1 : Negative direction
+<axis-Y>:= G-Sensor axis-y will map to which axis of device.
+0 : X
+1 : Y
+2 : Z
+<Y-dir>:= If G-Sensor axis-y direction is the same as device.
+1 : Positive direction
+-1 : Negative direction
+<axis-Z>:= G-Sensor axis-z will map to which axis of device.
+0 : X
+1 : Y
+2 : Z
+<Z-dir>:= If G-Sensor axis-z direction is the same as device.
+1 : Positive direction
+-1 : Negative direction
+<avg-count>:= For every new/current axes values stored, add the newly stored axes with previously (avg-count-1) stored axes values and do an average
+<8bit>:= Using acceleration data as 8bit
+0 : 6bit
+1 : 8bit
+Ex:
+#KXTE9-2050 G-sensor enabled, using 40 sampling rate, X->-Y, Y->X, Z->-Z, 4 average count, using 8bit
+setenv wmt.io.gsensor 1:40:1:-1:0:-1:2:-1:4:1
diff --git a/ANDROID_3.4.5/drivers/input/sensor/l3g4200d_gyro/Makefile b/ANDROID_3.4.5/drivers/input/sensor/l3g4200d_gyro/Makefile
new file mode 100755
index 00000000..2818c82f
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/l3g4200d_gyro/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the kernel device drivers.
+#
+obj-$(CONFIG_WMT_GYRO_L3G4200D) += s_wmt_gyro_l3g4200d.o
+s_wmt_gyro_l3g4200d-objs := l3g4200d_gyr.o \ No newline at end of file
diff --git a/ANDROID_3.4.5/drivers/input/sensor/l3g4200d_gyro/l3g4200d.h b/ANDROID_3.4.5/drivers/input/sensor/l3g4200d_gyro/l3g4200d.h
new file mode 100755
index 00000000..4cae2bc5
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/l3g4200d_gyro/l3g4200d.h
@@ -0,0 +1,108 @@
+/******************** (C) COPYRIGHT 2010 STMicroelectronics ********************
+*
+* File Name : l3g4200d.h
+* Authors : MH - C&I BU - Application Team
+* : Carmine Iascone (carmine.iascone@st.com)
+* : Matteo Dameno (matteo.dameno@st.com)
+* Version : V 1.1 sysfs
+* Date : 2010/Aug/19
+* Description : L3G4200D digital output gyroscope sensor API
+*
+********************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
+* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
+* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*
+********************************************************************************
+* REVISON HISTORY
+*
+* VERSION | DATE | AUTHORS | DESCRIPTION
+* 1.0 | 2010/Aug/19 | Carmine Iascone | First Release
+* 1.1 | 2011/02/28 | Matteo Dameno | Self Test Added
+* 1.2 | 2013/04/29 | Howay Huo | Android Interface Added
+*******************************************************************************/
+
+#ifndef __L3G4200D_H__
+#define __L3G4200D_H__
+
+#define L3G4200D_GYR_DEV_NAME "l3g4200d_gyr"
+#define GYRO_INPUT_NAME "gyroscope"
+#define GYRO_MISCDEV_NAME "gyro_ctrl"
+
+#define L3G4200D_DRVID 0
+
+#define L3G4200D_GYR_FS_250DPS 0x00
+#define L3G4200D_GYR_FS_500DPS 0x10
+#define L3G4200D_GYR_FS_2000DPS 0x30
+
+#define L3G4200D_GYR_ENABLED 1
+#define L3G4200D_GYR_DISABLED 0
+
+#define WMTGSENSOR_IOCTL_MAGIC 0x09
+#define WMT_GYRO_IOCTL_MAGIC 0x11
+#define GYRO_IOCTL_SET_ENABLE _IOW(WMT_GYRO_IOCTL_MAGIC, 0, int)
+#define GYRO_IOCTL_GET_ENABLE _IOW(WMT_GYRO_IOCTL_MAGIC, 1, int)
+#define GYRO_IOCTL_SET_DELAY _IOW(WMT_GYRO_IOCTL_MAGIC, 2, int)
+#define GYRO_IOCTL_GET_DELAY _IOW(WMT_GYRO_IOCTL_MAGIC, 3, int)
+#define WMT_IOCTL_SENSOR_GET_DRVID _IOW(WMTGSENSOR_IOCTL_MAGIC, 4, unsigned int)
+
+#ifdef __KERNEL__
+
+struct l3g4200d_triple {
+ short x, /* x-axis angular rate data. */
+ y, /* y-axis angluar rate data. */
+ z; /* z-axis angular rate data. */
+};
+
+
+struct reg_value_t {
+ u8 ctrl_reg1;
+ u8 ctrl_reg2;
+ u8 ctrl_reg3;
+ u8 ctrl_reg4;
+ u8 ctrl_reg5;
+ u8 ref_datacap;
+ u8 fifo_ctrl_reg;
+ u8 int1_cfg;
+ u8 int1_ths_xh;
+ u8 int1_ths_xl;
+ u8 int1_ths_yh;
+ u8 int1_ths_yl;
+ u8 int1_ths_zh;
+ u8 int1_ths_zl;
+ u8 int1_duration;
+};
+
+struct l3g4200d_gyr_platform_data {
+ int (*init)(void);
+ void (*exit)(void);
+ int (*power_on)(void);
+ int (*power_off)(void);
+ int poll_interval;
+ int min_interval;
+
+ u8 fs_range;
+
+ int axis_map_x;
+ int axis_map_y;
+ int axis_map_z;
+
+ int direction_x;
+ int direction_y;
+ int direction_z;
+
+ struct reg_value_t init_state;
+
+};
+#endif /* __KERNEL__ */
+
+#endif /* __L3G4200D_H__ */
diff --git a/ANDROID_3.4.5/drivers/input/sensor/l3g4200d_gyro/l3g4200d_gyr.c b/ANDROID_3.4.5/drivers/input/sensor/l3g4200d_gyro/l3g4200d_gyr.c
new file mode 100755
index 00000000..a30c00a6
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/l3g4200d_gyro/l3g4200d_gyr.c
@@ -0,0 +1,1681 @@
+/******************** (C) COPYRIGHT 2010 STMicroelectronics ********************
+*
+* File Name : l3g4200d_gyr_sysfs.c
+* Authors : MH - C&I BU - Application Team
+* : Carmine Iascone (carmine.iascone@st.com)
+* : Matteo Dameno (matteo.dameno@st.com)
+* : Both authors are willing to be considered the contact
+* : and update points for the driver.
+* Version : V 1.1 sysfs
+* Date : 2011/02/28
+* Description : L3G4200D digital output gyroscope sensor API
+*
+********************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
+* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
+* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*
+********************************************************************************
+* REVISON HISTORY
+*
+* VERSION | DATE | AUTHORS | DESCRIPTION
+* 1.0 | 2010/11/19 | Carmine Iascone | First Release
+* 1.1 | 2011/02/28 | Matteo Dameno | Self Test Added
+* 1.2 | 2013/04/29 | Howay Huo | Android Interface Added
+*******************************************************************************/
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/input-polldev.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <mach/hardware.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+
+#include "l3g4200d.h"
+
+#undef DEBUG
+#define DEBUG 1
+
+#define L3G4200D_I2C_ADDR 0x69
+
+/* WM8880 interrupt pin connect to the DRDY Pin of LL3G4200D */
+#define L3G4200D_IRQ_PIN WMT_PIN_GP2_GPIO17
+
+/** Maximum polled-device-reported rot speed value value in dps*/
+#define FS_MAX 32768
+
+/* l3g4200d gyroscope registers */
+#define WHO_AM_I 0x0F
+
+#define CTRL_REG1 0x20
+#define CTRL_REG2 0x21
+#define CTRL_REG3 0x22
+#define CTRL_REG4 0x23
+#define CTRL_REG5 0x24
+#define REF_DATACAP 0x25
+#define OUT_TEMP 0x26
+#define STATUS_REG 0x27
+#define OUT_X_L 0x28
+#define OUT_X_H 0x29
+#define OUT_Y_L 0x2A
+#define OUT_Y_H 0x2B
+#define OUT_Z_L 0x2C
+#define OUT_Z_H 0x2D
+#define FIFO_CTRL_REG 0x2E
+#define FIFO_SRC_REG 0x2F
+#define INT1_CFG 0x30
+#define INT1_SRC 0x31
+#define INT1_THS_XH 0x32
+#define INT1_THS_XL 0x33
+#define INT1_THS_YH 0x34
+#define INT1_THS_YL 0x35
+#define INT1_THS_ZH 0x36
+#define INT1_THS_ZL 0x37
+#define INT1_DURATION 0x38
+
+/* CTRL_REG1 */
+#define PM_MASK 0x08
+#define PM_NORMAL 0x08
+#define ENABLE_ALL_AXES 0x07
+
+/* CTRL_REG3 */
+#define I2_DRDY 0x08
+
+/* CTRL_REG4 bits */
+#define FS_MASK 0x30
+
+#define SELFTEST_MASK 0x06
+#define L3G4200D_SELFTEST_DIS 0x00
+#define L3G4200D_SELFTEST_EN_POS 0x02
+#define L3G4200D_SELFTEST_EN_NEG 0x04
+
+#define FUZZ 0
+#define FLAT 0
+#define AUTO_INCREMENT 0x80
+
+/* STATUS_REG */
+#define ZYXDA 0x08
+#define ZDA 0x04
+#define YDA 0x02
+#define XDA 0x01
+
+/** Registers Contents */
+#define WHOAMI_L3G4200D 0x00D3 /* Expected content for WAI register*/
+
+#define ODR_MASK 0xF0
+#define ODR100_BW25 0x10
+#define ODR200_BW70 0x70
+#define ODR400_BW110 0xB0
+#define ODR800_BW110 0xF0
+
+#define L3G4200D_PU_DELAY 320 //ms
+
+static struct i2c_client *l3g4200d_i2c_client = NULL;
+static int enable_print_log;
+static int interrupt_mode = 0;
+static int flush_polling_data;
+
+/*
+ * L3G4200D gyroscope data
+ * brief structure containing gyroscope values for yaw, pitch and roll in
+ * signed short
+ */
+
+struct output_rate{
+ u8 odr_mask;
+ u32 delay_us;
+};
+
+static const struct output_rate gyro_odr_table[] = {
+ { ODR800_BW110, 1250 },
+ { ODR400_BW110, 2500 },
+ { ODR200_BW70, 5000 },
+ { ODR100_BW25, 10000},
+};
+
+struct l3g4200d_data {
+ struct i2c_client *client;
+ struct l3g4200d_gyr_platform_data *pdata;
+
+ struct mutex lock;
+
+ struct delayed_work enable_work;
+ struct delayed_work input_work;
+ struct input_dev *input_dev;
+ int hw_initialized;
+ int selftest_enabled;
+ atomic_t enabled;
+
+ u8 reg_addr;
+ struct reg_value_t resume_state;
+};
+
+extern int wmt_getsyspara(char *varname, char *varval, int *varlen);
+
+static int l3g4200d_i2c_read(struct l3g4200d_data *gyro,
+ u8 *buf, int len)
+{
+ int err;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = gyro->client->addr,
+ .flags = gyro->client->flags & I2C_M_TEN,
+ .len = 1,
+ .buf = buf,
+ },
+ {
+ .addr = gyro->client->addr,
+ .flags = (gyro->client->flags & I2C_M_TEN) | I2C_M_RD,
+ .len = len,
+ .buf = buf,
+ },
+ };
+
+ err = i2c_transfer(gyro->client->adapter, msgs, 2);
+
+ if (err != 2) {
+ dev_err(&gyro->client->dev, "read transfer error: %d\n",err);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int l3g4200d_i2c_write(struct l3g4200d_data *gyro,
+ u8 *buf,
+ int len)
+{
+ int err;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = gyro->client->addr,
+ .flags = gyro->client->flags & I2C_M_TEN,
+ .len = len + 1,
+ .buf = buf,
+ },
+ };
+
+ err = i2c_transfer(gyro->client->adapter, msgs, 1);
+
+ if (err != 1) {
+ dev_err(&gyro->client->dev, "write transfer error\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int l3g4200d_register_write(struct l3g4200d_data *gyro, u8 *buf,
+ u8 reg_address, u8 new_value)
+{
+ int err = -1;
+
+ /* Sets configuration register at reg_address
+ * NOTE: this is a straight overwrite */
+ buf[0] = reg_address;
+ buf[1] = new_value;
+ err = l3g4200d_i2c_write(gyro, buf, 1);
+ if (err < 0)
+ return err;
+
+ return err;
+}
+
+static int l3g4200d_register_read(struct l3g4200d_data *gyro, u8 *buf,
+ u8 reg_address)
+{
+
+ int err = -1;
+ buf[0] = (reg_address);
+ err = l3g4200d_i2c_read(gyro, buf, 1);
+ return err;
+}
+
+static int l3g4200d_register_update(struct l3g4200d_data *gyro, u8 *buf,
+ u8 reg_address, u8 mask, u8 new_bit_values)
+{
+ int err = -1;
+ u8 init_val;
+ u8 updated_val;
+ err = l3g4200d_register_read(gyro, buf, reg_address);
+ if (!(err < 0)) {
+ init_val = buf[0];
+ if((new_bit_values & mask) != (init_val & mask)) {
+ updated_val = ((mask & new_bit_values) | ((~mask) & init_val));
+ err = l3g4200d_register_write(gyro, buf, reg_address,
+ updated_val);
+ }
+ else
+ return 0;
+ }
+ return err;
+}
+
+static int l3g4200d_register_store(struct l3g4200d_data *gyro, u8 reg)
+{
+ int err = -1;
+ u8 buf[2];
+
+ err = l3g4200d_register_read(gyro, buf, reg);
+ if (err)
+ return err;
+
+ switch (reg) {
+ case CTRL_REG1:
+ gyro->resume_state.ctrl_reg1 = buf[0];
+ break;
+ case CTRL_REG2:
+ gyro->resume_state.ctrl_reg2 = buf[0];
+ break;
+ case CTRL_REG3:
+ gyro->resume_state.ctrl_reg3 = buf[0];
+ break;
+ case CTRL_REG4:
+ gyro->resume_state.ctrl_reg4 = buf[0];
+ break;
+ case CTRL_REG5:
+ gyro->resume_state.ctrl_reg5 = buf[0];
+ break;
+ case REF_DATACAP:
+ gyro->resume_state.ref_datacap = buf[0];
+ break;
+ case FIFO_CTRL_REG:
+ gyro->resume_state.fifo_ctrl_reg = buf[0];
+ break;
+ case INT1_CFG:
+ gyro->resume_state.int1_cfg = buf[0];
+ break;
+ case INT1_THS_XH:
+ gyro->resume_state.int1_ths_xh = buf[0];
+ break;
+ case INT1_THS_XL:
+ gyro->resume_state.int1_ths_xl = buf[0];
+ break;
+ case INT1_THS_YH:
+ gyro->resume_state.int1_ths_yh = buf[0];
+ break;
+ case INT1_THS_YL:
+ gyro->resume_state.int1_ths_yl = buf[0];
+ break;
+ case INT1_THS_ZH:
+ gyro->resume_state.int1_ths_zh = buf[0];
+ break;
+ case INT1_THS_ZL:
+ gyro->resume_state.int1_ths_zl = buf[0];
+ break;
+ case INT1_DURATION:
+ gyro->resume_state.int1_duration = buf[0];
+ break;
+ default:
+ pr_err("%s: can't support reg (0x%02X) store\n", L3G4200D_GYR_DEV_NAME, reg);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int l3g4200d_update_fs_range(struct l3g4200d_data *gyro,
+ u8 new_fs)
+{
+ int res ;
+ u8 buf[2];
+
+ buf[0] = CTRL_REG4;
+
+ res = l3g4200d_register_update(gyro, buf, CTRL_REG4,
+ FS_MASK, new_fs);
+
+ if (res < 0) {
+ pr_err("%s : failed to update fs:0x%02x\n",
+ __func__, new_fs);
+ return res;
+ }
+
+ l3g4200d_register_store(gyro, CTRL_REG4);
+
+ return 0;
+}
+
+
+static int l3g4200d_selftest(struct l3g4200d_data *gyro, u8 enable)
+{
+ int err = -1;
+ u8 buf[2] = {0x00,0x00};
+ char reg_address, mask, bit_values;
+
+ reg_address = CTRL_REG4;
+ mask = SELFTEST_MASK;
+ if (enable > 0)
+ bit_values = L3G4200D_SELFTEST_EN_POS;
+ else
+ bit_values = L3G4200D_SELFTEST_DIS;
+ if (atomic_read(&gyro->enabled)) {
+ mutex_lock(&gyro->lock);
+ err = l3g4200d_register_update(gyro, buf, reg_address,
+ mask, bit_values);
+ gyro->selftest_enabled = enable;
+ mutex_unlock(&gyro->lock);
+ if (err < 0)
+ return err;
+
+ l3g4200d_register_store(gyro, CTRL_REG4);
+ }
+ return err;
+}
+
+
+static int l3g4200d_update_odr(struct l3g4200d_data *gyro,
+ int poll_interval)
+{
+ int err = -1;
+ int i;
+ u8 config[2];
+
+ for (i = ARRAY_SIZE(gyro_odr_table) - 1; i >= 0; i--) {
+ if (gyro_odr_table[i].delay_us <= poll_interval){
+ break;
+ }
+ }
+
+ gyro->pdata->poll_interval = gyro_odr_table[i].delay_us;
+
+ config[1] = gyro_odr_table[i].odr_mask;
+ config[1] |= (ENABLE_ALL_AXES + PM_NORMAL);
+
+ /* If device is currently enabled, we need to write new
+ * configuration out to it */
+ if (atomic_read(&gyro->enabled)) {
+ config[0] = CTRL_REG1;
+ err = l3g4200d_i2c_write(gyro, config, 1);
+ if (err < 0)
+ return err;
+
+ l3g4200d_register_store(gyro, CTRL_REG1);
+ }
+
+ return err;
+}
+
+/* gyroscope data readout */
+static int l3g4200d_get_data(struct l3g4200d_data *gyro,
+ struct l3g4200d_triple *data)
+{
+ int err;
+ unsigned char gyro_out[6];
+ /* y,p,r hardware data */
+ s16 hw_d[3] = { 0 };
+
+ gyro_out[0] = (AUTO_INCREMENT | OUT_X_L);
+
+ err = l3g4200d_i2c_read(gyro, gyro_out, 6);
+
+ if (err < 0)
+ return err;
+
+ hw_d[0] = (s16) (((gyro_out[1]) << 8) | gyro_out[0]);
+ hw_d[1] = (s16) (((gyro_out[3]) << 8) | gyro_out[2]);
+ hw_d[2] = (s16) (((gyro_out[5]) << 8) | gyro_out[4]);
+
+ data->x = ((gyro->pdata->direction_x < 0) ? (-hw_d[gyro->pdata->axis_map_x])
+ : (hw_d[gyro->pdata->axis_map_x]));
+ data->y = ((gyro->pdata->direction_y < 0) ? (-hw_d[gyro->pdata->axis_map_y])
+ : (hw_d[gyro->pdata->axis_map_y]));
+ data->z = ((gyro->pdata->direction_z < 0) ? (-hw_d[gyro->pdata->axis_map_z])
+ : (hw_d[gyro->pdata->axis_map_z]));
+
+ if(enable_print_log)
+ printk("x = %d, y = %d, z = %d\n", data->x, data->y, data->z);
+
+ return err;
+}
+
+static void l3g4200d_report_values(struct l3g4200d_data *l3g,
+ struct l3g4200d_triple *data)
+{
+ struct input_dev *input = l3g->input_dev;
+
+ input_report_abs(input, ABS_X, data->x);
+ input_report_abs(input, ABS_Y, data->y);
+ input_report_abs(input, ABS_Z, data->z);
+ input_sync(input);
+}
+
+static int l3g4200d_hw_init(struct l3g4200d_data *gyro)
+{
+ int err = -1;
+ u8 buf[8];
+
+ printk(KERN_INFO "%s hw init\n", L3G4200D_GYR_DEV_NAME);
+
+ buf[0] = (AUTO_INCREMENT | CTRL_REG1);
+ buf[1] = gyro->resume_state.ctrl_reg1;
+ buf[2] = gyro->resume_state.ctrl_reg2;
+ buf[3] = gyro->resume_state.ctrl_reg3;
+ buf[4] = gyro->resume_state.ctrl_reg4;
+ buf[5] = gyro->resume_state.ctrl_reg5;
+ buf[6] = gyro->resume_state.ref_datacap;
+ err = l3g4200d_i2c_write(gyro, buf, 6);
+ if(err)
+ return err;
+
+ buf[0] = FIFO_CTRL_REG;
+ buf[1] = gyro->resume_state.fifo_ctrl_reg;
+ err = l3g4200d_i2c_write(gyro, buf, 1);
+ if(err)
+ return err;
+
+ buf[0] = INT1_CFG;
+ buf[1] = gyro->resume_state.int1_cfg;
+ err = l3g4200d_i2c_write(gyro, buf, 1);
+ if(err)
+ return err;
+
+ buf[0] = (AUTO_INCREMENT | INT1_THS_XH);
+ buf[1] = gyro->resume_state.int1_ths_xh;
+ buf[2] = gyro->resume_state.int1_ths_xl;
+ buf[3] = gyro->resume_state.int1_ths_yh;
+ buf[4] = gyro->resume_state.int1_ths_yl;
+ buf[5] = gyro->resume_state.int1_ths_zh;
+ buf[6] = gyro->resume_state.int1_ths_zl;
+ buf[7] = gyro->resume_state.int1_duration;
+ err = l3g4200d_i2c_write(gyro, buf, 7);
+ if(err)
+ return err;
+
+ gyro->hw_initialized = 1;
+
+ return 0;
+}
+
+static void l3g4200d_gpio_irq_enable(void)
+{
+ wmt_gpio_unmask_irq(L3G4200D_IRQ_PIN);
+}
+
+static void l3g4200d_gpio_irq_disable(void)
+{
+ wmt_gpio_mask_irq(L3G4200D_IRQ_PIN);
+}
+
+static int l3g4200d_irq_hw_init(int resume)
+{
+ int ret;
+
+ if(!resume) {
+ ret = gpio_request(L3G4200D_IRQ_PIN, "l3g4200d-gyro irq"); //enable gpio
+ if(ret < 0) {
+ pr_err("gpio(%d) request fail for l3g4200d-gyro irq\n", L3G4200D_IRQ_PIN);
+ return ret;
+ }
+ }else
+ gpio_re_enabled(L3G4200D_IRQ_PIN); //re-enable gpio
+
+ gpio_direction_input(L3G4200D_IRQ_PIN); //gpio input
+
+ wmt_gpio_setpull(L3G4200D_IRQ_PIN, WMT_GPIO_PULL_DOWN); //enable pull and pull-down
+
+ wmt_gpio_mask_irq(L3G4200D_IRQ_PIN); //disable interrupt
+
+ wmt_gpio_set_irq_type(L3G4200D_IRQ_PIN, IRQ_TYPE_EDGE_RISING); //rise edge and clear interrupt
+
+ return 0;
+}
+
+static void l3g4200d_irq_hw_free(void)
+{
+ l3g4200d_gpio_irq_disable();
+ gpio_free(L3G4200D_IRQ_PIN);
+
+}
+
+static int l3g4200d_gpio_get_value(void)
+{
+ return (REG8_VAL(__GPIO_BASE + 0x0002) & BIT1);
+}
+
+static int l3g4200d_flush_gyro_data(struct l3g4200d_data *gyro)
+{
+ struct l3g4200d_triple data;
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ if (l3g4200d_gpio_get_value()) {
+ l3g4200d_get_data(gyro, &data);
+ pr_info("%s: flush_gyro_data: %d\n", L3G4200D_GYR_DEV_NAME, i);
+ }
+ else {
+ return 0;
+ }
+ }
+
+ return -EIO;
+}
+
+static void l3g4200d_device_power_off(struct l3g4200d_data *gyro)
+{
+ int err;
+ u8 buf[2];
+
+ pr_info("%s power off\n", L3G4200D_GYR_DEV_NAME);
+
+ buf[0] = CTRL_REG1;
+ err = l3g4200d_i2c_read(gyro, buf, 1);
+ if(err < 0) {
+ dev_err(&gyro->client->dev, "read ctrl_reg1 failed\n");
+ buf[0] = (gyro->resume_state.ctrl_reg1 | PM_MASK);
+ }
+
+ if(buf[0] & PM_MASK) {
+ buf[1] = buf[0] & ~PM_MASK;
+ buf[0] = CTRL_REG1;
+
+ err = l3g4200d_i2c_write(gyro, buf, 1);
+ if (err)
+ dev_err(&gyro->client->dev, "soft power off failed\n");
+
+ l3g4200d_register_store(gyro, CTRL_REG1);
+ }
+
+ if (gyro->pdata->power_off) {
+ gyro->pdata->power_off();
+// gyro->hw_initialized = 0;
+ }
+
+// if (gyro->hw_initialized)
+// gyro->hw_initialized = 0;
+
+}
+
+static int l3g4200d_device_power_on(struct l3g4200d_data *gyro)
+{
+ int err;
+ u8 buf[2];
+
+ pr_info("%s power on\n", L3G4200D_GYR_DEV_NAME);
+
+ if (gyro->pdata->power_on) {
+ err = gyro->pdata->power_on();
+ if (err < 0)
+ return err;
+ }
+
+ if (!gyro->hw_initialized) {
+ err = l3g4200d_hw_init(gyro);
+ if (err) {
+ l3g4200d_device_power_off(gyro);
+ return err;
+ }
+ }
+
+ buf[0] = CTRL_REG1;
+ err = l3g4200d_i2c_read(gyro, buf, 1);
+ if(err) {
+ dev_err(&gyro->client->dev, "read ctrl_reg1 failed\n");
+ buf[0] = (gyro->resume_state.ctrl_reg1 & ~PM_MASK);
+ }
+
+ if(!(buf[0] & PM_MASK)) {
+ buf[1] = buf[0] | PM_MASK;
+ buf[0] = CTRL_REG1;
+ err = l3g4200d_i2c_write(gyro, buf, 1);
+ if(err) {
+ dev_err(&gyro->client->dev, "soft power on failed\n");
+ return err;
+ }
+ l3g4200d_register_store(gyro, CTRL_REG1);
+ }
+
+ return 0;
+}
+
+static int l3g4200d_enable(struct l3g4200d_data *gyro)
+{
+ int err;
+
+ pr_info("%s enable\n", L3G4200D_GYR_DEV_NAME);
+
+ if (!atomic_cmpxchg(&gyro->enabled, 0, 1)) {
+ err = l3g4200d_device_power_on(gyro);
+ if (err) {
+ atomic_set(&gyro->enabled, 0);
+ return err;
+ }
+
+ //Android will call l3g4200d_set_delay() after l3g4200d_enable;
+ }
+
+ return 0;
+}
+
+static int l3g4200d_disable(struct l3g4200d_data *gyro)
+{
+ pr_info("%s disable\n", L3G4200D_GYR_DEV_NAME);
+
+ if (atomic_cmpxchg(&gyro->enabled, 1, 0)){
+ if(interrupt_mode) {
+ cancel_delayed_work_sync(&gyro->enable_work);
+ l3g4200d_gpio_irq_disable();
+ }else
+ cancel_delayed_work_sync(&gyro->input_work);
+
+ l3g4200d_device_power_off(gyro);
+ }
+ return 0;
+}
+
+static int l3g4200d_set_delay(struct l3g4200d_data *gyro, u32 delay_us)
+{
+ int odr_value = ODR100_BW25;
+ int err = -1;
+ int i;
+ u8 buf[2] = {CTRL_REG1, 0};
+
+ pr_info("l3g4200d_set_delay: %d us\n", delay_us);
+
+ /* do not report noise during ODR update */
+ if(interrupt_mode) {
+ cancel_delayed_work_sync(&gyro->enable_work);
+ l3g4200d_gpio_irq_disable();
+ }else
+ cancel_delayed_work_sync(&gyro->input_work);
+
+ for(i=0; i < ARRAY_SIZE(gyro_odr_table); i++)
+ if(delay_us <= gyro_odr_table[i].delay_us) {
+ odr_value = gyro_odr_table[i].odr_mask;
+ delay_us = gyro_odr_table[i].delay_us;
+ break;
+ }
+
+ if(delay_us >= gyro_odr_table[3].delay_us) {
+ odr_value = gyro_odr_table[3].odr_mask;
+ delay_us = gyro_odr_table[3].delay_us;
+ }
+
+ err = l3g4200d_register_update(gyro, buf, CTRL_REG1, ODR_MASK, odr_value);
+ if(err) {
+ dev_err(&gyro->client->dev, "update odr failed 0x%x,0x%x: %d\n",
+ buf[0], odr_value, err);
+ return err;
+ }
+
+ l3g4200d_register_store(gyro, CTRL_REG1);
+
+ gyro->pdata->poll_interval = max((int)delay_us, gyro->pdata->min_interval);
+
+ //do not report noise at IC power-up
+ // flush data before really read
+ if(interrupt_mode)
+ schedule_delayed_work(&gyro->enable_work, msecs_to_jiffies(
+ L3G4200D_PU_DELAY));
+ else {
+ flush_polling_data = 1;
+ schedule_delayed_work(&gyro->input_work, msecs_to_jiffies(
+ L3G4200D_PU_DELAY));
+ }
+
+ return 0;
+}
+
+static ssize_t attr_polling_rate_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int val;
+ struct l3g4200d_data *gyro = dev_get_drvdata(dev);
+ mutex_lock(&gyro->lock);
+ val = gyro->pdata->poll_interval;
+ mutex_unlock(&gyro->lock);
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t attr_polling_rate_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct l3g4200d_data *gyro = dev_get_drvdata(dev);
+ unsigned long interval_us;
+
+ if (strict_strtoul(buf, 10, &interval_us))
+ return -EINVAL;
+ if (!interval_us)
+ return -EINVAL;
+ mutex_lock(&gyro->lock);
+ gyro->pdata->poll_interval = interval_us;
+ l3g4200d_update_odr(gyro, interval_us);
+ mutex_unlock(&gyro->lock);
+ return size;
+}
+
+static ssize_t attr_range_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct l3g4200d_data *gyro = dev_get_drvdata(dev);
+ int range = 0;
+ char val;
+ mutex_lock(&gyro->lock);
+ val = gyro->pdata->fs_range;
+ switch (val) {
+ case L3G4200D_GYR_FS_250DPS:
+ range = 250;
+ break;
+ case L3G4200D_GYR_FS_500DPS:
+ range = 500;
+ break;
+ case L3G4200D_GYR_FS_2000DPS:
+ range = 2000;
+ break;
+ }
+ mutex_unlock(&gyro->lock);
+ return sprintf(buf, "%d\n", range);
+}
+
+static ssize_t attr_range_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct l3g4200d_data *gyro = dev_get_drvdata(dev);
+ unsigned long val;
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+ mutex_lock(&gyro->lock);
+ gyro->pdata->fs_range = val;
+ l3g4200d_update_fs_range(gyro, val);
+ mutex_unlock(&gyro->lock);
+ return size;
+}
+
+static ssize_t attr_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct l3g4200d_data *gyro = dev_get_drvdata(dev);
+ int val = atomic_read(&gyro->enabled);
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t attr_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct l3g4200d_data *gyro = dev_get_drvdata(dev);
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+
+ if (val) {
+ l3g4200d_enable(gyro);
+ l3g4200d_set_delay(gyro, gyro->pdata->poll_interval);
+ }
+ else
+ l3g4200d_disable(gyro);
+
+ return size;
+}
+
+static ssize_t attr_get_selftest(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int val;
+ struct l3g4200d_data *gyro = dev_get_drvdata(dev);
+ mutex_lock(&gyro->lock);
+ val = gyro->selftest_enabled;
+ mutex_unlock(&gyro->lock);
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t attr_set_selftest(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct l3g4200d_data *gyro = dev_get_drvdata(dev);
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+
+ l3g4200d_selftest(gyro, val);
+
+ return size;
+}
+
+#ifdef DEBUG
+static ssize_t attr_reg_set(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int rc;
+ struct l3g4200d_data *gyro = dev_get_drvdata(dev);
+ u8 x[2];
+ unsigned long val;
+
+ if (strict_strtoul(buf, 16, &val))
+ return -EINVAL;
+ mutex_lock(&gyro->lock);
+ x[0] = gyro->reg_addr;
+ mutex_unlock(&gyro->lock);
+ x[1] = val;
+ rc = l3g4200d_i2c_write(gyro, x, 1);
+ return size;
+}
+
+static ssize_t attr_reg_get(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ ssize_t ret;
+ struct l3g4200d_data *gyro = dev_get_drvdata(dev);
+ int rc;
+ u8 data;
+
+ mutex_lock(&gyro->lock);
+ data = gyro->reg_addr;
+ mutex_unlock(&gyro->lock);
+ rc = l3g4200d_i2c_read(gyro, &data, 1);
+ ret = sprintf(buf, "0x%02x\n", data);
+ return ret;
+}
+
+static ssize_t attr_addr_set(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct l3g4200d_data *gyro = dev_get_drvdata(dev);
+ unsigned long val;
+
+ if (strict_strtoul(buf, 16, &val))
+ return -EINVAL;
+
+ mutex_lock(&gyro->lock);
+
+ gyro->reg_addr = val;
+
+ mutex_unlock(&gyro->lock);
+
+ return size;
+}
+
+static ssize_t attr_get_printlog(struct device * dev,struct device_attribute * attr,
+ char * buf)
+{
+ ssize_t ret;
+
+ ret = sprintf(buf, "%d\n", enable_print_log);
+
+ return ret;
+}
+
+static ssize_t attr_set_printlog(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val))
+ return -EINVAL;
+
+ enable_print_log = val;
+
+ return size;
+}
+
+#endif /* DEBUG */
+
+static struct device_attribute attributes[] = {
+ __ATTR(pollrate_ms, 0666, attr_polling_rate_show,
+ attr_polling_rate_store),
+ __ATTR(range, 0666, attr_range_show, attr_range_store),
+ __ATTR(enable_device, 0666, attr_enable_show, attr_enable_store),
+ __ATTR(enable_selftest, 0666, attr_get_selftest, attr_set_selftest),
+#ifdef DEBUG
+ __ATTR(reg_value, 0600, attr_reg_get, attr_reg_set),
+ __ATTR(reg_addr, 0200, NULL, attr_addr_set),
+ __ATTR(printlog, 0600, attr_get_printlog, attr_set_printlog),
+#endif
+};
+
+static int create_sysfs_interfaces(struct device *dev)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(attributes); i++)
+ if (device_create_file(dev, attributes + i))
+ goto error;
+ return 0;
+
+error:
+ for ( ; i >= 0; i--)
+ device_remove_file(dev, attributes + i);
+ dev_err(dev, "%s:Unable to create interface\n", __func__);
+ return -1;
+}
+
+static int remove_sysfs_interfaces(struct device *dev)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(attributes); i++)
+ device_remove_file(dev, attributes + i);
+ return 0;
+}
+
+static void l3g4200d_data_report(struct l3g4200d_data *gyro)
+{
+ struct l3g4200d_triple data_out;
+ int err;
+
+ err = l3g4200d_get_data(gyro, &data_out);
+ if (err)
+ dev_err(&gyro->client->dev, "get_gyroscope_data failed\n");
+ else
+ l3g4200d_report_values(gyro, &data_out);
+
+}
+
+static int l3g4200d_validate_pdata(struct l3g4200d_data *gyro)
+{
+ gyro->pdata->poll_interval = max(gyro->pdata->poll_interval,
+ gyro->pdata->min_interval);
+
+ if (gyro->pdata->axis_map_x > 2 ||
+ gyro->pdata->axis_map_y > 2 ||
+ gyro->pdata->axis_map_z > 2) {
+ dev_err(&gyro->client->dev,
+ "invalid axis_map value x:%u y:%u z%u\n",
+ gyro->pdata->axis_map_x,
+ gyro->pdata->axis_map_y,
+ gyro->pdata->axis_map_z);
+ return -EINVAL;
+ }
+
+ /* Only allow 1 and -1 for direction flag */
+ if (abs(gyro->pdata->direction_x) != 1 ||
+ abs(gyro->pdata->direction_y) != 1 ||
+ abs(gyro->pdata->direction_z) != 1) {
+ dev_err(&gyro->client->dev,
+ "invalid direction value x:%d y:%d z:%d\n",
+ gyro->pdata->direction_x,
+ gyro->pdata->direction_y,
+ gyro->pdata->direction_z);
+ return -EINVAL;
+ }
+
+ /* Enforce minimum polling interval */
+ if (gyro->pdata->poll_interval < gyro->pdata->min_interval) {
+ dev_err(&gyro->client->dev,
+ "minimum poll interval violated\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int l3g4200d_misc_open(struct inode *inode, struct file *file)
+{
+ int err;
+
+ err = nonseekable_open(inode, file);
+ if(err < 0)
+ return err;
+
+ file->private_data = i2c_get_clientdata(l3g4200d_i2c_client);
+
+ return 0;
+}
+
+static int l3g4200d_misc_close(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+
+static long l3g4200d_misc_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ int interval, val;
+ int err = -1;
+ struct l3g4200d_data *gyro = file->private_data;
+
+ switch(cmd){
+ case GYRO_IOCTL_GET_DELAY:
+ interval = gyro->pdata->poll_interval;
+ if(copy_to_user(argp, &interval, sizeof(interval)))
+ return -EFAULT;
+ break;
+
+ case GYRO_IOCTL_SET_DELAY:
+ if(copy_from_user(&interval, argp, sizeof(interval)))
+ return -EFAULT;
+ err = l3g4200d_set_delay(gyro, interval);
+ if(err < 0)
+ return err;
+ break;
+
+ case GYRO_IOCTL_SET_ENABLE:
+ if(copy_from_user(&val, argp, sizeof(val)))
+ return -EFAULT;
+ if(val > 1)
+ return -EINVAL;
+
+ if(val)
+ l3g4200d_enable(gyro);
+ else
+ l3g4200d_disable(gyro);
+ break;
+
+ case GYRO_IOCTL_GET_ENABLE:
+ val = atomic_read(&gyro->enabled);
+ if(copy_to_user(argp, &val, sizeof(val)))
+ return -EINVAL;
+ break;
+
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ val = L3G4200D_DRVID;
+ if (copy_to_user(argp, &val, sizeof(val)))
+ return -EFAULT;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct file_operations l3g4200d_misc_fops = {
+ .owner = THIS_MODULE,
+ .open = l3g4200d_misc_open,
+ .unlocked_ioctl = l3g4200d_misc_ioctl,
+ .release = l3g4200d_misc_close,
+};
+
+static struct miscdevice l3g4200d_misc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = GYRO_MISCDEV_NAME,
+ .fops = &l3g4200d_misc_fops,
+};
+
+static int l3g4200d_input_init(struct l3g4200d_data *gyro)
+{
+ int err = -1;
+ struct input_dev *input;
+
+ gyro->input_dev = input_allocate_device();
+ if (!gyro->input_dev) {
+ err = -ENOMEM;
+ dev_err(&gyro->client->dev,
+ "input device allocate failed\n");
+ goto err0;
+ }
+
+ input = gyro->input_dev;
+
+ input_set_drvdata(input, gyro);
+
+ set_bit(EV_ABS, input->evbit);
+
+ input_set_abs_params(input, ABS_X, -FS_MAX, FS_MAX, FUZZ, FLAT);
+ input_set_abs_params(input, ABS_Y, -FS_MAX, FS_MAX, FUZZ, FLAT);
+ input_set_abs_params(input, ABS_Z, -FS_MAX, FS_MAX, FUZZ, FLAT);
+
+ input->name = GYRO_INPUT_NAME;
+
+ err = input_register_device(input);
+ if (err) {
+ dev_err(&gyro->client->dev,
+ "unable to register input polled device %s\n",
+ input->name);
+ goto err1;
+ }
+
+ return 0;
+
+err1:
+ input_free_device(input);
+err0:
+ return err;
+}
+
+static void l3g4200d_input_cleanup(struct l3g4200d_data *gyro)
+{
+ input_unregister_device(gyro->input_dev);
+ input_free_device(gyro->input_dev);
+}
+
+static int l3g4300d_detect(struct i2c_client *client)
+{
+ int ret;
+ u8 buf[1];
+ struct l3g4200d_data gyro;
+
+ gyro.client = client;
+
+ ret = l3g4200d_register_read(&gyro, buf, WHO_AM_I);
+ if(ret)
+ return 0;
+
+ if(buf[0] != WHOAMI_L3G4200D){
+ dev_err(&client->dev, "chipId = 0x%02X, error", buf[0]);
+ return 0;
+ }
+
+ return 1;
+}
+
+static irqreturn_t gyro_irq_handler(int irq, void *dev_id)
+{
+ if(!gpio_irqstatus(L3G4200D_IRQ_PIN))
+ return IRQ_NONE;
+
+ wmt_gpio_ack_irq(L3G4200D_IRQ_PIN); //clear interrupt
+
+ //printk("got gyro interrupt\n");
+ if(!is_gpio_irqenable(L3G4200D_IRQ_PIN)) {
+ //pr_err("l3g4200d irq is disabled\n");
+ return IRQ_HANDLED;
+ }else
+ return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t gyro_irq_thread(int irq, void *dev)
+{
+ struct l3g4200d_data *gyro = dev;
+
+ l3g4200d_data_report(gyro);
+
+ return IRQ_HANDLED;
+}
+
+static void l3g4200d_enable_work_func(struct work_struct *work)
+{
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct l3g4200d_data *gyro =
+ container_of(dwork, struct l3g4200d_data, enable_work);
+
+ l3g4200d_flush_gyro_data(gyro);
+ l3g4200d_gpio_irq_enable();
+}
+
+static void l3g4200d_input_poll_func(struct work_struct *work)
+{
+ struct l3g4200d_triple data;
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct l3g4200d_data *gyro =
+ container_of(dwork, struct l3g4200d_data, input_work);
+
+ if(flush_polling_data == 0)
+ l3g4200d_data_report(gyro);
+ else {
+ l3g4200d_get_data(gyro, &data); //flush the first data
+ flush_polling_data = 0;
+ }
+
+ schedule_delayed_work(&gyro->input_work,
+ usecs_to_jiffies(gyro->pdata->poll_interval));
+}
+
+static int l3g4200d_param_parse(int *p_int_mode, struct l3g4200d_gyr_platform_data *pdata)
+{
+ char varbuf[64] = {0};
+ int n, ret, varlen;
+ int tmp[7];
+
+ varlen = sizeof(varbuf);
+
+ ret = wmt_getsyspara("wmt.io.gyro.l3g4200d", varbuf, &varlen);
+ if(ret)
+ return 0;
+
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d",
+ &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4], &tmp[5], &tmp[6]);
+
+ if(n != 7) {
+ pr_err("l3g4200d-gyro param format error\n");
+ return -1;
+ }
+
+ pdata->axis_map_x = tmp[0];
+ pdata->direction_x = tmp[1];
+ pdata->axis_map_y = tmp[2];
+ pdata->direction_y = tmp[3];
+ pdata->axis_map_z = tmp[4];
+ pdata->direction_z = tmp[5];
+ *p_int_mode = tmp[6];
+
+ return 0;
+}
+
+static int l3g4200d_probe(struct i2c_client *client,
+ const struct i2c_device_id *devid)
+{
+ struct l3g4200d_data *gyro;
+ int err = -1;
+ u8 buf[2];
+
+ pr_info("%s: probe start.\n", L3G4200D_GYR_DEV_NAME);
+
+ if (client->dev.platform_data == NULL) {
+ dev_err(&client->dev, "platform data is NULL. exiting.\n");
+ err = -ENODEV;
+ goto err0;
+ }
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "client not i2c capable:1\n");
+ err = -ENODEV;
+ goto err0;
+ }
+
+ if(l3g4300d_detect(client) == 0){
+ dev_err(&client->dev, "not found the gyro\n");
+ err = -ENODEV;
+ goto err0;
+ }
+
+ gyro = kzalloc(sizeof(*gyro), GFP_KERNEL);
+ if (gyro == NULL) {
+ dev_err(&client->dev,
+ "failed to allocate memory for module data\n");
+ err = -ENOMEM;
+ goto err0;
+ }
+
+ l3g4200d_param_parse(&interrupt_mode, client->dev.platform_data);
+ if(interrupt_mode) {
+ pr_info("l3g4200d-gyro in interrupt mode\n");
+ err = l3g4200d_irq_hw_init(0);
+ if(err)
+ goto err0;
+ }
+ else
+ pr_info("l3g4200d-gyro in polling mode\n");
+
+ mutex_init(&gyro->lock);
+ mutex_lock(&gyro->lock);
+ gyro->client = client;
+
+ gyro->pdata = kmalloc(sizeof(*gyro->pdata), GFP_KERNEL);
+ if (gyro->pdata == NULL) {
+ dev_err(&client->dev,
+ "failed to allocate memory for pdata: %d\n", err);
+ goto err1;
+ }
+ memcpy(gyro->pdata, client->dev.platform_data,
+ sizeof(*gyro->pdata));
+
+ err = l3g4200d_validate_pdata(gyro);
+ if (err < 0) {
+ dev_err(&client->dev, "failed to validate platform data\n");
+ goto err1_1;
+ }
+
+ i2c_set_clientdata(client, gyro);
+
+ if (gyro->pdata->init) {
+ err = gyro->pdata->init();
+ if (err < 0) {
+ dev_err(&client->dev, "init failed: %d\n", err);
+ goto err1_1;
+ }
+ }
+
+ if(interrupt_mode)
+ gyro->pdata->init_state.ctrl_reg3 |= I2_DRDY;
+
+ //According to the introduction of L3G4200D's datasheet page 32,
+ //the bit7 and bit6 of CTRL_REG2's value is loaded at boot. This value must not be changed
+ buf[0] = CTRL_REG2;
+ err = l3g4200d_i2c_read(gyro, buf, 1);
+ if(err)
+ goto err1_1;
+
+ gyro->pdata->init_state.ctrl_reg2 = (gyro->pdata->init_state.ctrl_reg2 & 0x1F)
+ | (buf[0] & 0xC0);
+
+ gyro->pdata->init_state.ctrl_reg1 &= ~PM_MASK;
+
+ memcpy(&gyro->resume_state, &gyro->pdata->init_state,
+ sizeof(struct reg_value_t));
+
+ err = l3g4200d_hw_init(gyro);
+ if (err) {
+ dev_err(&client->dev, "hardware init failed: %d\n", err);
+ goto err2;
+ }
+
+ err = l3g4200d_input_init(gyro);
+ if (err < 0)
+ goto err3;
+
+ err = create_sysfs_interfaces(&client->dev);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "%s device register failed\n", L3G4200D_GYR_DEV_NAME);
+ goto err4;
+ }
+
+ /* As default, do not report information */
+ atomic_set(&gyro->enabled, 0);
+
+ if(interrupt_mode)
+ INIT_DELAYED_WORK(&gyro->enable_work, l3g4200d_enable_work_func);
+ else
+ INIT_DELAYED_WORK(&gyro->input_work, l3g4200d_input_poll_func);
+
+ err = misc_register(&l3g4200d_misc_device);
+ if(err){
+ dev_err(&client->dev, "l3g4200d_device register failed\n");
+ goto err5;
+ }
+
+ if(interrupt_mode) {
+ err = request_threaded_irq(gyro->client->irq, gyro_irq_handler,
+ gyro_irq_thread, IRQF_SHARED, L3G4200D_GYR_DEV_NAME, gyro);
+
+ if(err) {
+ pr_err("%s: irq request failed: %d\n", __func__, err);
+ err = -ENODEV;
+ goto err6;
+ }
+ }
+
+ mutex_unlock(&gyro->lock);
+
+#ifdef DEBUG
+ pr_info("%s probed: device created successfully\n",
+ L3G4200D_GYR_DEV_NAME);
+#endif
+
+ return 0;
+
+err6:
+ misc_deregister(&l3g4200d_misc_device);
+err5:
+ remove_sysfs_interfaces(&client->dev);
+err4:
+ l3g4200d_input_cleanup(gyro);
+err3:
+ l3g4200d_device_power_off(gyro);
+err2:
+ if (gyro->pdata->exit)
+ gyro->pdata->exit();
+err1_1:
+ mutex_unlock(&gyro->lock);
+ kfree(gyro->pdata);
+err1:
+ kfree(gyro);
+ if(interrupt_mode)
+ l3g4200d_irq_hw_free();
+err0:
+ pr_err("%s: Driver Initialization failed\n",
+ L3G4200D_GYR_DEV_NAME);
+ return err;
+}
+
+static int l3g4200d_remove(struct i2c_client *client)
+{
+ struct l3g4200d_data *gyro = i2c_get_clientdata(client);
+#ifdef DEBUG
+ pr_info(KERN_INFO "L3G4200D driver removing\n");
+#endif
+
+ l3g4200d_disable(gyro);
+ if(interrupt_mode) {
+ free_irq(gyro->client->irq, gyro);
+ l3g4200d_irq_hw_free();
+ }
+ misc_deregister(&l3g4200d_misc_device);
+ l3g4200d_input_cleanup(gyro);
+ remove_sysfs_interfaces(&client->dev);
+ kfree(gyro->pdata);
+ kfree(gyro);
+ return 0;
+}
+
+static void l3g4200d_shutdown(struct i2c_client *client)
+{
+ struct l3g4200d_data *gyro = i2c_get_clientdata(client);
+
+ pr_info("l3g4200d_shutdown\n");
+
+ l3g4200d_disable(gyro);
+}
+
+
+static int l3g4200d_suspend(struct device *dev)
+{
+ struct l3g4200d_data *gyro = i2c_get_clientdata(l3g4200d_i2c_client);
+ int err;
+ u8 buf[8];
+
+ pr_info(KERN_INFO "l3g4200d_suspend\n");
+
+ if(atomic_read(&gyro->enabled)) {
+ if(interrupt_mode) {
+ cancel_delayed_work_sync(&gyro->enable_work);
+ l3g4200d_gpio_irq_disable();
+ }
+ else
+ cancel_delayed_work_sync(&gyro->input_work);
+
+ //store register value
+ buf[0] = (AUTO_INCREMENT | CTRL_REG1);
+ err = l3g4200d_i2c_read(gyro, buf, 6);
+ if(err)
+ goto err1;
+ gyro->resume_state.ctrl_reg1 = buf[0];
+ gyro->resume_state.ctrl_reg2 = buf[1];
+ gyro->resume_state.ctrl_reg3 = buf[2];
+ gyro->resume_state.ctrl_reg4 = buf[3];
+ gyro->resume_state.ctrl_reg5 = buf[4];
+ gyro->resume_state.ref_datacap = buf[5];
+
+ buf[0] = FIFO_CTRL_REG;
+ err = l3g4200d_i2c_read(gyro, buf, 1);
+ if(err)
+ goto err1;
+ gyro->resume_state.fifo_ctrl_reg = buf[0];
+
+ buf[0] = INT1_CFG;
+ err = l3g4200d_i2c_read(gyro, buf, 1);
+ if(err)
+ goto err1;
+ gyro->resume_state.int1_cfg = buf[0];
+
+ buf[0] = (AUTO_INCREMENT | INT1_THS_XH);
+ err = l3g4200d_i2c_read(gyro, buf, 7);
+ if(err)
+ goto err1;
+
+ gyro->resume_state.int1_ths_xh = buf[0];
+ gyro->resume_state.int1_ths_xl = buf[1];
+ gyro->resume_state.int1_ths_yh = buf[2];
+ gyro->resume_state.int1_ths_yl = buf[3];
+ gyro->resume_state.int1_ths_zh = buf[4];
+ gyro->resume_state.int1_ths_zl = buf[5];
+ gyro->resume_state.int1_duration = buf[6];
+ }
+
+ goto exit1;
+
+err1:
+ dev_err(&gyro->client->dev, "save register value fail at suspend\n");
+ memcpy(&gyro->resume_state, &gyro->pdata->init_state,
+ sizeof(struct reg_value_t));
+exit1:
+ l3g4200d_device_power_off(gyro);
+
+ if (gyro->hw_initialized)
+ gyro->hw_initialized = 0;
+
+ return 0;
+}
+
+static int l3g4200d_resume(struct device *dev)
+{
+ struct l3g4200d_data *gyro = i2c_get_clientdata(l3g4200d_i2c_client);
+ int err;
+
+ pr_info(KERN_INFO "l3g4200d_resume\n");
+
+ if(interrupt_mode)
+ l3g4200d_irq_hw_init(1);
+
+ if(atomic_read(&gyro->enabled)) {
+
+ err = l3g4200d_device_power_on(gyro);
+ if(err)
+ {
+ dev_err(&gyro->client->dev, "power_on failed at resume\n");
+ atomic_set(&gyro->enabled, 0);
+
+ return 0;
+ }
+
+ //do not report noise at IC power-up
+ // flush data before really read
+ if(interrupt_mode)
+ schedule_delayed_work(&gyro->enable_work, msecs_to_jiffies(
+ L3G4200D_PU_DELAY));
+ else {
+ flush_polling_data = 1;
+ schedule_delayed_work(&gyro->input_work, msecs_to_jiffies(
+ L3G4200D_PU_DELAY));
+ }
+ }else {
+ memcpy(&gyro->resume_state, &gyro->pdata->init_state,
+ sizeof(struct reg_value_t));
+
+ err = l3g4200d_hw_init(gyro);
+ if (err)
+ dev_err(&gyro->client->dev, "hardware init failed at resume\n");
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id l3g4200d_id[] = {
+ { L3G4200D_GYR_DEV_NAME , 0 },
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, l3g4200d_id);
+
+static struct dev_pm_ops l3g4200d_pm = {
+ .suspend = l3g4200d_suspend,
+ .resume = l3g4200d_resume,
+};
+
+static struct i2c_driver l3g4200d_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = L3G4200D_GYR_DEV_NAME,
+ .pm = &l3g4200d_pm,
+ },
+ .probe = l3g4200d_probe,
+ .remove = __devexit_p(l3g4200d_remove),
+ .shutdown = l3g4200d_shutdown,
+ .id_table = l3g4200d_id,
+};
+
+static struct l3g4200d_gyr_platform_data gyr_drvr_platform_data={
+ .poll_interval = 10000, // us
+ .min_interval = 1250, // us
+
+ .fs_range = L3G4200D_GYR_FS_2000DPS,
+
+ .axis_map_x = 0,
+ .axis_map_y = 1,
+ .axis_map_z = 2,
+
+ .direction_x = 1,
+ .direction_y = -1,
+ .direction_z = -1,
+
+ .init_state.ctrl_reg1 = 0x17, //ODR100
+ .init_state.ctrl_reg2 = 0x00,
+ .init_state.ctrl_reg3 = 0x00, //DRDY interrupt
+ .init_state.ctrl_reg4 = 0xA0, //BDU enable, 2000 dps
+ .init_state.ctrl_reg5 = 0x00,
+ .init_state.ref_datacap = 0x00,
+ .init_state.fifo_ctrl_reg = 0x00,
+ .init_state.int1_cfg = 0x00,
+ .init_state.int1_ths_xh = 0x00,
+ .init_state.int1_ths_xl = 0x00,
+ .init_state.int1_ths_yh = 0x00,
+ .init_state.int1_ths_yl = 0x00,
+ .init_state.int1_ths_zh = 0x00,
+ .init_state.int1_ths_zl = 0x00,
+ .init_state.int1_duration = 0x00
+};
+
+static struct i2c_board_info __initdata l3g4200d_i2c_board[] = {
+ {
+ I2C_BOARD_INFO(L3G4200D_GYR_DEV_NAME, L3G4200D_I2C_ADDR),
+ .irq = IRQ_GPIO,
+ .platform_data = &gyr_drvr_platform_data,
+ },
+};
+
+static int __init l3g4200d_init(void)
+{
+ int ret;
+ struct i2c_adapter *adapter;
+
+#ifdef DEBUG
+ pr_info("%s: gyroscope sysfs driver init\n", L3G4200D_GYR_DEV_NAME);
+#endif
+
+ adapter = i2c_get_adapter(0);
+ if (adapter == NULL) {
+ pr_err("%s: i2c_get_adapter() error\n", L3G4200D_GYR_DEV_NAME);
+ return -ENODEV;
+ }
+
+ l3g4200d_i2c_client = i2c_new_device(adapter, l3g4200d_i2c_board);
+ if (l3g4200d_i2c_client == NULL) {
+ pr_err("%s: i2c_new_device() error\n", L3G4200D_GYR_DEV_NAME);
+ return -ENOMEM;
+ }
+
+ i2c_put_adapter(adapter);
+
+ ret = i2c_add_driver(&l3g4200d_driver);
+ if(ret){
+ pr_err("%s: i2c_add_driver() failed\n", L3G4200D_GYR_DEV_NAME);
+ i2c_unregister_device(l3g4200d_i2c_client);
+ return ret;
+ }
+
+ return ret;
+}
+
+static void __exit l3g4200d_exit(void)
+{
+#ifdef DEBUG
+ pr_info("L3G4200D exit\n");
+#endif
+
+ i2c_del_driver(&l3g4200d_driver);
+ i2c_unregister_device(l3g4200d_i2c_client);
+
+ return;
+}
+
+module_init(l3g4200d_init);
+module_exit(l3g4200d_exit);
+
+MODULE_DESCRIPTION("l3g4200d digital gyroscope sysfs driver");
+MODULE_AUTHOR("Matteo Dameno, Carmine Iascone, STMicroelectronics");
+MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/Makefile
new file mode 100755
index 00000000..8a419fc7
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_gsensor_mc3230
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := mc32x0.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/mc32x0.c b/ANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/mc32x0.c
new file mode 100755
index 00000000..4330dbb6
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/mc32x0.c
@@ -0,0 +1,2580 @@
+/* Date: 2011/4/8 11:00:00
+ * Revision: 2.5
+ */
+
+/*
+ * This software program is licensed subject to the GNU General Public License
+ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html
+
+ * (C) Copyright 2011 Bosch Sensortec GmbH
+ * All Rights Reserved
+ */
+
+
+/* file mc32x0.c
+ brief This file contains all function implementations for the mc32x0 in linux
+
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+//#include <linux/earlysuspend.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+
+//#include <linux/init-input.h>
+#include <mach/hardware.h>
+#include <linux/fs.h>
+
+#include "../sensor.h"
+#include "mc32x0_driver.h"
+
+
+#if 0
+#define mcprintkreg(x...) printk(x)
+#else
+#define mcprintkreg(x...)
+#endif
+
+#if 0
+#define mcprintkfunc(x...) printk(x)
+#else
+#define mcprintkfunc(x...)
+#endif
+
+#if 0
+#define GSE_ERR(x...) printk(x)
+#define GSE_LOG(x...) printk(x)
+#else
+#define GSE_ERR(x...)
+#define GSE_LOG(x...)
+#endif
+
+static int g_virtual_z = 0;
+#define G_2_REVERSE_VIRTUAL_Z 0 //!!!!! 1
+#define SUPPORT_VIRTUAL_Z_SENSOR //add 2013-10-23
+#define LOW_RESOLUTION 1
+#define HIGH_RESOLUTION 2
+#define RBM_RESOLUTION 3
+#ifdef SUPPORT_VIRTUAL_Z_SENSOR
+#define Low_Pos_Max 127
+#define Low_Neg_Max -128
+#define High_Pos_Max 8191
+#define High_Neg_Max -8192
+#define VIRTUAL_Z 1
+static int Railed = 0;
+#else
+#define VIRTUAL_Z 0
+#endif
+
+
+static struct class* l_dev_class = NULL;
+
+
+
+
+#define GSENSOR_NAME "mc3230"
+#define SENSOR_DATA_SIZE 3
+#define AVG_NUM 16
+/* Addresses to scan */
+//static const unsigned short normal_i2c[2] = {0x00,I2C_CLIENT_END};
+
+
+//volatile unsigned char mc32x0_on_off=0;
+//static int mc32x0_pin_hd;
+static char mc32x0_on_off_str[32];
+#define G_0 ABS_X
+#define G_1 ABS_Y
+#define G_2 ABS_Z
+#define G_0_REVERSE 1
+#define G_1_REVERSE 1
+#define G_2_REVERSE -1
+
+#define GRAVITY_1G_VALUE 1000
+
+#define SENSOR_DMARD_IOCTL_BASE 234
+
+#define IOCTL_SENSOR_SET_DELAY_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 100)
+#define IOCTL_SENSOR_GET_DELAY_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 101)
+#define IOCTL_SENSOR_GET_STATE_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 102)
+#define IOCTL_SENSOR_SET_STATE_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 103)
+#define IOCTL_SENSOR_GET_DATA_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 104)
+
+#define IOCTL_MSENSOR_SET_DELAY_MAGNE _IO(SENSOR_DMARD_IOCTL_BASE, 200)
+#define IOCTL_MSENSOR_GET_DATA_MAGNE _IO(SENSOR_DMARD_IOCTL_BASE, 201)
+#define IOCTL_MSENSOR_GET_STATE_MAGNE _IO(SENSOR_DMARD_IOCTL_BASE, 202)
+#define IOCTL_MSENSOR_SET_STATE_MAGNE _IO(SENSOR_DMARD_IOCTL_BASE, 203)
+
+#define IOCTL_SENSOR_GET_NAME _IO(SENSOR_DMARD_IOCTL_BASE, 301)
+#define IOCTL_SENSOR_GET_VENDOR _IO(SENSOR_DMARD_IOCTL_BASE, 302)
+
+#define IOCTL_SENSOR_GET_CONVERT_PARA _IO(SENSOR_DMARD_IOCTL_BASE, 401)
+
+#define SENSOR_CALIBRATION _IOWR(SENSOR_DMARD_IOCTL_BASE, 402, int[SENSOR_DATA_SIZE])
+
+
+#define mc32x0_CONVERT_PARAMETER (1.5f * (9.80665f) / 256.0f)
+//#define mc32x0_DISPLAY_NAME "mc32x0"
+//#define mc32x0_DIPLAY_VENDOR "domintech"
+
+#define X_OUT 0x41
+#define CONTROL_REGISTER 0x44
+#define SW_RESET 0x53
+#define WHO_AM_I 0x0f
+#define WHO_AM_I_VALUE 0x06
+
+#define MC32X0_AXIS_X 0
+#define MC32X0_AXIS_Y 1
+#define MC32X0_AXIS_Z 2
+#define MC32X0_AXES_NUM 3
+#define MC32X0_DATA_LEN 6
+
+#define MC32X0_XOUT_REG 0x00
+#define MC32X0_YOUT_REG 0x01
+#define MC32X0_ZOUT_REG 0x02
+#define MC32X0_Tilt_Status_REG 0x03
+#define MC32X0_Sampling_Rate_Status_REG 0x04
+#define MC32X0_Sleep_Count_REG 0x05
+#define MC32X0_Interrupt_Enable_REG 0x06
+#define MC32X0_Mode_Feature_REG 0x07
+#define MC32X0_Sample_Rate_REG 0x08
+#define MC32X0_Tap_Detection_Enable_REG 0x09
+#define MC32X0_TAP_Dwell_Reject_REG 0x0a
+#define MC32X0_DROP_Control_Register_REG 0x0b
+#define MC32X0_SHAKE_Debounce_REG 0x0c
+#define MC32X0_XOUT_EX_L_REG 0x0d
+#define MC32X0_XOUT_EX_H_REG 0x0e
+#define MC32X0_YOUT_EX_L_REG 0x0f
+#define MC32X0_YOUT_EX_H_REG 0x10
+#define MC32X0_ZOUT_EX_L_REG 0x11
+#define MC32X0_ZOUT_EX_H_REG 0x12
+#define MC32X0_CHIP_ID_REG 0x18
+#define MC32X0_RANGE_Control_REG 0x20
+#define MC32X0_SHAKE_Threshold_REG 0x2B
+#define MC32X0_UD_Z_TH_REG 0x2C
+#define MC32X0_UD_X_TH_REG 0x2D
+#define MC32X0_RL_Z_TH_REG 0x2E
+#define MC32X0_RL_Y_TH_REG 0x2F
+#define MC32X0_FB_Z_TH_REG 0x30
+#define MC32X0_DROP_Threshold_REG 0x31
+#define MC32X0_TAP_Threshold_REG 0x32
+#define MC32X0_HIGH_END 0x01
+/*******MC3210/20 define this**********/
+
+
+#define MCUBE_8G_14BIT 0x10
+
+#define DOT_CALI
+
+#define MC32X0_LOW_END 0x02
+/*******mc32x0 define this**********/
+
+#define MCUBE_1_5G_8BIT 0x20
+//#define MCUBE_1_5G_8BIT_TAP
+//#define MCUBE_1_5G_6BIT
+#define MC32X0_MODE_DEF 0x43
+
+#define MC32X0ADDRESS 0x4c
+
+#define mc32x0_I2C_NAME "mc32x0"
+#define GSENSOR_DEV_COUNT 1
+#define GSENSOR_DURATION_MAX 200
+#define GSENSOR_DURATION_MIN 10
+#define GSENSOR_DURATION_DEFAULT 20
+
+#define MAX_RETRY 20
+#define INPUT_FUZZ 0
+#define INPUT_FLAT 0
+
+#define AUTO_CALIBRATION 0
+
+static unsigned char is_new_mc34x0 = 0;
+static unsigned char is_mc3250 = 0;
+
+static unsigned char McubeID=0;
+#ifdef DOT_CALI
+#define CALIB_PATH "/data/data/com.mcube.acc/files/mcube-calib.txt"
+//MCUBE_BACKUP_FILE
+#define BACKUP_CALIB_PATH "/data/misc/sensors/mcube-calib.txt"
+//static char backup_buf[64];
+//MCUBE_BACKUP_FILE
+#define DATA_PATH "/sdcard/mcube-register-map.txt"
+
+typedef struct {
+ unsigned short x; /**< X axis */
+ unsigned short y; /**< Y axis */
+ unsigned short z; /**< Z axis */
+} GSENSOR_VECTOR3D;
+
+static GSENSOR_VECTOR3D gsensor_gain;
+static struct miscdevice mc32x0_device;
+
+//static struct file * fd_file = NULL;
+
+static mm_segment_t oldfs;
+//add by Liang for storage offset data
+static unsigned char offset_buf[9];
+static signed int offset_data[3];
+s16 G_RAW_DATA[3];
+static signed int gain_data[3];
+static signed int enable_RBM_calibration = 0;
+#endif
+
+#ifdef DOT_CALI
+
+#if 1
+#define GSENSOR 0xA1//0x95
+
+#define GSENSOR_IOCTL_INIT _IO(GSENSOR, 0x01)
+#define GSENSOR_IOCTL_READ_CHIPINFO _IOR(GSENSOR, 0x02, int)
+#define GSENSOR_IOCTL_READ_SENSORDATA _IOR(GSENSOR, 0x17, int)
+#define GSENSOR_IOCTL_READ_OFFSET _IOR(GSENSOR, 0x04, GSENSOR_VECTOR3D)
+#define GSENSOR_IOCTL_READ_GAIN _IOR(GSENSOR, 0x05, GSENSOR_VECTOR3D)
+#define GSENSOR_IOCTL_READ_RAW_DATA _IOR(GSENSOR, 0x30, int)
+//#define GSENSOR_IOCTL_SET_CALI _IOW(GSENSOR, 0x06, SENSOR_DATA)
+#define GSENSOR_IOCTL_GET_CALI _IOW(GSENSOR, 0x22, SENSOR_DATA)
+#define GSENSOR_IOCTL_CLR_CALI _IO(GSENSOR, 0x23)
+#define GSENSOR_MCUBE_IOCTL_READ_RBM_DATA _IOR(GSENSOR, 0x24, SENSOR_DATA)
+#define GSENSOR_MCUBE_IOCTL_SET_RBM_MODE _IO(GSENSOR, 0x25)
+#define GSENSOR_MCUBE_IOCTL_CLEAR_RBM_MODE _IO(GSENSOR, 0x26)
+#define GSENSOR_MCUBE_IOCTL_SET_CALI _IOW(GSENSOR, 0x27, SENSOR_DATA)
+#define GSENSOR_MCUBE_IOCTL_REGISTER_MAP _IO(GSENSOR, 0x28)
+#define GSENSOR_IOCTL_SET_CALI_MODE _IOW(GSENSOR, 0x29,int)
+#else
+
+#define GSENSOR_IOCTL_INIT 0xa1
+#define GSENSOR_IOCTL_READ_CHIPINFO 0xa2
+#define GSENSOR_IOCTL_READ_SENSORDATA 0xa3
+#define GSENSOR_IOCTL_READ_OFFSET 0xa4
+#define GSENSOR_IOCTL_READ_GAIN 0xa5
+#define GSENSOR_IOCTL_READ_RAW_DATA 0xa6
+#define GSENSOR_IOCTL_SET_CALI 0xa7
+#define GSENSOR_IOCTL_GET_CALI 0xa8
+#define GSENSOR_IOCTL_CLR_CALI 0xa9
+
+#define GSENSOR_MCUBE_IOCTL_READ_RBM_DATA 0xaa
+#define GSENSOR_MCUBE_IOCTL_SET_RBM_MODE 0xab
+#define GSENSOR_MCUBE_IOCTL_CLEAR_RBM_MODE 0xac
+#define GSENSOR_MCUBE_IOCTL_SET_CALI 0xad
+#define GSENSOR_MCUBE_IOCTL_REGISTER_MAP 0xae
+#define GSENSOR_IOCTL_SET_CALI_MODE 0xaf
+#endif
+
+typedef struct{
+ int x;
+ int y;
+ int z;
+}SENSOR_DATA;
+
+static int load_cali_flg = 0;
+//MCUBE_BACKUP_FILE
+//static bool READ_FROM_BACKUP = false;
+//MCUBE_BACKUP_FILE
+
+#endif
+
+#define MC32X0_WAKE 1
+#define MC32X0_SNIFF 2
+#define MC32X0_STANDBY 3
+
+struct dev_data {
+ struct i2c_client *client;
+};
+static struct dev_data dev;
+
+/* Addresses to scan */
+static const unsigned short normal_i2c[2] = {MC32X0ADDRESS, I2C_CLIENT_END};
+
+/*
+typedef union {
+ struct {
+ s16 x;
+ s16 y;
+ s16 z;
+ } u;
+ s16 v[SENSOR_DATA_SIZE];
+} raw_data;
+static raw_data offset;
+*/
+
+struct acceleration {
+ int x;
+ int y;
+ int z;
+};
+
+//void gsensor_write_offset_to_file(void);
+//void gsensor_read_offset_from_file(void);
+//char OffsetFileName[] = "/data/misc/dmt/offset.txt";
+/*static struct sensor_config_info gsensor_info = {
+ .input_type = GSENSOR_TYPE,
+};*/
+
+static u32 debug_mask = 0;
+#define dprintk(level_mask, fmt, arg...) if (unlikely(debug_mask & level_mask)) \
+ printk(KERN_DEBUG fmt , ## arg)
+
+module_param_named(debug_mask, debug_mask, int, 0644);
+
+
+enum {
+ DEBUG_INIT = 1U << 0,
+ DEBUG_CONTROL_INFO = 1U << 1,
+ DEBUG_DATA_INFO = 1U << 2,
+ DEBUG_SUSPEND = 1U << 3,
+};
+
+struct mc32x0_data {
+ struct mutex lock;
+ struct i2c_client *client;
+ struct delayed_work work;
+ struct workqueue_struct *mc32x0_wq;
+ struct hrtimer timer;
+ struct device *device;
+ struct input_dev *input_dev;
+ int use_count;
+ int enabled;
+ volatile unsigned int duration;
+ int use_irq;
+ int irq;
+ unsigned long irqflags;
+ int gpio;
+ unsigned int map[3];
+ int inv[3];
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ // for control
+ int int_gpio; //0-3
+ int op;
+ int samp;
+ //int xyz_axis[3][3]; // (axis,direction)
+ struct proc_dir_entry* sensor_proc;
+ int isdbg;
+ int sensor_samp; //
+ int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor
+ int test_pass;
+ int offset[MC32X0_AXES_NUM+1]; /*+1: for 4-byte alignment*/
+ s16 data[MC32X0_AXES_NUM+1];
+};
+
+static struct mc32x0_data l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .samp = 16,
+ /*.xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },*/
+ .sensor_proc = NULL,
+ .isdbg = 1,
+ .sensor_samp = 1, // 1 sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ //.offset={0,0,0},
+};
+
+
+//=============================================================================
+enum mc3xx0_orientation
+{
+ MC3XX0_TOP_LEFT_DOWN = 0,
+ MC3XX0_TOP_RIGHT_DOWN,
+ MC3XX0_TOP_RIGHT_UP,
+ MC3XX0_TOP_LEFT_UP,
+ MC3XX0_BOTTOM_LEFT_DOWN,
+ MC3XX0_BOTTOM_RIGHT_DOWN,
+ MC3XX0_BOTTOM_RIGHT_UP,
+ MC3XX0_BOTTOM_LEFT_UP
+};
+
+enum mc3xx0_axis
+{
+ MC3XX0_AXIS_X = 0,
+ MC3XX0_AXIS_Y,
+ MC3XX0_AXIS_Z,
+ MC3XX0_AXIS_NUM
+};
+
+struct mc3xx0_hwmsen_convert
+{
+ signed int sign[3];
+ unsigned int map[3];
+};
+
+// Transformation matrix for chip mounting position
+static const struct mc3xx0_hwmsen_convert mc3xx0_cvt[] =
+{
+ {{ 1, 1, 1}, {MC3XX0_AXIS_X, MC3XX0_AXIS_Y, MC3XX0_AXIS_Z}}, // 0: top , left-down
+ {{-1, 1, 1}, {MC3XX0_AXIS_Y, MC3XX0_AXIS_X, MC3XX0_AXIS_Z}}, // 1: top , right-down
+ {{-1, -1, 1}, {MC3XX0_AXIS_X, MC3XX0_AXIS_Y, MC3XX0_AXIS_Z}}, // 2: top , right-up
+ {{ 1, -1, 1}, {MC3XX0_AXIS_Y, MC3XX0_AXIS_X, MC3XX0_AXIS_Z}}, // 3: top , left-up
+ {{-1, 1, -1}, {MC3XX0_AXIS_X, MC3XX0_AXIS_Y, MC3XX0_AXIS_Z}}, // 4: bottom, left-down
+ {{ 1, 1, -1}, {MC3XX0_AXIS_Y, MC3XX0_AXIS_X, MC3XX0_AXIS_Z}}, // 5: bottom, right-down
+ {{ 1, -1, -1}, {MC3XX0_AXIS_X, MC3XX0_AXIS_Y, MC3XX0_AXIS_Z}}, // 6: bottom, right-up
+ {{-1, -1, -1}, {MC3XX0_AXIS_Y, MC3XX0_AXIS_X, MC3XX0_AXIS_Z}}, // 7: bottom, left-up
+};
+
+//static unsigned char mc3xx0_current_placement = MC3XX0_BOTTOM_LEFT_DOWN; // current soldered placement
+static struct mc3xx0_hwmsen_convert *pCvt;
+
+//volatile static short sensor_duration = SENSOR_DURATION_DEFAULT;//delay
+//volatile static short sensor_state_flag = 1;
+
+#ifdef SUPPORT_VIRTUAL_Z_SENSOR //add 2013-10-23
+int Verify_Z_Railed(int AccData, int resolution)
+{
+ int status = 0;
+ GSE_LOG("%s: AccData = %d",__func__, AccData);
+ if(resolution == 1) // Low resolution
+ {
+ if((AccData >= Low_Pos_Max && AccData >=0)|| (AccData <= Low_Neg_Max && AccData < 0))
+ {
+ status = 1;
+ GSE_LOG("%s: Railed at Low Resolution",__func__);
+ }
+ }
+ else if (resolution == 2) //High resolution
+ {
+ if((AccData >= High_Pos_Max && AccData >=0) || (AccData <= High_Neg_Max && AccData < 0))
+ {
+ status = 1;
+ GSE_LOG("%s: Railed at High Resolution",__func__);
+ }
+ }
+ else if (resolution == 3) //High resolution
+ {
+ if((AccData >= Low_Pos_Max*3 && AccData >=0) || (AccData <= Low_Neg_Max*3 && AccData < 0))
+ {
+ status = 1;
+ GSE_LOG("%s: Railed at High Resolution",__func__);
+ }
+ }
+ else
+ GSE_LOG("%s, Wrong resolution",__func__);
+
+ return status;
+}
+
+int SquareRoot(int x)
+{
+ int lowerbound;
+ int upperbound;
+ int root;
+
+ if(x < 0) return -1;
+ if(x == 0 || x == 1) return x;
+ lowerbound = 1;
+ upperbound = x;
+ root = lowerbound + (upperbound - lowerbound)/2;
+
+ while(root > x/root || root+1 <= x/(root+1))
+ {
+ if(root > x/root)
+ {
+ upperbound = root;
+ }
+ else
+ {
+ lowerbound = root;
+ }
+ root = lowerbound + (upperbound - lowerbound)/2;
+ }
+ GSE_LOG("%s: Sqrt root is %d",__func__, root);
+ return root;
+}
+#endif
+
+
+unsigned int sample_rate_2_memsec(unsigned int rate)
+{
+ return (1000/rate);
+}
+
+static ssize_t mc32x0_map_show(struct device *dev, struct device_attribute *attr,char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mc32x0_data *data;
+ int i;
+ data = i2c_get_clientdata(client);
+ for (i = 0; i< 3; i++)
+ {
+ if(data->inv[i] == 1)
+ {
+ switch(data->map[i])
+ {
+ case ABS_X:
+ buf[i] = 'x';
+ break;
+ case ABS_Y:
+ buf[i] = 'y';
+ break;
+ case ABS_Z:
+ buf[i] = 'z';
+ break;
+ default:
+ buf[i] = '_';
+ break;
+ }
+ }
+ else
+ {
+ switch(data->map[i])
+ {
+ case ABS_X:
+ buf[i] = 'X';
+ break;
+ case ABS_Y:
+ buf[i] = 'Y';
+ break;
+ case ABS_Z:
+ buf[i] = 'Z';
+ break;
+ default:
+ buf[i] = '-';
+ break;
+ }
+ }
+ }
+ sprintf(buf+3,"\r\n");
+ return 5;
+}
+/*
+//Function as i2c_master_send, and return 1 if operation is successful.
+static int i2c_write_bytes(struct i2c_client *client, uint8_t *data, uint16_t len)
+{
+ struct i2c_msg msg;
+ int ret=-1;
+
+ msg.flags = !I2C_M_RD;
+ msg.addr = client->addr;
+ msg.len = len;
+ msg.buf = data;
+
+ ret=i2c_transfer(client->adapter, &msg,1);
+ return ret;
+}
+
+static bool gsensor_i2c_test(struct i2c_client * client)
+{
+ int ret, retry;
+ uint8_t test_data[1] = { 0 }; //only write a data address.
+
+ for(retry=0; retry < 2; retry++)
+ {
+ ret =i2c_write_bytes(client, test_data, 1); //Test i2c.
+ if (ret == 1)
+ break;
+ msleep(5);
+ }
+
+ return ret==1 ? true : false;
+}
+*/
+/**
+ * gsensor_detect - Device detection callback for automatic device creation
+ * return value:
+ * = 0; success;
+ * < 0; err
+ */
+ /*
+static int gsensor_detect(struct i2c_client *client, struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ int ret;
+
+ dprintk(DEBUG_INIT, "%s enter \n", __func__);
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ if(twi_id == adapter->nr){
+ pr_info("%s: addr= %x\n",__func__,client->addr);
+
+ ret = gsensor_i2c_test(client);
+ if(!ret){
+ pr_info("%s:I2C connection might be something wrong or maybe the other gsensor equipment! \n",__func__);
+ return -ENODEV;
+ }else{
+ pr_info("I2C connection sucess!\n");
+ strlcpy(info->type, SENSOR_NAME, I2C_NAME_SIZE);
+ return 0;
+ }
+
+ }else{
+ return -ENODEV;
+ }
+}
+*/
+int mc32x0_set_image (struct i2c_client *client)
+{
+ int comres = 0;
+ unsigned char data;
+
+
+ data = i2c_smbus_read_byte_data(client, 0x3B);
+ //comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, 0x3B, &data, 1 );
+ if((data == 0x19)||(data == 0x29))
+ {
+ McubeID = 0x22;
+ }
+ else if((data == 0x90)||(data == 0xA8))
+ {
+ McubeID = 0x11;
+ }
+ else
+ {
+ McubeID = 0;
+ }
+
+ if (0x88 == data)
+ {
+ McubeID = 0x11;
+ is_mc3250 = 1;
+ }
+
+ if (0x39 == data)
+ {
+ McubeID = 0x22;
+ is_new_mc34x0 = 1;
+ }
+ else if (0xB8 == data)
+ {
+ McubeID = 0x11;
+ is_new_mc34x0 = 1;
+ }
+
+
+ if(McubeID &MCUBE_8G_14BIT)
+ {
+ //#ifdef MCUBE_8G_14BIT
+ data = MC32X0_MODE_DEF;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Mode_Feature_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_Mode_Feature_REG,data);
+ data = 0x00;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sleep_Count_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_Sleep_Count_REG,data);
+ data = 0x00;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sample_Rate_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_Sample_Rate_REG,data);
+ data = 0x00;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Tap_Detection_Enable_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_Tap_Detection_Enable_REG,data);
+ data = 0x3F;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_RANGE_Control_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_RANGE_Control_REG,data);
+ data = 0x00;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Interrupt_Enable_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_Interrupt_Enable_REG,data);
+#ifdef DOT_CALI
+ gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = 1024;
+#endif
+ //#endif
+ }
+ else if(McubeID &MCUBE_1_5G_8BIT)
+ {
+ #ifdef MCUBE_1_5G_8BIT
+ data = MC32X0_MODE_DEF;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Mode_Feature_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_Mode_Feature_REG,data);
+ data = 0x00;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sleep_Count_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_Sleep_Count_REG,data);
+ data = 0x00;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sample_Rate_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_Sample_Rate_REG,data);
+ data = 0x02;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_RANGE_Control_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_RANGE_Control_REG,data);
+ data = 0x00;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Tap_Detection_Enable_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_Tap_Detection_Enable_REG,data);
+ data = 0x00;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Interrupt_Enable_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_Interrupt_Enable_REG,data);
+#ifdef DOT_CALI
+ gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = 86;
+#endif
+ #endif
+ }
+
+ data = 0x41;
+ //comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Mode_Feature_REG, &data, 1 );
+ i2c_smbus_write_byte_data(client, MC32X0_Mode_Feature_REG,data);
+ //MC32X0_rbm(0,0);
+ return comres;
+}
+
+static ssize_t mc32x0_map_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mc32x0_data *data;
+ int i;
+ data = i2c_get_clientdata(client);
+
+ if(count < 3) return -EINVAL;
+
+ for(i = 0; i< 3; i++)
+ {
+ switch(buf[i])
+ {
+ case 'x':
+ data->map[i] = ABS_X;
+ data->inv[i] = 1;
+ break;
+ case 'y':
+ data->map[i] = ABS_Y;
+ data->inv[i] = 1;
+ break;
+ case 'z':
+ data->map[i] = ABS_Z;
+ data->inv[i] = 1;
+ break;
+ case 'X':
+ data->map[i] = ABS_X;
+ data->inv[i] = -1;
+ break;
+ case 'Y':
+ data->map[i] = ABS_Y;
+ data->inv[i] = -1;
+ break;
+ case 'Z':
+ data->map[i] = ABS_Z;
+ data->inv[i] = -1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return count;
+}
+
+static int mc32x0_enable(struct mc32x0_data *data, int enable);
+
+static ssize_t mc32x0_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = container_of(mc32x0_device.parent, struct i2c_client, dev);
+
+ struct mc32x0_data *mc32x0 = i2c_get_clientdata(client);
+
+ return sprintf(buf, "%d\n", mc32x0->enabled);
+}
+
+static ssize_t mc32x0_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ bool new_enable;
+
+ struct i2c_client *client = container_of(mc32x0_device.parent, struct i2c_client, dev);
+
+ struct mc32x0_data *mc32x0 = i2c_get_clientdata(client);
+
+ if (sysfs_streq(buf, "1"))
+ new_enable = true;
+ else if (sysfs_streq(buf, "0"))
+ new_enable = false;
+ else {
+ pr_debug("%s: invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ mc32x0_enable(mc32x0, new_enable);
+
+ return count;
+}
+
+static ssize_t mc32x0_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", 1000/l_sensorconfig.sensor_samp);
+}
+
+static ssize_t mc32x0_delay_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ return error;
+ if (data > GSENSOR_DURATION_MAX)
+ data = GSENSOR_DURATION_MAX;
+ if (data < GSENSOR_DURATION_MIN)
+ data = GSENSOR_DURATION_MIN;
+ l_sensorconfig.sensor_samp = 1000/data;
+
+ return count;
+}
+
+static DEVICE_ATTR(map, 0660, mc32x0_map_show, mc32x0_map_store);
+static DEVICE_ATTR(enable, 0660, mc32x0_enable_show, mc32x0_enable_store);
+static DEVICE_ATTR(delay, 0660, mc32x0_delay_show, mc32x0_delay_store);
+
+static struct attribute* mc32x0_attrs[] =
+{
+ &dev_attr_map.attr,
+ &dev_attr_enable.attr,
+ &dev_attr_delay.attr,
+ NULL
+};
+
+static const struct attribute_group mc32x0_group =
+{
+ .attrs = mc32x0_attrs,
+};
+
+static int mc32x0_chip_init(struct i2c_client *client)
+{
+
+ mc32x0_set_image(client);
+
+ return McubeID?0:-1;
+}
+
+int mc32x0_set_mode(struct i2c_client *client, unsigned char mode)
+{
+
+ int comres=0;
+ unsigned char data;
+
+
+ if (mode<4) {
+ data = 0x40|mode;
+ i2c_smbus_write_byte_data(client, MC32X0_Mode_Feature_REG,data);
+ }
+ return comres;
+
+}
+
+
+
+#ifdef DOT_CALI
+struct file *openFile(const char *path,int flag,int mode)
+{
+ struct file *fp;
+
+ fp=filp_open(path, flag, mode);
+ if (IS_ERR(fp) || !fp->f_op)
+ {
+ GSE_LOG("Calibration File filp_open return NULL\n");
+ return NULL;
+ }
+ else
+ {
+
+ return fp;
+ }
+}
+
+int readFile(struct file *fp,char *buf,int readlen)
+{
+ if (fp->f_op && fp->f_op->read)
+ return fp->f_op->read(fp,buf,readlen, &fp->f_pos);
+ else
+ return -1;
+}
+
+int writeFile(struct file *fp,char *buf,int writelen)
+{
+ if (fp->f_op && fp->f_op->write)
+ return fp->f_op->write(fp,buf,writelen, &fp->f_pos);
+ else
+ return -1;
+}
+
+int closeFile(struct file *fp)
+{
+ filp_close(fp,NULL);
+ return 0;
+}
+
+void initKernelEnv(void)
+{
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ printk(KERN_INFO "initKernelEnv\n");
+}
+
+ int MC32X0_WriteCalibration(struct i2c_client *client, int dat[MC32X0_AXES_NUM])
+{
+ int err;
+ u8 buf[9];
+ s16 tmp, x_gain, y_gain, z_gain ;
+ s32 x_off, y_off, z_off;
+ int temp_cali_dat[MC32X0_AXES_NUM] = { 0 };
+ //const struct mc3xx0_hwmsen_convert *pCvt = NULL;
+
+ //pCvt = &mc3xx0_cvt[mc3xx0_current_placement];
+
+ temp_cali_dat[pCvt->map[MC3XX0_AXIS_X]] = pCvt->sign[MC3XX0_AXIS_X] * dat[MC3XX0_AXIS_X];
+ temp_cali_dat[pCvt->map[MC3XX0_AXIS_Y]] = pCvt->sign[MC3XX0_AXIS_Y] * dat[MC3XX0_AXIS_Y];
+ temp_cali_dat[pCvt->map[MC3XX0_AXIS_Z]] = pCvt->sign[MC3XX0_AXIS_Z] * dat[MC3XX0_AXIS_Z];
+/*
+ temp_cali_dat[MC3XX0_AXIS_X] = ((temp_cali_dat[MC3XX0_AXIS_X] * gsensor_gain.x) / GRAVITY_1G_VALUE);
+ temp_cali_dat[MC3XX0_AXIS_Y] = ((temp_cali_dat[MC3XX0_AXIS_Y] * gsensor_gain.y) / GRAVITY_1G_VALUE);
+ temp_cali_dat[MC3XX0_AXIS_Z] = ((temp_cali_dat[MC3XX0_AXIS_Z] * gsensor_gain.z) / GRAVITY_1G_VALUE);
+*/
+ if (is_new_mc34x0)
+ {
+ temp_cali_dat[MC3XX0_AXIS_X] = -temp_cali_dat[MC3XX0_AXIS_X];
+ temp_cali_dat[MC3XX0_AXIS_Y] = -temp_cali_dat[MC3XX0_AXIS_Y];
+ }
+ else if (is_mc3250)
+ {
+ s16 temp = 0;
+
+ temp = temp_cali_dat[MC3XX0_AXIS_X];
+
+ temp_cali_dat[MC3XX0_AXIS_X] = -temp_cali_dat[MC3XX0_AXIS_Y];
+ temp_cali_dat[MC3XX0_AXIS_Y] = temp;
+ }
+
+ dat[MC3XX0_AXIS_X] = temp_cali_dat[MC3XX0_AXIS_X];
+ dat[MC3XX0_AXIS_Y] = temp_cali_dat[MC3XX0_AXIS_Y];
+ dat[MC3XX0_AXIS_Z] = temp_cali_dat[MC3XX0_AXIS_Z];
+
+#if 0 //modify by zwx
+
+ GSE_LOG("UPDATE dat: (%+3d %+3d %+3d)\n",
+ dat[MC32X0_AXIS_X], dat[MC32X0_AXIS_Y], dat[MC32X0_AXIS_Z]);
+
+ /*calculate the real offset expected by caller*/
+ //cali_temp[MC32X0_AXIS_X] = dat[MC32X0_AXIS_X];
+ //cali_temp[MC32X0_AXIS_Y] = dat[MC32X0_AXIS_Y];
+ //cali_temp[MC32X0_AXIS_Z] = dat[MC32X0_AXIS_Z];
+ //cali[MC32X0_AXIS_Z]= cali[MC32X0_AXIS_Z]-gsensor_gain.z;
+
+
+#endif
+// read register 0x21~0x28
+#if 1 //zwx
+ //if ((err = mc32x0_read_block(client, 0x21, buf, 3)))
+ //if ((err = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, 0x21, &buf[0],3)))
+ err = i2c_smbus_read_i2c_block_data(client , 0x21 , 3 , &buf[0]);
+
+ //if ((err = mc32x0_read_block(client, 0x24, &buf[3], 3)))
+ //if ((err = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, 0x24, &buf[3],3)))
+ err = i2c_smbus_read_i2c_block_data(client , 0x24 , 3 , &buf[3]);
+
+ //if ((err = mc32x0_read_block(client, 0x27, &buf[6], 3)))
+ //if ((err = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, 0x27, &buf[6],3)))
+ err = i2c_smbus_read_i2c_block_data(client , 0x27 , 3 , &buf[6]);
+
+#else
+ buf[0] = 0x21;
+ err = mc32x0_rx_data(client, &buf[0], 3);
+ buf[3] = 0x24;
+ err = mc32x0_rx_data(client, &buf[3], 3);
+ buf[6] = 0x27;
+ err = mc32x0_rx_data(client, &buf[6], 3);
+#endif
+#if 1
+ // get x,y,z offset
+ tmp = ((buf[1] & 0x3f) << 8) + buf[0];
+ if (tmp & 0x2000)
+ tmp |= 0xc000;
+ x_off = tmp;
+
+ tmp = ((buf[3] & 0x3f) << 8) + buf[2];
+ if (tmp & 0x2000)
+ tmp |= 0xc000;
+ y_off = tmp;
+
+ tmp = ((buf[5] & 0x3f) << 8) + buf[4];
+ if (tmp & 0x2000)
+ tmp |= 0xc000;
+ z_off = tmp;
+
+ // get x,y,z gain
+ x_gain = ((buf[1] >> 7) << 8) + buf[6];
+ y_gain = ((buf[3] >> 7) << 8) + buf[7];
+ z_gain = ((buf[5] >> 7) << 8) + buf[8];
+
+ // prepare new offset
+ x_off = x_off + 16 * dat[MC32X0_AXIS_X] * 256 * 128 / 3 / gsensor_gain.x / (40 + x_gain);
+ y_off = y_off + 16 * dat[MC32X0_AXIS_Y] * 256 * 128 / 3 / gsensor_gain.y / (40 + y_gain);
+ z_off = z_off + 16 * dat[MC32X0_AXIS_Z] * 256 * 128 / 3 / gsensor_gain.z / (40 + z_gain);
+
+ //storege the cerrunt offset data with DOT format
+ offset_data[0] = x_off;
+ offset_data[1] = y_off;
+ offset_data[2] = z_off;
+
+ //storege the cerrunt Gain data with GOT format
+ gain_data[0] = 256*8*128/3/(40+x_gain);
+ gain_data[1] = 256*8*128/3/(40+y_gain);
+ gain_data[2] = 256*8*128/3/(40+z_gain);
+ printk("%d %d ======================\n\n ",gain_data[0],x_gain);
+#endif
+ buf[0]=0x43;
+ //mc32x0_write_block(client, 0x07, buf, 1);
+ //mc32x0_write_reg(client,0x07,0x43);
+ //p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x07, &buf[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x07,buf[0]);
+ buf[0] = x_off & 0xff;
+ buf[1] = ((x_off >> 8) & 0x3f) | (x_gain & 0x0100 ? 0x80 : 0);
+ buf[2] = y_off & 0xff;
+ buf[3] = ((y_off >> 8) & 0x3f) | (y_gain & 0x0100 ? 0x80 : 0);
+ buf[4] = z_off & 0xff;
+ buf[5] = ((z_off >> 8) & 0x3f) | (z_gain & 0x0100 ? 0x80 : 0);
+
+
+ //mc32x0_write_block(client, 0x21, buf, 6);
+ //p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x21, &buf[0], 6 );
+ i2c_smbus_write_i2c_block_data(client, 0x21, 2,&buf[0]);
+ i2c_smbus_write_i2c_block_data(client, 0x21+2, 2,&buf[2]);
+ i2c_smbus_write_i2c_block_data(client, 0x21+4, 2,&buf[4]);
+
+
+ buf[0]=0x41;
+ //mc32x0_write_block(client, 0x07, buf, 1);
+ //p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x07, &buf[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x07,buf[0]);
+ //mc32x0_write_reg(client,0x07,0x41);
+
+ return err;
+
+}
+/*
+int mcube_read_cali_file(struct i2c_client *client)
+{
+ int cali_data[3];
+ int err =0;
+
+ printk("%s %d\n",__func__,__LINE__);
+ //MCUBE_BACKUP_FILE
+ READ_FROM_BACKUP = false;
+ //MCUBE_BACKUP_FILE
+ initKernelEnv();
+ fd_file = openFile(CALIB_PATH,O_RDONLY,0);
+ //MCUBE_BACKUP_FILE
+ if (fd_file == NULL)
+ {
+ fd_file = openFile(BACKUP_CALIB_PATH, O_RDONLY, 0);
+ if(fd_file != NULL)
+ {
+ READ_FROM_BACKUP = true;
+ }
+ }
+ //MCUBE_BACKUP_FILE
+ if (fd_file == NULL)
+ {
+ GSE_LOG("fail to open\n");
+ cali_data[0] = 0;
+ cali_data[1] = 0;
+ cali_data[2] = 0;
+ return 1;
+ }
+ else
+ {
+ printk("%s %d\n",__func__,__LINE__);
+ memset(backup_buf,0,64);
+ if ((err = readFile(fd_file,backup_buf,128))>0)
+ GSE_LOG("buf:%s\n",backup_buf);
+ else
+ GSE_LOG("read file error %d\n",err);
+ printk("%s %d\n",__func__,__LINE__);
+
+ set_fs(oldfs);
+ closeFile(fd_file);
+
+ sscanf(backup_buf, "%d %d %d",&cali_data[MC32X0_AXIS_X], &cali_data[MC32X0_AXIS_Y], &cali_data[MC32X0_AXIS_Z]);
+ GSE_LOG("cali_data: %d %d %d\n", cali_data[MC32X0_AXIS_X], cali_data[MC32X0_AXIS_Y], cali_data[MC32X0_AXIS_Z]);
+
+ //cali_data1[MC32X0_AXIS_X] = cali_data[MC32X0_AXIS_X] * gsensor_gain.x / GRAVITY_EARTH_1000;
+ //cali_data1[MC32X0_AXIS_Y] = cali_data[MC32X0_AXIS_Y] * gsensor_gain.y / GRAVITY_EARTH_1000;
+ //cali_data1[MC32X0_AXIS_Z] = cali_data[MC32X0_AXIS_Z] * gsensor_gain.z / GRAVITY_EARTH_1000;
+ //cali_data[MC32X0_AXIS_X]=-cali_data[MC32X0_AXIS_X];
+ //cali_data[MC32X0_AXIS_Y]=-cali_data[MC32X0_AXIS_Y];
+ //cali_data[MC32X0_AXIS_Z]=-cali_data[MC32X0_AXIS_Z];
+
+ //GSE_LOG("cali_data1: %d %d %d\n", cali_data1[MC32X0_AXIS_X], cali_data1[MC32X0_AXIS_Y], cali_data1[MC32X0_AXIS_Z]);
+ printk("%s %d\n",__func__,__LINE__);
+ MC32X0_WriteCalibration(client,cali_data);
+ }
+
+ return 0;
+}
+*/
+
+void MC32X0_rbm(struct i2c_client *client, int enable)
+{
+ //int err;
+ char buf1[3];
+ if(enable == 1 )
+ {
+#if 1
+ buf1[0] = 0x43;
+ //err = mc32x0_write_block(client, 0x07, buf1, 0x01);
+ //err = p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x07, &buf1[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x07,buf1[0]);
+ buf1[0] = 0x02;
+ //err = mc32x0_write_block(client, 0x14, buf1, 0x01);
+ //err = p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x14, &buf1[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x14,buf1[0]);
+ buf1[0] = 0x41;
+ //err = mc32x0_write_block(client, 0x07, buf1, 0x01);
+ //err = p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x07, &buf1[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x07,buf1[0]);
+#else
+ err = mc32x0_write_reg(client,0x07,0x43);
+ err = mc32x0_write_reg(client,0x14,0x02);
+ err = mc32x0_write_reg(client,0x07,0x41);
+#endif
+ enable_RBM_calibration =1;
+
+ GSE_LOG("set rbm!!\n");
+
+ msleep(10);
+ }
+ else if(enable == 0 )
+ {
+#if 1
+ buf1[0] = 0x43;
+ //err = mc32x0_write_block(client, 0x07, buf1, 0x01);
+ //err = p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x07, &buf1[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x07,buf1[0]);
+
+ buf1[0] = 0x00;
+ //err = mc32x0_write_block(client, 0x14, buf1, 0x01);
+ //err = p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x14, &buf1[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x14,buf1[0]);
+ buf1[0] = 0x41;
+ //err = mc32x0_write_block(client, 0x07, buf1, 0x01);
+ //err = p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x07, &buf1[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x07,buf1[0]);
+#else
+ err = mc32x0_write_reg(client,0x07,0x43);
+ err = mc32x0_write_reg(client,0x14,0x00);
+ err = mc32x0_write_reg(client,0x07,0x41);
+#endif
+ enable_RBM_calibration =0;
+
+ GSE_LOG("clear rbm!!\n");
+
+ msleep(10);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+ int MC32X0_ReadData_RBM(struct i2c_client *client,int data[MC32X0_AXES_NUM])
+{
+ //u8 uData;
+ u8 addr = 0x0d;
+ u8 rbm_buf[MC32X0_DATA_LEN] = {0};
+ int err = 0;
+
+
+ //err = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, addr, &rbm_buf[0],6);
+ err = i2c_smbus_read_i2c_block_data(client , addr , 6 , rbm_buf);
+ //err = mc32x0_read_block(client, addr, rbm_buf, 0x06);
+
+ data[MC32X0_AXIS_X] = (s16)((rbm_buf[0]) | (rbm_buf[1] << 8));
+ data[MC32X0_AXIS_Y] = (s16)((rbm_buf[2]) | (rbm_buf[3] << 8));
+ data[MC32X0_AXIS_Z] = (s16)((rbm_buf[4]) | (rbm_buf[5] << 8));
+
+ GSE_LOG("rbm_buf<<<<<[%02x %02x %02x %02x %02x %02x]\n",rbm_buf[0], rbm_buf[2], rbm_buf[2], rbm_buf[3], rbm_buf[4], rbm_buf[5]);
+ GSE_LOG("RBM<<<<<[%04x %04x %04x]\n", data[MC32X0_AXIS_X], data[MC32X0_AXIS_Y], data[MC32X0_AXIS_Z]);
+ GSE_LOG("RBM<<<<<[%04d %04d %04d]\n", data[MC32X0_AXIS_X], data[MC32X0_AXIS_Y], data[MC32X0_AXIS_Z]);
+ return err;
+}
+
+
+ int MC32X0_ReadRBMData(struct i2c_client *client, char *buf)
+{
+ //struct mc32x0_data *mc32x0 = i2c_get_clientdata(client);
+ int res = 0;
+ int data[3];
+
+ if (!buf)
+ {
+ return EINVAL;
+ }
+
+ mc32x0_set_mode(client,MC32X0_WAKE);
+/*
+ if(mc32x0->status == mc32x0_CLOSE)
+ {
+ res = mc32x0_start(client, 0);
+ if(res)
+ {
+ GSE_ERR("Power on mc32x0 error %d!\n", res);
+ }
+ }
+*/
+ if((res = MC32X0_ReadData_RBM(client,data)))
+ {
+ GSE_ERR("%s I2C error: ret value=%d",__func__, res);
+ return EIO;
+ }
+ else
+ {
+ sprintf(buf, "%04x %04x %04x", data[MC32X0_AXIS_X],
+ data[MC32X0_AXIS_Y], data[MC32X0_AXIS_Z]);
+
+ }
+
+ return 0;
+}
+ int MC32X0_ReadOffset(struct i2c_client *client,s16 ofs[MC32X0_AXES_NUM])
+{
+ int err;
+ u8 off_data[6];
+
+
+ if(McubeID &MCUBE_8G_14BIT)
+ {
+
+ //if ((err = mc32x0_read_block(client, MC32X0_XOUT_EX_L_REG, off_data, MC32X0_DATA_LEN)))
+ //if ((err = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_XOUT_EX_L_REG, &off_data[0],MC32X0_DATA_LEN)))
+ err = i2c_smbus_read_i2c_block_data(client , MC32X0_XOUT_EX_L_REG , MC32X0_DATA_LEN , off_data);
+
+ ofs[MC32X0_AXIS_X] = ((s16)(off_data[0]))|((s16)(off_data[1])<<8);
+ ofs[MC32X0_AXIS_Y] = ((s16)(off_data[2]))|((s16)(off_data[3])<<8);
+ ofs[MC32X0_AXIS_Z] = ((s16)(off_data[4]))|((s16)(off_data[5])<<8);
+ }
+ else if(McubeID &MCUBE_1_5G_8BIT)
+ {
+ //if ((err = mc32x0_read_block(client, 0, off_data, 3)))
+ //if ((err = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, 0, &off_data[0],3)))
+ err = i2c_smbus_read_i2c_block_data(client , 0 , 3 , off_data);
+
+ ofs[MC32X0_AXIS_X] = (s8)off_data[0];
+ ofs[MC32X0_AXIS_Y] = (s8)off_data[1];
+ ofs[MC32X0_AXIS_Z] = (s8)off_data[2];
+ }
+
+ GSE_LOG("MC32X0_ReadOffset %d %d %d \n",ofs[MC32X0_AXIS_X] ,ofs[MC32X0_AXIS_Y],ofs[MC32X0_AXIS_Z]);
+
+ return 0;
+}
+/*----------------------------------------------------------------------------*/
+ int MC32X0_ResetCalibration(struct i2c_client *client)
+{
+
+ u8 buf[6];
+ s16 tmp;
+ int err;
+#if 1 //zwx
+ buf[0] = 0x43;
+ //if(err = mc32x0_write_block(client, 0x07, buf, 1))
+ //if(err = p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x07, &buf[0], 1 ))
+ if((err = i2c_smbus_write_byte_data(client, 0x07,buf[0])))
+ {
+ GSE_ERR("error 0x07: %d\n", err);
+ }
+
+
+ //if(err = mc32x0_write_block(client, 0x21, offset_buf, 6)) // add by liang for writing offset register as OTP value
+ //if(err = p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x21, &offset_buf[0], 6 ))
+ if((err = i2c_smbus_write_i2c_block_data(client, 0x21, 6,offset_buf)))
+ {
+ GSE_ERR("error: %d\n", err);
+ }
+
+ buf[0] = 0x41;
+ //if(err = mc32x0_write_block(client, 0x07, buf, 1))
+ //if(err = p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x07, &buf[0], 1 ))
+ if((err = i2c_smbus_write_byte_data(client, 0x07,buf[0])))
+ {
+ GSE_ERR("error: %d\n", err);
+ }
+#else
+ mc32x0_write_reg(client,0x07,0x43);
+
+ mc32x0_write_block(client, 0x21, offset_buf, 6);
+
+ mc32x0_write_reg(client,0x07,0x41);
+#endif
+ msleep(20);
+
+ tmp = ((offset_buf[1] & 0x3f) << 8) + offset_buf[0]; // add by Liang for set offset_buf as OTP value
+ if (tmp & 0x2000)
+ tmp |= 0xc000;
+ offset_data[0] = tmp;
+
+ tmp = ((offset_buf[3] & 0x3f) << 8) + offset_buf[2]; // add by Liang for set offset_buf as OTP value
+ if (tmp & 0x2000)
+ tmp |= 0xc000;
+ offset_data[1] = tmp;
+
+ tmp = ((offset_buf[5] & 0x3f) << 8) + offset_buf[4]; // add by Liang for set offset_buf as OTP value
+ if (tmp & 0x2000)
+ tmp |= 0xc000;
+ offset_data[2] = tmp;
+
+ //memset(mc32x0->cali_sw, 0x00, sizeof(mc32x0->cali_sw));
+ return 0;
+
+}
+/*----------------------------------------------------------------------------*/
+ int MC32X0_ReadCalibration(struct i2c_client *client,int dat[MC32X0_AXES_NUM])
+{
+
+ signed short MC_offset[MC32X0_AXES_NUM+1]; /*+1: for 4-byte alignment*/
+ int err;
+ memset(MC_offset, 0, sizeof(MC_offset));
+ if ((err = MC32X0_ReadOffset(client, MC_offset))) {
+ GSE_ERR("read offset fail, %d\n", err);
+ return err;
+ }
+
+ dat[MC32X0_AXIS_X] = MC_offset[MC32X0_AXIS_X];
+ dat[MC32X0_AXIS_Y] = MC_offset[MC32X0_AXIS_Y];
+ dat[MC32X0_AXIS_Z] = MC_offset[MC32X0_AXIS_Z];
+ //modify by zwx
+ //GSE_LOG("MC32X0_ReadCalibration %d %d %d \n",dat[mc32x0->cvt.map[MC32X0_AXIS_X]] ,dat[mc32x0->cvt.map[MC32X0_AXIS_Y]],dat[mc32x0->cvt.map[MC32X0_AXIS_Z]]);
+
+ return 0;
+}
+
+/*----------------------------------------------------------------------------*/
+
+ int MC32X0_ReadData(struct i2c_client *client, s16 buffer[MC32X0_AXES_NUM])
+{
+ unsigned char buf[6];
+ signed char buf1[6];
+ char rbm_buf[6];
+ int ret;
+ //int err = 0;
+
+ #ifdef SUPPORT_VIRTUAL_Z_SENSOR
+ int tempX=0;
+ int tempY=0;
+ int tempZ=0;
+ #endif
+
+ if ( enable_RBM_calibration == 0)
+ {
+ //err = hwmsen_read_block(client, addr, buf, 0x06);
+ }
+ else if (enable_RBM_calibration == 1)
+ {
+ memset(rbm_buf, 0, 6);
+ //rbm_buf[0] = mc32x0_REG_RBM_DATA;
+ //ret = mc32x0_rx_data(client, &rbm_buf[0], 6);
+ //ret = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, 0x0d, &rbm_buf[0],6);
+ i2c_smbus_read_i2c_block_data(client , 0x0d , 2 , &rbm_buf[0]);
+ i2c_smbus_read_i2c_block_data(client , 0x0d+2 , 2 , &rbm_buf[2]);
+ i2c_smbus_read_i2c_block_data(client , 0x0d+4 , 2 , &rbm_buf[4]);
+ }
+
+ if ( enable_RBM_calibration == 0)
+ {
+
+ if(McubeID &MC32X0_HIGH_END)
+ {
+ #ifdef MC32X0_HIGH_END
+ ret = i2c_smbus_read_i2c_block_data(client , MC32X0_XOUT_EX_L_REG , 6 , buf);
+ //ret = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_XOUT_EX_L_REG, &buf[0],6);
+
+ buffer[0] = (signed short)((buf[0])|(buf[1]<<8));
+ buffer[1] = (signed short)((buf[2])|(buf[3]<<8));
+ buffer[2] = (signed short)((buf[4])|(buf[5]<<8));
+ #endif
+ }
+ else if(McubeID &MC32X0_LOW_END)
+ {
+ #ifdef MC32X0_LOW_END
+ ret = i2c_smbus_read_i2c_block_data(client , MC32X0_XOUT_REG , 3 , buf1);
+ //ret = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_XOUT_REG, &buf[0],3);
+
+ buffer[0] = (signed short)buf1[0];
+ buffer[1] = (signed short)buf1[1];
+ buffer[2] = (signed short)buf1[2];
+ #endif
+ }
+ #ifdef SUPPORT_VIRTUAL_Z_SENSOR //add 2013-10-23
+ if (g_virtual_z)
+ {
+ //printk("%s 1\n", __FUNCTION__);
+
+ tempX = buffer[MC32X0_AXIS_X];
+ tempY = buffer[MC32X0_AXIS_Y];
+ tempZ = buffer[MC32X0_AXIS_Z];
+ //printk(" %d:Verify_Z_Railed() %d\n", (int)buffer[MC32X0_AXIS_Z], Verify_Z_Railed((int)buffer[MC32X0_AXIS_Z], LOW_RESOLUTION));
+ if(1 == Verify_Z_Railed((int)buffer[MC32X0_AXIS_Z], LOW_RESOLUTION)) // z-railed
+ {
+ Railed = 1;
+
+ GSE_LOG("%s: Z railed", __func__);
+ //printk("%s: Z railed \n", __func__);
+ if (G_2_REVERSE_VIRTUAL_Z == 1)
+ buffer[MC32X0_AXIS_Z] = (s8) ( gsensor_gain.z - (abs(tempX) + abs(tempY)));
+ else
+ buffer[MC32X0_AXIS_Z] = (s8) -( gsensor_gain.z - (abs(tempX) + abs(tempY)));
+ }
+ else
+ {
+ Railed = 0;
+ }
+ }
+ #endif
+ mcprintkreg("MC32X0_ReadData : %d %d %d \n",buffer[0],buffer[1],buffer[2]);
+ }
+ else if (enable_RBM_calibration == 1)
+ {
+ buffer[MC32X0_AXIS_X] = (s16)((rbm_buf[0]) | (rbm_buf[1] << 8));
+ buffer[MC32X0_AXIS_Y] = (s16)((rbm_buf[2]) | (rbm_buf[3] << 8));
+ buffer[MC32X0_AXIS_Z] = (s16)((rbm_buf[4]) | (rbm_buf[5] << 8));
+
+ GSE_LOG("%s RBM<<<<<[%08d %08d %08d]\n", __func__,buffer[MC32X0_AXIS_X], buffer[MC32X0_AXIS_Y], buffer[MC32X0_AXIS_Z]);
+ if(gain_data[0] == 0)
+ {
+ buffer[MC32X0_AXIS_X] = 0;
+ buffer[MC32X0_AXIS_Y] = 0;
+ buffer[MC32X0_AXIS_Z] = 0;
+ return 0;
+ }
+ buffer[MC32X0_AXIS_X] = (buffer[MC32X0_AXIS_X] + offset_data[0]/2)*gsensor_gain.x/gain_data[0];
+ buffer[MC32X0_AXIS_Y] = (buffer[MC32X0_AXIS_Y] + offset_data[1]/2)*gsensor_gain.y/gain_data[1];
+ buffer[MC32X0_AXIS_Z] = (buffer[MC32X0_AXIS_Z] + offset_data[2]/2)*gsensor_gain.z/gain_data[2];
+
+ #ifdef SUPPORT_VIRTUAL_Z_SENSOR // add 2013-10-23
+ if (g_virtual_z)
+ {
+ tempX = buffer[MC32X0_AXIS_X];
+ tempY = buffer[MC32X0_AXIS_Y];
+ tempZ = buffer[MC32X0_AXIS_Z];
+ //printk("%s 2\n", __FUNCTION__);
+ GSE_LOG("Original RBM<<<<<[%08d %08d %08d]\n", buffer[MC32X0_AXIS_X], buffer[MC32X0_AXIS_Y], buffer[MC32X0_AXIS_Z]);
+ printk("Verify_Z_Railed() %d\n", Verify_Z_Railed((int)buffer[MC32X0_AXIS_Z], RBM_RESOLUTION));
+ if(1 == Verify_Z_Railed(buffer[MC32X0_AXIS_Z], RBM_RESOLUTION)) // z-railed
+ {
+ GSE_LOG("%s: Z Railed in RBM mode",__FUNCTION__);
+ //printk("%s: Z Railed in RBM mode\n",__FUNCTION__);
+ if (G_2_REVERSE_VIRTUAL_Z == 1)
+ buffer[MC32X0_AXIS_Z] = (s16) ( gsensor_gain.z - (abs(tempX) + abs(tempY)));
+ else
+ buffer[MC32X0_AXIS_Z] = (s16) -( gsensor_gain.z - (abs(tempX) + abs(tempY)));
+ }
+ GSE_LOG("RBM<<<<<[%08d %08d %08d]\n", buffer[MC32X0_AXIS_X], buffer[MC32X0_AXIS_Y], buffer[MC32X0_AXIS_Z]);
+ }
+ #endif
+
+ GSE_LOG("%s offset_data <<<<<[%d %d %d]\n", __func__,offset_data[0], offset_data[1], offset_data[2]);
+
+ GSE_LOG("%s gsensor_gain <<<<<[%d %d %d]\n", __func__,gsensor_gain.x, gsensor_gain.y, gsensor_gain.z);
+
+ GSE_LOG("%s gain_data <<<<<[%d %d %d]\n", __func__,gain_data[0], gain_data[1], gain_data[2]);
+
+ GSE_LOG("%s RBM->RAW <<<<<[%d %d %d]\n", __func__,buffer[MC32X0_AXIS_X], buffer[MC32X0_AXIS_Y], buffer[MC32X0_AXIS_Z]);
+ }
+
+ return 0;
+}
+
+int MC32X0_ReadRawData(struct i2c_client *client, char * buf)
+{
+
+
+ int res = 0;
+ s16 raw_buf[3];
+
+ if (!buf)
+ {
+ return EINVAL;
+ }
+
+ //mc32x0_power_up(mc32x0);
+ mc32x0_set_mode(client, MC32X0_WAKE);
+ if((res = MC32X0_ReadData(client,&raw_buf[0])))
+ {
+ printk("%s %d\n",__FUNCTION__, __LINE__);
+ GSE_ERR("I2C error: ret value=%d", res);
+ return EIO;
+ }
+ else
+ {
+ //const struct mc3xx0_hwmsen_convert *pCvt = &mc3xx0_cvt[mc3xx0_current_placement];
+ GSE_LOG("UPDATE dat: (%+3d %+3d %+3d)\n",
+ raw_buf[MC32X0_AXIS_X], raw_buf[MC32X0_AXIS_Y], raw_buf[MC32X0_AXIS_Z]);
+
+ //G_RAW_DATA[MC32X0_AXIS_X] = raw_buf[0];
+ //G_RAW_DATA[MC32X0_AXIS_Y] = raw_buf[1];
+ //G_RAW_DATA[MC32X0_AXIS_Z] = raw_buf[2];
+ //G_RAW_DATA[MC32X0_AXIS_Z] = G_RAW_DATA[MC32X0_AXIS_Z] + gsensor_gain.z;
+/*
+ raw_buf[MC3XX0_AXIS_X] = ((raw_buf[MC3XX0_AXIS_X] * GRAVITY_1G_VALUE) / gsensor_gain.x);
+ raw_buf[MC3XX0_AXIS_Y] = ((raw_buf[MC3XX0_AXIS_Y] * GRAVITY_1G_VALUE) / gsensor_gain.y);
+ raw_buf[MC3XX0_AXIS_Z] = ((raw_buf[MC3XX0_AXIS_Z] * GRAVITY_1G_VALUE) / gsensor_gain.z);
+*/
+ if (is_new_mc34x0)
+ {
+ raw_buf[MC3XX0_AXIS_X] = -raw_buf[MC3XX0_AXIS_X];
+ raw_buf[MC3XX0_AXIS_Y] = -raw_buf[MC3XX0_AXIS_Y];
+ }
+ else if (is_mc3250)
+ {
+ s16 temp = 0;
+
+ temp = raw_buf[MC3XX0_AXIS_X];
+
+ raw_buf[MC3XX0_AXIS_X] = raw_buf[MC3XX0_AXIS_Y];
+ raw_buf[MC3XX0_AXIS_Y] = -temp;
+ }
+
+ G_RAW_DATA[MC3XX0_AXIS_X] = pCvt->sign[MC3XX0_AXIS_X] * raw_buf[pCvt->map[MC3XX0_AXIS_X]];
+ G_RAW_DATA[MC3XX0_AXIS_Y] = pCvt->sign[MC3XX0_AXIS_Y] * raw_buf[pCvt->map[MC3XX0_AXIS_Y]];
+ G_RAW_DATA[MC3XX0_AXIS_Z] = pCvt->sign[MC3XX0_AXIS_Z] * raw_buf[pCvt->map[MC3XX0_AXIS_Z]];
+
+ G_RAW_DATA[MC32X0_AXIS_Z] += gsensor_gain.z*(pCvt->sign[MC3XX0_AXIS_Z])*(1);//-=GRAVITY_1G_VALUE;
+
+ //printk("%s %d\n",__FUNCTION__, __LINE__);
+ sprintf(buf, "%04x %04x %04x", G_RAW_DATA[MC32X0_AXIS_X],
+ G_RAW_DATA[MC32X0_AXIS_Y], G_RAW_DATA[MC32X0_AXIS_Z]);
+ GSE_LOG("G_RAW_DATA: (%+3d %+3d %+3d)\n",
+ G_RAW_DATA[MC32X0_AXIS_X], G_RAW_DATA[MC32X0_AXIS_Y], G_RAW_DATA[MC32X0_AXIS_Z]);
+ }
+ return 0;
+}
+
+int mc32x0_reset (struct i2c_client *client)
+{
+
+ s16 tmp, x_gain, y_gain, z_gain ;
+ s32 x_off, y_off, z_off;
+ u8 buf[3];
+ int err;
+ //mc32x0_write_reg(client,0x1b,0x6d);
+ buf[0]=0x6d;
+ //p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x1b, &buf[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x1b,buf[0]);
+
+ //mc32x0_write_reg(client,0x1b,0x43);
+ buf[0]=0x43;
+ //p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x1b, &buf[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x1b,buf[0]);
+ msleep(5);
+
+ //mc32x0_write_reg(client,0x07,0x43);
+ buf[0]=0x43;
+ //p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x07, &buf[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x07,buf[0]);
+ //mc32x0_write_reg(client,0x1C,0x80);
+ buf[0]=0x80;
+ //p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x1C, &buf[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x1c,buf[0]);
+ //mc32x0_write_reg(client,0x17,0x80);
+ buf[0]=0x80;
+ //p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x17, &buf[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x17,buf[0]);
+ msleep(5);
+ //mc32x0_write_reg(client,0x1C,0x00);
+ buf[0]=0x00;
+ //p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x1C, &buf[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x1c,buf[0]);
+ //mc32x0_write_reg(client,0x17,0x00);
+ buf[0]=0x00;
+ //p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x17, &buf[0], 1 );
+ i2c_smbus_write_byte_data(client, 0x17,buf[0]);
+ msleep(5);
+
+
+/*
+ if ((err = mc32x0_read_block(new_client, 0x21, offset_buf, 6))) //add by Liang for storeage OTP offsef register value
+ {
+ GSE_ERR("error: %d\n", err);
+ return err;
+ }
+*/
+ memset(offset_buf, 0, 9);
+ //offset_buf[0] = 0x21;
+ //err = mc32x0_rx_data(client, offset_buf, 9);
+ //err = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, 0x21, &offset_buf[0],9);
+ err = i2c_smbus_read_i2c_block_data(client , 0x21 , 9 , offset_buf);
+
+
+ tmp = ((offset_buf[1] & 0x3f) << 8) + offset_buf[0];
+ if (tmp & 0x2000)
+ tmp |= 0xc000;
+ x_off = tmp;
+
+ tmp = ((offset_buf[3] & 0x3f) << 8) + offset_buf[2];
+ if (tmp & 0x2000)
+ tmp |= 0xc000;
+ y_off = tmp;
+
+ tmp = ((offset_buf[5] & 0x3f) << 8) + offset_buf[4];
+ if (tmp & 0x2000)
+ tmp |= 0xc000;
+ z_off = tmp;
+
+ // get x,y,z gain
+ x_gain = ((offset_buf[1] >> 7) << 8) + offset_buf[6];
+ y_gain = ((offset_buf[3] >> 7) << 8) + offset_buf[7];
+ z_gain = ((offset_buf[5] >> 7) << 8) + offset_buf[8];
+
+
+ //storege the cerrunt offset data with DOT format
+ offset_data[0] = x_off;
+ offset_data[1] = y_off;
+ offset_data[2] = z_off;
+
+ //storege the cerrunt Gain data with GOT format
+ gain_data[0] = 256*8*128/3/(40+x_gain);
+ gain_data[1] = 256*8*128/3/(40+y_gain);
+ gain_data[2] = 256*8*128/3/(40+z_gain);
+ printk("offser gain = %d %d %d %d %d %d======================\n\n ",
+ gain_data[0],gain_data[1],gain_data[2],offset_data[0],offset_data[1],offset_data[2]);
+
+ return 0;
+}
+#endif
+
+int mc32x0_read_accel_xyz(struct i2c_client *client, s16 * acc)
+{
+ int comres;
+ s16 raw_data[MC3XX0_AXIS_NUM] = { 0 };
+ //const struct mc3xx0_hwmsen_convert *pCvt = &mc3xx0_cvt[mc3xx0_current_placement];
+#ifdef DOT_CALI
+ s16 raw_buf[6];
+
+
+ comres = MC32X0_ReadData(client,&raw_buf[0]);
+
+ acc[0] = raw_buf[0];
+ acc[1] = raw_buf[1];
+ acc[2] = raw_buf[2];
+#else
+ unsigned char raw_buf[6];
+ signed char raw_buf1[3];
+ if(McubeID &MC32X0_HIGH_END)
+ {
+ #ifdef MC32X0_HIGH_END
+ comres = i2c_smbus_read_i2c_block_data(client , MC32X0_XOUT_EX_L_REG , 6 , raw_buf);
+ //comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_XOUT_EX_L_REG, &data[0],6);
+
+ acc[0] = (signed short)((raw_buf[0])|(raw_buf[1]<<8));
+ acc[1] = (signed short)((raw_buf[2])|(raw_buf[3]<<8));
+ acc[2] = (signed short)((raw_buf[4])|(raw_buf[5]<<8));
+ #endif
+ }
+ else if(McubeID &MC32X0_LOW_END)
+ {
+ #ifdef MC32X0_LOW_END
+ comres = i2c_smbus_read_i2c_block_data(client , MC32X0_XOUT_REG , 3 , raw_buf1);
+ //comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_XOUT_REG, &data[0],3);
+
+ acc[0] = (signed short)raw_buf1[0];
+ acc[1] = (signed short)raw_buf1[1];
+ acc[2] = (signed short)raw_buf1[2];
+ #endif
+ }
+#endif
+
+ raw_data[MC3XX0_AXIS_X] = acc[MC3XX0_AXIS_X];
+ raw_data[MC3XX0_AXIS_Y] = acc[MC3XX0_AXIS_Y];
+ raw_data[MC3XX0_AXIS_Z] = acc[MC3XX0_AXIS_Z];
+/*
+ raw_data[MC3XX0_AXIS_X] = ((raw_data[MC3XX0_AXIS_X] * GRAVITY_1G_VALUE) / gsensor_gain.x);
+ raw_data[MC3XX0_AXIS_Y] = ((raw_data[MC3XX0_AXIS_Y] * GRAVITY_1G_VALUE) / gsensor_gain.y);
+ raw_data[MC3XX0_AXIS_Z] = ((raw_data[MC3XX0_AXIS_Z] * GRAVITY_1G_VALUE) / gsensor_gain.z);
+*/
+ if (is_new_mc34x0)
+ {
+ raw_data[MC3XX0_AXIS_X] = -raw_data[MC3XX0_AXIS_X];
+ raw_data[MC3XX0_AXIS_Y] = -raw_data[MC3XX0_AXIS_Y];
+ }
+ else if (is_mc3250)
+ {
+ s16 temp = 0;
+
+ temp = raw_data[MC3XX0_AXIS_X];
+
+ raw_data[MC3XX0_AXIS_X] = raw_data[MC3XX0_AXIS_Y];
+ raw_data[MC3XX0_AXIS_Y] = -temp;
+ }
+
+ acc[MC3XX0_AXIS_X] = pCvt->sign[MC3XX0_AXIS_X] * raw_data[pCvt->map[MC3XX0_AXIS_X]];
+ acc[MC3XX0_AXIS_Y] = pCvt->sign[MC3XX0_AXIS_Y] * raw_data[pCvt->map[MC3XX0_AXIS_Y]];
+ acc[MC3XX0_AXIS_Z] = pCvt->sign[MC3XX0_AXIS_Z] * raw_data[pCvt->map[MC3XX0_AXIS_Z]];
+
+ return comres;
+
+}
+
+static int mc32x0_measure(struct i2c_client *client, struct acceleration *accel)
+{
+
+ s16 raw[3];
+
+#ifdef DOT_CALI
+ //int ret;
+#endif
+
+
+#ifdef DOT_CALI
+ if( load_cali_flg > 0)
+ {
+ /*ret =mcube_read_cali_file(client);
+ if(ret == 0)
+ load_cali_flg = ret;
+ else
+ load_cali_flg --;
+ GSE_LOG("load_cali %d\n",ret); */
+ MC32X0_WriteCalibration(client,l_sensorconfig.offset);
+ load_cali_flg = 0;
+ }
+#endif
+ /* read acceleration data */
+ mc32x0_read_accel_xyz(client,&raw[0]);
+
+ accel->x = raw[0] ;
+ accel->y = raw[1] ;
+ accel->z = raw[2] ;
+ return 0;
+}
+
+static void mc32x0_work_func(struct work_struct *work)
+{
+ struct mc32x0_data *data = container_of(work, struct mc32x0_data, work);
+ struct acceleration accel = {0};
+
+ mc32x0_measure(data->client, &accel);
+
+ //printk(KERN_ERR"mc32x0_measure: acc.x=%d, acc.y=%d, acc.z=%d\n", data->inv[0]*accel.x,data->inv[1]*accel.y, data->inv[2]*accel.z);
+
+ //input_report_abs(data->input_dev, data->map[0], data->inv[0]*accel.x);
+ //input_report_abs(data->input_dev, data->map[1], data->inv[1]*accel.y);
+ //input_report_abs(data->input_dev, data->map[2], data->inv[2]*accel.z);
+
+ //accel.x = (accel.x&0x00FF) | ((accel.y&0xFF)<<8) | ((accel.z&0xFF)<<16);
+
+ input_report_abs(data->input_dev, ABS_X, accel.x);
+ input_report_abs(data->input_dev, ABS_Y, accel.y);
+ input_report_abs(data->input_dev, ABS_Z, accel.z);
+ input_sync(data->input_dev);
+
+ queue_delayed_work(data->mc32x0_wq, &data->work, msecs_to_jiffies(sample_rate_2_memsec(data->sensor_samp)));
+}
+/*
+static enum hrtimer_restart mc32x0_timer_func(struct hrtimer *timer)
+{
+ struct mc32x0_data *data = container_of(timer, struct mc32x0_data, timer);
+
+ queue_work(data->mc32x0_wq, &data->work);
+ hrtimer_start(&data->timer, ktime_set(0, sensor_duration*1000000), HRTIMER_MODE_REL);
+
+ return HRTIMER_NORESTART;
+}
+*/
+static int mc32x0_enable(struct mc32x0_data *data, int enable)
+{
+ if(enable){
+ msleep(10);
+ mc32x0_chip_init(data->client);
+ queue_delayed_work(data->mc32x0_wq, &data->work, msecs_to_jiffies(sample_rate_2_memsec(data->sensor_samp)));//hrtimer_start(&data->timer, ktime_set(0, asensor_duration*1000000), HRTIMER_MODE_REL);
+ data->enabled = true;
+ }else{
+ cancel_delayed_work_sync(&l_sensorconfig.work);//hrtimer_cancel(&data->timer);
+ data->enabled = false;
+ }
+ return 0;
+}
+/*
+//MCUBE_BACKUP_FILE
+static void mcube_copy_file(const char *dstFilePath)
+{
+
+ int err =0;
+ initKernelEnv();
+
+ fd_file = openFile(dstFilePath,O_RDWR,0);
+ if (fd_file == NULL)
+ {
+ GSE_LOG("open %s fail\n",dstFilePath);
+ return;
+ }
+
+ if ((err = writeFile(fd_file,backup_buf,64))>0)
+ GSE_LOG("buf:%s\n",backup_buf);
+ else
+ GSE_LOG("write file error %d\n",err);
+
+ set_fs(oldfs); ;
+ closeFile(fd_file);
+
+}
+//MCUBE_BACKUP_FILE
+*/
+
+extern int wmt_setsyspara(char *varname, char *varval);
+static void update_var(void)
+{
+ char varbuf[64];
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+
+ sprintf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ (pCvt->map[MC3XX0_AXIS_X]),
+ (pCvt->sign[MC3XX0_AXIS_X]),
+ (pCvt->map[MC3XX0_AXIS_Y]),
+ (pCvt->sign[MC3XX0_AXIS_Y]),
+ (pCvt->map[MC3XX0_AXIS_Z]),
+ (pCvt->sign[MC3XX0_AXIS_Z]),
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+
+ wmt_setsyspara("wmt.io.mc3230sensor",varbuf);
+}
+
+static long mc32x0_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ //int intBuf[SENSOR_DATA_SIZE];
+ int ret = 0;
+ //float convert_para=0.0f;
+ short enable = 0;
+ short delay = 0;
+ //short val=1000/l_sensorconfig.sensor_samp;
+ unsigned int uval ;
+#ifdef DOT_CALI
+ void __user *data1;
+ char strbuf[256];
+ //int cali[3];
+ SENSOR_DATA sensor_data;
+ struct i2c_client *client = container_of(mc32x0_device.parent, struct i2c_client, dev);
+ //struct mc32x0_data* this = (struct mc32x0_data *)i2c_get_clientdata(client); /* ?õô????????????. */
+#endif
+
+ switch (cmd) {
+ case ECS_IOCTL_APP_SET_AFLAG:
+ // enable/disable sensor
+
+ if (copy_from_user(&enable, (short*)arg, sizeof(short)))
+ {
+ errlog("Can't get enable flag!!!\n");
+ ret = -EFAULT;
+ goto errioctl;
+ }
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor. l_sensorconfig.sensor_samp=%d\n", enable, l_sensorconfig.sensor_samp);
+
+ if (enable != l_sensorconfig.sensor_enable)
+ {
+
+ l_sensorconfig.sensor_enable = enable;
+
+ }
+ } else {
+ errlog("Wrong enable argument!!!\n");
+ ret = -EFAULT;
+ goto errioctl;
+ }
+ break;
+ case ECS_IOCTL_APP_SET_DELAY://IOCTL_SENSOR_SET_DELAY_ACCEL:
+ /*if(copy_from_user((void *)&sensor_duration, (void __user *) arg, sizeof(short))!=0){
+ printk("copy from error in %s.\n",__func__);
+ }*/
+
+ // set the rate of g-sensor
+ if (copy_from_user(&delay,(short*)arg, sizeof(short)))
+ {
+ errlog("Can't get set delay!!!\n");
+ ret = -EFAULT;
+ goto errioctl;
+ }
+ dbg("Get delay=%d \n", delay);
+
+ if ((delay >=0) && (delay < 20))
+ {
+ delay = 20;
+ } else if (delay > 200)
+ {
+ delay = 200;
+ }
+ if (delay > 0)
+ {
+ l_sensorconfig.sensor_samp = 1000/delay;
+ } else {
+ errlog("error delay argument(delay=%d)!!!\n",delay);
+ ret = -EFAULT;
+ goto errioctl;
+ }
+
+ break;
+/*
+ case IOCTL_SENSOR_GET_DELAY_ACCEL:
+
+ if(copy_to_user((void __user *) arg, (const void *)&val, sizeof(short))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+
+ break;*/
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ uval = MC3230_DRVID;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("mc32x0_driver_id:%d\n",uval);
+ break;
+ case WMT_IOCTL_SENOR_GET_RESOLUTION:
+ if(McubeID &MCUBE_1_5G_8BIT)
+ uval = (8<<8) | 3; //mc3230:8 bit ,+/-1.5g
+ if (copy_to_user((unsigned int *)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ printk("<<<<<<<resolution:0x%x\n",uval);
+ break;
+ /*case IOCTL_SENSOR_GET_STATE_ACCEL:
+ if(copy_to_user((void __user *) arg, (const void *)&sensor_state_flag, sizeof(short))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+
+ break;
+
+ case IOCTL_SENSOR_SET_STATE_ACCEL:
+ if(copy_from_user((void *)&sensor_state_flag, (void __user *) arg, sizeof(short))!=0){
+ printk("copy from error in %s.\n",__func__);
+ }
+
+ break;
+ case IOCTL_SENSOR_GET_NAME:
+ if(copy_to_user((void __user *) arg,(const void *)mc32x0_DISPLAY_NAME, sizeof(mc32x0_DISPLAY_NAME))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+ break;
+
+ case IOCTL_SENSOR_GET_VENDOR:
+ if(copy_to_user((void __user *) arg,(const void *)mc32x0_DIPLAY_VENDOR, sizeof(mc32x0_DIPLAY_VENDOR))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+ break;
+
+ case IOCTL_SENSOR_GET_CONVERT_PARA:
+ convert_para = mc32x0_CONVERT_PARAMETER;
+ if(copy_to_user((void __user *) arg,(const void *)&convert_para,sizeof(float))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+ break;
+ */
+
+ #ifdef DOT_CALI
+ case GSENSOR_IOCTL_READ_SENSORDATA:
+ case GSENSOR_IOCTL_READ_RAW_DATA:
+ GSE_LOG("fwq GSENSOR_IOCTL_READ_RAW_DATA\n");
+ MC32X0_ReadRawData(client,strbuf);
+ if (copy_to_user((void __user *) arg, &strbuf, strlen(strbuf)+1)) {
+ printk("failed to copy sense data to user space.");
+ return -EFAULT;
+ }
+
+
+ break;
+
+
+ case GSENSOR_MCUBE_IOCTL_SET_CALI:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_SET_CALI!!\n");
+ data1 = (void __user *)arg;
+
+
+ //data = (unsigned char*)arg;
+
+
+ if(data1 == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
+ if(copy_from_user(&sensor_data, data1, sizeof(sensor_data)))
+ {
+ ret = -EFAULT;
+ break;
+ }
+ //if(atomic_read(&this->suspend))
+ //{
+ // GSE_ERR("Perform calibration in suspend state!!\n");
+ // err = -EINVAL;
+ //}
+ else
+ {
+ //this->cali_sw[MC32X0_AXIS_X] += sensor_data.x;
+ //this->cali_sw[MC32X0_AXIS_Y] += sensor_data.y;
+ //this->cali_sw[MC32X0_AXIS_Z] += sensor_data.z;
+
+ l_sensorconfig.offset[MC32X0_AXIS_X] = sensor_data.x;
+ l_sensorconfig.offset[MC32X0_AXIS_Y] = sensor_data.y;
+ l_sensorconfig.offset[MC32X0_AXIS_Z] = sensor_data.z;
+
+ GSE_LOG("GSENSOR_MCUBE_IOCTL_SET_CALI %d %d %d %d %d %d!!\n", l_sensorconfig.offset[MC32X0_AXIS_X], l_sensorconfig.offset[MC32X0_AXIS_Y],l_sensorconfig.offset[MC32X0_AXIS_Z] ,sensor_data.x, sensor_data.y ,sensor_data.z);
+
+ update_var();
+ ret = MC32X0_WriteCalibration(client, l_sensorconfig.offset);
+ }
+
+ break;
+
+ case GSENSOR_IOCTL_CLR_CALI:
+ GSE_LOG("fwq GSENSOR_IOCTL_CLR_CALI!!\n");
+ l_sensorconfig.offset[0] = 0;
+ l_sensorconfig.offset[1] = 0;
+ l_sensorconfig.offset[2] = 0;
+
+ update_var();
+ ret = MC32X0_ResetCalibration(client);
+ break;
+
+ case GSENSOR_IOCTL_GET_CALI:
+ GSE_LOG("fwq mc32x0 GSENSOR_IOCTL_GET_CALI\n");
+
+ data1 = (unsigned char*)arg;
+
+ if(data1 == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ if((ret = MC32X0_ReadCalibration(client,l_sensorconfig.offset)))
+ {
+ GSE_LOG("fwq mc32x0 MC32X0_ReadCalibration error!!!!\n");
+ break;
+ }
+
+ sensor_data.x = l_sensorconfig.offset[0];//this->cali_sw[MC32X0_AXIS_X];
+ sensor_data.y = l_sensorconfig.offset[1];//this->cali_sw[MC32X0_AXIS_Y];
+ sensor_data.z = l_sensorconfig.offset[2];//this->cali_sw[MC32X0_AXIS_Z];
+ // if(copy_to_user(data, &sensor_data, sizeof(sensor_data)))
+
+ if(copy_to_user(data1, &sensor_data, sizeof(sensor_data)))
+ {
+ ret = -EFAULT;
+ break;
+ }
+ break;
+ // add by liang ****
+ //add in Sensors_io.h
+ //#define GSENSOR_IOCTL_SET_CALI_MODE _IOW(GSENSOR, 0x0e, int)
+ case GSENSOR_IOCTL_SET_CALI_MODE:
+ GSE_LOG("fwq mc32x0 GSENSOR_IOCTL_SET_CALI_MODE\n");
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_READ_RBM_DATA:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_READ_RBM_DATA\n");
+ data1 = (void __user *) arg;
+ if(data1 == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
+ MC32X0_ReadRBMData(client,(char *)&strbuf);
+ if(copy_to_user(data1, &strbuf, strlen(strbuf)+1))
+ {
+ ret = -EFAULT;
+ break;
+ }
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_SET_RBM_MODE:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_SET_RBM_MODE\n");
+ //MCUBE_BACKUP_FILE
+ /*if(READ_FROM_BACKUP==true)
+ {
+
+ mcube_copy_file(CALIB_PATH);
+
+ READ_FROM_BACKUP = false;
+ }*/
+ //MCUBE_BACKUP_FILE
+ MC32X0_rbm(client, 1);
+
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_CLEAR_RBM_MODE:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_CLEAR_RBM_MODE\n");
+
+ MC32X0_rbm(client, 0);
+
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_REGISTER_MAP:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_REGISTER_MAP\n");
+
+ //MC32X0_Read_Reg_Map(client);
+
+ break;
+#endif
+
+
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+errioctl:
+
+ return ret;
+}
+
+
+static int mc32x0_open(struct inode *inode, struct file *filp)
+{
+ /*int ret;
+ ret = nonseekable_open(inode, filp);*/
+ return 0;
+}
+
+static int mc32x0_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static struct file_operations sensor_fops =
+{
+ .owner = THIS_MODULE,
+ .open = mc32x0_open,
+ .release = mc32x0_release,
+ .unlocked_ioctl = mc32x0_ioctl,
+};
+
+//#ifdef CONFIG_HAS_EARLYSUSPEND
+static int mc32x0_i2c_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ /*struct mc32x0_data *data;
+ char mc32x0_address;
+ char mc32x0_data;
+
+ //printk("mc32x0_early_suspend 2 \n");
+
+ data = container_of(handler, struct mc32x0_data, early_suspend);
+
+ hrtimer_cancel(&data->timer);
+ */
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ mc32x0_set_mode(l_sensorconfig.client,MC32X0_STANDBY);
+ return 0;
+}
+
+static int mc32x0_i2c_resume(struct platform_device *pdev)
+{
+ struct mc32x0_data *data = &l_sensorconfig;
+ //char mc32x0_address;
+ //char mc32x0_data;
+
+ //printk("mc32x0_early_resume 2\n");
+
+ //data = container_of(handler, struct mc32x0_data, early_suspend);
+
+ //Add 20130722
+ mc32x0_chip_init(data->client);
+ MC32X0_ResetCalibration(data->client);
+ MC32X0_WriteCalibration(data->client,l_sensorconfig.offset);//mcube_read_cali_file(data->client);
+ //before
+
+ mc32x0_set_mode(data->client,MC32X0_WAKE);
+
+ queue_delayed_work(data->mc32x0_wq, &data->work, msecs_to_jiffies(sample_rate_2_memsec(data->sensor_samp)));
+ //hrtimer_start(&data->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ return 0;
+}
+//#endif
+
+static struct miscdevice mc32x0_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "sensor_ctrl",
+ .fops = &sensor_fops,
+};
+
+static int sensor_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+
+ //int inputval = -1;
+ int enable, sample = -1;
+ char tembuf[8];
+ //unsigned int amsr = 0;
+ int test = 0;
+
+ mutex_lock(&l_sensorconfig.lock);
+ memset(tembuf, 0, sizeof(tembuf));
+ // get sensor level and set sensor level
+ if (sscanf(buffer, "isdbg=%d\n", &l_sensorconfig.isdbg))
+ {
+ // only set the dbg flag
+ } else if (sscanf(buffer, "samp=%d\n", &sample))
+ {
+ if (sample > 0)
+ {
+ if (sample != l_sensorconfig.sensor_samp)
+ {
+ // should do sth
+ }
+ //printk(KERN_ALERT "sensor samp=%d(amsr:%d) has been set.\n", sample, amsr);
+ } else {
+ klog("Wrong sample argumnet of sensor.\n");
+ }
+ } else if (sscanf(buffer, "enable=%d\n", &enable))
+ {
+ if ((enable < 0) || (enable > 1))
+ {
+ dbg("The argument to enable/disable g-sensor should be 0 or 1 !!!\n");
+ } else if (enable != l_sensorconfig.sensor_enable)
+ {
+ //mma_enable_disable(enable);
+ l_sensorconfig.sensor_enable = enable;
+ }
+ } else if (sscanf(buffer, "sensor_test=%d\n", &test))
+ { // for test begin
+ l_sensorconfig.test_pass = 0;
+ } else if (sscanf(buffer, "sensor_testend=%d\n", &test))
+ { // Don nothing only to be compatible the before testing program
+ }
+ mutex_unlock(&l_sensorconfig.lock);
+ return count;
+}
+
+static int sensor_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "test_pass=%d\nisdbg=%d\nrate=%d\nenable=%d\n",
+ l_sensorconfig.test_pass,
+ l_sensorconfig.isdbg,
+ l_sensorconfig.sensor_samp,
+ l_sensorconfig.sensor_enable
+ );
+ return len;
+}
+
+static int mc32x0_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct mc32x0_data *data = &l_sensorconfig;
+ struct i2c_client *client = data->client;
+
+#ifdef DOT_CALI
+ load_cali_flg = 30;
+#endif
+ data->sensor_proc = create_proc_entry(GSENSOR_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (data->sensor_proc != NULL)
+ {
+ data->sensor_proc->write_proc = sensor_writeproc;
+ data->sensor_proc->read_proc = sensor_readproc;
+ }
+
+ data->mc32x0_wq = create_singlethread_workqueue("mc32x0_wq");
+ if (!data->mc32x0_wq )
+ {
+ ret = -ENOMEM;
+ goto err_create_workqueue_failed;
+ }
+
+ INIT_DELAYED_WORK(&data->work, mc32x0_work_func);
+ //INIT_WORK(&data->work, mc32x0_work_func);
+ mutex_init(&data->lock);
+
+
+ data->input_dev = input_allocate_device();
+ if (!data->input_dev) {
+ ret = -ENOMEM;
+ goto exit_input_dev_alloc_failed;
+ }
+
+
+ dev.client=client;
+
+ i2c_set_clientdata(client, data);
+ #ifdef DOT_CALI
+ mc32x0_reset(client);
+ #endif
+
+ set_bit(EV_ABS, data->input_dev->evbit);
+ data->map[0] = G_0;
+ data->map[1] = G_1;
+ data->map[2] = G_2;
+ data->inv[0] = G_0_REVERSE;
+ data->inv[1] = G_1_REVERSE;
+ data->inv[2] = G_2_REVERSE;
+
+ input_set_abs_params(data->input_dev, ABS_X, -32*8, 32*8, INPUT_FUZZ, INPUT_FLAT);
+ input_set_abs_params(data->input_dev, ABS_Y, -32*8, 32*8, INPUT_FUZZ, INPUT_FLAT);
+ input_set_abs_params(data->input_dev, ABS_Z, -32*8, 32*8, INPUT_FUZZ, INPUT_FLAT);
+
+ data->input_dev->name = "g-sensor";
+
+
+ ret = input_register_device(data->input_dev);
+ if (ret) {
+ goto exit_input_register_device_failed;
+ }
+ mc32x0_device.parent = &client->dev;
+ ret = misc_register(&mc32x0_device);
+ if (ret) {
+ goto exit_misc_device_register_failed;
+ }
+
+ ret = sysfs_create_group(&client->dev.kobj, &mc32x0_group);
+/*
+ if (!data->use_irq){
+ hrtimer_init(&data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ data->timer.function = mc32x0_timer_func;
+ hrtimer_start(&data->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+*/
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ data->early_suspend.suspend = mc32x0_early_suspend;
+ data->early_suspend.resume = mc32x0_early_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+ data->enabled = true;
+ queue_delayed_work(data->mc32x0_wq, &data->work, msecs_to_jiffies(sample_rate_2_memsec(data->sensor_samp)));
+ strcpy(mc32x0_on_off_str,"gsensor_int2");
+ dprintk(DEBUG_INIT,"mc32x0 probe ok \n");
+
+ return 0;
+exit_misc_device_register_failed:
+exit_input_register_device_failed:
+ input_free_device(data->input_dev);
+exit_input_dev_alloc_failed:
+ destroy_workqueue(data->mc32x0_wq);
+err_create_workqueue_failed:
+ kfree(data);
+ printk("mc32x0 probe failed \n");
+ return ret;
+
+}
+
+static int mc32x0_remove(struct platform_device *pdev)
+{
+ /*struct mc32x0_data *data = i2c_get_clientdata(client);
+
+ hrtimer_cancel(&data->timer);
+ input_unregister_device(data->input_dev);
+ //gpio_release(mc32x0_pin_hd, 2);
+ misc_deregister(&mc32x0_device);
+ sysfs_remove_group(&client->dev.kobj, &mc32x0_group);
+ kfree(data);*/
+
+ if (NULL != l_sensorconfig.mc32x0_wq)
+ {
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ flush_workqueue(l_sensorconfig.mc32x0_wq);
+ destroy_workqueue(l_sensorconfig.mc32x0_wq);
+ l_sensorconfig.mc32x0_wq = NULL;
+ }
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ remove_proc_entry(GSENSOR_PROC_NAME, NULL);
+ l_sensorconfig.sensor_proc = NULL;
+ }
+ misc_deregister(&mc32x0_device);
+ input_unregister_device(l_sensorconfig.input_dev);
+ sysfs_remove_group(&l_sensorconfig.client->dev.kobj, &mc32x0_group);
+ return 0;
+}
+
+static void mc32x0_shutdown(struct platform_device *pdev)
+{
+ struct mc32x0_data *data = &l_sensorconfig;//i2c_get_clientdata(client);
+ if(data->enabled)
+ mc32x0_enable(data,0);
+}
+/*
+static const struct i2c_device_id mc32x0_id[] = {
+ { SENSOR_NAME, 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, mc32x0_id);
+
+static struct i2c_driver mc32x0_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_NAME,
+ },
+ .id_table = mc32x0_id,
+ .probe = mc32x0_probe,
+ .remove = mc32x0_remove,
+ .shutdown = mc32x0_shutdown,
+ .detect = gsensor_detect,
+ .address_list = normal_i2c,
+};
+*/
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static int get_axisset(void)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+ //int tmpoff[3] = {0};
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+
+ pCvt = (struct mc3xx0_hwmsen_convert *)kzalloc(sizeof(struct mc3xx0_hwmsen_convert), GFP_KERNEL);
+
+ if (wmt_getsyspara("wmt.io.mc3230.virtualz", varbuf, &varlen)) {
+ errlog("Can't get gsensor config in u-boot!!!!\n");
+ //return -1;
+ } else {
+ sscanf(varbuf, "%d", &g_virtual_z);
+
+ }
+ printk("%s g_virtual_z %d\n", __FUNCTION__, g_virtual_z);
+ memset(varbuf, 0, sizeof(varbuf));
+ if (wmt_getsyspara("wmt.io.mc3230sensor", varbuf, &varlen)) {
+ errlog("Can't get gsensor config in u-boot!!!!\n");
+ return -1; //open it for no env just,not insmod such module 2014-6-30
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &l_sensorconfig.op,
+ &l_sensorconfig.int_gpio,
+ &l_sensorconfig.samp,
+ &(pCvt->map[MC3XX0_AXIS_X]),
+ &(pCvt->sign[MC3XX0_AXIS_X]),
+ &(pCvt->map[MC3XX0_AXIS_Y]),
+ &(pCvt->sign[MC3XX0_AXIS_Y]),
+ &(pCvt->map[MC3XX0_AXIS_Z]),
+ &(pCvt->sign[MC3XX0_AXIS_Z]),
+ &(l_sensorconfig.offset[0]),
+ &(l_sensorconfig.offset[1]),
+ &(l_sensorconfig.offset[2])
+ );
+ if (n != 12) {
+ printk(KERN_ERR "gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+ l_sensorconfig.sensor_samp = l_sensorconfig.samp;
+
+
+ dbg("get the sensor config: %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ pCvt->map[MC3XX0_AXIS_X],
+ pCvt->sign[MC3XX0_AXIS_X],
+ pCvt->map[MC3XX0_AXIS_Y],
+ pCvt->sign[MC3XX0_AXIS_Y],
+ pCvt->map[MC3XX0_AXIS_Z],
+ pCvt->sign[MC3XX0_AXIS_Z],
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+ }
+ return 0;
+}
+
+static void mc32x0_platform_release(struct device *device)
+{
+ return;
+}
+
+static struct platform_device mc32x0_pdevice = {
+ .name = GSENSOR_NAME,
+ .id = 0,
+ .dev = {
+ .release = mc32x0_platform_release,
+ },
+};
+
+static struct platform_driver mc32x0_pdriver = {
+ .probe = mc32x0_probe,
+ .remove = mc32x0_remove,
+ .suspend = mc32x0_i2c_suspend,
+ .resume = mc32x0_i2c_resume,
+ .shutdown = mc32x0_shutdown,
+ .driver = {
+ .name = GSENSOR_NAME,
+ },
+};
+
+
+static int __init mc32x0_init(void)
+{
+ struct i2c_client *this_client;
+ int ret = 0;
+
+ dprintk(DEBUG_INIT, "======%s=========. \n", __func__);
+ // parse g-sensor u-boot arg
+ ret = get_axisset();
+ if (ret < 0)
+ {
+ printk("<<<<<%s user choose to no sensor chip!\n", __func__);
+ return ret;
+ }
+ if (!(this_client = sensor_i2c_register_device(0, MC32X0_I2C_ADDR, GSENSOR_NAME)))
+ {
+ printk(KERN_ERR"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+
+ if (mc32x0_chip_init(this_client))
+ {
+ printk(KERN_ERR"Failed to init MC32X0!\n");
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+ }
+
+ //printk(KERN_ERR"McubeID:%d\n",McubeID);
+ l_sensorconfig.client = this_client;
+
+ l_dev_class = class_create(THIS_MODULE, GSENSOR_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create gsensor device !!\n");
+ return ret;
+ }
+ if((ret = platform_device_register(&mc32x0_pdevice)))
+ {
+ klog("Can't register mc3230 platform devcie!!!\n");
+ return ret;
+ }
+ if ((ret = platform_driver_register(&mc32x0_pdriver)) != 0)
+ {
+ errlog("Can't register mc3230 platform driver!!!\n");
+ return ret;
+ }
+ return ret;
+}
+
+static void __exit mc32x0_exit(void)
+{
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&l_sensorconfig.earlysuspend);
+#endif
+ platform_driver_unregister(&mc32x0_pdriver);
+ platform_device_unregister(&mc32x0_pdevice);
+ sensor_i2c_unregister_device(l_sensorconfig.client);
+ class_destroy(l_dev_class);
+}
+
+//*********************************************************************************************************
+MODULE_AUTHOR("Long Chen <lchen@mcube-inc.com>");
+MODULE_DESCRIPTION("mc32x0 driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("1.1");
+
+module_init(mc32x0_init);
+module_exit(mc32x0_exit);
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/mc32x0_driver.c b/ANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/mc32x0_driver.c
new file mode 100755
index 00000000..19c81b97
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/mc32x0_driver.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2011 MCUBE, Inc.
+ *
+ * Initial Code:
+ * Tan Liang
+ */
+
+
+
+
+
+#include <linux/delay.h>
+
+#include "mc32x0_driver.h"
+
+
+mc32x0_t *p_mc32x0; /**< pointer to MC32X0 device structure */
+
+
+/** API Initialization routine
+ \param *mc32x0 pointer to MC32X0 structured type
+ \return result of communication routines
+ */
+
+int mcube_mc32x0_init(mc32x0_t *mc32x0)
+{
+ int comres=0;
+ unsigned char data;
+
+ p_mc32x0 = mc32x0; /* assign mc32x0 ptr */
+ p_mc32x0->dev_addr = MC32X0_I2C_ADDR; /* preset I2C_addr */
+ comres += p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_CHIP_ID, &data, 1); /* read Chip Id */
+
+ p_mc32x0->chip_id = data;
+
+ // init other reg
+ data = 0x63;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x1b, &data, 1);
+ data = 0x43;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x1b, &data, 1);
+ msleep(5);
+
+ data = 0x43;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x07, &data, 1);
+ data = 0x80;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x1c, &data, 1);
+ data = 0x80;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x17, &data, 1);
+ msleep(5);
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x1c, &data, 1);
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, 0x17, &data, 1);
+
+ return comres;
+}
+
+int mc32x0_set_image (void)
+{
+ int comres;
+ unsigned char data;
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+
+#ifdef MCUBE_2G_10BIT_TAP
+ data = MC32X0_MODE_DEF;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Mode_Feature_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sleep_Count_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sample_Rate_REG, &data, 1 );
+
+ data = 0x80;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Tap_Detection_Enable_REG, &data, 1 );
+
+ data = 0x05;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_TAP_Dwell_Reject_REG, &data, 1 );
+
+ data = 0x33;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_RANGE_Control_REG, &data, 1 );
+
+ data = 0x07;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_TAP_Threshold_REG, &data, 1 );
+
+ data = 0x04;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Interrupt_Enable_REG, &data, 1 );
+
+#endif
+
+#ifdef MCUBE_2G_10BIT
+ data = MC32X0_MODE_DEF;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Mode_Feature_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sleep_Count_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sample_Rate_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Tap_Detection_Enable_REG, &data, 1 );
+
+ data = 0x33;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_RANGE_Control_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Interrupt_Enable_REG, &data, 1 );
+
+#endif
+
+#ifdef MCUBE_8G_14BIT_TAP
+ data = MC32X0_MODE_DEF;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Mode_Feature_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sleep_Count_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sample_Rate_REG, &data, 1 );
+
+ data = 0x80;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Tap_Detection_Enable_REG, &data, 1 );
+
+ data = 0x05;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_TAP_Dwell_Reject_REG, &data, 1 );
+
+ data = 0x3F;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_RANGE_Control_REG, &data, 1 );
+
+ data = 0x07;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_TAP_Threshold_REG, &data, 1 );
+
+ data = 0x04;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Interrupt_Enable_REG, &data, 1 );
+
+#endif
+
+#ifdef MCUBE_8G_14BIT
+ data = MC32X0_MODE_DEF;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Mode_Feature_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sleep_Count_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sample_Rate_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Tap_Detection_Enable_REG, &data, 1 );
+
+ data = 0x3F;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_RANGE_Control_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Interrupt_Enable_REG, &data, 1 );
+
+#endif
+
+
+
+#ifdef MCUBE_1_5G_8BIT
+ data = MC32X0_MODE_DEF;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Mode_Feature_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sleep_Count_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sample_Rate_REG, &data, 1 );
+
+ data = 0x02;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_RANGE_Control_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Tap_Detection_Enable_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Interrupt_Enable_REG, &data, 1 );
+
+#endif
+
+
+#ifdef MCUBE_1_5G_8BIT_TAP
+ data = MC32X0_MODE_DEF;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Mode_Feature_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sleep_Count_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sample_Rate_REG, &data, 1 );
+
+ data = 0x80;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Tap_Detection_Enable_REG, &data, 1 );
+
+ data = 0x02;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_RANGE_Control_REG, &data, 1 );
+
+ data = 0x03;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_TAP_Dwell_Reject_REG, &data, 1 );
+
+ data = 0x07;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_TAP_Threshold_REG, &data, 1 );
+
+ data = 0x04;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Interrupt_Enable_REG, &data, 1 );
+
+#endif
+
+
+#ifdef MCUBE_1_5G_6BIT
+
+ data = MC32X0_MODE_DEF;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Mode_Feature_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sleep_Count_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Sample_Rate_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_RANGE_Control_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Tap_Detection_Enable_REG, &data, 1 );
+
+ data = 0x00;
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_Interrupt_Enable_REG, &data, 1 );
+
+
+#endif
+
+
+
+ return comres;
+}
+
+
+int mc32x0_get_offset(unsigned char *offset)
+{
+ return 0;
+}
+
+
+int mc32x0_set_offset(unsigned char offset)
+{
+ return 0;
+}
+
+
+
+
+/** set mc32x0s range
+ \param range
+
+ \see MC32X0_RANGE_2G
+ \see MC32X0_RANGE_4G
+ \see MC32X0_RANGE_8G
+*/
+int mc32x0_set_range(char range)
+{
+ int comres = 0;
+ unsigned char data;
+
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+
+ if (range<3) {
+ comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_RANGE__REG, &data, 1);
+ data = MC32X0_SET_BITSLICE(data, MC32X0_RANGE, range);
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_RANGE__REG, &data, 1);
+
+ }
+ return comres;
+
+}
+
+
+/* readout select range from MC32X0
+ \param *range pointer to range setting
+ \return result of bus communication function
+ \see MC32X0_RANGE_2G, MC32X0_RANGE_4G, MC32X0_RANGE_8G
+ \see mc32x0_set_range()
+*/
+int mc32x0_get_range(unsigned char *range)
+{
+
+ int comres = 0;
+ unsigned char data;
+
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+ comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_RANGE__REG, &data, 1);
+ data = MC32X0_GET_BITSLICE(data, MC32X0_RANGE);
+
+ *range = data;
+
+
+ return comres;
+
+}
+
+
+
+int mc32x0_set_mode(unsigned char mode) {
+
+ int comres=0;
+ unsigned char data;
+
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+
+ if (mode<4) {
+ data = MC32X0_MODE_DEF;
+ data = MC32X0_SET_BITSLICE(data, MC32X0_MODE, mode);
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_MODE__REG, &data, 1 );
+
+ p_mc32x0->mode = mode;
+ }
+ return comres;
+
+}
+
+
+
+int mc32x0_get_mode(unsigned char *mode)
+{
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+ *mode = p_mc32x0->mode;
+ return 0;
+}
+
+
+int mc32x0_set_bandwidth(char bw)
+{
+ int comres = 0;
+ unsigned char data;
+
+
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+
+ if (bw<7) {
+
+ comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_BANDWIDTH__REG, &data, 1 );
+ data = MC32X0_SET_BITSLICE(data, MC32X0_BANDWIDTH, bw);
+ comres += p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, MC32X0_BANDWIDTH__REG, &data, 1 );
+
+ }
+
+ return comres;
+
+
+}
+
+int mc32x0_get_bandwidth(unsigned char *bw) {
+ int comres = 1;
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+
+ comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_BANDWIDTH__REG, bw, 1 );
+
+ *bw = MC32X0_GET_BITSLICE(*bw, MC32X0_BANDWIDTH);
+
+ return comres;
+
+}
+
+
+int mc32x0_read_accel_x(short *a_x)
+{
+ int comres;
+ unsigned char data[2];
+
+
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+
+ comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_XOUT_EX_L_REG, &data[0],2);
+
+ *a_x = ((short)data[0])|(((short)data[1])<<8);
+
+ return comres;
+
+}
+
+
+
+int mc32x0_read_accel_y(short *a_y)
+{
+ int comres;
+ unsigned char data[2];
+
+
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+
+ comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_YOUT_EX_L_REG, &data[0],2);
+
+ *a_y = ((short)data[0])|(((short)data[1])<<8);
+
+ return comres;
+}
+
+
+int mc32x0_read_accel_z(short *a_z)
+{
+ int comres;
+ unsigned char data[2];
+
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+
+ comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_ZOUT_EX_L_REG, &data[0],2);
+
+ *a_z = ((short)data[0])|(((short)data[1])<<8);
+
+ return comres;
+}
+
+
+int mc32x0_read_accel_xyz(mc32x0acc_t * acc)
+{
+ int comres;
+ unsigned char data[6];
+
+
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+
+#ifdef MC32X0_HIGH_END
+ comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_XOUT_EX_L_REG, &data[0],6);
+
+ acc->x = ((signed short)data[0])|(((signed short)data[1])<<8);
+ acc->y = ((signed short)data[2])|(((signed short)data[3])<<8);
+ acc->z = ((signed short)data[4])|(((signed short)data[5])<<8);
+#endif
+
+#ifdef MC32X0_LOW_END
+ comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_XOUT_REG, &data[0],3);
+
+#ifndef MCUBE_1_5G_6BIT
+ acc->x = (signed char)data[0];
+ acc->y = (signed char)data[1];
+ acc->z = (signed char)data[2];
+#else
+ acc->x = (signed short)GET_REAL_VALUE(data[0],6);
+ acc->y = (signed short)GET_REAL_VALUE(data[1],6);
+ acc->z = (signed short)GET_REAL_VALUE(data[2],6);
+#endif
+
+#endif
+
+
+
+
+ return comres;
+
+}
+
+
+
+int mc32x0_get_interrupt_status(unsigned char * ist)
+{
+
+ int comres=0;
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+ comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, MC32X0_Tilt_Status_REG, ist, 1);
+ return comres;
+}
+
+
+
+int mc32x0_read_reg(unsigned char addr, unsigned char *data, unsigned char len)
+{
+
+ int comres;
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+
+ comres = p_mc32x0->MC32X0_BUS_READ_FUNC(p_mc32x0->dev_addr, addr, data, len);
+ return comres;
+
+}
+
+
+int mc32x0_write_reg(unsigned char addr, unsigned char *data, unsigned char len)
+{
+
+ int comres;
+
+ if (p_mc32x0==0)
+ return E_NULL_PTR;
+
+ comres = p_mc32x0->MC32X0_BUS_WRITE_FUNC(p_mc32x0->dev_addr, addr, data, len);
+
+ return comres;
+
+}
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/mc32x0_driver.h b/ANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/mc32x0_driver.h
new file mode 100755
index 00000000..0aca80e8
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mc3230_gsensor/mc32x0_driver.h
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2011 MCUBE, Inc.
+ *
+ * Initial Code:
+ * Tan Liang
+ */
+
+
+
+#ifndef __MC32X0_H__
+#define __MC32X0_H__
+
+
+
+#define MC32X0_WR_FUNC_PTR char (* bus_write)(unsigned char, unsigned char *, unsigned char)
+
+#define MC32X0_BUS_WRITE_FUNC(dev_addr, reg_addr, reg_data, wr_len)\
+ bus_write(reg_addr, reg_data, wr_len)
+
+#define MC32X0_RD_FUNC_PTR char (* bus_read)( unsigned char, unsigned char *, unsigned char)
+
+#define MC32X0_BUS_READ_FUNC(dev_addr, reg_addr, reg_data, r_len)\
+ bus_read(reg_addr, reg_data, r_len)
+
+#define GET_REAL_VALUE(rv, bn) \
+ ((rv & (0x01 << (bn - 1))) ? (- (rv & ~(0xffff << (bn - 1)))) : (rv & ~(0xffff << (bn - 1))))
+
+
+
+//#define MC32X0_HIGH_END
+/*******MC3210/20 define this**********/
+
+//#define MCUBE_2G_10BIT_TAP
+//#define MCUBE_2G_10BIT
+//#define MCUBE_8G_14BIT_TAP
+//#define MCUBE_8G_14BIT
+
+
+
+//#define MC32X0_LOW_END
+/*******MC3230 define this**********/
+
+//#define MCUBE_1_5G_8BIT
+//#define MCUBE_1_5G_8BIT_TAP
+
+
+
+
+
+/** MC32X0 I2C Address
+*/
+
+#define MC32X0_I2C_ADDR 0x4c // 0x98 >> 1
+
+
+
+/*
+ MC32X0 API error codes
+*/
+
+#define E_NULL_PTR (char)-127
+
+/*
+ *
+ * register definitions
+ *
+ */
+
+#define MC32X0_XOUT_REG 0x00
+#define MC32X0_YOUT_REG 0x01
+#define MC32X0_ZOUT_REG 0x02
+#define MC32X0_Tilt_Status_REG 0x03
+#define MC32X0_Sampling_Rate_Status_REG 0x04
+#define MC32X0_Sleep_Count_REG 0x05
+#define MC32X0_Interrupt_Enable_REG 0x06
+#define MC32X0_Mode_Feature_REG 0x07
+#define MC32X0_Sample_Rate_REG 0x08
+#define MC32X0_Tap_Detection_Enable_REG 0x09
+#define MC32X0_TAP_Dwell_Reject_REG 0x0a
+#define MC32X0_DROP_Control_Register_REG 0x0b
+#define MC32X0_SHAKE_Debounce_REG 0x0c
+#define MC32X0_XOUT_EX_L_REG 0x0d
+#define MC32X0_XOUT_EX_H_REG 0x0e
+#define MC32X0_YOUT_EX_L_REG 0x0f
+#define MC32X0_YOUT_EX_H_REG 0x10
+#define MC32X0_ZOUT_EX_L_REG 0x11
+#define MC32X0_ZOUT_EX_H_REG 0x12
+#define MC32X0_CHIP_ID 0x18
+#define MC32X0_RANGE_Control_REG 0x20
+#define MC32X0_SHAKE_Threshold_REG 0x2B
+#define MC32X0_UD_Z_TH_REG 0x2C
+#define MC32X0_UD_X_TH_REG 0x2D
+#define MC32X0_RL_Z_TH_REG 0x2E
+#define MC32X0_RL_Y_TH_REG 0x2F
+#define MC32X0_FB_Z_TH_REG 0x30
+#define MC32X0_DROP_Threshold_REG 0x31
+#define MC32X0_TAP_Threshold_REG 0x32
+
+
+
+
+/** MC32X0 acceleration data
+ \brief Structure containing acceleration values for x,y and z-axis in signed short
+
+*/
+
+typedef struct {
+ short x, /**< holds x-axis acceleration data sign extended. Range -512 to 511. */
+ y, /**< holds y-axis acceleration data sign extended. Range -512 to 511. */
+ z; /**< holds z-axis acceleration data sign extended. Range -512 to 511. */
+} mc32x0acc_t;
+
+/* RANGE */
+
+#define MC32X0_RANGE__POS 2
+#define MC32X0_RANGE__LEN 2
+#define MC32X0_RANGE__MSK 0x0c
+#define MC32X0_RANGE__REG MC32X0_RANGE_Control_REG
+
+/* MODE */
+
+#define MC32X0_MODE__POS 0
+#define MC32X0_MODE__LEN 2
+#define MC32X0_MODE__MSK 0x03
+#define MC32X0_MODE__REG MC32X0_Mode_Feature_REG
+
+#define MC32X0_MODE_DEF 0x43
+
+
+/* BANDWIDTH */
+
+#define MC32X0_BANDWIDTH__POS 4
+#define MC32X0_BANDWIDTH__LEN 3
+#define MC32X0_BANDWIDTH__MSK 0x70
+#define MC32X0_BANDWIDTH__REG MC32X0_RANGE_Control_REG
+
+
+#define MC32X0_GET_BITSLICE(regvar, bitname)\
+ (regvar & bitname##__MSK) >> bitname##__POS
+
+
+#define MC32X0_SET_BITSLICE(regvar, bitname, val)\
+ (regvar & ~bitname##__MSK) | ((val<<bitname##__POS)&bitname##__MSK)
+
+
+
+
+
+
+#define MC32X0_RANGE_2G 0
+#define MC32X0_RANGE_4G 1
+#define MC32X0_RANGE_8G 2
+
+
+#define MC32X0_WAKE 1
+#define MC32X0_SNIFF 2
+#define MC32X0_STANDBY 3
+
+
+#define MC32X0_LOW_PASS_512HZ 0
+#define MC32X0_LOW_PASS_256HZ 1
+#define MC32X0_LOW_PASS_128HZ 2
+#define MC32X0_LOW_PASS_64HZ 3
+#define MC32X0_LOW_PASS_32HZ 4
+#define MC32X0_LOW_PASS_16HZ 5
+#define MC32X0_LOW_PASS_8HZ 6
+
+
+
+
+
+typedef struct {
+ unsigned char mode; /**< save current MC32X0 operation mode */
+ unsigned char chip_id; /**< save MC32X0's chip id which has to be 0x00/0x01 after calling mc32x0_init() */
+ unsigned char dev_addr; /**< initializes MC32X0's I2C device address 0x4c */
+ MC32X0_WR_FUNC_PTR; /**< function pointer to the SPI/I2C write function */
+ MC32X0_RD_FUNC_PTR; /**< function pointer to the SPI/I2C read function */
+} mc32x0_t;
+
+
+
+/* Function prototypes */
+
+
+
+
+int mcube_mc32x0_init(mc32x0_t *mc32x0);
+
+int mc32x0_set_image (struct i2c_client *client) ;
+
+int mc32x0_set_range(char);
+
+int mc32x0_get_range(unsigned char*);
+
+int mc32x0_set_mode(struct i2c_client *client, unsigned char mode);
+
+int mc32x0_get_mode(unsigned char *);
+
+int mc32x0_set_bandwidth(char);
+
+int mc32x0_get_bandwidth(unsigned char *);
+
+int mc32x0_read_accel_x(short *);
+
+int mc32x0_read_accel_y(short *);
+
+int mc32x0_read_accel_z(short *);
+
+int mc32x0_read_accel_xyz(struct i2c_client *client, s16 * acc);
+
+int mc32x0_get_interrupt_status(unsigned char *);
+
+int mc32x0_read_reg(unsigned char , unsigned char *, unsigned char);
+
+int mc32x0_write_reg(unsigned char , unsigned char*, unsigned char );
+
+
+#endif
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mc3xxx_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/mc3xxx_gsensor/Makefile
new file mode 100644
index 00000000..de65868d
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mc3xxx_gsensor/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_gsensor_mc3xxx
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := mc3xxx.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mc3xxx_gsensor/mc3xxx.c b/ANDROID_3.4.5/drivers/input/sensor/mc3xxx_gsensor/mc3xxx.c
new file mode 100644
index 00000000..c7d37a7a
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mc3xxx_gsensor/mc3xxx.c
@@ -0,0 +1,2719 @@
+/*****************************************************************************
+ *
+ * Copyright (c) 2013 mCube, Inc. All rights reserved.
+ *
+ * This source is subject to the mCube Software License.
+ * This software is protected by Copyright and the information and source code
+ * contained herein is confidential. The software including the source code
+ * may not be copied and the information contained herein may not be used or
+ * disclosed except with the written permission of mCube Inc.
+ *
+ * All other rights reserved.
+ *
+ * This code and information are provided "as is" without warranty of any
+ * kind, either expressed or implied, including but not limited to the
+ * implied warranties of merchantability and/or fitness for a
+ * particular purpose.
+ *
+ * The following software/firmware and/or related documentation ("mCube Software")
+ * have been modified by mCube Inc. All revisions are subject to any receiver's
+ * applicable license agreements with mCube Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ *****************************************************************************/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+//#include <linux/earlysuspend.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+
+
+#include <mach/hardware.h>
+#include <linux/fs.h>
+
+#include "../sensor.h"
+
+
+//#include <mach/sys_config.h>
+
+//=== CONFIGURATIONS ==========================================================
+//#define _MC3XXX_DEBUG_ON_
+
+//=============================================================================
+#ifdef _MC3XXX_DEBUG_ON_
+ #define mcprintkreg(x...) printk(x)
+ #define mcprintkfunc(x...) printk(x)
+ #define GSE_ERR(x...) printk(x)
+ #define GSE_LOG(x...) printk(x)
+#else
+ #define mcprintkreg(x...)
+ #define mcprintkfunc(x...)
+ #define GSE_ERR(x...)
+ #define GSE_LOG(x...)
+#endif
+
+static int g_virtual_z = 0;
+#define G_2_REVERSE_VIRTUAL_Z 0 //!!!!! 1
+#define SUPPORT_VIRTUAL_Z_SENSOR //add 2013-10-23
+#define LOW_RESOLUTION 1
+#define HIGH_RESOLUTION 2
+#define RBM_RESOLUTION 3
+#ifdef SUPPORT_VIRTUAL_Z_SENSOR
+#define Low_Pos_Max 127
+#define Low_Neg_Max -128
+#define High_Pos_Max 8191
+#define High_Neg_Max -8192
+#define VIRTUAL_Z 1
+static int Railed = 0;
+#else
+#define VIRTUAL_Z 0
+#endif
+
+
+static struct class* l_dev_class = NULL;
+
+
+#define SENSOR_NAME "mc3xxx"
+#define SENSOR_DRIVER_VERSION "1.0.0"
+#define SENSOR_DATA_SIZE 3
+
+//static int mc3xxx_pin_hd;
+//static char mc3xxx_on_off_str[32];
+#define G_0 ABS_Y
+#define G_1 ABS_X
+#define G_2 ABS_Z
+#define G_0_REVERSE 1
+#define G_1_REVERSE 1
+#define G_2_REVERSE 1
+
+//static unsigned char s_bResolution = 0x00;
+static unsigned char s_bPCODE = 0x00;
+static unsigned short mc3xxx_i2c_auto_probe_addr[] = { 0x4C, 0x6C, 0x4E, 0x6D, 0x6E, 0x6F };
+
+//=============================================================================
+#define SENSOR_DMARD_IOCTL_BASE 234
+#define IOCTL_SENSOR_SET_DELAY_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 100)
+#define IOCTL_SENSOR_GET_DELAY_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 101)
+#define IOCTL_SENSOR_GET_STATE_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 102)
+#define IOCTL_SENSOR_SET_STATE_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 103)
+#define IOCTL_SENSOR_GET_DATA_ACCEL _IO(SENSOR_DMARD_IOCTL_BASE, 104)
+
+#define IOCTL_MSENSOR_SET_DELAY_MAGNE _IO(SENSOR_DMARD_IOCTL_BASE, 200)
+#define IOCTL_MSENSOR_GET_DATA_MAGNE _IO(SENSOR_DMARD_IOCTL_BASE, 201)
+#define IOCTL_MSENSOR_GET_STATE_MAGNE _IO(SENSOR_DMARD_IOCTL_BASE, 202)
+#define IOCTL_MSENSOR_SET_STATE_MAGNE _IO(SENSOR_DMARD_IOCTL_BASE, 203)
+
+#define IOCTL_SENSOR_GET_NAME _IO(SENSOR_DMARD_IOCTL_BASE, 301)
+#define IOCTL_SENSOR_GET_VENDOR _IO(SENSOR_DMARD_IOCTL_BASE, 302)
+#define IOCTL_SENSOR_GET_CONVERT_PARA _IO(SENSOR_DMARD_IOCTL_BASE, 401)
+//#define SENSOR_CALIBRATION _IOWR(SENSOR_DMARD_IOCTL_BASE, 402, int[SENSOR_DATA_SIZE])
+
+//=============================================================================
+#define MC3XXX_CONVERT_PARAMETER (1.5f * (9.80665f) / 256.0f)
+#define MC3XXX_DISPLAY_NAME SENSOR_NAME
+#define MC3XXX_DIPLAY_VENDOR "mCube"
+
+//=============================================================================
+#define MC3XXX_AXIS_X 0
+#define MC3XXX_AXIS_Y 1
+#define MC3XXX_AXIS_Z 2
+#define MC3XXX_AXIS_NUM 3
+#define MC3XXX_DATA_LEN 6
+
+
+/***********************************************
+ *** REGISTER MAP
+ ***********************************************/
+#define MC3XXX_REG_XOUT 0x00
+#define MC3XXX_REG_YOUT 0x01
+#define MC3XXX_REG_ZOUT 0x02
+#define MC3XXX_REG_TILT_STATUS 0x03
+#define MC3XXX_REG_SAMPLE_RATE_STATUS 0x04
+#define MC3XXX_REG_SLEEP_COUNT 0x05
+#define MC3XXX_REG_INTERRUPT_ENABLE 0x06
+#define MC3XXX_REG_MODE_FEATURE 0x07
+#define MC3XXX_REG_SAMPLE_RATE 0x08
+#define MC3XXX_REG_TAP_DETECTION_ENABLE 0x09
+#define MC3XXX_REG_TAP_DWELL_REJECT 0x0A
+#define MC3XXX_REG_DROP_CONTROL 0x0B
+#define MC3XXX_REG_SHAKE_DEBOUNCE 0x0C
+#define MC3XXX_REG_XOUT_EX_L 0x0D
+#define MC3XXX_REG_XOUT_EX_H 0x0E
+#define MC3XXX_REG_YOUT_EX_L 0x0F
+#define MC3XXX_REG_YOUT_EX_H 0x10
+#define MC3XXX_REG_ZOUT_EX_L 0x11
+#define MC3XXX_REG_ZOUT_EX_H 0x12
+#define MC3XXX_REG_RANGE_CONTROL 0x20
+#define MC3XXX_REG_SHAKE_THRESHOLD 0x2B
+#define MC3XXX_REG_UD_Z_TH 0x2C
+#define MC3XXX_REG_UD_X_TH 0x2D
+#define MC3XXX_REG_RL_Z_TH 0x2E
+#define MC3XXX_REG_RL_Y_TH 0x2F
+#define MC3XXX_REG_FB_Z_TH 0x30
+#define MC3XXX_REG_DROP_THRESHOLD 0x31
+#define MC3XXX_REG_TAP_THRESHOLD 0x32
+#define MC3XXX_REG_PRODUCT_CODE 0x3B
+
+/***********************************************
+ *** RETURN CODE
+ ***********************************************/
+#define MC3XXX_RETCODE_SUCCESS (0)
+#define MC3XXX_RETCODE_ERROR_I2C (-1)
+#define MC3XXX_RETCODE_ERROR_NULL_POINTER (-2)
+#define MC3XXX_RETCODE_ERROR_STATUS (-3)
+#define MC3XXX_RETCODE_ERROR_SETUP (-4)
+#define MC3XXX_RETCODE_ERROR_GET_DATA (-5)
+#define MC3XXX_RETCODE_ERROR_IDENTIFICATION (-6)
+
+
+/***********************************************
+ *** CONFIGURATION
+ ***********************************************/
+#define MC3XXX_BUF_SIZE 256
+
+#define MCUBE_1_5G_8BIT 0x01 //MC3XXX_LOW_END
+#define MCUBE_8G_14BIT 0x02 //MC3XXX_HIGH_END
+
+#define DOT_CALI
+
+
+#define SENSOR_DURATION_DEFAULT 20
+
+#define INPUT_FUZZ 0
+#define INPUT_FLAT 0
+
+/***********************************************
+ *** PRODUCT ID
+ ***********************************************/
+#define MC3XXX_PCODE_3210 0x90
+#define MC3XXX_PCODE_3230 0x19
+#define MC3XXX_PCODE_3250 0x88
+#define MC3XXX_PCODE_3410 0xA8
+#define MC3XXX_PCODE_3410N 0xB8
+#define MC3XXX_PCODE_3430 0x29
+#define MC3XXX_PCODE_3430N 0x39
+#define MC3XXX_PCODE_3510B 0x40
+#define MC3XXX_PCODE_3530B 0x30
+#define MC3XXX_PCODE_3510C 0x10
+#define MC3XXX_PCODE_3530C 0x6E
+
+//=============================================================================
+static unsigned char is_new_mc34x0 = 0;
+static unsigned char is_mc3250 = 0;
+static unsigned char is_mc35xx = 0;
+static unsigned char Sensor_Accuracy = 0;
+
+
+//=============================================================================
+#ifdef DOT_CALI
+#define CALIB_PATH "/data/data/com.mcube.acc/files/mcube-calib.txt"
+//MCUBE_BACKUP_FILE
+#define BACKUP_CALIB_PATH "/data/misc/mcube-calib.txt"
+static char backup_buf[64];
+//MCUBE_BACKUP_FILE
+#define DATA_PATH "/sdcard/mcube-register-map.txt"
+
+typedef struct {
+ unsigned short x; /**< X axis */
+ unsigned short y; /**< Y axis */
+ unsigned short z; /**< Z axis */
+} GSENSOR_VECTOR3D;
+
+static GSENSOR_VECTOR3D gsensor_gain = { 0 };
+static struct miscdevice mc3xxx_device;
+
+static struct file * fd_file = NULL;
+
+static mm_segment_t oldfs = { 0 };
+static unsigned char offset_buf[6] = { 0 };
+static signed int offset_data[3] = { 0 };
+s16 G_RAW_DATA[3] = { 0 };
+static signed int gain_data[3] = { 0 };
+static signed int enable_RBM_calibration = 0;
+
+#define GSENSOR 0x95
+#define GSENSOR_IOCTL_INIT _IO(GSENSOR, 0x01)
+#define GSENSOR_IOCTL_READ_CHIPINFO _IOR(GSENSOR, 0x02, int)
+#define GSENSOR_IOCTL_READ_SENSORDATA _IOR(GSENSOR, 0x03, int)
+#define GSENSOR_IOCTL_READ_OFFSET _IOR(GSENSOR, 0x04, GSENSOR_VECTOR3D)
+#define GSENSOR_IOCTL_READ_GAIN _IOR(GSENSOR, 0x05, GSENSOR_VECTOR3D)
+#define GSENSOR_IOCTL_READ_RAW_DATA _IOR(GSENSOR, 0x06, int)
+//#define GSENSOR_IOCTL_SET_CALI _IOW(GSENSOR, 0x06, SENSOR_DATA)
+#define GSENSOR_IOCTL_GET_CALI _IOW(GSENSOR, 0x07, SENSOR_DATA)
+#define GSENSOR_IOCTL_CLR_CALI _IO(GSENSOR, 0x08)
+#define GSENSOR_MCUBE_IOCTL_READ_RBM_DATA _IOR(GSENSOR, 0x09, SENSOR_DATA)
+#define GSENSOR_MCUBE_IOCTL_SET_RBM_MODE _IO(GSENSOR, 0x0a)
+#define GSENSOR_MCUBE_IOCTL_CLEAR_RBM_MODE _IO(GSENSOR, 0x0b)
+#define GSENSOR_MCUBE_IOCTL_SET_CALI _IOW(GSENSOR, 0x0c, SENSOR_DATA)
+#define GSENSOR_MCUBE_IOCTL_REGISTER_MAP _IO(GSENSOR, 0x0d)
+#define GSENSOR_IOCTL_SET_CALI_MODE _IOW(GSENSOR, 0x0e,int)
+#define GSENSOR_MCUBE_IOCTL_READ_PRODUCT_ID _IOR(GSENSOR, 0x0f, int)
+#define GSENSOR_MCUBE_IOCTL_READ_FILEPATH _IOR(GSENSOR, 0x10, char[256])
+
+
+static int MC3XXX_ReadRegMap(struct i2c_client *client, u8 *pbUserBuf);
+static int mc3xxx_chip_init(struct i2c_client *client);
+static int MC3XXX_ResetCalibration(struct i2c_client *client);
+static int MC3XX0_ValidateSensorIC(unsigned char bPCode);
+
+
+typedef struct{
+ int x;
+ int y;
+ int z;
+}SENSOR_DATA;
+
+static int load_cali_flg = 0;
+static int wake_mc3xxx_flg = 0;
+
+//MCUBE_BACKUP_FILE
+static bool READ_FROM_BACKUP = false;
+//MCUBE_BACKUP_FILE
+
+#endif
+
+#define MC3XXX_WAKE 1
+#define MC3XXX_SNIFF 2
+#define MC3XXX_STANDBY 3
+
+struct dev_data {
+ struct i2c_client *client;
+};
+
+static struct dev_data dev = { 0 };
+
+struct acceleration {
+ int x;
+ int y;
+ int z;
+};
+
+struct mc3xxx_data {
+ struct mutex lock;
+ struct i2c_client *client;
+ struct delayed_work work;
+ struct workqueue_struct *mc3xxx_wq;
+ struct hrtimer timer;
+ struct device *device;
+ struct input_dev *input_dev;
+ int use_count;
+ int enabled;
+ volatile unsigned int duration;
+ int use_irq;
+ int irq;
+ unsigned long irqflags;
+ int gpio;
+ unsigned int map[3];
+ int inv[3];
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+ // for control
+ int int_gpio; //0-3
+ int op;
+ int samp;
+ //int xyz_axis[3][3]; // (axis,direction)
+ struct proc_dir_entry* sensor_proc;
+ int isdbg;
+ int sensor_samp; //
+ int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor
+ int test_pass;
+ int offset[MC3XXX_AXIS_NUM+1]; /*+1: for 4-byte alignment*/
+ s16 data[MC3XXX_AXIS_NUM+1];
+};
+
+static struct mc3xxx_data l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .samp = 16,
+ /*.xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },*/
+ .sensor_proc = NULL,
+ .isdbg = 1,
+ .sensor_samp = 1, // 1 sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ //.offset={0,0,0},
+};
+
+
+//=============================================================================
+enum mc3xx0_orientation
+{
+ MC3XX0_TOP_LEFT_DOWN = 0,
+ MC3XX0_TOP_RIGHT_DOWN,
+ MC3XX0_TOP_RIGHT_UP,
+ MC3XX0_TOP_LEFT_UP,
+ MC3XX0_BOTTOM_LEFT_DOWN,
+ MC3XX0_BOTTOM_RIGHT_DOWN,
+ MC3XX0_BOTTOM_RIGHT_UP,
+ MC3XX0_BOTTOM_LEFT_UP
+};
+
+
+struct mc3xx0_hwmsen_convert
+{
+ signed int sign[3];
+ unsigned int map[3];
+};
+
+// Transformation matrix for chip mounting position
+static const struct mc3xx0_hwmsen_convert mc3xx0_cvt[] =
+{
+ {{ 1, 1, 1}, {MC3XXX_AXIS_X, MC3XXX_AXIS_Y, MC3XXX_AXIS_Z}}, // 0: top , left-down
+ {{-1, 1, 1}, {MC3XXX_AXIS_Y, MC3XXX_AXIS_X, MC3XXX_AXIS_Z}}, // 1: top , right-down
+ {{-1, -1, 1}, {MC3XXX_AXIS_X, MC3XXX_AXIS_Y, MC3XXX_AXIS_Z}}, // 2: top , right-up
+ {{ 1, -1, 1}, {MC3XXX_AXIS_Y, MC3XXX_AXIS_X, MC3XXX_AXIS_Z}}, // 3: top , left-up
+ {{-1, 1, -1}, {MC3XXX_AXIS_X, MC3XXX_AXIS_Y, MC3XXX_AXIS_Z}}, // 4: bottom, left-down
+ {{ 1, 1, -1}, {MC3XXX_AXIS_Y, MC3XXX_AXIS_X, MC3XXX_AXIS_Z}}, // 5: bottom, right-down
+ {{ 1, -1, -1}, {MC3XXX_AXIS_X, MC3XXX_AXIS_Y, MC3XXX_AXIS_Z}}, // 6: bottom, right-up
+ {{-1, -1, -1}, {MC3XXX_AXIS_Y, MC3XXX_AXIS_X, MC3XXX_AXIS_Z}}, // 7: bottom, left-up
+};
+
+//static unsigned char mc3xx0_current_placement = MC3XX0_TOP_RIGHT_UP; // current soldered placement
+static struct mc3xx0_hwmsen_convert *pCvt;
+
+#ifdef SUPPORT_VIRTUAL_Z_SENSOR //add 2013-10-23
+int Verify_Z_Railed(int AccData, int resolution)
+{
+ int status = 0;
+ GSE_LOG("%s: AccData = %d",__func__, AccData);
+ if(resolution == 1) // Low resolution
+ {
+ if((AccData >= Low_Pos_Max && AccData >=0)|| (AccData <= Low_Neg_Max && AccData < 0))
+ {
+ status = 1;
+ GSE_LOG("%s: Railed at Low Resolution",__func__);
+ }
+ }
+ else if (resolution == 2) //High resolution
+ {
+ if((AccData >= High_Pos_Max && AccData >=0) || (AccData <= High_Neg_Max && AccData < 0))
+ {
+ status = 1;
+ GSE_LOG("%s: Railed at High Resolution",__func__);
+ }
+ }
+ else if (resolution == 3) //High resolution
+ {
+ if((AccData >= Low_Pos_Max*3 && AccData >=0) || (AccData <= Low_Neg_Max*3 && AccData < 0))
+ {
+ status = 1;
+ GSE_LOG("%s: Railed at High Resolution",__func__);
+ }
+ }
+ else
+ GSE_LOG("%s, Wrong resolution",__func__);
+
+ return status;
+}
+
+int SquareRoot(int x)
+{
+ int lowerbound;
+ int upperbound;
+ int root;
+
+ if(x < 0) return -1;
+ if(x == 0 || x == 1) return x;
+ lowerbound = 1;
+ upperbound = x;
+ root = lowerbound + (upperbound - lowerbound)/2;
+
+ while(root > x/root || root+1 <= x/(root+1))
+ {
+ if(root > x/root)
+ {
+ upperbound = root;
+ }
+ else
+ {
+ lowerbound = root;
+ }
+ root = lowerbound + (upperbound - lowerbound)/2;
+ }
+ GSE_LOG("%s: Sqrt root is %d",__func__, root);
+ return root;
+}
+#endif
+
+
+unsigned int sample_rate_2_memsec(unsigned int rate)
+{
+ return (1000/rate);
+}
+
+
+//=============================================================================
+//volatile static short sensor_duration = SENSOR_DURATION_DEFAULT;
+//volatile static short sensor_state_flag = 1;
+
+//=============================================================================
+static ssize_t mc3xxx_map_show(struct device *dev, struct device_attribute *attr,char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mc3xxx_data *data = NULL;
+ int i = 0;
+ data = i2c_get_clientdata(client);
+ for (i = 0; i< 3; i++)
+ {
+ if(data->inv[i] == 1)
+ {
+ switch(data->map[i])
+ {
+ case ABS_X:
+ buf[i] = 'x';
+ break;
+ case ABS_Y:
+ buf[i] = 'y';
+ break;
+ case ABS_Z:
+ buf[i] = 'z';
+ break;
+ default:
+ buf[i] = '_';
+ break;
+ }
+ }
+ else
+ {
+ switch(data->map[i])
+ {
+ case ABS_X:
+ buf[i] = 'X';
+ break;
+ case ABS_Y:
+ buf[i] = 'Y';
+ break;
+ case ABS_Z:
+ buf[i] = 'Z';
+ break;
+ default:
+ buf[i] = '-';
+ break;
+ }
+ }
+ }
+ sprintf(buf+3,"\r\n");
+ return 5;
+}
+
+/*****************************************
+ *** show_regiter_map
+ *****************************************/
+static ssize_t show_regiter_map(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ u8 _bIndex = 0;
+ u8 _baRegMap[64] = { 0 };
+ ssize_t _tLength = 0;
+
+ struct i2c_client *client = to_i2c_client(dev);
+
+ MC3XXX_ReadRegMap(client, _baRegMap);
+
+ for (_bIndex = 0; _bIndex < 64; _bIndex++)
+ _tLength += snprintf((buf + _tLength), (PAGE_SIZE - _tLength), "Reg[0x%02X]: 0x%02X\n", _bIndex, _baRegMap[_bIndex]);
+
+ return (_tLength);
+}
+
+static ssize_t mc3xxx_map_store(struct device *dev, struct device_attribute *attr,const char *buf, size_t count)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct mc3xxx_data *data = NULL;
+ int i = 0;
+ data = i2c_get_clientdata(client);
+
+ if(count < 3) return -EINVAL;
+
+ for(i = 0; i< 3; i++)
+ {
+ switch(buf[i])
+ {
+ case 'x':
+ data->map[i] = ABS_X;
+ data->inv[i] = 1;
+ break;
+ case 'y':
+ data->map[i] = ABS_Y;
+ data->inv[i] = 1;
+ break;
+ case 'z':
+ data->map[i] = ABS_Z;
+ data->inv[i] = 1;
+ break;
+ case 'X':
+ data->map[i] = ABS_X;
+ data->inv[i] = -1;
+ break;
+ case 'Y':
+ data->map[i] = ABS_Y;
+ data->inv[i] = -1;
+ break;
+ case 'Z':
+ data->map[i] = ABS_Z;
+ data->inv[i] = -1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return count;
+}
+
+//=============================================================================
+static ssize_t mc3xxx_version_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%s\n", SENSOR_DRIVER_VERSION);
+}
+
+//=============================================================================
+static ssize_t mc3xxx_chip_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ unsigned char bChipID[4] = { 0 };
+ struct i2c_client *client = to_i2c_client(dev);
+
+ i2c_smbus_read_i2c_block_data(client, 0x3C, 4, bChipID);
+
+ return sprintf(buf, "%02X-%02X-%02X-%02X\n", bChipID[0], bChipID[1], bChipID[2], bChipID[3]);
+}
+/*
+//=============================================================================
+static ssize_t mc3xxx_position_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ printk("%s called\n", __func__);
+ return sprintf(buf, "%d\n", mc3xx0_current_placement);
+}
+
+//=============================================================================
+static ssize_t mc3xxx_position_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned long position = 0;
+
+ printk("%s called\n", __func__);
+
+ position = simple_strtoul(buf, NULL,10);
+
+ if (position < 8)
+ mc3xx0_current_placement = position;
+
+ return count;
+}
+*/
+
+static int mc3xxx_enable(struct mc3xxx_data *data, int enable)
+{
+ if(enable)
+ {
+ msleep(10);
+ //mutex_lock(&data->lock);
+ mc3xxx_chip_init(data->client);
+ //mutex_unlock(&data->lock);
+ queue_delayed_work(data->mc3xxx_wq, &data->work, msecs_to_jiffies(sample_rate_2_memsec(data->sensor_samp)));//hrtimer_start(&data->timer, ktime_set(0, sensor_duration*1000000), HRTIMER_MODE_REL);
+ data->enabled = true;
+ }
+ else
+ {
+ cancel_delayed_work_sync(&l_sensorconfig.work);//hrtimer_cancel(&data->timer);
+ data->enabled = false;
+ }
+ return 0;
+}
+
+static ssize_t mc3xxx_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = container_of(mc3xxx_device.parent, struct i2c_client, dev);
+
+ struct mc3xxx_data *mc3xxx = i2c_get_clientdata(client);
+
+
+ return sprintf(buf, "%d\n", mc3xxx->enabled);
+}
+
+static ssize_t mc3xxx_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+
+ bool new_enable;
+
+ struct i2c_client *client = container_of(mc3xxx_device.parent, struct i2c_client, dev);
+
+ struct mc3xxx_data *mc3xxx = i2c_get_clientdata(client);
+
+ if (sysfs_streq(buf, "1"))
+ new_enable = true;
+ else if (sysfs_streq(buf, "0"))
+ new_enable = false;
+ else
+ {
+ pr_debug("%s: invalid value %d\n", __func__, *buf);
+ return -EINVAL;
+ }
+
+ mc3xxx_enable(mc3xxx, new_enable);
+
+ return count;
+}
+
+
+static DRIVER_ATTR(regmap , S_IRUGO, show_regiter_map, NULL );
+static DEVICE_ATTR(map, S_IWUSR | S_IRUGO, mc3xxx_map_show, mc3xxx_map_store);
+static DEVICE_ATTR(version , S_IRUGO , mc3xxx_version_show , NULL );
+static DEVICE_ATTR(chipid , S_IRUGO , mc3xxx_chip_id_show , NULL );
+//static DEVICE_ATTR(position, S_IRUGO | S_IWUSR | S_IWGRP, mc3xxx_position_show, mc3xxx_position_store);
+static DEVICE_ATTR(enable, S_IRUGO|S_IWUSR|S_IWGRP|S_IWOTH, mc3xxx_enable_show, mc3xxx_enable_store);
+static struct attribute* mc3xxx_attrs[] =
+{
+ &driver_attr_regmap,
+ &dev_attr_map.attr,
+ &dev_attr_version.attr,
+ &dev_attr_chipid.attr,
+ //&dev_attr_position.attr,
+ &dev_attr_enable.attr,
+ NULL
+};
+
+static const struct attribute_group mc3xxx_group =
+{
+ .attrs = mc3xxx_attrs,
+};
+
+//=============================================================================
+static int mc3xxx_chip_init(struct i2c_client *client)
+{
+ unsigned char data = 0;
+
+ data = i2c_smbus_read_byte_data(client, MC3XXX_REG_PRODUCT_CODE);
+ s_bPCODE =data;
+ if((data == MC3XXX_PCODE_3230)||(data == MC3XXX_PCODE_3430)
+ ||(data == MC3XXX_PCODE_3430N)||(data == MC3XXX_PCODE_3530B)
+ ||((data|0x0E) == MC3XXX_PCODE_3530C))
+ Sensor_Accuracy = MCUBE_1_5G_8BIT; //8bit
+ else if((data == MC3XXX_PCODE_3210)||(data == MC3XXX_PCODE_3410)
+ ||(data == MC3XXX_PCODE_3250)||(data == MC3XXX_PCODE_3410N)
+ ||(data == MC3XXX_PCODE_3510B)||(data == MC3XXX_PCODE_3510C))
+ Sensor_Accuracy = MCUBE_8G_14BIT; //14bit
+ else
+ Sensor_Accuracy = 0;
+
+ if (data == MC3XXX_PCODE_3250)
+ is_mc3250 = 1;
+
+ if ((data == MC3XXX_PCODE_3430N)||(data == MC3XXX_PCODE_3410N))
+ is_new_mc34x0 = 1;
+
+ if((MC3XXX_PCODE_3510B == data) || (MC3XXX_PCODE_3510C == data)
+ ||(data == MC3XXX_PCODE_3530B)||((data|0x0E) == MC3XXX_PCODE_3530C))
+ is_mc35xx = 1;
+
+
+ if(MCUBE_8G_14BIT == Sensor_Accuracy)
+ {
+ data = 0x43;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_MODE_FEATURE, data);
+ data = 0x00;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_SLEEP_COUNT, data);
+
+ data = 0x00;
+ if (is_mc35xx)
+ {
+ data = 0x0A;
+ }
+
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_SAMPLE_RATE, data);
+
+ data = 0x3F;
+ if ((MC3XXX_PCODE_3510B == s_bPCODE) || (MC3XXX_PCODE_3510C == s_bPCODE))
+ data = 0x25;
+ else if ((MC3XXX_PCODE_3530B == s_bPCODE) || (MC3XXX_PCODE_3530C == (s_bPCODE|0x0E)))
+ data = 0x02;
+
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_RANGE_CONTROL, data);
+ data = 0x00;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_TAP_DETECTION_ENABLE, data);
+ data = 0x00;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_INTERRUPT_ENABLE, data);
+
+ #ifdef DOT_CALI
+ gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = 1024;
+ #endif
+ }
+ else if(MCUBE_1_5G_8BIT == Sensor_Accuracy)
+ {
+ data = 0x43;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_MODE_FEATURE, data);
+ data = 0x00;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_SLEEP_COUNT, data);
+
+ data = 0x00;
+ if (is_mc35xx)
+ {
+ data = 0x0A;
+ }
+
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_SAMPLE_RATE, data);
+
+ data = 0x32;
+ if ((MC3XXX_PCODE_3510B == s_bPCODE) || (MC3XXX_PCODE_3510C == s_bPCODE))
+ data = 0x25;
+ else if ((MC3XXX_PCODE_3530B == s_bPCODE) || (MC3XXX_PCODE_3530C == (s_bPCODE|0x0E)))
+ data = 0x02;
+
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_RANGE_CONTROL,data);
+ data = 0x00;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_TAP_DETECTION_ENABLE, data);
+ data = 0x00;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_INTERRUPT_ENABLE, data);
+
+ #ifdef DOT_CALI
+ gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = 86;
+ if (is_mc35xx)
+ {
+ gsensor_gain.x = gsensor_gain.y = gsensor_gain.z = 64;
+ }
+ #endif
+ }
+
+ data = 0x41;
+ i2c_smbus_write_byte_data(client, MC3XXX_REG_MODE_FEATURE, data);
+
+ return 0;
+}
+
+//=============================================================================
+int mc3xxx_set_mode(struct i2c_client *client, unsigned char mode)
+{
+ int comres = 0;
+ unsigned char data = 0;
+
+ if (mode < 4)
+ {
+ data = (0x40 | mode);
+ comres = i2c_smbus_write_byte_data(client, MC3XXX_REG_MODE_FEATURE, data);
+ }
+
+ return comres;
+}
+
+
+
+#ifdef DOT_CALI
+//=============================================================================
+struct file *openFile(char *path,int flag,int mode)
+{
+ struct file *fp = NULL;
+
+ fp = filp_open(path, flag, mode);
+
+ if (IS_ERR(fp) || !fp->f_op)
+ {
+ GSE_LOG("Calibration File filp_open return NULL\n");
+ return NULL;
+ }
+
+ return fp;
+}
+
+//=============================================================================
+int readFile(struct file *fp,char *buf,int readlen)
+{
+ if (fp->f_op && fp->f_op->read)
+ return fp->f_op->read(fp,buf,readlen, &fp->f_pos);
+ else
+ return -1;
+}
+
+//=============================================================================
+int writeFile(struct file *fp,char *buf,int writelen)
+{
+ if (fp->f_op && fp->f_op->write)
+ return fp->f_op->write(fp,buf,writelen, &fp->f_pos);
+ else
+ return -1;
+}
+
+//=============================================================================
+int closeFile(struct file *fp)
+{
+ filp_close(fp,NULL);
+
+ return 0;
+}
+
+//=============================================================================
+void initKernelEnv(void)
+{
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ printk(KERN_INFO "initKernelEnv\n");
+}
+
+//=============================================================================
+ int MC3XXX_WriteCalibration(struct i2c_client *client, int dat[MC3XXX_AXIS_NUM])
+{
+ int err = 0;
+ u8 buf[9] = { 0 };
+ s16 tmp = 0, x_gain = 0, y_gain = 0, z_gain = 0;
+ s32 x_off = 0, y_off = 0, z_off = 0;
+ int temp_cali_dat[MC3XXX_AXIS_NUM] = { 0 };
+ //const struct mc3xx0_hwmsen_convert *pCvt = NULL;
+
+ u8 bMsbFilter = 0x3F;
+ s16 wSignBitMask = 0x2000;
+ s16 wSignPaddingBits = 0xC000;
+ s32 dwRangePosLimit = 0x1FFF;
+ s32 dwRangeNegLimit = -0x2000;
+
+ if (is_mc35xx)
+ {
+ bMsbFilter = 0x7F;
+ wSignBitMask = 0x4000;
+ wSignPaddingBits = 0x8000;
+ dwRangePosLimit = 0x3FFF;
+ dwRangeNegLimit = -0x4000;
+ }
+
+ //pCvt = &mc3xx0_cvt[mc3xx0_current_placement];
+
+ temp_cali_dat[pCvt->map[MC3XXX_AXIS_X]] = pCvt->sign[MC3XXX_AXIS_X] * dat[MC3XXX_AXIS_X];
+ temp_cali_dat[pCvt->map[MC3XXX_AXIS_Y]] = pCvt->sign[MC3XXX_AXIS_Y] * dat[MC3XXX_AXIS_Y];
+ temp_cali_dat[pCvt->map[MC3XXX_AXIS_Z]] = pCvt->sign[MC3XXX_AXIS_Z] * dat[MC3XXX_AXIS_Z];
+
+ if ((is_new_mc34x0)||(is_mc35xx))
+ {
+ temp_cali_dat[MC3XXX_AXIS_X] = -temp_cali_dat[MC3XXX_AXIS_X];
+ temp_cali_dat[MC3XXX_AXIS_Y] = -temp_cali_dat[MC3XXX_AXIS_Y];
+ }
+ else if (is_mc3250)
+ {
+ s16 temp = 0;
+
+ temp = temp_cali_dat[MC3XXX_AXIS_X];
+
+ temp_cali_dat[MC3XXX_AXIS_X] = -temp_cali_dat[MC3XXX_AXIS_Y];
+ temp_cali_dat[MC3XXX_AXIS_Y] = temp;
+ }
+
+ dat[MC3XXX_AXIS_X] = temp_cali_dat[MC3XXX_AXIS_X];
+ dat[MC3XXX_AXIS_Y] = temp_cali_dat[MC3XXX_AXIS_Y];
+ dat[MC3XXX_AXIS_Z] = temp_cali_dat[MC3XXX_AXIS_Z];
+
+ GSE_LOG("UPDATE dat: (%+3d %+3d %+3d)\n",
+ dat[MC3XXX_AXIS_X], dat[MC3XXX_AXIS_Y], dat[MC3XXX_AXIS_Z]);
+
+ // read register 0x21~0x29
+ err = i2c_smbus_read_i2c_block_data(client , 0x21 , 3 , &buf[0]);
+ err |= i2c_smbus_read_i2c_block_data(client , 0x24 , 3 , &buf[3]);
+ err |= i2c_smbus_read_i2c_block_data(client , 0x27 , 3 , &buf[6]);
+
+
+ // get x,y,z offset
+ tmp = ((buf[1] & bMsbFilter) << 8) + buf[0];
+ if (tmp & wSignBitMask)
+ tmp |= wSignPaddingBits;
+ x_off = tmp;
+
+ tmp = ((buf[3] & bMsbFilter) << 8) + buf[2];
+ if (tmp & wSignBitMask)
+ tmp |= wSignPaddingBits;
+ y_off = tmp;
+
+ tmp = ((buf[5] & bMsbFilter) << 8) + buf[4];
+ if (tmp & wSignBitMask)
+ tmp |= wSignPaddingBits;
+ z_off = tmp;
+
+ // get x,y,z gain
+ x_gain = ((buf[1] >> 7) << 8) + buf[6];
+ y_gain = ((buf[3] >> 7) << 8) + buf[7];
+ z_gain = ((buf[5] >> 7) << 8) + buf[8];
+
+ // prepare new offset
+ x_off = x_off + 16 * dat[MC3XXX_AXIS_X] * 256 * 128 / 3 / gsensor_gain.x / (40 + x_gain);
+ y_off = y_off + 16 * dat[MC3XXX_AXIS_Y] * 256 * 128 / 3 / gsensor_gain.y / (40 + y_gain);
+ z_off = z_off + 16 * dat[MC3XXX_AXIS_Z] * 256 * 128 / 3 / gsensor_gain.z / (40 + z_gain);
+
+ //add for over range
+ if( x_off > dwRangePosLimit)
+ {
+ x_off = dwRangePosLimit;
+ }
+ else if( x_off < dwRangeNegLimit)
+ {
+ x_off = dwRangeNegLimit;
+ }
+
+ if( y_off > dwRangePosLimit)
+ {
+ y_off = dwRangePosLimit;
+ }
+ else if( y_off < dwRangeNegLimit)
+ {
+ y_off = dwRangeNegLimit;
+ }
+
+ if( z_off > dwRangePosLimit)
+ {
+ z_off = dwRangePosLimit;
+ }
+ else if( z_off < dwRangeNegLimit)
+ {
+ z_off = dwRangeNegLimit;
+ }
+
+ //storege the cerrunt offset data with DOT format
+ offset_data[0] = x_off;
+ offset_data[1] = y_off;
+ offset_data[2] = z_off;
+
+ //storege the cerrunt Gain data with GOT format
+ gain_data[0] = 256*8*128/3/(40+x_gain);
+ gain_data[1] = 256*8*128/3/(40+y_gain);
+ gain_data[2] = 256*8*128/3/(40+z_gain);
+ printk("%d %d ======================\n\n ",gain_data[0],x_gain);
+
+ buf[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x07, buf[0]);
+
+ buf[0] = x_off & 0xff;
+ buf[1] = ((x_off >> 8) & bMsbFilter) | (x_gain & 0x0100 ? 0x80 : 0);
+ buf[2] = y_off & 0xff;
+ buf[3] = ((y_off >> 8) & bMsbFilter) | (y_gain & 0x0100 ? 0x80 : 0);
+ buf[4] = z_off & 0xff;
+ buf[5] = ((z_off >> 8) & bMsbFilter) | (z_gain & 0x0100 ? 0x80 : 0);
+
+ i2c_smbus_write_i2c_block_data(client, 0x21, 2, &buf[0]);
+ i2c_smbus_write_i2c_block_data(client, 0x21+2, 2, &buf[2]);
+ i2c_smbus_write_i2c_block_data(client, 0x21+4, 2, &buf[4]);
+
+ buf[0] = 0x41;
+ i2c_smbus_write_byte_data(client, 0x07,buf[0]);
+
+ msleep(50);
+
+ return err;
+
+}
+
+int mcube_read_cali_file(struct i2c_client *client)
+{
+ int cali_data[3] = { 0 };
+ int err =0;
+ //char buf[64];
+ printk("%s %d\n",__func__,__LINE__);
+ //MCUBE_BACKUP_FILE
+ READ_FROM_BACKUP = false;
+ //MCUBE_BACKUP_FILE
+ initKernelEnv();
+ fd_file = openFile(CALIB_PATH,O_RDONLY,0);
+ //MCUBE_BACKUP_FILE
+ if (fd_file == NULL)
+ {
+ fd_file = openFile(BACKUP_CALIB_PATH, O_RDONLY, 0);
+ if(fd_file != NULL)
+ {
+ READ_FROM_BACKUP = true;
+ }
+ }
+ //MCUBE_BACKUP_FILE
+ if (fd_file == NULL)
+ {
+ GSE_LOG("fail to open\n");
+ cali_data[0] = 0;
+ cali_data[1] = 0;
+ cali_data[2] = 0;
+
+ return -1;
+ }
+ else
+ {
+ printk("%s %d\n",__func__,__LINE__);
+ memset(backup_buf,0,64);
+ if ((err = readFile(fd_file,backup_buf,128))>0)
+ GSE_LOG("buf:%s\n",backup_buf);
+ else
+ GSE_LOG("read file error %d\n",err);
+ printk("%s %d\n",__func__,__LINE__);
+
+ set_fs(oldfs);
+ closeFile(fd_file);
+
+ sscanf(backup_buf, "%d %d %d",&cali_data[MC3XXX_AXIS_X], &cali_data[MC3XXX_AXIS_Y], &cali_data[MC3XXX_AXIS_Z]);
+ GSE_LOG("cali_data: %d %d %d\n", cali_data[MC3XXX_AXIS_X], cali_data[MC3XXX_AXIS_Y], cali_data[MC3XXX_AXIS_Z]);
+
+ MC3XXX_WriteCalibration(client, cali_data);
+ }
+ return 0;
+}
+
+//=============================================================================
+static int mcube_write_log_data(struct i2c_client *client, u8 data[0x3f])
+{
+ #define _WRT_LOG_DATA_BUFFER_SIZE (66 * 50)
+
+ s16 rbm_data[3]={0}, raw_data[3]={0};
+ int err =0;
+ char *_pszBuffer = NULL;
+ int n=0,i=0;
+
+ initKernelEnv();
+ fd_file = openFile(DATA_PATH ,O_RDWR | O_CREAT,0);
+ if (fd_file == NULL)
+ {
+ GSE_LOG("mcube_write_log_data fail to open\n");
+ }
+ else
+ {
+ rbm_data[MC3XXX_AXIS_X] = (s16)((data[0x0d]) | (data[0x0e] << 8));
+ rbm_data[MC3XXX_AXIS_Y] = (s16)((data[0x0f]) | (data[0x10] << 8));
+ rbm_data[MC3XXX_AXIS_Z] = (s16)((data[0x11]) | (data[0x12] << 8));
+
+ raw_data[MC3XXX_AXIS_X] = (rbm_data[MC3XXX_AXIS_X] + offset_data[0]/2)*gsensor_gain.x/gain_data[0];
+ raw_data[MC3XXX_AXIS_Y] = (rbm_data[MC3XXX_AXIS_Y] + offset_data[1]/2)*gsensor_gain.y/gain_data[1];
+ raw_data[MC3XXX_AXIS_Z] = (rbm_data[MC3XXX_AXIS_Z] + offset_data[2]/2)*gsensor_gain.z/gain_data[2];
+
+ _pszBuffer = kzalloc(_WRT_LOG_DATA_BUFFER_SIZE, GFP_KERNEL);
+ if (NULL == _pszBuffer)
+ {
+ GSE_ERR("fail to allocate memory for buffer\n");
+ closeFile(fd_file);
+ return -1;
+ }
+ memset(_pszBuffer, 0, _WRT_LOG_DATA_BUFFER_SIZE);
+
+ n += sprintf(_pszBuffer+n, "G-sensor RAW X = %d Y = %d Z = %d\n", raw_data[0] ,raw_data[1] ,raw_data[2]);
+ n += sprintf(_pszBuffer+n, "G-sensor RBM X = %d Y = %d Z = %d\n", rbm_data[0] ,rbm_data[1] ,rbm_data[2]);
+ for(i=0; i<64; i++)
+ {
+ n += sprintf(_pszBuffer+n, "mCube register map Register[%x] = 0x%x\n",i,data[i]);
+ }
+ msleep(50);
+ if ((err = writeFile(fd_file,_pszBuffer,n))>0)
+ GSE_LOG("buf:%s\n",_pszBuffer);
+ else
+ GSE_LOG("write file error %d\n",err);
+
+ kfree(_pszBuffer);
+
+ set_fs(oldfs);
+ closeFile(fd_file);
+ }
+ return 0;
+}
+
+//=============================================================================
+void MC3XXX_rbm(struct i2c_client *client, int enable)
+{
+ char buf1[3] = { 0 };
+ if(enable == 1 )
+ {
+ buf1[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x07, buf1[0]);
+
+ buf1[0] = 0x6D;
+ i2c_smbus_write_byte_data(client, 0x1B, buf1[0]);
+
+ buf1[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x1B, buf1[0]);
+
+ buf1[0] = 0x00;
+ i2c_smbus_write_byte_data(client, 0x3B, buf1[0]);
+
+ buf1[0] = 0x02;
+ i2c_smbus_write_byte_data(client, 0x14, buf1[0]);
+
+ buf1[0] = 0x41;
+ i2c_smbus_write_byte_data(client, 0x07, buf1[0]);
+
+ enable_RBM_calibration = 1;
+
+ GSE_LOG("set rbm!!\n");
+
+ msleep(10);
+ }
+ else if(enable == 0 )
+ {
+ buf1[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x07, buf1[0]);
+
+ buf1[0] = 0x00;
+ i2c_smbus_write_byte_data(client, 0x14, buf1[0]);
+ GSE_LOG("set rbm!! %x @@@@\n",s_bPCODE);
+
+ buf1[0] = s_bPCODE;
+ i2c_smbus_write_byte_data(client, 0x3B, buf1[0]);
+
+ buf1[0] = 0x6D;
+ i2c_smbus_write_byte_data(client, 0x1B, buf1[0]);
+
+ buf1[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x1B, buf1[0]);
+
+ buf1[0] = 0x41;
+ i2c_smbus_write_byte_data(client, 0x07, buf1[0]);
+
+ enable_RBM_calibration = 0;
+
+ GSE_LOG("clear rbm!!\n");
+
+ msleep(10);
+ }
+}
+
+/*----------------------------------------------------------------------------*/
+ int MC3XXX_ReadData_RBM(struct i2c_client *client,int data[MC3XXX_AXIS_NUM])
+{
+ u8 addr = 0x0d;
+ u8 rbm_buf[MC3XXX_DATA_LEN] = {0};
+ int err = 0;
+
+ //err = p_mc3xxx->MC3XXX_BUS_READ_FUNC(p_mc3xxx->dev_addr, addr, &rbm_buf[0],6);
+ err = i2c_smbus_read_i2c_block_data(client , addr , 6 , rbm_buf);
+ //err = mc3xxx_read_block(client, addr, rbm_buf, 0x06);
+
+ data[MC3XXX_AXIS_X] = (s16)((rbm_buf[0]) | (rbm_buf[1] << 8));
+ data[MC3XXX_AXIS_Y] = (s16)((rbm_buf[2]) | (rbm_buf[3] << 8));
+ data[MC3XXX_AXIS_Z] = (s16)((rbm_buf[4]) | (rbm_buf[5] << 8));
+
+ GSE_LOG("rbm_buf<<<<<[%02x %02x %02x %02x %02x %02x]\n",rbm_buf[0], rbm_buf[2], rbm_buf[2], rbm_buf[3], rbm_buf[4], rbm_buf[5]);
+ GSE_LOG("RBM<<<<<[%04x %04x %04x]\n", data[MC3XXX_AXIS_X], data[MC3XXX_AXIS_Y], data[MC3XXX_AXIS_Z]);
+ GSE_LOG("RBM<<<<<[%04d %04d %04d]\n", data[MC3XXX_AXIS_X], data[MC3XXX_AXIS_Y], data[MC3XXX_AXIS_Z]);
+ return err;
+}
+
+
+ int MC3XXX_ReadRBMData(struct i2c_client *client, char *buf)
+{
+ int res = 0;
+ int data[3];
+
+ if (!buf)
+ {
+ return EINVAL;
+ }
+
+ mc3xxx_set_mode(client,MC3XXX_WAKE);
+
+ res = MC3XXX_ReadData_RBM(client,data);
+
+ if(res)
+ {
+ GSE_ERR("%s I2C error: ret value=%d",__func__, res);
+ return EIO;
+ }
+ else
+ {
+ sprintf(buf, "%04x %04x %04x", data[MC3XXX_AXIS_X],
+ data[MC3XXX_AXIS_Y], data[MC3XXX_AXIS_Z]);
+
+ }
+
+ return 0;
+}
+ int MC3XXX_ReadOffset(struct i2c_client *client,s16 ofs[MC3XXX_AXIS_NUM])
+{
+ int err = 0;
+ u8 off_data[6] = { 0 };
+
+ if(Sensor_Accuracy == MCUBE_8G_14BIT)
+ {
+ err = i2c_smbus_read_i2c_block_data(client, MC3XXX_REG_XOUT_EX_L, MC3XXX_DATA_LEN, off_data);
+
+ ofs[MC3XXX_AXIS_X] = ((s16)(off_data[0]))|((s16)(off_data[1])<<8);
+ ofs[MC3XXX_AXIS_Y] = ((s16)(off_data[2]))|((s16)(off_data[3])<<8);
+ ofs[MC3XXX_AXIS_Z] = ((s16)(off_data[4]))|((s16)(off_data[5])<<8);
+ }
+ else if(Sensor_Accuracy == MCUBE_1_5G_8BIT)
+ {
+ err = i2c_smbus_read_i2c_block_data(client, 0, 3, off_data);
+
+ ofs[MC3XXX_AXIS_X] = (s8)off_data[0];
+ ofs[MC3XXX_AXIS_Y] = (s8)off_data[1];
+ ofs[MC3XXX_AXIS_Z] = (s8)off_data[2];
+ }
+
+ GSE_LOG("MC3XXX_ReadOffset %d %d %d\n", ofs[MC3XXX_AXIS_X], ofs[MC3XXX_AXIS_Y], ofs[MC3XXX_AXIS_Z]);
+
+ return err;
+}
+/*----------------------------------------------------------------------------*/
+ static int MC3XXX_ResetCalibration(struct i2c_client *client)
+{
+ u8 buf[6] = { 0 };
+ s16 tmp = 0;
+ int err = 0;
+
+ u8 bMsbFilter = 0x3F;
+ s16 wSignBitMask = 0x2000;
+ s16 wSignPaddingBits = 0xC000;
+
+ buf[0] = 0x43;
+ err = i2c_smbus_write_byte_data(client, 0x07, buf[0]);
+ if(err)
+ {
+ GSE_ERR("error 0x07: %d\n", err);
+ }
+
+ err = i2c_smbus_write_i2c_block_data(client, 0x21, 6, offset_buf);
+ if(err)
+ {
+ GSE_ERR("error: %d\n", err);
+ }
+
+ buf[0] = 0x41;
+ err = i2c_smbus_write_byte_data(client, 0x07, buf[0]);
+ if(err)
+ {
+ GSE_ERR("error: %d\n", err);
+ }
+
+ msleep(20);
+
+
+ if (is_mc35xx)
+ {
+ bMsbFilter = 0x7F;
+ wSignBitMask = 0x4000;
+ wSignPaddingBits = 0x8000;
+ }
+
+ tmp = ((offset_buf[1] & bMsbFilter) << 8) + offset_buf[0];
+ if (tmp & wSignBitMask)
+ tmp |= wSignPaddingBits;
+ offset_data[0] = tmp;
+
+ tmp = ((offset_buf[3] & bMsbFilter) << 8) + offset_buf[2];
+ if (tmp & wSignBitMask)
+ tmp |= wSignPaddingBits;
+ offset_data[1] = tmp;
+
+ tmp = ((offset_buf[5] & bMsbFilter) << 8) + offset_buf[4];
+ if (tmp & wSignBitMask)
+ tmp |= wSignPaddingBits;
+ offset_data[2] = tmp;
+
+ return 0;
+}
+
+//=============================================================================
+ int MC3XXX_ReadCalibration(struct i2c_client *client,int dat[MC3XXX_AXIS_NUM])
+{
+ signed short MC_offset[MC3XXX_AXIS_NUM + 1] = { 0 }; // +1: for 4-byte alignment
+ int err = 0;
+
+ memset(MC_offset, 0, sizeof(MC_offset));
+
+ err = MC3XXX_ReadOffset(client, MC_offset);
+
+ if (err)
+ {
+ GSE_ERR("read offset fail, %d\n", err);
+ return err;
+ }
+
+ dat[MC3XXX_AXIS_X] = MC_offset[MC3XXX_AXIS_X];
+ dat[MC3XXX_AXIS_Y] = MC_offset[MC3XXX_AXIS_Y];
+ dat[MC3XXX_AXIS_Z] = MC_offset[MC3XXX_AXIS_Z];
+
+ return 0;
+}
+
+//=============================================================================
+int MC3XXX_ReadData(struct i2c_client *client, s16 buffer[MC3XXX_AXIS_NUM])
+{
+ unsigned char buf[6] = { 0 };
+ signed char buf1[6] = { 0 };
+ char rbm_buf[6] = { 0 };
+ int ret = 0;
+
+ #ifdef SUPPORT_VIRTUAL_Z_SENSOR
+ int tempX=0;
+ int tempY=0;
+ int tempZ=0;
+ #endif
+
+ if (enable_RBM_calibration == 0)
+ {
+ //err = hwmsen_read_block(client, addr, buf, 0x06);
+ }
+ else if (enable_RBM_calibration == 1)
+ {
+ memset(rbm_buf, 0, 6);
+ i2c_smbus_read_i2c_block_data(client, 0x0d , 2, &rbm_buf[0]);
+ i2c_smbus_read_i2c_block_data(client, 0x0d+2, 2, &rbm_buf[2]);
+ i2c_smbus_read_i2c_block_data(client, 0x0d+4, 2, &rbm_buf[4]);
+ }
+
+ if (enable_RBM_calibration == 0)
+ {
+ if(Sensor_Accuracy == MCUBE_8G_14BIT)
+ {
+ ret = i2c_smbus_read_i2c_block_data(client, MC3XXX_REG_XOUT_EX_L, 6, buf);
+
+ buffer[0] = (signed short)((buf[0])|(buf[1]<<8));
+ buffer[1] = (signed short)((buf[2])|(buf[3]<<8));
+ buffer[2] = (signed short)((buf[4])|(buf[5]<<8));
+ }
+ else if(Sensor_Accuracy == MCUBE_1_5G_8BIT)
+ {
+ ret = i2c_smbus_read_i2c_block_data(client, MC3XXX_REG_XOUT, 3, buf1);
+
+ buffer[0] = (signed short)buf1[0];
+ buffer[1] = (signed short)buf1[1];
+ buffer[2] = (signed short)buf1[2];
+ }
+
+ #ifdef SUPPORT_VIRTUAL_Z_SENSOR //add 2013-10-23
+ if (g_virtual_z)
+ {
+ //printk("%s 1\n", __FUNCTION__);
+
+ tempX = buffer[MC3XXX_AXIS_X];
+ tempY = buffer[MC3XXX_AXIS_Y];
+ tempZ = buffer[MC3XXX_AXIS_Z];
+ //printk(" %d:Verify_Z_Railed() %d\n", (int)buffer[MC32X0_AXIS_Z], Verify_Z_Railed((int)buffer[MC32X0_AXIS_Z], LOW_RESOLUTION));
+ if(1 == Verify_Z_Railed((int)buffer[MC3XXX_AXIS_Z], LOW_RESOLUTION)) // z-railed
+ {
+ Railed = 1;
+
+ GSE_LOG("%s: Z railed", __func__);
+ //printk("%s: Z railed \n", __func__);
+ if (G_2_REVERSE_VIRTUAL_Z == 1)
+ buffer[MC3XXX_AXIS_Z] = (s8) ( gsensor_gain.z - (abs(tempX) + abs(tempY)));
+ else
+ buffer[MC3XXX_AXIS_Z] = (s8) -( gsensor_gain.z - (abs(tempX) + abs(tempY)));
+ }
+ else
+ {
+ Railed = 0;
+ }
+ }
+ #endif
+ mcprintkreg("MC3XXX_ReadData: %d %d %d\n", buffer[0], buffer[1], buffer[2]);
+ }
+ else if (enable_RBM_calibration == 1)
+ {
+ buffer[MC3XXX_AXIS_X] = (s16)((rbm_buf[0]) | (rbm_buf[1] << 8));
+ buffer[MC3XXX_AXIS_Y] = (s16)((rbm_buf[2]) | (rbm_buf[3] << 8));
+ buffer[MC3XXX_AXIS_Z] = (s16)((rbm_buf[4]) | (rbm_buf[5] << 8));
+
+ GSE_LOG("%s RBM<<<<<[%08d %08d %08d]\n", __func__, buffer[MC3XXX_AXIS_X], buffer[MC3XXX_AXIS_Y], buffer[MC3XXX_AXIS_Z]);
+
+ if(gain_data[0] == 0)
+ {
+ buffer[MC3XXX_AXIS_X] = 0;
+ buffer[MC3XXX_AXIS_Y] = 0;
+ buffer[MC3XXX_AXIS_Z] = 0;
+
+ return 0;
+ }
+
+ buffer[MC3XXX_AXIS_X] = (buffer[MC3XXX_AXIS_X] + offset_data[0]/2)*gsensor_gain.x/gain_data[0];
+ buffer[MC3XXX_AXIS_Y] = (buffer[MC3XXX_AXIS_Y] + offset_data[1]/2)*gsensor_gain.y/gain_data[1];
+ buffer[MC3XXX_AXIS_Z] = (buffer[MC3XXX_AXIS_Z] + offset_data[2]/2)*gsensor_gain.z/gain_data[2];
+
+ #ifdef SUPPORT_VIRTUAL_Z_SENSOR // add 2013-10-23
+ if (g_virtual_z)
+ {
+ tempX = buffer[MC3XXX_AXIS_X];
+ tempY = buffer[MC3XXX_AXIS_Y];
+ tempZ = buffer[MC3XXX_AXIS_Z];
+ //printk("%s 2\n", __FUNCTION__);
+ GSE_LOG("Original RBM<<<<<[%08d %08d %08d]\n", buffer[MC3XXX_AXIS_X], buffer[MC3XXX_AXIS_Y], buffer[MC3XXX_AXIS_Z]);
+ printk("Verify_Z_Railed() %d\n", Verify_Z_Railed((int)buffer[MC3XXX_AXIS_Z], RBM_RESOLUTION));
+ if(1 == Verify_Z_Railed(buffer[MC3XXX_AXIS_Z], RBM_RESOLUTION)) // z-railed
+ {
+ GSE_LOG("%s: Z Railed in RBM mode",__FUNCTION__);
+ //printk("%s: Z Railed in RBM mode\n",__FUNCTION__);
+ if (G_2_REVERSE_VIRTUAL_Z == 1)
+ buffer[MC3XXX_AXIS_Z] = (s16) ( gsensor_gain.z - (abs(tempX) + abs(tempY)));
+ else
+ buffer[MC3XXX_AXIS_Z] = (s16) -( gsensor_gain.z - (abs(tempX) + abs(tempY)));
+ }
+ GSE_LOG("RBM<<<<<[%08d %08d %08d]\n", buffer[MC3XXX_AXIS_X], buffer[MC3XXX_AXIS_Y], buffer[MC3XXX_AXIS_Z]);
+ }
+ #endif
+
+ GSE_LOG("%s offset_data <<<<<[%d %d %d]\n", __func__, offset_data[0], offset_data[1], offset_data[2]);
+ GSE_LOG("%s gsensor_gain <<<<<[%d %d %d]\n", __func__, gsensor_gain.x, gsensor_gain.y, gsensor_gain.z);
+ GSE_LOG("%s gain_data <<<<<[%d %d %d]\n", __func__, gain_data[0], gain_data[1], gain_data[2]);
+ GSE_LOG("%s RBM->RAW <<<<<[%d %d %d]\n", __func__, buffer[MC3XXX_AXIS_X], buffer[MC3XXX_AXIS_Y], buffer[MC3XXX_AXIS_Z]);
+ }
+
+ return 0;
+}
+
+//=============================================================================
+int MC3XXX_ReadRawData(struct i2c_client *client, char * buf)
+{
+ int res = 0;
+ s16 raw_buf[3] = { 0 };
+
+ if (!buf || !client)
+ {
+ return -EINVAL;
+ }
+
+ mc3xxx_set_mode(client, MC3XXX_WAKE);
+ res = MC3XXX_ReadData(client,&raw_buf[0]);
+ if(res)
+ {
+ printk("%s %d\n",__FUNCTION__, __LINE__);
+ GSE_ERR("I2C error: ret value=%d", res);
+ return -EIO;
+ }
+ else
+ {
+ //const struct mc3xx0_hwmsen_convert *pCvt = &mc3xx0_cvt[mc3xx0_current_placement];
+
+ GSE_LOG("UPDATE dat: (%+3d %+3d %+3d)\n",
+ raw_buf[MC3XXX_AXIS_X], raw_buf[MC3XXX_AXIS_Y], raw_buf[MC3XXX_AXIS_Z]);
+
+ if ((is_new_mc34x0)||(is_mc35xx))
+ {
+ raw_buf[MC3XXX_AXIS_X] = -raw_buf[MC3XXX_AXIS_X];
+ raw_buf[MC3XXX_AXIS_Y] = -raw_buf[MC3XXX_AXIS_Y];
+ }
+ else if (is_mc3250)
+ {
+ s16 temp = 0;
+
+ temp = raw_buf[MC3XXX_AXIS_X];
+
+ raw_buf[MC3XXX_AXIS_X] = raw_buf[MC3XXX_AXIS_Y];
+ raw_buf[MC3XXX_AXIS_Y] = -temp;
+ }
+
+ G_RAW_DATA[MC3XXX_AXIS_X] = pCvt->sign[MC3XXX_AXIS_X] * raw_buf[pCvt->map[MC3XXX_AXIS_X]];
+ G_RAW_DATA[MC3XXX_AXIS_Y] = pCvt->sign[MC3XXX_AXIS_Y] * raw_buf[pCvt->map[MC3XXX_AXIS_Y]];
+ G_RAW_DATA[MC3XXX_AXIS_Z] = pCvt->sign[MC3XXX_AXIS_Z] * raw_buf[pCvt->map[MC3XXX_AXIS_Z]];
+
+ G_RAW_DATA[MC3XXX_AXIS_Z] += gsensor_gain.z*(pCvt->sign[MC3XXX_AXIS_Z])*(1);//G_RAW_DATA[MC3XXX_AXIS_Z]+gsensor_gain.z;
+
+ sprintf(buf, "%04x %04x %04x", G_RAW_DATA[MC3XXX_AXIS_X],
+ G_RAW_DATA[MC3XXX_AXIS_Y], G_RAW_DATA[MC3XXX_AXIS_Z]);
+
+ GSE_LOG("G_RAW_DATA: (%+3d %+3d %+3d)\n",
+ G_RAW_DATA[MC3XXX_AXIS_X], G_RAW_DATA[MC3XXX_AXIS_Y], G_RAW_DATA[MC3XXX_AXIS_Z]);
+ }
+
+ return 0;
+}
+
+//=============================================================================
+static int MC3XXX_ReadRegMap(struct i2c_client *client, u8 *pbUserBuf)
+{
+ u8 data[128] = {0};
+ //u8 addr = 0x00;
+ int err = 0;
+ int i = 0;
+
+ if(NULL == client)
+ {
+ err = -EINVAL;
+ return err;
+ }
+
+
+ for(i = 0; i < 64; i++)
+ {
+ data[i] = i2c_smbus_read_byte_data(client, i);
+ printk(KERN_INFO "mcube register map Register[%x] = 0x%x\n", i ,data[i]);
+ }
+
+ msleep(50);
+
+ mcube_write_log_data(client, data);
+
+ msleep(50);
+
+ if (NULL != pbUserBuf)
+ {
+ printk(KERN_INFO "copy to user buffer\n");
+ memcpy(pbUserBuf, data, 64);
+ }
+
+ return err;
+}
+
+//=============================================================================
+void MC3XXX_Reset(struct i2c_client *client)
+{
+ //s16 tmp = 0, x_gain = 0, y_gain = 0, z_gain = 0;
+ u8 buf[3] = { 0 };
+ int err = 0;
+
+ buf[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x07, buf[0]);
+
+ i2c_smbus_read_i2c_block_data(client, 0x04, 1, buf);
+
+ if (0x00 == (buf[0] & 0x40))
+ {
+ buf[0] = 0x6d;
+ i2c_smbus_write_byte_data(client, 0x1b, buf[0]);
+
+ buf[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x1b, buf[0]);
+ }
+
+ msleep(5);
+
+ buf[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x07, buf[0]);
+
+ buf[0] = 0x80;
+ i2c_smbus_write_byte_data(client, 0x1c, buf[0]);
+
+ buf[0] = 0x80;
+ i2c_smbus_write_byte_data(client, 0x17, buf[0]);
+
+ msleep(5);
+
+ buf[0] = 0x00;
+ i2c_smbus_write_byte_data(client, 0x1c, buf[0]);
+
+ buf[0] = 0x00;
+ i2c_smbus_write_byte_data(client, 0x17, buf[0]);
+
+ msleep(5);
+
+ memset(offset_buf, 0, sizeof(offset_buf));
+
+ err = i2c_smbus_read_i2c_block_data(client, 0x21, 6, offset_buf);
+
+ i2c_smbus_read_i2c_block_data(client, 0x04, 1, buf);
+
+ if (0x00 == (buf[0] & 0x40))
+ {
+ buf[0] = 0x6d;
+ i2c_smbus_write_byte_data(client, 0x1b, buf[0]);
+
+ buf[0] = 0x43;
+ i2c_smbus_write_byte_data(client, 0x1b, buf[0]);
+ }
+
+ buf[0] = 0x41;
+ i2c_smbus_write_byte_data(client, 0x07, buf[0]);
+
+}
+#endif
+
+int mc3xxx_read_accel_xyz(struct i2c_client *client, s16 * acc)
+{
+ int comres = 0;
+ s16 raw_data[MC3XXX_AXIS_NUM] = { 0 };
+ //const struct mc3xx0_hwmsen_convert *pCvt = &mc3xx0_cvt[mc3xx0_current_placement];
+
+#ifdef DOT_CALI
+ s16 raw_buf[6] = { 0 };
+
+ comres = MC3XXX_ReadData(client, &raw_buf[0]);
+
+ raw_data[MC3XXX_AXIS_X] = raw_buf[0];
+ raw_data[MC3XXX_AXIS_Y] = raw_buf[1];
+ raw_data[MC3XXX_AXIS_Z] = raw_buf[2];
+#else
+ unsigned char raw_buf[6] = { 0 };
+ signed char raw_buf1[3] = { 0 };
+
+ if(Sensor_Accuracy == MCUBE_8G_14BIT)
+ {
+ comres = i2c_smbus_read_i2c_block_data(client, MC3XXX_REG_XOUT_EX_L, 6, raw_buf);
+
+ raw_data[MC3XXX_AXIS_X] = (signed short)((raw_buf[0])|(raw_buf[1]<<8));
+ raw_data[MC3XXX_AXIS_Y] = (signed short)((raw_buf[2])|(raw_buf[3]<<8));
+ raw_data[MC3XXX_AXIS_Z] = (signed short)((raw_buf[4])|(raw_buf[5]<<8));
+ }
+ else if(Sensor_Accuracy == MCUBE_1_5G_8BIT)
+ {
+ comres = i2c_smbus_read_i2c_block_data(client, MC3XXX_REG_XOUT, 3, raw_buf1);
+
+ raw_data[MC3XXX_AXIS_X] = (signed short)raw_buf1[0];
+ raw_data[MC3XXX_AXIS_Y] = (signed short)raw_buf1[1];
+ raw_data[MC3XXX_AXIS_Z] = (signed short)raw_buf1[2];
+ }
+#endif
+
+ if((is_new_mc34x0)||(is_mc35xx))
+ {
+ raw_data[MC3XXX_AXIS_X] = -raw_data[MC3XXX_AXIS_X];
+ raw_data[MC3XXX_AXIS_Y] = -raw_data[MC3XXX_AXIS_Y];
+ }
+ else if (is_mc3250)
+ {
+ s16 temp = 0;
+
+ temp = raw_data[MC3XXX_AXIS_X];
+
+ raw_data[MC3XXX_AXIS_X] = raw_data[MC3XXX_AXIS_Y];
+ raw_data[MC3XXX_AXIS_Y] = -temp;
+ }
+ //printk("%s:%d %d %d\n",__FUNCTION__,raw_data[0],raw_data[1],raw_data[2]);
+ acc[MC3XXX_AXIS_X] = pCvt->sign[MC3XXX_AXIS_X] * raw_data[pCvt->map[MC3XXX_AXIS_X]];
+ acc[MC3XXX_AXIS_Y] = pCvt->sign[MC3XXX_AXIS_Y] * raw_data[pCvt->map[MC3XXX_AXIS_Y]];
+ acc[MC3XXX_AXIS_Z] = pCvt->sign[MC3XXX_AXIS_Z] * raw_data[pCvt->map[MC3XXX_AXIS_Z]];
+
+ return comres;
+}
+
+//=============================================================================
+static void mc3xxx_work_func(struct work_struct *work)
+{
+ struct mc3xxx_data *data = &l_sensorconfig;//container_of(work, struct mc3xxx_data, work);
+ //int ret = 0;
+ s16 raw[3] = { 0 };
+
+#ifdef DOT_CALI
+ if( load_cali_flg > 0)
+ {
+ /* ret = mcube_read_cali_file(data->client);
+
+ if(ret == 0)
+ load_cali_flg = ret;
+ else
+ load_cali_flg--;
+
+ GSE_LOG("load_cali %d\n",ret); */
+ MC3XXX_WriteCalibration(data->client,l_sensorconfig.offset);
+ load_cali_flg = 0;
+ }
+#endif
+#if 1
+//gsensor not use when resume
+ if(wake_mc3xxx_flg==1){
+ wake_mc3xxx_flg=0;
+
+
+ mc3xxx_chip_init(data->client);
+ MC3XXX_ResetCalibration(data->client);
+
+ MC3XXX_WriteCalibration(data->client,l_sensorconfig.offset);
+ /*ret =mcube_read_cali_file(data->client);
+ if(ret !=0)
+ printk("*load_cali %d\n",ret); */
+ }
+#endif
+
+ mc3xxx_read_accel_xyz(data->client, &raw[0]);
+ //printk("%s:%d %d %d\n",__FUNCTION__,raw[0],raw[1],raw[2]);
+ input_report_abs(data->input_dev, ABS_X, raw[0]);
+ input_report_abs(data->input_dev, ABS_Y, raw[1]);
+ input_report_abs(data->input_dev, ABS_Z, raw[2]);
+ input_sync(data->input_dev);
+
+ queue_delayed_work(data->mc3xxx_wq, &data->work, msecs_to_jiffies(sample_rate_2_memsec(data->sensor_samp)));
+}
+/*
+//=============================================================================
+static enum hrtimer_restart mc3xxx_timer_func(struct hrtimer *timer)
+{
+ struct mc3xxx_data *data = container_of(timer, struct mc3xxx_data, timer);
+
+ queue_work(data->mc3xxx_wq, &data->work);
+
+ hrtimer_start(&data->timer, ktime_set(0, sensor_duration*1000000), HRTIMER_MODE_REL);
+
+ return HRTIMER_NORESTART;
+}
+*/
+//MCUBE_BACKUP_FILE
+static void mcube_copy_file(const char *dstFilePath)
+{
+ int err =0;
+ initKernelEnv();
+
+ fd_file = openFile(dstFilePath,O_RDWR,0);
+ if (fd_file == NULL)
+ {
+ GSE_LOG("open %s fail\n",dstFilePath);
+ return;
+ }
+
+ if ((err = writeFile(fd_file,backup_buf,64))>0)
+ GSE_LOG("buf:%s\n",backup_buf);
+ else
+ GSE_LOG("write file error %d\n",err);
+
+ set_fs(oldfs); ;
+ closeFile(fd_file);
+
+}
+//MCUBE_BACKUP_FILE
+
+extern int wmt_setsyspara(char *varname, char *varval);
+static void update_var(void)
+{
+ char varbuf[64];
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+
+ sprintf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ (pCvt->map[MC3XXX_AXIS_X]),
+ (pCvt->sign[MC3XXX_AXIS_X]),
+ (pCvt->map[MC3XXX_AXIS_Y]),
+ (pCvt->sign[MC3XXX_AXIS_Y]),
+ (pCvt->map[MC3XXX_AXIS_Z]),
+ (pCvt->sign[MC3XXX_AXIS_Z]),
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+
+ wmt_setsyspara("wmt.io.mc3230sensor",varbuf);
+}
+
+static long wmt_mc3xxx_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ short enable = 0;
+ short delay = 0;
+ unsigned int temp;
+
+ switch (cmd){
+
+ case ECS_IOCTL_APP_SET_AFLAG:
+ // enable/disable sensor
+ if (copy_from_user(&enable, (short*)arg, sizeof(short)))
+ {
+ errlog("Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor. l_sensorconfig.sensor_samp=%d\n", enable, l_sensorconfig.sensor_samp);
+
+ if (enable != l_sensorconfig.sensor_enable)
+ {
+
+ l_sensorconfig.sensor_enable = enable;
+
+ }
+ } else {
+ errlog("Wrong enable argument!!!\n");
+ return -EFAULT;
+ }
+ break;
+ case ECS_IOCTL_APP_SET_DELAY://IOCTL_SENSOR_SET_DELAY_ACCEL:
+ // set the rate of g-sensor
+ if (copy_from_user(&delay,(short*)arg, sizeof(short)))
+ {
+ errlog("Can't get set delay!!!\n");
+ return -EFAULT;
+ }
+ dbg("Get delay=%d \n", delay);
+
+ if ((delay >=0) && (delay < 20))
+ {
+ delay = 20;
+ } else if (delay > 200)
+ {
+ delay = 200;
+ }
+ if (delay > 0)
+ {
+ l_sensorconfig.sensor_samp = 1000/delay;
+ } else {
+ errlog("error delay argument(delay=%d)!!!\n",delay);
+ return -EFAULT;
+ }
+
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ temp = MC3230_DRVID;
+ if (copy_to_user((unsigned int*)arg, &temp, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("mc32x0_driver_id:%d\n",temp);
+ break;
+ case WMT_IOCTL_SENOR_GET_RESOLUTION:
+ if(Sensor_Accuracy &MCUBE_1_5G_8BIT){
+ if(is_mc35xx) //mc3236:8 bit ,+/-2g
+ temp = (8<<8) | 4;
+ else
+ temp = (8<<8) | 3; //mc3230:8 bit ,+/-1.5g
+
+ }
+ if (copy_to_user((unsigned int *)arg, &temp, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ printk("<<<<<<<resolution:0x%x\n",temp);
+ break;
+ default:
+ return -EINVAL;
+ break;
+ }
+ return 0;
+}
+
+
+static long mc3xxx_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ //int intBuf[SENSOR_DATA_SIZE] = { 0 };
+ int ret = 0;
+ float convert_para = 0.0f;
+
+ int prod = -1;
+
+
+#ifdef DOT_CALI
+ void __user *data1 = NULL;
+ char strbuf[256] = { 0 };
+ //int cali[3] = { 0 };
+ SENSOR_DATA sensor_data = { 0 };
+ struct i2c_client *client = container_of(mc3xxx_device.parent, struct i2c_client, dev);
+#endif
+
+ struct mc3xxx_data *data = NULL;
+
+ data = i2c_get_clientdata(client);
+
+ switch (cmd) {
+
+
+/* case IOCTL_SENSOR_SET_DELAY_ACCEL:
+ if(copy_from_user((void *)&sensor_duration, (void __user *) arg, sizeof(short))!=0){
+ printk("copy from error in %s.\n",__func__);
+ }
+
+ break;
+
+ case IOCTL_SENSOR_GET_DELAY_ACCEL:
+ if(copy_to_user((void __user *) arg, (const void *)&sensor_duration, sizeof(short))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+
+ break;
+
+ case IOCTL_SENSOR_GET_STATE_ACCEL:
+ if(copy_to_user((void __user *) arg, (const void *)&sensor_state_flag, sizeof(short))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+
+ break;
+
+ case IOCTL_SENSOR_SET_STATE_ACCEL:
+ if(copy_from_user((void *)&sensor_state_flag, (void __user *) arg, sizeof(short))!=0){
+ printk("copy from error in %s.\n",__func__);
+ }
+
+ break;*/
+ case IOCTL_SENSOR_GET_NAME:
+ if(copy_to_user((void __user *) arg,(const void *)MC3XXX_DISPLAY_NAME, sizeof(MC3XXX_DISPLAY_NAME))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+ break;
+
+ case IOCTL_SENSOR_GET_VENDOR:
+ if(copy_to_user((void __user *) arg,(const void *)MC3XXX_DIPLAY_VENDOR, sizeof(MC3XXX_DIPLAY_VENDOR))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+ break;
+
+ case IOCTL_SENSOR_GET_CONVERT_PARA:
+ convert_para = MC3XXX_CONVERT_PARAMETER;
+ if(copy_to_user((void __user *) arg,(const void *)&convert_para,sizeof(float))!=0){
+ printk("copy to error in %s.\n",__func__);
+ }
+ break;
+
+#ifdef DOT_CALI
+ case GSENSOR_IOCTL_READ_SENSORDATA:
+ case GSENSOR_IOCTL_READ_RAW_DATA:
+ //case GSENSOR_MCUBE_IOCTL_READ_RBM_DATA:
+ GSE_LOG("fwq GSENSOR_IOCTL_READ_RAW_DATA\n");
+
+ //mutex_lock(&data->lock);
+ MC3XXX_ReadRawData(client, strbuf);
+ //mutex_unlock(&data->lock);
+
+ if (copy_to_user((void __user *) arg, &strbuf, strlen(strbuf)+1))
+ {
+ printk("failed to copy sense data to user space.");
+ return -EFAULT;
+ }
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_SET_CALI:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_SET_CALI!!\n");
+ data1 = (void __user *)arg;
+
+ if(data1 == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
+ if(copy_from_user(&sensor_data, data1, sizeof(sensor_data)))
+ {
+ ret = -EFAULT;
+ break;
+ }
+ else
+ {
+ l_sensorconfig.offset[MC3XXX_AXIS_X] = sensor_data.x;
+ l_sensorconfig.offset[MC3XXX_AXIS_Y] = sensor_data.y;
+ l_sensorconfig.offset[MC3XXX_AXIS_Z] = sensor_data.z;
+ update_var();
+ GSE_LOG("GSENSOR_MCUBE_IOCTL_SET_CALI %d %d %d %d %d %d!!\n", l_sensorconfig.offset[MC3XXX_AXIS_X], l_sensorconfig.offset[MC3XXX_AXIS_Y],l_sensorconfig.offset[MC3XXX_AXIS_Z] ,sensor_data.x, sensor_data.y ,sensor_data.z);
+
+ //mutex_lock(&data->lock);
+ ret = MC3XXX_WriteCalibration(client, l_sensorconfig.offset);
+ //mutex_unlock(&data->lock);
+ }
+ break;
+
+ case GSENSOR_IOCTL_CLR_CALI:
+ GSE_LOG("fwq GSENSOR_IOCTL_CLR_CALI!!\n");
+ //mutex_lock(&data->lock);
+ l_sensorconfig.offset[0] = 0;
+ l_sensorconfig.offset[1] = 0;
+ l_sensorconfig.offset[2] = 0;
+
+ update_var();
+ ret = MC3XXX_ResetCalibration(client);
+ //mutex_unlock(&data->lock);
+ break;
+
+ case GSENSOR_IOCTL_GET_CALI:
+ GSE_LOG("fwq mc3xxx GSENSOR_IOCTL_GET_CALI\n");
+
+ data1 = (unsigned char*)arg;
+
+ if(data1 == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ if((ret = MC3XXX_ReadCalibration(client,l_sensorconfig.offset)))
+ {
+ GSE_LOG("fwq mc3xxx MC3XXX_ReadCalibration error!!!!\n");
+ break;
+ }
+
+ sensor_data.x = l_sensorconfig.offset[MC3XXX_AXIS_X];
+ sensor_data.y = l_sensorconfig.offset[MC3XXX_AXIS_Y];
+ sensor_data.z = l_sensorconfig.offset[MC3XXX_AXIS_Z];
+
+ if(copy_to_user(data1, &sensor_data, sizeof(sensor_data)))
+ {
+ ret = -EFAULT;
+ break;
+ }
+ break;
+
+ case GSENSOR_IOCTL_SET_CALI_MODE:
+ GSE_LOG("fwq mc3xxx GSENSOR_IOCTL_SET_CALI_MODE\n");
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_READ_RBM_DATA:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_READ_RBM_DATA\n");
+ data1 = (void __user *) arg;
+ if(data1 == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
+ MC3XXX_ReadRBMData(client,(char *)&strbuf);
+ if(copy_to_user(data1, &strbuf, strlen(strbuf)+1))
+ {
+ ret = -EFAULT;
+ break;
+ }
+ break;
+ case GSENSOR_MCUBE_IOCTL_SET_RBM_MODE:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_SET_RBM_MODE\n");
+ //MCUBE_BACKUP_FILE
+ if(READ_FROM_BACKUP==true)
+ {
+
+ //mcube_copy_file(CALIB_PATH);
+
+ READ_FROM_BACKUP = false;
+ }
+ //MCUBE_BACKUP_FILE
+ //mutex_lock(&data->lock);
+ MC3XXX_rbm(client, 1);
+ //mutex_unlock(&data->lock);
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_CLEAR_RBM_MODE:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_CLEAR_RBM_MODE\n");
+ //mutex_lock(&data->lock);
+ MC3XXX_rbm(client, 0);
+ //mutex_unlock(&data->lock);
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_REGISTER_MAP:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_REGISTER_MAP\n");
+ MC3XXX_ReadRegMap(client, NULL);
+ break;
+
+ case GSENSOR_MCUBE_IOCTL_READ_PRODUCT_ID:
+ GSE_LOG("fwq GSENSOR_MCUBE_IOCTL_READ_PRODUCT_ID\n");
+ data1 = (void __user *) arg;
+ if(data1 == NULL)
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (MC3XXX_RETCODE_SUCCESS != (prod = MC3XX0_ValidateSensorIC(s_bPCODE)))
+ GSE_LOG("Not mCube accelerometers!\n");
+
+ if(copy_to_user(data1, &prod, sizeof(prod)))
+ {
+ GSE_LOG("%s: read pcode fail to copy!\n", __func__);
+ return -EFAULT;
+ }
+ break;
+#endif
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+
+static int mc3xxx_open(struct inode *inode, struct file *filp)
+{
+ return nonseekable_open(inode, filp);
+}
+
+static int mc3xxx_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static int wmt_mc3xxx_open(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static int wmt_mc3xxx_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+
+//=============================================================================
+static struct file_operations sensor_fops =
+{
+ .owner = THIS_MODULE,
+ .open = mc3xxx_open,
+ .release = mc3xxx_release,
+ .unlocked_ioctl = mc3xxx_ioctl,
+};
+
+static struct file_operations wmt_sensor_fops =
+{
+ .owner = THIS_MODULE,
+ .open = wmt_mc3xxx_open,
+ .release = wmt_mc3xxx_release,
+ .unlocked_ioctl = wmt_mc3xxx_ioctl,
+};
+
+
+
+static int sensor_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+
+ //int inputval = -1;
+ int enable, sample = -1;
+ char tembuf[8];
+ //unsigned int amsr = 0;
+ int test = 0;
+
+ mutex_lock(&l_sensorconfig.lock);
+ memset(tembuf, 0, sizeof(tembuf));
+ // get sensor level and set sensor level
+ if (sscanf(buffer, "isdbg=%d\n", &l_sensorconfig.isdbg))
+ {
+ // only set the dbg flag
+ } else if (sscanf(buffer, "samp=%d\n", &sample))
+ {
+ if (sample > 0)
+ {
+ if (sample != l_sensorconfig.sensor_samp)
+ {
+ // should do sth
+ }
+ //printk(KERN_ALERT "sensor samp=%d(amsr:%d) has been set.\n", sample, amsr);
+ } else {
+ klog("Wrong sample argumnet of sensor.\n");
+ }
+ } else if (sscanf(buffer, "enable=%d\n", &enable))
+ {
+ if ((enable < 0) || (enable > 1))
+ {
+ dbg("The argument to enable/disable g-sensor should be 0 or 1 !!!\n");
+ } else if (enable != l_sensorconfig.sensor_enable)
+ {
+ //mma_enable_disable(enable);
+ l_sensorconfig.sensor_enable = enable;
+ }
+ } else if (sscanf(buffer, "sensor_test=%d\n", &test))
+ { // for test begin
+ l_sensorconfig.test_pass = 0;
+ } else if (sscanf(buffer, "sensor_testend=%d\n", &test))
+ { // Don nothing only to be compatible the before testing program
+ }
+ mutex_unlock(&l_sensorconfig.lock);
+ return count;
+}
+
+static int sensor_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "test_pass=%d\nisdbg=%d\nrate=%d\nenable=%d\n",
+ l_sensorconfig.test_pass,
+ l_sensorconfig.isdbg,
+ l_sensorconfig.sensor_samp,
+ l_sensorconfig.sensor_enable
+ );
+ return len;
+}
+
+
+//#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mc3xxx_early_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ /*struct mc3xxx_data *data = NULL;
+
+ data = container_of(handler, struct mc3xxx_data, early_suspend);
+
+ hrtimer_cancel(&data->timer);*/
+
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ mc3xxx_set_mode(l_sensorconfig.client,MC3XXX_STANDBY);
+}
+
+//=============================================================================
+static void mc3xxx_early_resume(struct platform_device *pdev)
+{
+ struct mc3xxx_data *data = &l_sensorconfig;
+
+ wake_mc3xxx_flg =1;
+ //data = container_of(handler, struct mc3xxx_data, early_suspend);
+
+ mc3xxx_set_mode(data->client,MC3XXX_WAKE);
+
+ queue_delayed_work(data->mc3xxx_wq, &data->work, msecs_to_jiffies(sample_rate_2_memsec(data->sensor_samp)));
+ //hrtimer_start(&data->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+}
+//#endif
+
+//=============================================================================
+static struct miscdevice mc3xxx_device =
+{
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = SENSOR_NAME,
+ .fops = &sensor_fops,
+};
+
+static struct miscdevice mc3xxx_wmt_device =
+{
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "sensor_ctrl",
+ .fops = &wmt_sensor_fops,
+};
+
+
+
+/*****************************************
+ *** MC3XX0_ValidateSensorIC
+ *****************************************/
+static int MC3XX0_ValidateSensorIC(unsigned char bPCode)
+{
+ unsigned char _baOurSensorList[] = { MC3XXX_PCODE_3210 , MC3XXX_PCODE_3230 ,
+ MC3XXX_PCODE_3250 ,
+ MC3XXX_PCODE_3410 , MC3XXX_PCODE_3430 ,
+ MC3XXX_PCODE_3410N, MC3XXX_PCODE_3430N,
+ MC3XXX_PCODE_3510B, MC3XXX_PCODE_3530B,
+ MC3XXX_PCODE_3510C, MC3XXX_PCODE_3530C
+ };
+
+ int _nSensorCount = (sizeof(_baOurSensorList) / sizeof(_baOurSensorList[0]));
+ int _nCheckIndex = 0;
+
+ GSE_LOG("[%s] code to be verified: 0x%X, _nSensorCount: %d\n", __FUNCTION__, bPCode, _nSensorCount);
+
+ for (_nCheckIndex = 0; _nCheckIndex < _nSensorCount; _nCheckIndex++)
+ {
+ if (_baOurSensorList[_nCheckIndex] == bPCode)
+ return (MC3XXX_RETCODE_SUCCESS);
+ }
+
+ if (MC3XXX_PCODE_3530C == (bPCode | 0x0E))
+ return (MC3XXX_RETCODE_SUCCESS);
+
+ return (MC3XXX_RETCODE_ERROR_IDENTIFICATION);
+}
+
+/*****************************************
+ *** _mc3xxx_i2c_auto_probe
+ *****************************************/
+static int _mc3xxx_i2c_auto_probe(struct i2c_client *client)
+{
+ unsigned char _baDataBuf[2] = {0};
+ int _nProbeAddrCount = (sizeof(mc3xxx_i2c_auto_probe_addr) / sizeof(mc3xxx_i2c_auto_probe_addr[0]));
+ int _nCount = 0;
+ int _nCheckCount = 0;
+
+ //GSE_FUN();
+
+ s_bPCODE = 0x00;
+
+ for (_nCount = 0; _nCount < _nProbeAddrCount; _nCount++)
+ {
+ _nCheckCount = 0;
+ client->addr = mc3xxx_i2c_auto_probe_addr[_nCount];
+
+ //GSE_LOG("[%s] probing addr: 0x%X\n", __FUNCTION__, client->addr);
+
+_I2C_AUTO_PROBE_RECHECK_:
+ _baDataBuf[0] = MC3XXX_REG_PRODUCT_CODE;
+ if (0 > i2c_master_send(client, &(_baDataBuf[0]), 1))
+ {
+ //GSE_ERR("ERR: addr: 0x%X fail to communicate-2!\n", client->addr);
+ continue;
+ }
+
+ if (0 > i2c_master_recv(client, &(_baDataBuf[0]), 1))
+ {
+ //GSE_ERR("ERR: addr: 0x%X fail to communicate-3!\n", client->addr);
+ continue;
+ }
+
+ _nCheckCount++;
+
+ //GSE_LOG("[%s][%d] addr: 0x%X ok to read REG(0x3B): 0x%X\n", __FUNCTION__, _nCheckCount, client->addr, _baDataBuf[0]);
+
+ if (0x00 == _baDataBuf[0])
+ {
+ if (1 == _nCheckCount)
+ {
+ MC3XXX_Reset(client);
+ goto _I2C_AUTO_PROBE_RECHECK_;
+ }
+ }
+
+ if (MC3XXX_RETCODE_SUCCESS == MC3XX0_ValidateSensorIC(_baDataBuf[0]))
+ {
+ //GSE_LOG("[%s] addr: 0x%X confirmed ok to use.\n", __FUNCTION__, client->addr);
+
+ s_bPCODE = _baDataBuf[0];
+
+ return (MC3XXX_RETCODE_SUCCESS);
+ }
+ }
+
+ return (MC3XXX_RETCODE_ERROR_I2C);
+}
+
+
+//=============================================================================
+//static int mc3xxx_probe(struct i2c_client *client,
+// const struct i2c_device_id *id)
+static int mc3xxx_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ //int product_code = 0;
+ struct mc3xxx_data *data = &l_sensorconfig;
+ struct i2c_client *client = l_sensorconfig.client;
+
+ #ifdef DOT_CALI
+ load_cali_flg = 30;
+ #endif
+/*
+ if (MC3XXX_RETCODE_SUCCESS != _mc3xxx_i2c_auto_probe(client))
+ {
+ GSE_ERR("ERR: fail to probe mCube sensor!\n");
+ goto err_check_functionality_failed;
+ }
+
+ data = kzalloc(sizeof(struct mc3xxx_data), GFP_KERNEL);
+ if(data == NULL)
+ {
+ ret = -ENOMEM;
+ goto err_alloc_data_failed;
+ }
+*/
+ data->sensor_proc = create_proc_entry(GSENSOR_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (data->sensor_proc != NULL)
+ {
+ data->sensor_proc->write_proc = sensor_writeproc;
+ data->sensor_proc->read_proc = sensor_readproc;
+ }
+
+ data->mc3xxx_wq = create_singlethread_workqueue("mc3xxx_wq");
+ if (!data->mc3xxx_wq )
+ {
+ ret = -ENOMEM;
+ goto err_create_workqueue_failed;
+ }
+ INIT_DELAYED_WORK(&data->work, mc3xxx_work_func);
+ mutex_init(&data->lock);
+
+ //sensor_duration = SENSOR_DURATION_DEFAULT;
+ //sensor_state_flag = 1;
+
+
+ data->client = client;
+ dev.client=client;
+
+ i2c_set_clientdata(client, data);
+
+ data->input_dev = input_allocate_device();
+ if (!data->input_dev) {
+ ret = -ENOMEM;
+ goto exit_input_dev_alloc_failed;
+ }
+
+ #ifdef DOT_CALI
+ MC3XXX_Reset(client);
+ #endif
+
+ ret = mc3xxx_chip_init(client);
+ if (ret < 0) {
+ goto err_chip_init_failed;
+ }
+
+ set_bit(EV_ABS, data->input_dev->evbit);
+ data->map[0] = G_0;
+ data->map[1] = G_1;
+ data->map[2] = G_2;
+ data->inv[0] = G_0_REVERSE;
+ data->inv[1] = G_1_REVERSE;
+ data->inv[2] = G_2_REVERSE;
+
+ input_set_abs_params(data->input_dev, ABS_X, -32*8, 32*8, INPUT_FUZZ, INPUT_FLAT);
+ input_set_abs_params(data->input_dev, ABS_Y, -32*8, 32*8, INPUT_FUZZ, INPUT_FLAT);
+ input_set_abs_params(data->input_dev, ABS_Z, -32*8, 32*8, INPUT_FUZZ, INPUT_FLAT);
+
+ data->input_dev->name = "g-sensor";
+
+ ret = input_register_device(data->input_dev);
+ if (ret) {
+ goto exit_input_register_device_failed;
+ }
+
+ mc3xxx_device.parent = &client->dev;
+
+ ret = misc_register(&mc3xxx_device);
+ if (ret) {
+ goto exit_misc_device_register_failed;
+ }
+
+ ret = misc_register(&mc3xxx_wmt_device);
+ if (ret) {
+ goto exit_misc_device_register_failed;
+ }
+
+ ret = sysfs_create_group(&data->input_dev->dev.kobj, &mc3xxx_group);
+/*
+ if (!data->use_irq){
+ hrtimer_init(&data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ data->timer.function = mc3xxx_timer_func;
+ //hrtimer_start(&data->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
+ }
+*/
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ data->early_suspend.suspend = mc3xxx_early_suspend;
+ data->early_suspend.resume = mc3xxx_early_resume;
+ register_early_suspend(&data->early_suspend);
+#endif
+ data->enabled = 1;
+ queue_delayed_work(data->mc3xxx_wq, &data->work, msecs_to_jiffies(sample_rate_2_memsec(data->sensor_samp)));
+ //strcpy(mc3xxx_on_off_str,"gsensor_int2");
+ //gpio_set_one_pin_io_status(mc3xxx_pin_hd,0,mc3xxx_on_off_str);
+
+ printk("mc3xxx probe ok \n");
+
+ return 0;
+exit_misc_device_register_failed:
+exit_input_register_device_failed:
+ input_free_device(data->input_dev);
+err_chip_init_failed:
+exit_input_dev_alloc_failed:
+ destroy_workqueue(data->mc3xxx_wq);
+err_create_workqueue_failed:
+ kfree(data);
+//err_alloc_data_failed:
+//err_check_functionality_failed:
+ printk("mc3xxx probe failed \n");
+ return ret;
+
+}
+
+//static int mc3xxx_remove(struct i2c_client *client)
+static int mc3xxx_remove(struct platform_device *pdev)
+{
+ /*struct mc3xxx_data *data = i2c_get_clientdata(client);
+
+ hrtimer_cancel(&data->timer);
+ input_unregister_device(data->input_dev);
+// gpio_release(mc3xxx_pin_hd, 2);
+ misc_deregister(&mc3xxx_device);
+ sysfs_remove_group(&data->input_dev->dev.kobj, &mc3xxx_group);
+ kfree(data);
+ return 0;*/
+
+ if (NULL != l_sensorconfig.mc3xxx_wq)
+ {
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ flush_workqueue(l_sensorconfig.mc3xxx_wq);
+ destroy_workqueue(l_sensorconfig.mc3xxx_wq);
+ l_sensorconfig.mc3xxx_wq = NULL;
+ }
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ remove_proc_entry(GSENSOR_PROC_NAME, NULL);
+ l_sensorconfig.sensor_proc = NULL;
+ }
+ misc_deregister(&mc3xxx_device);
+ misc_deregister(&mc3xxx_wmt_device);
+ sysfs_remove_group(&l_sensorconfig.input_dev->dev.kobj, &mc3xxx_group);
+ input_unregister_device(l_sensorconfig.input_dev);
+ return 0;
+}
+
+//=============================================================================
+/*
+static void mc3xxx_shutdown(struct i2c_client *client)
+{
+ struct mc3xxx_data *data = i2c_get_clientdata(client);
+
+ if(data->enabled)
+ mc3xxx_enable(data, 0);
+}
+*/
+
+//=============================================================================
+
+static const struct i2c_device_id mc3xxx_id[] =
+{
+ { SENSOR_NAME, 0 },
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, mc3xxx_id);
+/*
+static struct i2c_driver mc3xxx_driver =
+{
+ .class = I2C_CLASS_HWMON,
+
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = SENSOR_NAME,
+ },
+ .id_table = mc3xxx_id,
+ .probe = mc3xxx_probe,
+ .remove = mc3xxx_remove,
+ //.shutdown = mc3xxx_shutdown,
+};
+*/
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static int get_axisset(void)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+ //int tmpoff[3] = {0};
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+
+ pCvt = (struct mc3xx0_hwmsen_convert *)kzalloc(sizeof(struct mc3xx0_hwmsen_convert), GFP_KERNEL);
+
+ if (wmt_getsyspara("wmt.io.mc3230.virtualz", varbuf, &varlen)) {
+ errlog("Can't get gsensor config in u-boot!!!!\n");
+ //return -1;
+ } else {
+ sscanf(varbuf, "%d", &g_virtual_z);
+
+ }
+ printk("%s g_virtual_z %d\n", __FUNCTION__, g_virtual_z);
+ memset(varbuf, 0, sizeof(varbuf));
+ if (wmt_getsyspara("wmt.io.mc3230sensor", varbuf, &varlen)) {
+ errlog("Can't get gsensor config in u-boot!!!!\n");
+ return -1; //open it for no env just,not insmod such module 2014-6-30
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &l_sensorconfig.op,
+ &l_sensorconfig.int_gpio,
+ &l_sensorconfig.samp,
+ &(pCvt->map[MC3XXX_AXIS_X]),
+ &(pCvt->sign[MC3XXX_AXIS_X]),
+ &(pCvt->map[MC3XXX_AXIS_Y]),
+ &(pCvt->sign[MC3XXX_AXIS_Y]),
+ &(pCvt->map[MC3XXX_AXIS_Z]),
+ &(pCvt->sign[MC3XXX_AXIS_Z]),
+ &(l_sensorconfig.offset[0]),
+ &(l_sensorconfig.offset[1]),
+ &(l_sensorconfig.offset[2])
+ );
+ if (n != 12) {
+ printk(KERN_ERR "gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+ l_sensorconfig.sensor_samp = l_sensorconfig.samp;
+
+
+ dbg("get the sensor config: %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ pCvt->map[MC3XXX_AXIS_X],
+ pCvt->sign[MC3XXX_AXIS_X],
+ pCvt->map[MC3XXX_AXIS_Y],
+ pCvt->sign[MC3XXX_AXIS_Y],
+ pCvt->map[MC3XXX_AXIS_Z],
+ pCvt->sign[MC3XXX_AXIS_Z],
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+ }
+ return 0;
+}
+
+static void mc3xxx_platform_release(struct device *device)
+{
+ return;
+}
+
+
+static struct platform_device mc3xxx_pdevice = {
+ .name = SENSOR_NAME,
+ .id = 0,
+ .dev = {
+ .release = mc3xxx_platform_release,
+ },
+};
+
+static struct platform_driver mc3xxx_pdriver = {
+ .probe = mc3xxx_probe,
+ .remove = mc3xxx_remove,
+ .suspend = mc3xxx_early_suspend,
+ .resume = mc3xxx_early_resume,
+ //.shutdown = mc3xxx_shutdown,
+ .driver = {
+ .name = SENSOR_NAME,
+ },
+};
+
+
+static int __init mc3xxx_init(void)
+{
+ int ret = -1;
+ struct i2c_client *this_client;
+ printk("mc3xxx: init\n");
+
+ //ret = i2c_add_driver(&mc3xxx_driver);
+
+ // parse g-sensor u-boot arg
+ ret = get_axisset();
+ if (ret < 0)
+ {
+ printk("<<<<<%s user choose to no sensor chip!\n", __func__);
+ return ret;
+ }
+
+ if (!(this_client = sensor_i2c_register_device(0, mc3xxx_i2c_auto_probe_addr[0], SENSOR_NAME)))
+ {
+ printk(KERN_ERR"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+
+ if (MC3XXX_RETCODE_SUCCESS != _mc3xxx_i2c_auto_probe(this_client))
+ {
+ GSE_ERR("ERR: fail to auto_probe mCube sensor!\n");
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+ }
+
+
+ l_sensorconfig.client = this_client;
+
+ l_dev_class = class_create(THIS_MODULE, SENSOR_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create gsensor device !!\n");
+ return ret;
+ }
+ if((ret = platform_device_register(&mc3xxx_pdevice)))
+ {
+ klog("Can't register mc3xxx platform devcie!!!\n");
+ return ret;
+ }
+ if ((ret = platform_driver_register(&mc3xxx_pdriver)) != 0)
+ {
+ errlog("Can't register mc3xxx platform driver!!!\n");
+ return ret;
+ }
+
+
+ return ret;
+}
+
+static void __exit mc3xxx_exit(void)
+{
+ //i2c_del_driver(&mc3xxx_driver);
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ unregister_early_suspend(&l_sensorconfig.earlysuspend);
+#endif
+ platform_driver_unregister(&mc3xxx_pdriver);
+ platform_device_unregister(&mc3xxx_pdevice);
+ sensor_i2c_unregister_device(l_sensorconfig.client);
+ class_destroy(l_dev_class);
+}
+
+//=============================================================================
+module_init(mc3xxx_init);
+module_exit(mc3xxx_exit);
+
+MODULE_DESCRIPTION("mc3xxx accelerometer driver");
+MODULE_AUTHOR("mCube-inc");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SENSOR_DRIVER_VERSION);
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mma7660_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/mma7660_gsensor/Makefile
new file mode 100755
index 00000000..99ecc6a1
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mma7660_gsensor/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_gsensor_mma7660
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := mma7660.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mma7660_gsensor/mma7660.c b/ANDROID_3.4.5/drivers/input/sensor/mma7660_gsensor/mma7660.c
new file mode 100755
index 00000000..f0a0b1ee
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mma7660_gsensor/mma7660.c
@@ -0,0 +1,1052 @@
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/miscdevice.h>
+#include <linux/gpio.h>
+#include <asm/uaccess.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/freezer.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <mach/hardware.h>
+#include "mma7660.h"
+
+
+//#define DEBUG 1
+
+#undef dbg
+
+//#if 0
+ #define dbg(fmt, args...) if (l_sensorconfig.isdbg) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+ //#define dbg(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+#define klog(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+ //#define dbg(format, arg...) printk(KERN_ALERT format, ## arg)
+
+
+//#else
+// #define dbg(format, arg...)
+//#endif
+
+/////////////////////Macro constant
+#define SENSOR_POLL_WAIT_TIME 1837
+#define MAX_FAILURE_COUNT 10
+#define MMA7660_ADDR 0x4C
+#define LAND_PORT_MASK 0x1C
+#define LAND_LEFT 0x1
+#define LAND_RIGHT 0x2
+#define PORT_INVERT 0x5
+#define PORT_NORMAL 0x6
+
+#define LANDSCAPE_LOCATION 0
+#define PORTRAIT_LOCATION 1
+
+#define SENSOR_UI_MODE 0
+#define SENSOR_GRAVITYGAME_MODE 1
+
+#define UI_SAMPLE_RATE 0xFC
+
+#define GSENSOR_PROC_NAME "gsensor_config"
+#define GSENSOR_MAJOR 161
+#define GSENSOR_NAME "mma7660"
+#define GSENSOR_DRIVER_NAME "mma7660_drv"
+
+
+#define sin30_1000 500
+#define cos30_1000 866
+
+#define DISABLE 0
+#define ENABLE 1
+
+////////////////////////the rate of g-sensor/////////////////////////////////////////////
+#define SENSOR_DELAY_FASTEST 0
+#define SENSOR_DELAY_GAME 20
+#define SENSOR_DELAY_UI 60
+#define SENSOR_DELAY_NORMAL 200
+
+#define FASTEST_MMA_AMSR 0 // 120 samples/sec
+#define GAME_MMA_AMSR 1 // 1, (64, samples/sec)
+#define UI_MMA_AMSR 3 // 2, 3,4, (16, 8,32 samples/sec)
+#define NORMAL_MMA_AMSR 5 // 5, 6, 7 (4, 2, 1 samples/sec)
+
+/////////////////////////////////////////////////////////////////////////
+static int xyz_g_table[64] = {
+0,47,94,141,188,234,281,328,
+375,422,469,516,563,609,656,703,
+750,797,844,891,938,984,1031,1078,
+1125,1172,1219,1266,1313,1359,1406,1453,
+-1500,-1453,-1406,-1359,-1313,-1266,-1219,-1172,
+-1125,-1078,-1031,-984,-938,-891,-844,-797,
+-750,-703,-656,-609,-563,-516,-469,-422,
+-375,-328,-281,-234,-188,-141,-94,-47
+};
+
+static struct platform_device *this_pdev;
+
+static struct class* l_dev_class = NULL;
+static struct device *l_clsdevice = NULL;
+
+
+
+struct mma7660_config
+{
+ int op;
+ int int_gpio; //0-3
+ int xyz_axis[3][2]; // (axis,direction)
+ int rxyz_axis[3][2];
+ int irq;
+ struct proc_dir_entry* sensor_proc;
+ int sensorlevel;
+ int shake_enable; // 1--enable shake, 0--disable shake
+ int manual_rotation; // 0--landance, 90--vertical
+ struct input_dev *input_dev;
+ //struct work_struct work;
+ struct delayed_work work; // for polling
+ struct workqueue_struct *queue;
+ int isdbg; // 0-- no debug log, 1--show debug log
+ int sensor_samp; // 1,2,4,8,16,32,64,120
+ int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor
+ int test_pass;
+ spinlock_t spinlock;
+ int pollcnt; // the counts of polling
+ int offset[3];
+};
+
+static struct mma7660_config l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },
+ .irq = 6,
+ .int_gpio = 3,
+ .sensor_proc = NULL,
+ .sensorlevel = SENSOR_GRAVITYGAME_MODE,
+ .shake_enable = 0, // default enable shake
+ .isdbg = 0,
+ .sensor_samp = 10, // 4sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ .pollcnt = 0, // Don't report the x,y,z when the driver is loaded until 2~3 seconds
+ .offset = {0,0,0},
+};
+
+
+static struct timer_list l_polltimer; // for shaking
+static int is_sensor_good = 0; // 1-- work well, 0 -- exception
+struct work_struct poll_work;
+static struct mutex sense_data_mutex;
+static int revision = -1;
+static int l_resumed = 0; // 1: suspend --> resume;2: suspend but not resumed; other values have no meaning
+
+//////////////////Macro function//////////////////////////////////////////////////////
+
+#define SET_MMA_SAMPLE(buf,samp) { \
+ buf[0] = 0; \
+ sensor_i2c_write(MMA7660_ADDR,7,buf,1); \
+ buf[0] = samp; \
+ sensor_i2c_write(MMA7660_ADDR,8,buf,1); \
+ buf[0] = 0x01; \
+ sensor_i2c_write(MMA7660_ADDR,7,buf,1); \
+}
+
+////////////////////////Function define/////////////////////////////////////////////////////////
+
+static unsigned int mma_sample2AMSR(unsigned int samp);
+
+////////////////////////Function implement/////////////////////////////////////////////////
+// rate: 1,2,4,8,16,32,64,120
+static unsigned int sample_rate_2_memsec(unsigned int rate)
+{
+ return (1000/rate);
+}
+
+
+
+static ssize_t gsensor_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+
+ sprintf(buf, "MMA7660_%#x\n", revision);
+ ret = strlen(buf) + 1;
+
+ return ret;
+}
+
+static DEVICE_ATTR(vendor, 0444, gsensor_vendor_show, NULL);
+
+static struct kobject *android_gsensor_kobj;
+static int gsensor_sysfs_init(void)
+{
+ int ret ;
+
+ android_gsensor_kobj = kobject_create_and_add("android_gsensor", NULL);
+ if (android_gsensor_kobj == NULL) {
+ printk(KERN_ERR
+ "mma7660 gsensor_sysfs_init:"\
+ "subsystem_register failed\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ret = sysfs_create_file(android_gsensor_kobj, &dev_attr_vendor.attr);
+ if (ret) {
+ printk(KERN_ERR
+ "mma7660 gsensor_sysfs_init:"\
+ "sysfs_create_group failed\n");
+ goto err4;
+ }
+
+ return 0 ;
+err4:
+ kobject_del(android_gsensor_kobj);
+err:
+ return ret ;
+}
+
+static int gsensor_sysfs_exit(void)
+{
+ sysfs_remove_file(android_gsensor_kobj, &dev_attr_vendor.attr);
+ kobject_del(android_gsensor_kobj);
+ return 0;
+}
+
+//extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num, int bus_id);
+extern int i2c_api_do_send(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size);
+extern int i2c_api_do_recv(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size);
+
+int sensor_i2c_write(unsigned int addr,unsigned int index,char *pdata,int len)
+{
+ /*struct i2c_msg msg[1];
+ unsigned char buf[len+1];
+
+ //addr = (addr >> 1);
+ buf[0] = index;
+ memcpy(&buf[1],pdata,len);
+ msg[0].addr = addr;
+ msg[0].flags = 0 ;
+ msg[0].flags &= ~(I2C_M_RD);
+ msg[0].len = len+1;
+ msg[0].buf = buf;
+//tmp sensor_i2c_do_xfer(msg,1);
+ if (wmt_i2c_xfer_continue_if_4(msg,1,0) <= 0)
+ {
+ klog("write error!\n");
+ return -1;
+ }*/
+ int ret;
+ ret = i2c_api_do_send(0, addr, index, pdata, len);
+ if (ret <= 0) {
+ klog("i2c_api_do_send error!\n");
+ return -1;
+ }
+
+#ifdef DEBUG
+{
+ int i;
+
+ printk("sensor_i2c_write(addr 0x%x,index 0x%x,len %d\n",addr,index,len);
+ for(i=0;i<len;i+=8){
+ printk("%d : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",i,
+ pdata[i],pdata[i+1],pdata[i+2],pdata[i+3],pdata[i+4],pdata[i+5],pdata[i+6],pdata[i+7]);
+ }
+}
+#endif
+ return 0;
+} /* End of sensor_i2c_write */
+
+int sensor_i2c_read(unsigned int addr,unsigned int index,char *pdata,int len)
+{
+ /*struct i2c_msg msg[2];
+ unsigned char buf[len+1];
+ int ret = 0;
+
+ //addr = (addr >> 1);
+ memset(buf,0x55,len+1);
+ buf[0] = index;
+ buf[1] = 0x0;
+
+ msg[0].addr = addr;
+ msg[0].flags = 0 ;
+ msg[0].flags &= ~(I2C_M_RD);
+ msg[0].len = 1;
+ msg[0].buf = buf;
+
+ msg[1].addr = addr;
+ msg[1].flags = 0 ;
+ msg[1].flags |= (I2C_M_RD);
+ msg[1].len = len;
+ msg[1].buf = buf;
+
+ //tmp sensor_i2c_do_xfer(msg, 2);
+ ret = wmt_i2c_xfer_continue_if_4(msg, 2,0);
+ if (ret < 0)
+ {
+ klog("read error!\n");
+ return ret;
+ }
+
+ memcpy(pdata,buf,len);*/
+ int ret;
+ ret = i2c_api_do_recv(0, addr, index, pdata, len);
+ if (ret <= 0) {
+ klog("i2c_api_do_recv error!\n");
+ return -1;
+ }
+#ifdef DEBUG
+{
+ int i;
+
+ printk("sensor_i2c_read(addr 0x%x,index 0x%x,len %d\n",addr,index,len);
+ for(i=0;i<len;i+=8){
+ printk("%d : 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",i,
+ pdata[i],pdata[i+1],pdata[i+2],pdata[i+3],pdata[i+4],pdata[i+5],pdata[i+6],pdata[i+7]);
+ }
+}
+#endif
+ return 0;
+} /* End of sensor_i2c_read */
+
+void mma7660_chip_init(void)
+{
+ char txData[1];
+ char amsr = 0;
+
+ // the default mode is for UI
+ txData[0]=0;
+ sensor_i2c_write(MMA7660_ADDR,7,txData,1);
+ txData[0] = 0;
+ sensor_i2c_write(MMA7660_ADDR,5,txData,1);
+ //txData[0] = (1 == l_sensorconfig.shake_enable) ? 0xF0:0x10;
+ txData[0] = 0; // disable all int ,for polling
+ sensor_i2c_write(MMA7660_ADDR,6,txData,1);
+ amsr = 0;// 8 - i;
+ txData[0] = 0xF8 | amsr;
+ dbg("G-Sensor: SR = 0x%X\n", txData[0]);
+ sensor_i2c_write(MMA7660_ADDR,8,txData,1);
+ txData[0] = 0x01; // for polling
+ sensor_i2c_write(MMA7660_ADDR,7,txData,1);
+ return;
+}
+
+static unsigned int mma_sample2AMSR(unsigned int samp)
+{
+ int i = 0;
+ unsigned int amsr;
+
+ if (samp >= 120)
+ {
+ return 0;
+ }
+ while (samp)
+ {
+ samp = samp >> 1;
+ i++;
+ }
+ amsr = 8 - i;
+ return amsr;
+}
+
+static int mma_enable_disable(int enable)
+{
+ char buf[1];
+
+ // disable all interrupt of g-sensor
+ memset(buf, 0, sizeof(buf));
+ if ((enable < 0) || (enable > 1))
+ {
+ return -1;
+ }
+ buf[0] = 0;
+ sensor_i2c_write(MMA7660_ADDR,7,buf,1);
+ if (enable != 0)
+ {
+ buf[0] = (1 == l_sensorconfig.shake_enable) ? 0xF0:0x10;
+ } else {
+ buf[0] = 0;
+ }
+ sensor_i2c_write(MMA7660_ADDR,6,buf,1);
+ buf[0] = 0xf9;
+ sensor_i2c_write(MMA7660_ADDR,7,buf,1);
+ return 0;
+}
+
+// To contol the g-sensor for UI
+static int mmad_open(struct inode *inode, struct file *file)
+{
+ dbg("Open the g-sensor node...\n");
+ return 0;
+}
+
+static int mmad_release(struct inode *inode, struct file *file)
+{
+ dbg("Close the g-sensor node...\n");
+ return 0;
+}
+
+static /*int*/ long
+mmad_ioctl(/*struct inode *inode,*/ struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ char rwbuf[5];
+ short delay, enable; //amsr = -1;
+ unsigned int uval = 0;
+ int i = 0;
+ unsigned char rxData[3] = {0};
+ int intBuf[3] = {0};
+ dbg("g-sensor ioctr...\n");
+ memset(rwbuf, 0, sizeof(rwbuf));
+ switch (cmd) {
+ case ECS_IOCTL_APP_SET_DELAY:
+ // set the rate of g-sensor
+ if (copy_from_user(&delay, argp, sizeof(short)))
+ {
+ printk(KERN_ALERT "Can't get set delay!!!\n");
+ return -EFAULT;
+ }
+ klog("Get delay=%d\n", delay);
+ //klog("before change sensor sample:%d...\n", l_sensorconfig.sensor_samp);
+ if ((delay >=0) && (delay < 20))
+ {
+ delay = 20;
+ } else if (delay > 200)
+ {
+ delay = 200;
+ }
+ l_sensorconfig.sensor_samp = 1000/delay;
+
+ break;
+ case ECS_IOCTL_APP_SET_AFLAG:
+ // enable/disable sensor
+ if (copy_from_user(&enable, argp, sizeof(short)))
+ {
+ printk(KERN_ERR "Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ klog("enable=%d\n",enable);
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor.\n", enable);
+
+ l_sensorconfig.sensor_enable = enable;
+
+ } else {
+ printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ uval = MMA7660_DRVID;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("mma7660_driver_id:%d\n",uval);
+ break;
+ case ECS_IOCTL_APP_READ_XYZ:
+ sensor_i2c_read(MMA7660_ADDR,0,rxData,3);
+
+ for (i=0; i < 3; i++)
+ {
+ if (rxData[i]&0x40) break;
+ }
+ //if (l_sensorconfig.pollcnt >= 20)
+ if (3 == i)
+ {
+ intBuf[0] = xyz_g_table[rxData[l_sensorconfig.xyz_axis[0][0]]]*l_sensorconfig.xyz_axis[0][1];
+ intBuf[1] = xyz_g_table[rxData[l_sensorconfig.xyz_axis[1][0]]]*l_sensorconfig.xyz_axis[1][1];
+ intBuf[2] = xyz_g_table[rxData[l_sensorconfig.xyz_axis[2][0]]]*l_sensorconfig.xyz_axis[2][1];
+
+ if (copy_to_user((unsigned int*)arg, intBuf, sizeof(intBuf)))
+ {
+ return -EFAULT;
+ }
+ }
+ break;
+ }
+
+
+
+ return 0;
+}
+
+
+static void mma_work_func(struct work_struct *work)
+{
+ struct mma7660_config *data;
+ unsigned char rxData[3];
+ //unsigned char tiltval = 0;
+ int i = 0;
+ int x,y,z;
+
+ dbg("enter...\n");
+ data = dev_get_drvdata(&this_pdev->dev);
+ if (!l_sensorconfig.sensor_enable)
+ {
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+ return;
+ }
+ mutex_lock(&sense_data_mutex);
+ is_sensor_good = 1; // for watchdog
+ l_sensorconfig.test_pass = 1; // for testing
+
+ /*sensor_i2c_read(MMA7660_ADDR,3,rxData,1);
+ tiltval = rxData[0];
+ if (tiltval & 0x80) {
+ if (1 == l_sensorconfig.shake_enable) {
+ printk(KERN_NOTICE "shake!!!\n");
+ input_report_key(data->input_dev, KEY_NEXTSONG, 1);
+ input_report_key(data->input_dev, KEY_NEXTSONG, 0);
+ input_sync(data->input_dev);
+
+ }
+ } else*/ {
+ sensor_i2c_read(MMA7660_ADDR,0,rxData,3);
+ /* dbg(KERN_DEBUG "Angle: x=%d, y=%d, z=%d\n",
+ xy_degree_table[rxData[0]],
+ xy_degree_table[rxData[1]],
+ z_degree_table[rxData[2]]);
+ dbg(KERN_DEBUG "G value: x=%d, y=%d, z=%d\n",
+ xyz_g_table[rxData[0]],
+ xyz_g_table[rxData[1]],
+ xyz_g_table[rxData[2]]);
+ */
+ for (i=0; i < 3; i++)
+ {
+ if (rxData[i]&0x40) break;
+ }
+ //if (l_sensorconfig.pollcnt >= 20)
+ if (3 == i)
+ {
+ x = xyz_g_table[rxData[l_sensorconfig.xyz_axis[0][0]]]*l_sensorconfig.xyz_axis[0][1];
+ y = xyz_g_table[rxData[l_sensorconfig.xyz_axis[1][0]]]*l_sensorconfig.xyz_axis[1][1];
+ z = xyz_g_table[rxData[l_sensorconfig.xyz_axis[2][0]]]*l_sensorconfig.xyz_axis[2][1];
+ input_report_abs(data->input_dev, ABS_X, x);
+ input_report_abs(data->input_dev, ABS_Y, y);
+ input_report_abs(data->input_dev, ABS_Z, z);
+ input_sync(data->input_dev);
+ dbg("gx=%x,gy=%x,gz=%x\n",x,y,z);
+ }
+ }
+ //gsensor_int_ctrl(ENABLE);
+ mutex_unlock(&sense_data_mutex);
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+}
+
+static int sensor_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+
+ int inputval = -1;
+ int enable, sample = -1;
+ char tembuf[8];
+ unsigned int amsr = 0;
+ int test = 0;
+
+ mutex_lock(&sense_data_mutex);
+ // disable int
+ //gsensor_int_ctrl(DISABLE);
+ memset(tembuf, 0, sizeof(tembuf));
+ // get sensor level and set sensor level
+ if (sscanf(buffer, "level=%d\n", &l_sensorconfig.sensorlevel))
+ {
+ } else if (sscanf(buffer, "shakenable=%d\n", &l_sensorconfig.shake_enable))
+ {
+ /*
+ regval[0] = 0;
+ sensor_i2c_write(MMA7660_ADDR,7,regval,1); // standard mode
+ sensor_i2c_read(MMA7660_ADDR,6,regval,1);
+ switch (l_sensorconfig.shake_enable)
+ {
+ case 0: // disable shake
+ regval[0] &= 0x1F;
+ sensor_i2c_write(MMA7660_ADDR,6, regval,1);
+ dbg("Shake disable!!\n");
+ break;
+ case 1: // enable shake
+ regval[0] |= 0xE0;
+ sensor_i2c_write(MMA7660_ADDR,6, regval,1);
+ dbg("Shake enable!!\n");
+ break;
+ };
+ sensor_i2c_write(MMA7660_ADDR,7,&oldval,1);
+ */
+ } /*else if (sscanf(buffer, "rotation=%d\n", &l_sensorconfig.manual_rotation))
+ {
+ switch (l_sensorconfig.manual_rotation)
+ {
+ case 90:
+ // portrait
+ input_report_abs(mma7660data->input_dev, ABS_X, cos30_1000);
+ input_report_abs(mma7660data->input_dev, ABS_Y, 0);
+ input_report_abs(mma7660data->input_dev, ABS_Z, sin30_1000);
+ input_sync(mma7660data->input_dev);
+ break;
+ case 0:
+ // landscape
+ input_report_abs(mma7660data->input_dev, ABS_X, 0);
+ input_report_abs(mma7660data->input_dev, ABS_Y, cos30_1000);
+ input_report_abs(mma7660data->input_dev, ABS_Z, sin30_1000);
+ input_sync(mma7660data->input_dev);
+ break;
+ };
+ }*/ else if (sscanf(buffer, "isdbg=%d\n", &l_sensorconfig.isdbg))
+ {
+ // only set the dbg flag
+ } else if (sscanf(buffer, "init=%d\n", &inputval))
+ {
+ mma7660_chip_init();
+ dbg("Has reinit sensor !!!\n");
+ } else if (sscanf(buffer, "samp=%d\n", &sample))
+ {
+ if (sample > 0)
+ {
+ if (sample != l_sensorconfig.sensor_samp)
+ {
+ amsr = mma_sample2AMSR(sample);
+ SET_MMA_SAMPLE(tembuf, amsr);
+ klog("sample:%d ,amsr:%d \n", sample, amsr);
+ l_sensorconfig.sensor_samp = sample;
+ }
+ printk(KERN_ALERT "sensor samp=%d(amsr:%d) has been set.\n", sample, amsr);
+ } else {
+ printk(KERN_ALERT "Wrong sample argumnet of sensor.\n");
+ }
+ } else if (sscanf(buffer, "enable=%d\n", &enable))
+ {
+ if ((enable < 0) || (enable > 1))
+ {
+ printk(KERN_ERR "The argument to enable/disable g-sensor should be 0 or 1 !!!\n");
+ } else if (enable != l_sensorconfig.sensor_enable)
+ {
+ mma_enable_disable(enable);
+ l_sensorconfig.sensor_enable = enable;
+ }
+ } else if (sscanf(buffer, "sensor_test=%d\n", &test))
+ { // for test begin
+ l_sensorconfig.test_pass = 0;
+ } else if (sscanf(buffer, "sensor_testend=%d\n", &test))
+ { // Don nothing only to be compatible the before testing program
+ }
+ mutex_unlock(&sense_data_mutex);
+ return count;
+}
+
+static int sensor_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "test_pass=%d\nisdbg=%d\nrate=%d\nenable=%d\n",
+ l_sensorconfig.test_pass,
+ l_sensorconfig.isdbg,
+ l_sensorconfig.sensor_samp,
+ l_sensorconfig.sensor_enable
+ );
+ return len;
+}
+
+
+
+static int mma7660_init_client(struct platform_device *pdev)
+{
+ struct mma7660_config *data;
+// int ret;
+
+ data = dev_get_drvdata(&pdev->dev);
+ mutex_init(&sense_data_mutex);
+ /*Only for polling, not interrupt*/
+ l_sensorconfig.sensor_proc = create_proc_entry(GSENSOR_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ l_sensorconfig.sensor_proc->write_proc = sensor_writeproc;
+ l_sensorconfig.sensor_proc->read_proc = sensor_readproc;
+ }
+
+
+ return 0;
+
+//err:
+// return ret;
+}
+
+static struct file_operations mmad_fops = {
+ .owner = THIS_MODULE,
+ .open = mmad_open,
+ .release = mmad_release,
+ .unlocked_ioctl = mmad_ioctl,
+};
+
+
+static struct miscdevice mmad_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "sensor_ctrl",
+ .fops = &mmad_fops,
+};
+
+static int mma7660_probe(
+ struct platform_device *pdev)
+{
+ int err;
+
+ this_pdev = pdev;
+ l_sensorconfig.queue = create_singlethread_workqueue("sensor-intterupt-handle");
+ INIT_DELAYED_WORK(&l_sensorconfig.work, mma_work_func);
+
+ l_sensorconfig.input_dev = input_allocate_device();
+ if (!l_sensorconfig.input_dev) {
+ err = -ENOMEM;
+ printk(KERN_ERR
+ "mma7660_probe: Failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+ l_sensorconfig.input_dev->evbit[0] = BIT(EV_ABS) | BIT_MASK(EV_KEY);
+ set_bit(KEY_NEXTSONG, l_sensorconfig.input_dev->keybit);
+
+ /* x-axis acceleration */
+ input_set_abs_params(l_sensorconfig.input_dev, ABS_X, -65532, 65532, 0, 0);
+ /* y-axis acceleration */
+ input_set_abs_params(l_sensorconfig.input_dev, ABS_Y, -65532, 65532, 0, 0);
+ /* z-axis acceleration */
+ input_set_abs_params(l_sensorconfig.input_dev, ABS_Z, -65532, 65532, 0, 0);
+
+ l_sensorconfig.input_dev->name = "g-sensor";
+
+ err = input_register_device(l_sensorconfig.input_dev);
+
+ if (err) {
+ printk(KERN_ERR
+ "mma7660_probe: Unable to register input device: %s\n",
+ l_sensorconfig.input_dev->name);
+ goto exit_input_register_device_failed;
+ }
+
+ err = misc_register(&mmad_device);
+ if (err) {
+ printk(KERN_ERR
+ "mma7660_probe: mmad_device register failed\n");
+ goto exit_misc_device_register_failed;
+ }
+
+ dev_set_drvdata(&pdev->dev, &l_sensorconfig);
+ mma7660_chip_init();
+ mma7660_init_client(pdev);
+ gsensor_sysfs_init();
+
+ // satrt the polling work
+ l_sensorconfig.sensor_samp = 10;
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+ return 0;
+
+exit_misc_device_register_failed:
+exit_input_register_device_failed:
+ input_free_device(l_sensorconfig.input_dev);
+//exit_alloc_data_failed:
+exit_input_dev_alloc_failed:
+//exit_check_functionality_failed:
+ return err;
+}
+
+static int mma7660_remove(struct platform_device *pdev)
+{
+ if (NULL != l_sensorconfig.queue)
+ {
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ flush_workqueue(l_sensorconfig.queue);
+ destroy_workqueue(l_sensorconfig.queue);
+ l_sensorconfig.queue = NULL;
+ }
+ gsensor_sysfs_exit();
+ misc_deregister(&mmad_device);
+ input_unregister_device(l_sensorconfig.input_dev);
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ remove_proc_entry(GSENSOR_PROC_NAME, NULL);
+ l_sensorconfig.sensor_proc = NULL;
+ }
+ //free_irq(l_sensorconfig.irq, &l_sensorconfig);
+ return 0;
+}
+
+static int mma7660_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ //gsensor_int_ctrl(DISABLE);
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ del_timer(&l_polltimer);
+ dbg("...ok\n");
+ //l_resumed = 2;
+
+ return 0;
+}
+
+static int mma7660_resume(struct platform_device *pdev)
+{
+
+ //mma7660_chip_init();
+ //gsensor_int_ctrl(ENABLE);
+ //mma_enable_disable(1);
+ l_resumed = 1;
+ mod_timer(&l_polltimer, jiffies + msecs_to_jiffies(SENSOR_POLL_WAIT_TIME));
+ dbg("...ok\n");
+
+ return 0;
+}
+
+static void mma7660_platform_release(struct device *device)
+{
+ return;
+}
+
+static void mma7660_shutdown(struct platform_device *pdev)
+{
+
+ flush_delayed_work_sync(&l_sensorconfig.work);
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+
+}
+
+static struct platform_device mma7660_device = {
+ .name = "mma7660",
+ .id = 0,
+ .dev = {
+ .release = mma7660_platform_release,
+ },
+};
+
+static struct platform_driver mma7660_driver = {
+ .probe = mma7660_probe,
+ .remove = mma7660_remove,
+ .suspend = mma7660_suspend,
+ .resume = mma7660_resume,
+ .shutdown = mma7660_shutdown,
+ .driver = {
+ .name = "mma7660",
+ },
+};
+
+/*
+ * Brief:
+ * Get the configure of sensor from u-boot.
+ * Input:
+ * no use.
+ * Output:
+ * no use.
+ * Return:
+ * 0--success, -1--error.
+ * History:
+ * Created by HangYan on 2010-4-19
+ * Author:
+ * Hang Yan in ShenZhen.
+ */
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static int get_axisset(void* param)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.mma7660gsensor", varbuf, &varlen)) {
+ printk(KERN_DEBUG "Can't get gsensor config in u-boot!!!!\n");
+ return -1;
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &l_sensorconfig.op,
+ &(l_sensorconfig.xyz_axis[0][0]),
+ &(l_sensorconfig.xyz_axis[0][1]),
+ &(l_sensorconfig.xyz_axis[1][0]),
+ &(l_sensorconfig.xyz_axis[1][1]),
+ &(l_sensorconfig.xyz_axis[2][0]),
+ &(l_sensorconfig.xyz_axis[2][1]),
+ &(l_sensorconfig.offset[0]),
+ &(l_sensorconfig.offset[1]),
+ &(l_sensorconfig.offset[2]));
+ if (n != 10) {
+ printk(KERN_ERR "gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+
+ dbg("get the sensor config: %d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ l_sensorconfig.op,
+ l_sensorconfig.xyz_axis[0][0],
+ l_sensorconfig.xyz_axis[0][1],
+ l_sensorconfig.xyz_axis[1][0],
+ l_sensorconfig.xyz_axis[1][1],
+ l_sensorconfig.xyz_axis[2][0],
+ l_sensorconfig.xyz_axis[2][1],
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+ }
+ return 0;
+}
+
+
+// Add one timer to reinit sensor every 5s
+static void sensor_polltimer_timeout(unsigned long timeout)
+{
+ schedule_work(&poll_work);
+}
+
+static void poll_work_func(struct work_struct *work)
+{
+ char rxData[1];
+
+ //mutex_lock(&sense_data_mutex);
+ if (l_sensorconfig.pollcnt != 20)
+ {
+ l_sensorconfig.pollcnt++;
+ }
+ dbg("read to work!\n");
+ //spin_lock(&l_sensorconfig.spinlock);
+ mutex_lock(&sense_data_mutex);
+ if (1 == l_resumed)
+ {
+ mma7660_chip_init();
+ //gsensor_int_ctrl(ENABLE);
+ //mma_enable_disable(1);
+ dbg("reinit for resume...\n");
+ l_resumed = 0;
+ //spin_unlock(&l_sensorconfig.spinlock);
+ mutex_unlock(&sense_data_mutex);
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+
+ return;
+ }
+ //spin_unlock(&l_sensorconfig.spinlock);
+ mutex_unlock(&sense_data_mutex);
+ if (!is_sensor_good)
+ {
+ //mma7660_chip_init();
+ // if ic is blocked then wake g-sensor
+ sensor_i2c_read(MMA7660_ADDR,3,rxData,1);
+ } else {
+ is_sensor_good = 0;
+ }
+
+ //mutex_unlock(&sense_data_mutex);
+ mod_timer(&l_polltimer, jiffies + msecs_to_jiffies(SENSOR_POLL_WAIT_TIME));
+
+}
+
+static int mma7660_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int mma7660_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+
+static struct file_operations mma7660_fops = {
+ .owner = THIS_MODULE,
+ .open = mma7660_open,
+ .release = mma7660_release,
+};
+
+static int is_mma7660(void)
+{
+ char txData[2];
+ int i = 0;
+
+ txData[1] = 0;
+ for (i = 0; i < 3; i++)
+ {
+ if(sensor_i2c_write(MMA7660_ADDR,7,txData,1) == 0)
+ {
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static int __init mma7660_init(void)
+{
+ int ret = 0;
+
+ if (is_mma7660())
+ {
+ printk(KERN_ERR "Can't find mma7660!!\n");
+ return -1;
+ }
+ ret = get_axisset(NULL); // get gsensor config from u-boot
+ if (ret < 0)
+ {
+ printk("<<<<<%s user choose to no sensor chip!\n", __func__);
+ return ret;
+ }
+ /*if ((ret != 0) || !l_sensorconfig.op)
+ return -EINVAL;*/
+
+
+ printk(KERN_INFO "mma7660fc g-sensor driver init\n");
+
+ spin_lock_init(&l_sensorconfig.spinlock);
+ INIT_WORK(&poll_work, poll_work_func);
+ // Create device node
+ if (register_chrdev (GSENSOR_MAJOR, GSENSOR_NAME, &mma7660_fops)) {
+ printk (KERN_ERR "unable to get major %d\n", GSENSOR_MAJOR);
+ return -EIO;
+ }
+
+ l_dev_class = class_create(THIS_MODULE, GSENSOR_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create gsensor device !!\n");
+ return ret;
+ }
+ l_clsdevice = device_create(l_dev_class, NULL, MKDEV(GSENSOR_MAJOR, 0), NULL, GSENSOR_NAME);
+ if (IS_ERR(l_clsdevice)){
+ ret = PTR_ERR(l_clsdevice);
+ printk(KERN_ERR "Failed to create device %s !!!",GSENSOR_NAME);
+ return ret;
+ }
+
+ if((ret = platform_device_register(&mma7660_device)))
+ {
+ printk(KERN_ERR "%s Can't register mma7660 platform devcie!!!\n", __FUNCTION__);
+ return ret;
+ }
+ if ((ret = platform_driver_register(&mma7660_driver)) != 0)
+ {
+ printk(KERN_ERR "%s Can't register mma7660 platform driver!!!\n", __FUNCTION__);
+ return ret;
+ }
+
+ setup_timer(&l_polltimer, sensor_polltimer_timeout, 0);
+ mod_timer(&l_polltimer, jiffies + msecs_to_jiffies(SENSOR_POLL_WAIT_TIME));
+ is_sensor_good = 1;
+
+ return 0;
+}
+
+static void __exit mma7660_exit(void)
+{
+ del_timer(&l_polltimer);
+ platform_driver_unregister(&mma7660_driver);
+ platform_device_unregister(&mma7660_device);
+ device_destroy(l_dev_class, MKDEV(GSENSOR_MAJOR, 0));
+ unregister_chrdev(GSENSOR_MAJOR, GSENSOR_NAME);
+ class_destroy(l_dev_class);
+
+}
+
+module_init(mma7660_init);
+module_exit(mma7660_exit);
+MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mma7660_gsensor/mma7660.h b/ANDROID_3.4.5/drivers/input/sensor/mma7660_gsensor/mma7660.h
new file mode 100755
index 00000000..db6c06c0
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mma7660_gsensor/mma7660.h
@@ -0,0 +1,106 @@
+/*
+ * Definitions for akm8976 compass chip.
+ */
+#ifndef AKM8976_H
+#define AKM8976_H
+
+#include <linux/ioctl.h>
+
+/* Compass device dependent definition */
+#define AKECS_MODE_MEASURE 0x00 /* Starts measurement. Please use AKECS_MODE_MEASURE_SNG */
+ /* or AKECS_MODE_MEASURE_SEQ instead of this. */
+#define AKECS_MODE_PFFD 0x01 /* Start pedometer and free fall detect. */
+#define AKECS_MODE_E2P_READ 0x02 /* E2P access mode (read). */
+#define AKECS_MODE_POWERDOWN 0x03 /* Power down mode */
+
+#define AKECS_MODE_MEASURE_SNG 0x10 /* Starts single measurement */
+#define AKECS_MODE_MEASURE_SEQ 0x11 /* Starts sequential measurement */
+
+/* Default register settings */
+#define CSPEC_AINT 0x01 /* Amplification for acceleration sensor */
+#define CSPEC_SNG_NUM 0x01 /* Single measurement mode */
+#define CSPEC_SEQ_NUM 0x02 /* Sequential measurement mode */
+#define CSPEC_SFRQ_32 0x00 /* Measurement frequency: 32Hz */
+#define CSPEC_SFRQ_64 0x01 /* Measurement frequency: 64Hz */
+#define CSPEC_MCS 0x07 /* Clock frequency */
+#define CSPEC_MKS 0x01 /* Clock type: CMOS level */
+#define CSPEC_INTEN 0x01 /* Interruption pin enable: Enable */
+
+#define RBUFF_SIZE 31 /* Rx buffer size */
+#define MAX_CALI_SIZE 0x1000U /* calibration buffer size */
+
+/* AK8976A register address */
+#define AKECS_REG_ST 0xC0
+#define AKECS_REG_TMPS 0xC1
+#define AKECS_REG_MS1 0xE0
+#define AKECS_REG_MS2 0xE1
+#define AKECS_REG_MS3 0xE2
+
+#define AKMIO 0xA1
+
+/* IOCTLs for AKM library */
+#define ECS_IOCTL_RESET _IO(AKMIO, 0x04)
+#define ECS_IOCTL_INT_STATUS _IO(AKMIO, 0x05)
+#define ECS_IOCTL_FFD_STATUS _IO(AKMIO, 0x06)
+#define ECS_IOCTL_SET_MODE _IOW(AKMIO, 0x07, short)
+#define ECS_IOCTL_GETDATA _IOR(AKMIO, 0x08, char[RBUFF_SIZE+1])
+#define ECS_IOCTL_GET_NUMFRQ _IOR(AKMIO, 0x09, char[2])
+#define ECS_IOCTL_SET_PERST _IO(AKMIO, 0x0A)
+#define ECS_IOCTL_SET_G0RST _IO(AKMIO, 0x0B)
+#define ECS_IOCTL_SET_YPR _IOW(AKMIO, 0x0C, short[12])
+#define ECS_IOCTL_GET_OPEN_STATUS _IOR(AKMIO, 0x0D, int)
+#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(AKMIO, 0x0E, int)
+#define ECS_IOCTL_GET_CALI_DATA _IOR(AKMIO, 0x0F, char[MAX_CALI_SIZE])
+#define ECS_IOCTL_GET_DELAY _IOR(AKMIO, 0x30, short)
+
+/* IOCTLs for APPs */
+#define ECS_IOCTL_APP_SET_MODE _IOW(AKMIO, 0x10, short)
+#define ECS_IOCTL_APP_SET_MFLAG _IOW(AKMIO, 0x11, short)
+#define ECS_IOCTL_APP_GET_MFLAG _IOW(AKMIO, 0x12, short)
+#define ECS_IOCTL_APP_GET_AFLAG _IOR(AKMIO, 0x14, short)
+#define ECS_IOCTL_APP_SET_TFLAG _IOR(AKMIO, 0x15, short)
+#define ECS_IOCTL_APP_GET_TFLAG _IOR(AKMIO, 0x16, short)
+#define ECS_IOCTL_APP_RESET_PEDOMETER _IO(AKMIO, 0x17)
+#define ECS_IOCTL_APP_GET_DELAY ECS_IOCTL_GET_DELAY
+#define ECS_IOCTL_APP_SET_MVFLAG _IOW(AKMIO, 0x19, short) /* Set raw magnetic vector flag */
+#define ECS_IOCTL_APP_GET_MVFLAG _IOR(AKMIO, 0x1A, short) /* Get raw magnetic vector flag */
+
+/* IOCTLs for pedometer */
+#define ECS_IOCTL_SET_STEP_CNT _IOW(AKMIO, 0x20, short)
+#define SENSOR_DATA_SIZE 3
+#define WMTGSENSOR_IOCTL_MAGIC 0x09
+#define ECS_IOCTL_APP_SET_AFLAG _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x02, short)
+#define ECS_IOCTL_APP_SET_DELAY _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x03, short)
+#define WMT_IOCTL_SENSOR_GET_DRVID _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x04, unsigned int)
+#define ECS_IOCTL_APP_READ_XYZ _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x05, int[SENSOR_DATA_SIZE])
+
+#define MMA7660_DRVID 0
+
+
+
+/* Default GPIO setting */
+#define ECS_RST 146 /*MISC4, bit2 */
+#define ECS_CLK_ON 155 /*MISC5, bit3 */
+#define ECS_INTR 161 /*INT2, bit1 */
+
+/* MISC */
+#define MMA7660_ADDR 0x4C
+#define SENSOR_UI_MODE 0
+#define SENSOR_GRAVITYGAME_MODE 1
+#define UI_SAMPLE_RATE 0xFC
+#define GSENSOR_PROC_NAME "gsensor_config"
+#define sin30_1000 500
+#define cos30_1000 866
+#define DISABLE 0
+#define ENABLE 1
+
+struct mma7660_platform_data {
+ int reset;
+ int clk_on;
+ int intr;
+};
+
+extern char *get_mma_cal_ram(void);
+
+#endif
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mma8452q_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/mma8452q_gsensor/Makefile
new file mode 100755
index 00000000..4dcceb42
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mma8452q_gsensor/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_gsensor_mma8452q
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := mma8x5x.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mma8452q_gsensor/mma8x5x.c b/ANDROID_3.4.5/drivers/input/sensor/mma8452q_gsensor/mma8x5x.c
new file mode 100755
index 00000000..443d3b18
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mma8452q_gsensor/mma8x5x.c
@@ -0,0 +1,982 @@
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/miscdevice.h>
+#include <linux/gpio.h>
+#include <asm/uaccess.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/freezer.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <mach/hardware.h>
+#include "mma8x5x.h" //"mma8452q.h"
+#include "../sensor.h"
+
+//#define DEBUG 1
+
+#undef dbg
+
+//#if 0
+ #define dbg(fmt, args...) if (l_sensorconfig.isdbg) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+ //#define dbg(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+#define klog(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+ //#define dbg(format, arg...) printk(KERN_ALERT format, ## arg)
+
+
+//#else
+// #define dbg(format, arg...)
+//#endif
+
+/////////////////////Macro constant
+#define SENSOR_POLL_WAIT_TIME 1837
+#define MAX_FAILURE_COUNT 10
+#define MMA8452_ADDR 0x1C //slave 0x1D??high
+#define LAND_PORT_MASK 0x1C
+#define LAND_LEFT 0x1
+#define LAND_RIGHT 0x2
+#define PORT_INVERT 0x5
+#define PORT_NORMAL 0x6
+
+#define LANDSCAPE_LOCATION 0
+#define PORTRAIT_LOCATION 1
+
+#define SENSOR_UI_MODE 0
+#define SENSOR_GRAVITYGAME_MODE 1
+
+#define UI_SAMPLE_RATE 0xFC
+
+#define GSENSOR_PROC_NAME "gsensor_config"
+#define GSENSOR_MAJOR 161
+#define GSENSOR_NAME "mma8452q"
+#define GSENSOR_DRIVER_NAME "mma8452q_drv"
+
+
+#define sin30_1000 500
+#define cos30_1000 866
+
+#define DISABLE 0
+#define ENABLE 1
+
+////////////////////////the rate of g-sensor/////////////////////////////////////////////
+#define SENSOR_DELAY_FASTEST 0
+#define SENSOR_DELAY_GAME 20
+#define SENSOR_DELAY_UI 60
+#define SENSOR_DELAY_NORMAL 200
+
+#define FASTEST_MMA_AMSR 0 // 120 samples/sec
+#define GAME_MMA_AMSR 1 // 1, (64, samples/sec)
+#define UI_MMA_AMSR 3 // 2, 3,4, (16, 8,32 samples/sec)
+#define NORMAL_MMA_AMSR 5 // 5, 6, 7 (4, 2, 1 samples/sec)
+
+#define MMA8451_ID 0x1A
+#define MMA8452_ID 0x2A
+#define MMA8453_ID 0x3A
+#define MMA8652_ID 0x4A
+#define MMA8653_ID 0x5A
+#define MODE_CHANGE_DELAY_MS 100
+/* register enum for mma8x5x registers */
+enum {
+ MMA8X5X_STATUS = 0x00,
+ MMA8X5X_OUT_X_MSB,
+ MMA8X5X_OUT_X_LSB,
+ MMA8X5X_OUT_Y_MSB,
+ MMA8X5X_OUT_Y_LSB,
+ MMA8X5X_OUT_Z_MSB,
+ MMA8X5X_OUT_Z_LSB,
+
+ MMA8X5X_F_SETUP = 0x09,
+ MMA8X5X_TRIG_CFG,
+ MMA8X5X_SYSMOD,
+ MMA8X5X_INT_SOURCE,
+ MMA8X5X_WHO_AM_I,
+ MMA8X5X_XYZ_DATA_CFG,
+ MMA8X5X_HP_FILTER_CUTOFF,
+
+ MMA8X5X_PL_STATUS,
+ MMA8X5X_PL_CFG,
+ MMA8X5X_PL_COUNT,
+ MMA8X5X_PL_BF_ZCOMP,
+ MMA8X5X_P_L_THS_REG,
+
+ MMA8X5X_FF_MT_CFG,
+ MMA8X5X_FF_MT_SRC,
+ MMA8X5X_FF_MT_THS,
+ MMA8X5X_FF_MT_COUNT,
+
+ MMA8X5X_TRANSIENT_CFG = 0x1D,
+ MMA8X5X_TRANSIENT_SRC,
+ MMA8X5X_TRANSIENT_THS,
+ MMA8X5X_TRANSIENT_COUNT,
+
+ MMA8X5X_PULSE_CFG,
+ MMA8X5X_PULSE_SRC,
+ MMA8X5X_PULSE_THSX,
+ MMA8X5X_PULSE_THSY,
+ MMA8X5X_PULSE_THSZ,
+ MMA8X5X_PULSE_TMLT,
+ MMA8X5X_PULSE_LTCY,
+ MMA8X5X_PULSE_WIND,
+
+ MMA8X5X_ASLP_COUNT,
+ MMA8X5X_CTRL_REG1,
+ MMA8X5X_CTRL_REG2,
+ MMA8X5X_CTRL_REG3,
+ MMA8X5X_CTRL_REG4,
+ MMA8X5X_CTRL_REG5,
+
+ MMA8X5X_OFF_X,
+ MMA8X5X_OFF_Y,
+ MMA8X5X_OFF_Z,
+
+ MMA8X5X_REG_END,
+};
+
+enum {
+ MODE_2G = 0,
+ MODE_4G,
+ MODE_8G,
+};
+
+static int mma8x5x_chip_id[] ={
+ MMA8451_ID,
+ MMA8452_ID,
+ MMA8453_ID,
+ MMA8652_ID,
+ MMA8653_ID,
+};
+
+static struct i2c_client *this_client = NULL;
+/////////////////////////////////////////////////////////////////////////
+
+static struct platform_device *this_pdev;
+
+static struct class* l_dev_class = NULL;
+static struct device *l_clsdevice = NULL;
+
+
+
+struct mma8452q_config
+{
+ int op;
+ int int_gpio; //0-3
+ int xyz_axis[3][2]; // (axis,direction)
+ int rxyz_axis[3][2];
+ int irq;
+ struct proc_dir_entry* sensor_proc;
+ int sensorlevel;
+ int shake_enable; // 1--enable shake, 0--disable shake
+ int manual_rotation; // 0--landance, 90--vertical
+ struct input_dev *input_dev;
+ //struct work_struct work;
+ struct delayed_work work; // for polling
+ struct workqueue_struct *queue;
+ int isdbg; // 0-- no debug log, 1--show debug log
+ int sensor_samp; // 1,2,4,8,16,32,64,120
+ int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor
+ int test_pass;
+ spinlock_t spinlock;
+ int pollcnt; // the counts of polling
+ int offset[3];
+};
+
+static struct mma8452q_config l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },
+ .irq = 6,
+ .int_gpio = 3,
+ .sensor_proc = NULL,
+ .sensorlevel = SENSOR_GRAVITYGAME_MODE,
+ .shake_enable = 0, // default enable shake
+ .isdbg = 0,
+ .sensor_samp = 10, // 4sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ .pollcnt = 0, // Don't report the x,y,z when the driver is loaded until 2~3 seconds
+ .offset = {0,0,0},
+};
+
+
+
+struct work_struct poll_work;
+static struct mutex sense_data_mutex;
+static int revision = -1;
+static int l_resumed = 0; // 1: suspend --> resume;2: suspend but not resumed; other values have no meaning
+
+//////////////////Macro function//////////////////////////////////////////////////////
+
+#define SET_MMA_SAMPLE(buf,samp) { \
+ buf[0] = 0; \
+ sensor_i2c_write(/*MMA8452_ADDR,*/7,buf,1); \
+ buf[0] = samp; \
+ sensor_i2c_write(/*MMA8452_ADDR,*/8,buf,1); \
+ buf[0] = 0x01; \
+ sensor_i2c_write(/*MMA8452_ADDR,*/7,buf,1); \
+}
+
+////////////////////////Function define/////////////////////////////////////////////////////////
+
+static unsigned int mma_sample2AMSR(unsigned int samp);
+
+////////////////////////Function implement/////////////////////////////////////////////////
+// rate: 1,2,4,8,16,32,64,120
+static unsigned int sample_rate_2_memsec(unsigned int rate)
+{
+ return (1000/rate);
+}
+
+
+
+static ssize_t gsensor_vendor_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+
+ sprintf(buf, "MMA8452_%#x\n", revision);
+ ret = strlen(buf) + 1;
+
+ return ret;
+}
+
+static DEVICE_ATTR(vendor, 0444, gsensor_vendor_show, NULL);
+
+static struct kobject *android_gsensor_kobj;
+static int gsensor_sysfs_init(void)
+{
+ int ret ;
+
+ android_gsensor_kobj = kobject_create_and_add("android_gsensor", NULL);
+ if (android_gsensor_kobj == NULL) {
+ printk(KERN_ERR
+ "mma8452q gsensor_sysfs_init:"\
+ "subsystem_register failed\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ ret = sysfs_create_file(android_gsensor_kobj, &dev_attr_vendor.attr);
+ if (ret) {
+ printk(KERN_ERR
+ "mma8452q gsensor_sysfs_init:"\
+ "sysfs_create_group failed\n");
+ goto err4;
+ }
+
+ return 0 ;
+err4:
+ kobject_del(android_gsensor_kobj);
+err:
+ return ret ;
+}
+
+static int gsensor_sysfs_exit(void)
+{
+ sysfs_remove_file(android_gsensor_kobj, &dev_attr_vendor.attr);
+ kobject_del(android_gsensor_kobj);
+ return 0;
+}
+
+//extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, unsigned int num, int bus_id);
+extern int i2c_api_do_send(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size);
+extern int i2c_api_do_recv(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size);
+
+int sensor_i2c_write(/*unsigned int addr,*/unsigned int index,char *pdata,int len)
+{
+
+ char wrData[12] = {0};
+ struct i2c_client *client = this_client;
+
+ struct i2c_msg msgs =
+ {.addr = client->addr, .flags = 0, .len = len+1, .buf = wrData,};
+
+
+ if (!client || (!pdata))
+ {
+ printk("%s NULL client!\n", __FUNCTION__);
+ return -EIO;
+ }
+
+ wrData[0] = index;
+ strncpy(&wrData[1], pdata, len);
+
+ if (i2c_transfer(client->adapter, &msgs, 1) < 0) {
+ printk( "%s: transfer failed.", __func__);
+ return -EIO;
+ }
+
+ return 0;
+} /* End of sensor_i2c_write */
+
+int sensor_i2c_read(/*unsigned int addr,*/unsigned int index,char *pdata,int len)
+{
+ char rdData[2] = {0};
+ struct i2c_client *client = this_client;
+
+ struct i2c_msg msgs[2] =
+ {
+ {.addr = client->addr, .flags = 0|I2C_M_NOSTART, .len = 1, .buf = rdData,},
+ {.addr = client->addr, .flags = I2C_M_RD, .len = len, .buf = pdata,},
+ };
+ rdData[0] = index;
+ if (!client || (!pdata))
+ {
+ printk("%s NULL client!\n", __FUNCTION__);
+ return -EIO;
+ }
+ if (i2c_transfer(client->adapter, msgs, 2) < 0) {
+ printk( "%s: transfer failed.", __func__);
+ return -EIO;
+ }
+
+ return 0;//rdData[0]; i2c read ok!!
+
+} /* End of sensor_i2c_read */
+
+//****************add for mma8452q******************************
+
+static int mma8452q_chip_init(void)
+{
+ char txData[1] = {0};
+
+ int result;
+
+ txData[0] = 0x1; //active mode
+ result = sensor_i2c_write(/*MMA8452_ADDR,*/MMA8X5X_CTRL_REG1,txData,1);
+ if (result < 0)
+ goto out;
+
+ txData[0] = MODE_2G;
+ result = sensor_i2c_write(/*MMA8452_ADDR,*/MMA8X5X_XYZ_DATA_CFG,txData,1);
+ if (result < 0)
+ goto out;
+
+ txData[0] = 0x1; //wake mode
+ result = sensor_i2c_write(/*MMA8452_ADDR,*/MMA8X5X_SYSMOD,txData,1);
+ if (result < 0)
+ goto out;
+
+ msleep(MODE_CHANGE_DELAY_MS);
+ return 0;
+out:
+
+ return result;
+
+}
+
+static unsigned int mma_sample2AMSR(unsigned int samp)
+{
+ int i = 0;
+ unsigned int amsr;
+
+ if (samp >= 120)
+ {
+ return 0;
+ }
+ while (samp)
+ {
+ samp = samp >> 1;
+ i++;
+ }
+ amsr = 8 - i;
+ return amsr;
+}
+
+static int mma_enable_disable(int enable)
+{
+ char buf[1];
+
+ // disable all interrupt of g-sensor
+ memset(buf, 0, sizeof(buf));
+ if ((enable < 0) || (enable > 1))
+ {
+ return -1;
+ }
+ buf[0] = 0;
+ sensor_i2c_write(/*MMA8452_ADDR,*/7,buf,1);
+ if (enable != 0)
+ {
+ buf[0] = (1 == l_sensorconfig.shake_enable) ? 0xF0:0x10;
+ } else {
+ buf[0] = 0;
+ }
+ sensor_i2c_write(/*MMA8452_ADDR,*/6,buf,1);
+ buf[0] = 0xf9;
+ sensor_i2c_write(/*MMA8452_ADDR,*/7,buf,1);
+ return 0;
+}
+
+// To contol the g-sensor for UI
+static int mmad_open(struct inode *inode, struct file *file)
+{
+ dbg("Open the g-sensor node...\n");
+ return 0;
+}
+
+static int mmad_release(struct inode *inode, struct file *file)
+{
+ dbg("Close the g-sensor node...\n");
+ return 0;
+}
+
+static long
+mmad_ioctl(/*struct inode *inode,*/ struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ char rwbuf[5];
+ short delay, enable; //amsr = -1;
+ unsigned int uval = 0;
+
+ dbg("g-sensor ioctr...\n");
+ memset(rwbuf, 0, sizeof(rwbuf));
+ switch (cmd) {
+ case ECS_IOCTL_APP_SET_DELAY:
+ // set the rate of g-sensor
+ if (copy_from_user(&delay, argp, sizeof(short)))
+ {
+ printk(KERN_ALERT "Can't get set delay!!!\n");
+ return -EFAULT;
+ }
+ klog("Get delay=%d\n", delay);
+ //klog("before change sensor sample:%d...\n", l_sensorconfig.sensor_samp);
+ if ((delay >=0) && (delay < 20))
+ {
+ delay = 20;
+ } else if (delay > 200)
+ {
+ delay = 200;
+ }
+ l_sensorconfig.sensor_samp = 1000/delay;
+
+ break;
+ case ECS_IOCTL_APP_SET_AFLAG:
+ // enable/disable sensor
+ if (copy_from_user(&enable, argp, sizeof(short)))
+ {
+ printk(KERN_ERR "Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ klog("enable=%d\n",enable);
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor.\n", enable);
+
+ l_sensorconfig.sensor_enable = enable;
+
+ } else {
+ printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ uval = MMA8452Q_DRVID;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("mma8452q_driver_id:%d\n",uval);
+ break;
+ case WMT_IOCTL_SENOR_GET_RESOLUTION:
+
+ uval = (16<<8) | 4; // 16bit:4g 0xxx xx //mma8452Q
+ if (copy_to_user((unsigned int *)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ printk("<<<<<<<resolution:0x%x\n",uval);
+ default:
+ break;
+ }
+
+
+
+ return 0;
+}
+
+
+static void mma_work_func(struct work_struct *work)
+{
+ struct mma8452q_config *data;
+ /*unsigned*/ short rxData[3] = {0};
+ //unsigned char tiltval = 0;
+ int i = 0;
+ int x,y,z;
+ char tmp[6] = {0};
+
+ data = dev_get_drvdata(&this_pdev->dev);
+ if (!l_sensorconfig.sensor_enable)
+ {
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+ return;
+ }
+ mutex_lock(&sense_data_mutex);
+
+
+ i = sensor_i2c_read(/*MMA8452_ADDR,*/MMA8X5X_OUT_X_MSB,tmp, sizeof(tmp));
+#if 0
+ for (i=0; i<6; i++)
+ sensor_i2c_read(/*MMA8452_ADDR,*/MMA8X5X_OUT_X_MSB+i,&tmp[i], 1);
+ i = 0;
+#endif
+
+ if (0 == i)
+ {
+ rxData[0] = ((tmp[0] << 8 )&0xff00 ) | (tmp[1] );
+ rxData[1] = ((tmp[2] << 8) &0xff00 ) | (tmp[3] );
+ rxData[2] = ((tmp[4] << 8) &0xff00 ) | (tmp[5] );
+ x = rxData[l_sensorconfig.xyz_axis[0][0]]*l_sensorconfig.xyz_axis[0][1];
+ y = rxData[l_sensorconfig.xyz_axis[1][0]]*l_sensorconfig.xyz_axis[1][1];
+ z = rxData[l_sensorconfig.xyz_axis[2][0]]*l_sensorconfig.xyz_axis[2][1];
+ #if 0
+ x = (x*9800) >> 14;
+ y = (y*9800) >> 14;
+ z = (z*9800) >> 14;
+ #endif
+ //printk("x,y,z (%d, %d, %d) \n", rxData[0], rxData[1], rxData[2]);
+ //printk("x,y,z (%d, %d, %d) \n", x, y, z);
+ //printk("x 0x%x\n", tmp[0]);
+ input_report_abs(data->input_dev, ABS_X, x);
+ input_report_abs(data->input_dev, ABS_Y, y);
+ input_report_abs(data->input_dev, ABS_Z, z);
+ input_sync(data->input_dev);
+ }
+
+
+ mutex_unlock(&sense_data_mutex);
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+}
+
+static int sensor_writeproc( struct file *file,
+ const char *buffer,
+ unsigned long count,
+ void *data )
+{
+
+ int inputval = -1;
+ int enable, sample = -1;
+ char tembuf[8];
+ unsigned int amsr = 0;
+ int test = 0;
+
+ mutex_lock(&sense_data_mutex);
+ // disable int
+ //gsensor_int_ctrl(DISABLE);
+ memset(tembuf, 0, sizeof(tembuf));
+ // get sensor level and set sensor level
+ if (sscanf(buffer, "level=%d\n", &l_sensorconfig.sensorlevel))
+ {
+ } else if (sscanf(buffer, "shakenable=%d\n", &l_sensorconfig.shake_enable))
+ {
+
+ }
+ else if (sscanf(buffer, "isdbg=%d\n", &l_sensorconfig.isdbg))
+ {
+ // only set the dbg flag
+ } else if (sscanf(buffer, "init=%d\n", &inputval))
+ {
+ mma8452q_chip_init();
+ dbg("Has reinit sensor !!!\n");
+ } else if (sscanf(buffer, "samp=%d\n", &sample))
+ {
+ if (sample > 0)
+ {
+ if (sample != l_sensorconfig.sensor_samp)
+ {
+ amsr = mma_sample2AMSR(sample);
+ SET_MMA_SAMPLE(tembuf, amsr);
+ klog("sample:%d ,amsr:%d \n", sample, amsr);
+ l_sensorconfig.sensor_samp = sample;
+ }
+ printk(KERN_ALERT "sensor samp=%d(amsr:%d) has been set.\n", sample, amsr);
+ } else {
+ printk(KERN_ALERT "Wrong sample argumnet of sensor.\n");
+ }
+ } else if (sscanf(buffer, "enable=%d\n", &enable))
+ {
+ if ((enable < 0) || (enable > 1))
+ {
+ printk(KERN_ERR "The argument to enable/disable g-sensor should be 0 or 1 !!!\n");
+ } else if (enable != l_sensorconfig.sensor_enable)
+ {
+ mma_enable_disable(enable);
+ l_sensorconfig.sensor_enable = enable;
+ }
+ } else if (sscanf(buffer, "sensor_test=%d\n", &test))
+ { // for test begin
+ l_sensorconfig.test_pass = 0;
+ } else if (sscanf(buffer, "sensor_testend=%d\n", &test))
+ { // Don nothing only to be compatible the before testing program
+ }
+ mutex_unlock(&sense_data_mutex);
+ return count;
+}
+
+static int sensor_readproc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = 0;
+
+ len = sprintf(page,
+ "test_pass=%d\nisdbg=%d\nrate=%d\nenable=%d\n",
+ l_sensorconfig.test_pass,
+ l_sensorconfig.isdbg,
+ l_sensorconfig.sensor_samp,
+ l_sensorconfig.sensor_enable
+ );
+ return len;
+}
+
+
+
+static int mma8452q_init_client(struct platform_device *pdev)
+{
+ struct mma8452q_config *data;
+// int ret;
+
+ data = dev_get_drvdata(&pdev->dev);
+ mutex_init(&sense_data_mutex);
+ /*Only for polling, not interrupt*/
+ l_sensorconfig.sensor_proc = create_proc_entry(GSENSOR_PROC_NAME, 0666, NULL/*&proc_root*/);
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ l_sensorconfig.sensor_proc->write_proc = sensor_writeproc;
+ l_sensorconfig.sensor_proc->read_proc = sensor_readproc;
+ }
+
+
+ return 0;
+
+//err:
+// return ret;
+}
+
+static struct file_operations mmad_fops = {
+ .owner = THIS_MODULE,
+ .open = mmad_open,
+ .release = mmad_release,
+ .unlocked_ioctl = mmad_ioctl,
+};
+
+
+static struct miscdevice mmad_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "sensor_ctrl",
+ .fops = &mmad_fops,
+};
+
+static int mma8452q_probe(struct platform_device *pdev)
+{
+ int err;
+
+ this_pdev = pdev;
+ l_sensorconfig.queue = create_singlethread_workqueue("sensor-intterupt-handle");
+ INIT_DELAYED_WORK(&l_sensorconfig.work, mma_work_func);
+
+ l_sensorconfig.input_dev = input_allocate_device();
+ if (!l_sensorconfig.input_dev) {
+ err = -ENOMEM;
+ printk(KERN_ERR
+ "mma8452q_probe: Failed to allocate input device\n");
+ goto exit_input_dev_alloc_failed;
+ }
+ l_sensorconfig.input_dev->evbit[0] = BIT(EV_ABS) | BIT_MASK(EV_KEY);
+ set_bit(KEY_NEXTSONG, l_sensorconfig.input_dev->keybit);
+
+ /* x-axis acceleration */
+ input_set_abs_params(l_sensorconfig.input_dev, ABS_X, -65532, 65532, 0, 0);
+ /* y-axis acceleration */
+ input_set_abs_params(l_sensorconfig.input_dev, ABS_Y, -65532, 65532, 0, 0);
+ /* z-axis acceleration */
+ input_set_abs_params(l_sensorconfig.input_dev, ABS_Z, -65532, 65532, 0, 0);
+
+ l_sensorconfig.input_dev->name = "g-sensor";
+
+ err = input_register_device(l_sensorconfig.input_dev);
+
+ if (err) {
+ printk(KERN_ERR
+ "mma8452q_probe: Unable to register input device: %s\n",
+ l_sensorconfig.input_dev->name);
+ goto exit_input_register_device_failed;
+ }
+
+ err = misc_register(&mmad_device);
+ if (err) {
+ printk(KERN_ERR
+ "mma8452q_probe: mmad_device register failed\n");
+ goto exit_misc_device_register_failed;
+ }
+
+ dev_set_drvdata(&pdev->dev, &l_sensorconfig);
+ mma8452q_chip_init();
+ mma8452q_init_client(pdev);
+ gsensor_sysfs_init();
+
+ // satrt the polling work
+ l_sensorconfig.sensor_samp = 10;
+ queue_delayed_work(l_sensorconfig.queue, &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+ return 0;
+
+exit_misc_device_register_failed:
+exit_input_register_device_failed:
+ input_free_device(l_sensorconfig.input_dev);
+
+exit_input_dev_alloc_failed:
+
+ return err;
+}
+
+static int mma8452q_remove(struct platform_device *pdev)
+{
+ if (NULL != l_sensorconfig.queue)
+ {
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+ flush_workqueue(l_sensorconfig.queue);
+ destroy_workqueue(l_sensorconfig.queue);
+ l_sensorconfig.queue = NULL;
+ }
+ gsensor_sysfs_exit();
+ misc_deregister(&mmad_device);
+ input_unregister_device(l_sensorconfig.input_dev);
+ if (l_sensorconfig.sensor_proc != NULL)
+ {
+ remove_proc_entry(GSENSOR_PROC_NAME, NULL);
+ l_sensorconfig.sensor_proc = NULL;
+ }
+
+ return 0;
+}
+
+static int mma8452q_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ //gsensor_int_ctrl(DISABLE);
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+
+ dbg("...ok\n");
+ //l_resumed = 2;
+
+ return 0;
+}
+
+static int mma8452q_resume(struct platform_device *pdev)
+{
+
+ l_resumed = 1;
+
+ mma8452q_chip_init();
+ queue_delayed_work(l_sensorconfig.queue, \
+ &l_sensorconfig.work, msecs_to_jiffies(sample_rate_2_memsec(l_sensorconfig.sensor_samp)));
+ dbg("...ok\n");
+
+ return 0;
+}
+
+static void mma8452q_platform_release(struct device *device)
+{
+ return;
+}
+
+static void mma8452q_shutdown(struct platform_device *pdev)
+{
+ flush_delayed_work_sync(&l_sensorconfig.work);
+ cancel_delayed_work_sync(&l_sensorconfig.work);
+
+}
+
+static struct platform_device mma8452q_device = {
+ .name = "mma8452q",
+ .id = 0,
+ .dev = {
+ .release = mma8452q_platform_release,
+ },
+};
+
+static struct platform_driver mma8452q_driver = {
+ .probe = mma8452q_probe,
+ .remove = mma8452q_remove,
+ .suspend = mma8452q_suspend,
+ .resume = mma8452q_resume,
+ .shutdown = mma8452q_shutdown,
+ .driver = {
+ .name = "mma8452q",
+ },
+};
+
+/*
+ * Brief:
+ * Get the configure of sensor from u-boot.
+ * Input:
+ * no use.
+ * Output:
+ * no use.
+ * Return:
+ * 0--success, -1--error.
+ * History:
+ * Created by HangYan on 2010-4-19
+ * Author:
+ * Hang Yan in ShenZhen.
+ */
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static int get_axisset(void* param)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.mma8452qgsensor", varbuf, &varlen)) {
+ printk(KERN_DEBUG "Can't get gsensor config in u-boot!!!!\n");
+ return -1;
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &l_sensorconfig.op,
+ &(l_sensorconfig.xyz_axis[0][0]),
+ &(l_sensorconfig.xyz_axis[0][1]),
+ &(l_sensorconfig.xyz_axis[1][0]),
+ &(l_sensorconfig.xyz_axis[1][1]),
+ &(l_sensorconfig.xyz_axis[2][0]),
+ &(l_sensorconfig.xyz_axis[2][1]),
+ &(l_sensorconfig.offset[0]),
+ &(l_sensorconfig.offset[1]),
+ &(l_sensorconfig.offset[2]));
+ if (n != 10) {
+ printk(KERN_ERR "gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+
+ printk("get the sensor config: %d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ l_sensorconfig.op,
+ l_sensorconfig.xyz_axis[0][0],
+ l_sensorconfig.xyz_axis[0][1],
+ l_sensorconfig.xyz_axis[1][0],
+ l_sensorconfig.xyz_axis[1][1],
+ l_sensorconfig.xyz_axis[2][0],
+ l_sensorconfig.xyz_axis[2][1],
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+ }
+ return 0;
+}
+
+static int is_mma8452q(void)
+{
+ char rxData[2] = {0};
+ int ret = 0;
+ int i = 0;
+ //char rdData[10] = {0};
+ //char wbuf[6] = {0};
+ //char rbuf[0x33] = {0};
+
+ ret = sensor_i2c_read(MMA8X5X_WHO_AM_I,rxData,1);
+ //printk("<<<<%s ret %d, val 0x%x\n", __FUNCTION__, ret, rxData[0]);
+ for(i = 0 ; i < sizeof(mma8x5x_chip_id)/sizeof(mma8x5x_chip_id[0]);i++)
+ if(rxData[0] == mma8x5x_chip_id[i])
+ return 0;
+#if 0
+ struct i2c_client* client = gsensor_get_i2c_client();
+ if (!client){
+ printk("client NULL!\n");
+ return -1;
+ }
+
+ for (i=0; i<6; i++)
+ wbuf[i] = i+2;
+ //sensor_i2c_write(0x25, wbuf, 6);
+ //rbuf[0] = 0x11;
+ //sensor_i2c_read(0xb, rbuf, 0x1);
+ mma8452q_chip_init();
+ for (i=0; i<0x12; i++) {
+ sensor_i2c_read(0xb+i, rbuf, 0x1);
+ printk("<<<<%s reg 0x%x val 0x%x\n", __FUNCTION__, 0xb+i, rbuf[0]);
+ }
+#endif
+ return -1;
+}
+
+static int __init mma8452q_init(void)
+{
+ int ret = 0;
+
+ ret = get_axisset(NULL);
+ if (ret < 0)
+ {
+ printk("<<<<<%s user choose to no sensor chip!\n", __func__);
+ return ret;
+ }
+
+ if (!(this_client = sensor_i2c_register_device(0, GSENSOR_I2C_ADDR, GSENSOR_I2C_NAME)))
+ {
+ printk(KERN_EMERG"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+
+ if (is_mma8452q())
+ {
+ printk(KERN_ERR "Can't find mma8452q!!\n");
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+ }
+
+
+
+ printk(KERN_INFO "mma8452qfc g-sensor driver init\n");
+
+ spin_lock_init(&l_sensorconfig.spinlock);
+
+ // Create device node
+
+ l_dev_class = class_create(THIS_MODULE, GSENSOR_NAME);
+ //for S40 module to judge whether insmod is ok
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create gsensor device !!\n");
+ return ret;
+ }
+ l_clsdevice = device_create(l_dev_class, NULL, MKDEV(GSENSOR_MAJOR, 0), NULL, GSENSOR_NAME);
+ if (IS_ERR(l_clsdevice)){
+ ret = PTR_ERR(l_clsdevice);
+ printk(KERN_ERR "Failed to create device %s !!!",GSENSOR_NAME);
+ return ret;
+ }
+
+ if((ret = platform_device_register(&mma8452q_device)))
+ {
+ printk(KERN_ERR "%s Can't register mma8452q platform devcie!!!\n", __FUNCTION__);
+ return ret;
+ }
+ if ((ret = platform_driver_register(&mma8452q_driver)) != 0)
+ {
+ printk(KERN_ERR "%s Can't register mma8452q platform driver!!!\n", __FUNCTION__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __exit mma8452q_exit(void)
+{
+ platform_driver_unregister(&mma8452q_driver);
+ platform_device_unregister(&mma8452q_device);
+ device_destroy(l_dev_class, MKDEV(GSENSOR_MAJOR, 0));
+
+ class_destroy(l_dev_class);
+ sensor_i2c_unregister_device(this_client);
+
+}
+
+module_init(mma8452q_init);
+module_exit(mma8452q_exit);
+MODULE_LICENSE("GPL");
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mma8452q_gsensor/mma8x5x.h b/ANDROID_3.4.5/drivers/input/sensor/mma8452q_gsensor/mma8x5x.h
new file mode 100755
index 00000000..d8d386b2
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mma8452q_gsensor/mma8x5x.h
@@ -0,0 +1,107 @@
+/*
+ * Definitions for akm8976 compass chip.
+ */
+#ifndef AKM8976_H
+#define AKM8976_H
+
+#include <linux/ioctl.h>
+
+#define GSENSOR_I2C_NAME "mma8452q"
+#define GSENSOR_I2C_ADDR 0x1c
+/* Compass device dependent definition */
+#define AKECS_MODE_MEASURE 0x00 /* Starts measurement. Please use AKECS_MODE_MEASURE_SNG */
+ /* or AKECS_MODE_MEASURE_SEQ instead of this. */
+#define AKECS_MODE_PFFD 0x01 /* Start pedometer and free fall detect. */
+#define AKECS_MODE_E2P_READ 0x02 /* E2P access mode (read). */
+#define AKECS_MODE_POWERDOWN 0x03 /* Power down mode */
+
+#define AKECS_MODE_MEASURE_SNG 0x10 /* Starts single measurement */
+#define AKECS_MODE_MEASURE_SEQ 0x11 /* Starts sequential measurement */
+
+/* Default register settings */
+#define CSPEC_AINT 0x01 /* Amplification for acceleration sensor */
+#define CSPEC_SNG_NUM 0x01 /* Single measurement mode */
+#define CSPEC_SEQ_NUM 0x02 /* Sequential measurement mode */
+#define CSPEC_SFRQ_32 0x00 /* Measurement frequency: 32Hz */
+#define CSPEC_SFRQ_64 0x01 /* Measurement frequency: 64Hz */
+#define CSPEC_MCS 0x07 /* Clock frequency */
+#define CSPEC_MKS 0x01 /* Clock type: CMOS level */
+#define CSPEC_INTEN 0x01 /* Interruption pin enable: Enable */
+
+#define RBUFF_SIZE 31 /* Rx buffer size */
+#define MAX_CALI_SIZE 0x1000U /* calibration buffer size */
+
+/* AK8976A register address */
+#define AKECS_REG_ST 0xC0
+#define AKECS_REG_TMPS 0xC1
+#define AKECS_REG_MS1 0xE0
+#define AKECS_REG_MS2 0xE1
+#define AKECS_REG_MS3 0xE2
+
+#define AKMIO 0xA1
+
+/* IOCTLs for AKM library */
+#define ECS_IOCTL_RESET _IO(AKMIO, 0x04)
+#define ECS_IOCTL_INT_STATUS _IO(AKMIO, 0x05)
+#define ECS_IOCTL_FFD_STATUS _IO(AKMIO, 0x06)
+#define ECS_IOCTL_SET_MODE _IOW(AKMIO, 0x07, short)
+#define ECS_IOCTL_GETDATA _IOR(AKMIO, 0x08, char[RBUFF_SIZE+1])
+#define ECS_IOCTL_GET_NUMFRQ _IOR(AKMIO, 0x09, char[2])
+#define ECS_IOCTL_SET_PERST _IO(AKMIO, 0x0A)
+#define ECS_IOCTL_SET_G0RST _IO(AKMIO, 0x0B)
+#define ECS_IOCTL_SET_YPR _IOW(AKMIO, 0x0C, short[12])
+#define ECS_IOCTL_GET_OPEN_STATUS _IOR(AKMIO, 0x0D, int)
+#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(AKMIO, 0x0E, int)
+#define ECS_IOCTL_GET_CALI_DATA _IOR(AKMIO, 0x0F, char[MAX_CALI_SIZE])
+#define ECS_IOCTL_GET_DELAY _IOR(AKMIO, 0x30, short)
+
+/* IOCTLs for APPs */
+#define ECS_IOCTL_APP_SET_MODE _IOW(AKMIO, 0x10, short)
+#define ECS_IOCTL_APP_SET_MFLAG _IOW(AKMIO, 0x11, short)
+#define ECS_IOCTL_APP_GET_MFLAG _IOW(AKMIO, 0x12, short)
+#define ECS_IOCTL_APP_GET_AFLAG _IOR(AKMIO, 0x14, short)
+#define ECS_IOCTL_APP_SET_TFLAG _IOR(AKMIO, 0x15, short)
+#define ECS_IOCTL_APP_GET_TFLAG _IOR(AKMIO, 0x16, short)
+#define ECS_IOCTL_APP_RESET_PEDOMETER _IO(AKMIO, 0x17)
+#define ECS_IOCTL_APP_GET_DELAY ECS_IOCTL_GET_DELAY
+#define ECS_IOCTL_APP_SET_MVFLAG _IOW(AKMIO, 0x19, short) /* Set raw magnetic vector flag */
+#define ECS_IOCTL_APP_GET_MVFLAG _IOR(AKMIO, 0x1A, short) /* Get raw magnetic vector flag */
+
+/* IOCTLs for pedometer */
+#define ECS_IOCTL_SET_STEP_CNT _IOW(AKMIO, 0x20, short)
+
+#define WMTGSENSOR_IOCTL_MAGIC 0x09
+#define ECS_IOCTL_APP_SET_AFLAG _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x02, short)
+#define ECS_IOCTL_APP_SET_DELAY _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x03, short)
+#define WMT_IOCTL_SENSOR_GET_DRVID _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x04, unsigned int)
+
+//#define MMA8452_DRVID 6
+
+
+
+/* Default GPIO setting */
+#define ECS_RST 146 /*MISC4, bit2 */
+#define ECS_CLK_ON 155 /*MISC5, bit3 */
+#define ECS_INTR 161 /*INT2, bit1 */
+
+/* MISC */
+#define MMA8452_ADDR 0x1C
+#define SENSOR_UI_MODE 0
+#define SENSOR_GRAVITYGAME_MODE 1
+#define UI_SAMPLE_RATE 0xFC
+#define GSENSOR_PROC_NAME "gsensor_config"
+#define sin30_1000 500
+#define cos30_1000 866
+#define DISABLE 0
+#define ENABLE 1
+
+struct mma7660_platform_data {
+ int reset;
+ int clk_on;
+ int intr;
+};
+
+extern char *get_mma_cal_ram(void);
+
+#endif
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/Makefile
new file mode 100755
index 00000000..bdf4598d
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/Makefile
@@ -0,0 +1,4 @@
+s_wmt_msensor_mmc328x-objs += mmc328x.o
+obj-m += s_wmt_msensor_mmc328x.o
+s_wmt_generic_mecs-objs += mecs.o
+obj-m += s_wmt_generic_mecs.o \ No newline at end of file
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mecs.c b/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mecs.c
new file mode 100755
index 00000000..335ad266
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mecs.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2010 MEMSIC, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/freezer.h>
+#include <asm/uaccess.h>
+//#include <linux/export.h>
+#include <linux/module.h>
+#include "mecs.h"
+
+#define DEBUG 0
+
+#define ECS_DATA_DEV_NAME "ecompass_data"
+#define ECS_CTRL_DEV_NAME "ecompass_ctrl"
+
+static int ecs_ctrl_open(struct inode *inode, struct file *file);
+static int ecs_ctrl_release(struct inode *inode, struct file *file);
+static int ecs_ctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+
+static DECLARE_WAIT_QUEUE_HEAD(open_wq);
+
+static atomic_t open_count;
+static atomic_t open_flag;
+static atomic_t reserve_open_flag;
+
+static atomic_t a_flag;
+static atomic_t m_flag;
+static atomic_t o_flag;
+
+static short ecompass_delay = 0;
+
+
+static struct input_dev *ecs_data_device;
+
+static struct file_operations ecs_ctrl_fops = {
+ .owner = THIS_MODULE,
+ .open = ecs_ctrl_open,
+ .release = ecs_ctrl_release,
+ .unlocked_ioctl = ecs_ctrl_ioctl,
+};
+
+static struct miscdevice ecs_ctrl_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = ECS_CTRL_DEV_NAME,
+ .fops = &ecs_ctrl_fops,
+};
+
+static int ecs_ctrl_open(struct inode *inode, struct file *file)
+{
+#if 1
+ atomic_set(&reserve_open_flag, 1);
+ atomic_set(&open_flag, 1);
+ atomic_set(&open_count, 1);
+ wake_up(&open_wq);
+
+ return 0;
+#else
+ int ret = -1;
+
+ if (atomic_cmpxchg(&open_count, 0, 1) == 0) {
+ if (atomic_cmpxchg(&open_flag, 0, 1) == 0) {
+ atomic_set(&reserve_open_flag, 1);
+ wake_up(&open_wq);
+ ret = 0;
+ }
+ }
+
+ return ret;
+#endif
+}
+
+static int ecs_ctrl_release(struct inode *inode, struct file *file)
+{
+ atomic_set(&reserve_open_flag, 0);
+ atomic_set(&open_flag, 0);
+ atomic_set(&open_count, 0);
+ wake_up(&open_wq);
+
+ return 0;
+}
+
+static int ecs_ctrl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void __user *pa = (void __user *)arg;
+ short flag;
+ short delay;
+ int parms[4];
+ int ypr[12];
+ unsigned int uval = 0;
+
+ switch (cmd) {
+ case ECOMPASS_IOC_SET_MODE:
+ break;
+ case ECOMPASS_IOC_SET_DELAY:
+ if (copy_from_user(&delay, pa, sizeof(delay)))
+ return -EFAULT;
+ ecompass_delay = delay;
+ break;
+ case ECOMPASS_IOC_GET_DELAY:
+ delay = ecompass_delay;
+ if (copy_to_user(pa, &delay, sizeof(delay)))
+ return -EFAULT;
+ break;
+
+ case ECOMPASS_IOC_SET_AFLAG:
+ if (copy_from_user(&flag, pa, sizeof(flag)))
+ return -EFAULT;
+ if (flag < 0 || flag > 1)
+ return -EINVAL;
+ atomic_set(&a_flag, flag);
+ break;
+ case ECOMPASS_IOC_GET_AFLAG:
+ flag = atomic_read(&a_flag);
+ if (copy_to_user(pa, &flag, sizeof(flag)))
+ return -EFAULT;
+ break;
+ case ECOMPASS_IOC_SET_MFLAG:
+ if (copy_from_user(&flag, pa, sizeof(flag)))
+ return -EFAULT;
+ if (flag < 0 || flag > 1)
+ return -EINVAL;
+ atomic_set(&m_flag, flag);
+ break;
+ case ECOMPASS_IOC_GET_MFLAG:
+ flag = atomic_read(&m_flag);
+ if (copy_to_user(pa, &flag, sizeof(flag)))
+ return -EFAULT;
+ break;
+ case ECOMPASS_IOC_SET_OFLAG:
+ if (copy_from_user(&flag, pa, sizeof(flag)))
+ return -EFAULT;
+ if (flag < 0 || flag > 1)
+ return -EINVAL;
+ atomic_set(&o_flag, flag);
+ break;
+ case ECOMPASS_IOC_GET_OFLAG:
+ flag = atomic_read(&o_flag);
+ if (copy_to_user(pa, &flag, sizeof(flag)))
+ return -EFAULT;
+ break;
+
+ case ECOMPASS_IOC_SET_APARMS:
+ if (copy_from_user(parms, pa, sizeof(parms)))
+ return -EFAULT;
+ /* acceleration x-axis */
+ input_set_abs_params(ecs_data_device, ABS_X,
+ parms[0], parms[1], parms[2], parms[3]);
+ /* acceleration y-axis */
+ input_set_abs_params(ecs_data_device, ABS_Y,
+ parms[0], parms[1], parms[2], parms[3]);
+ /* acceleration z-axis */
+ input_set_abs_params(ecs_data_device, ABS_Z,
+ parms[0], parms[1], parms[2], parms[3]);
+ break;
+ case ECOMPASS_IOC_GET_APARMS:
+ break;
+ case ECOMPASS_IOC_SET_MPARMS:
+ if (copy_from_user(parms, pa, sizeof(parms)))
+ return -EFAULT;
+ /* magnetic raw x-axis */
+ input_set_abs_params(ecs_data_device, ABS_HAT0X,
+ parms[0], parms[1], parms[2], parms[3]);
+ /* magnetic raw y-axis */
+ input_set_abs_params(ecs_data_device, ABS_HAT0Y,
+ parms[0], parms[1], parms[2], parms[3]);
+ /* magnetic raw z-axis */
+ input_set_abs_params(ecs_data_device, ABS_BRAKE,
+ parms[0], parms[1], parms[2], parms[3]);
+ break;
+ case ECOMPASS_IOC_GET_MPARMS:
+ break;
+ case ECOMPASS_IOC_SET_OPARMS_YAW:
+ if (copy_from_user(parms, pa, sizeof(parms)))
+ return -EFAULT;
+ /* orientation yaw */
+ input_set_abs_params(ecs_data_device, ABS_RX,
+ parms[0], parms[1], parms[2], parms[3]);
+ break;
+ case ECOMPASS_IOC_GET_OPARMS_YAW:
+ break;
+ case ECOMPASS_IOC_SET_OPARMS_PITCH:
+ if (copy_from_user(parms, pa, sizeof(parms)))
+ return -EFAULT;
+ /* orientation pitch */
+ input_set_abs_params(ecs_data_device, ABS_RY,
+ parms[0], parms[1], parms[2], parms[3]);
+ break;
+ case ECOMPASS_IOC_GET_OPARMS_PITCH:
+ break;
+ case ECOMPASS_IOC_SET_OPARMS_ROLL:
+ if (copy_from_user(parms, pa, sizeof(parms)))
+ return -EFAULT;
+ /* orientation roll */
+ input_set_abs_params(ecs_data_device, ABS_RZ,
+ parms[0], parms[1], parms[2], parms[3]);
+ break;
+ case ECOMPASS_IOC_GET_OPARMS_ROLL:
+ break;
+
+ case ECOMPASS_IOC_SET_YPR:
+ if (copy_from_user(ypr, pa, sizeof(ypr)))
+ return -EFAULT;
+ /* Report acceleration sensor information */
+ if (atomic_read(&a_flag)) {
+ input_report_abs(ecs_data_device, ABS_X, ypr[0]);
+ input_report_abs(ecs_data_device, ABS_Y, ypr[1]);
+ input_report_abs(ecs_data_device, ABS_Z, ypr[2]);
+ input_report_abs(ecs_data_device, ABS_WHEEL, ypr[3]);
+ }
+
+ /* Report magnetic sensor information */
+ if (atomic_read(&m_flag)) {
+ input_report_abs(ecs_data_device, ABS_HAT0X, ypr[4]);
+ input_report_abs(ecs_data_device, ABS_HAT0Y, ypr[5]);
+ input_report_abs(ecs_data_device, ABS_BRAKE, ypr[6]);
+ input_report_abs(ecs_data_device, ABS_GAS, ypr[7]);
+ }
+
+ /* Report orientation information */
+ if (atomic_read(&o_flag)) {
+ input_report_abs(ecs_data_device, ABS_RX, ypr[8]);
+ input_report_abs(ecs_data_device, ABS_RY, ypr[9]);
+ input_report_abs(ecs_data_device, ABS_RZ, ypr[10]);
+ input_report_abs(ecs_data_device, ABS_RUDDER, ypr[11]);
+ }
+
+ input_sync(ecs_data_device);
+ break;
+
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ uval = 0;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static ssize_t ecs_ctrl_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+
+ sprintf(buf, "ecompass_ctrl");//!!!
+ ret = strlen(buf) + 1;
+
+ return ret;
+}
+
+static DEVICE_ATTR(ecs_ctrl, S_IRUGO, ecs_ctrl_show, NULL);
+
+//**********************
+static struct input_dev *g_input;
+struct timer_list mytimer;
+static void rep_pwer(long var)
+{
+ static int i = 0;
+ i++;
+#if 0
+ input_report_abs(g_input, ABS_X,i);
+ input_report_abs(g_input, ABS_Y, i);
+ input_report_abs(g_input, ABS_Z, i);
+ //input_report_abs(ecs_data_device, ABS_GAS, 2);
+ input_sync(g_input);
+#endif
+
+ input_report_abs(ecs_data_device, ABS_HAT0X,i);
+ input_report_abs(ecs_data_device, ABS_HAT0Y, i);
+ input_report_abs(ecs_data_device, ABS_BRAKE, i);
+ input_report_abs(ecs_data_device, ABS_GAS, 2);
+ input_sync(ecs_data_device);
+ //printk("<<<<memscid timer\n");
+ mod_timer(&mytimer, jiffies + HZ/10);
+}
+//**********************************
+
+static int __init ecompass_init(void)
+{
+ int res = 0;
+
+ pr_info("ecompass driver: init\n");
+
+ //*******************here want to report KEY_POWER using timer*** to test suspend & resume
+ init_timer(&mytimer);
+ mytimer.function = rep_pwer;
+ mytimer.expires = jiffies + 2*HZ;
+ mytimer.data = 100;
+ // add_timer(&mytimer);
+ printk("<<<<%s add timer ok!\n", __FUNCTION__);
+
+
+ int err=0;
+ g_input=input_allocate_device();
+ if (!g_input)
+ return -ENOMEM;
+ else
+ printk(KERN_INFO "input device allocate Success !!\n");
+ /* Setup input device */
+ set_bit(EV_ABS, g_input->evbit);
+ /* Accelerometer [-78.5, 78.5]m/s2 in Q16 */
+ input_set_abs_params(g_input, ABS_HAT0X, -5144576, 5144576, 0, 0);
+ input_set_abs_params(g_input, ABS_HAT0Y, -5144576, 5144576, 0, 0);
+ input_set_abs_params(g_input, ABS_BRAKE, -5144576, 5144576, 0, 0);
+
+ /* Set InputDevice Name */
+ g_input->name = "ecompass_data";
+
+ /* Register */
+ //err = input_register_device(g_input);
+ //*****************************************2013-4-13
+
+ ecs_data_device = input_allocate_device();
+ if (!ecs_data_device) {
+ res = -ENOMEM;
+ pr_err("%s: failed to allocate input device\n", __FUNCTION__);
+ goto out;
+ }
+
+ set_bit(EV_ABS, ecs_data_device->evbit);
+
+ /* 32768 == 1g, range -4g ~ +4g */
+ /* acceleration x-axis */
+ input_set_abs_params(ecs_data_device, ABS_X,
+ -32768*4, 32768*4, 0, 0);
+ /* acceleration y-axis */
+ input_set_abs_params(ecs_data_device, ABS_Y,
+ -32768*4, 32768*4, 0, 0);
+ /* acceleration z-axis */
+ input_set_abs_params(ecs_data_device, ABS_Z,
+ -32768*4, 32768*4, 0, 0);
+ /* acceleration status, 0 ~ 3 */
+ input_set_abs_params(ecs_data_device, ABS_WHEEL,
+ 0, 100, 0, 0);
+
+ /* 32768 == 1gauss, range -4gauss ~ +4gauss */
+ /* magnetic raw x-axis */
+ input_set_abs_params(ecs_data_device, ABS_HAT0X,
+ -32768*4, 32768*4, 0, 0);
+ /* magnetic raw y-axis */
+ input_set_abs_params(ecs_data_device, ABS_HAT0Y,
+ -32768*4, 32768*4, 0, 0);
+ /* magnetic raw z-axis */
+ input_set_abs_params(ecs_data_device, ABS_BRAKE,
+ -32768*4, 32768*4, 0, 0);
+ /* magnetic raw status, 0 ~ 3 */
+ input_set_abs_params(ecs_data_device, ABS_GAS,
+ 0, 100, 0, 0);
+
+ /* 65536 == 360degree */
+ /* orientation yaw, 0 ~ 360 */
+ input_set_abs_params(ecs_data_device, ABS_RX,
+ 0, 65536, 0, 0);
+ /* orientation pitch, -180 ~ 180 */
+ input_set_abs_params(ecs_data_device, ABS_RY,
+ -65536/2, 65536/2, 0, 0);
+ /* orientation roll, -90 ~ 90 */
+ input_set_abs_params(ecs_data_device, ABS_RZ,
+ -65536/4, 65536/4, 0, 0);
+ /* orientation status, 0 ~ 3 */
+ input_set_abs_params(ecs_data_device, ABS_RUDDER,
+ 0, 100, 0, 0);
+
+ ecs_data_device->name = ECS_DATA_DEV_NAME;
+#if 1
+ res = input_register_device(ecs_data_device);
+ if (res) {
+ pr_err("%s: unable to register input device: %s\n",
+ __FUNCTION__, ecs_data_device->name);
+ goto out_free_input;
+ }
+#endif
+
+ res = misc_register(&ecs_ctrl_device);
+ if (res) {
+ pr_err("%s: ecs_ctrl_device register failed\n", __FUNCTION__);
+ goto out_free_input;
+ }
+ res = device_create_file(ecs_ctrl_device.this_device, &dev_attr_ecs_ctrl);
+ if (res) {
+ pr_err("%s: device_create_file failed\n", __FUNCTION__);
+ goto out_deregister_misc;
+ }
+
+ return 0;
+
+out_deregister_misc:
+ misc_deregister(&ecs_ctrl_device);
+out_free_input:
+ input_free_device(ecs_data_device);
+out:
+ return res;
+}
+
+static void __exit ecompass_exit(void)
+{
+ pr_info("ecompass driver: exit\n");
+ device_remove_file(ecs_ctrl_device.this_device, &dev_attr_ecs_ctrl);
+ misc_deregister(&ecs_ctrl_device);
+ input_free_device(ecs_data_device);
+}
+
+module_init(ecompass_init);
+module_exit(ecompass_exit);
+
+MODULE_DESCRIPTION("MEMSIC eCompass Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mecs.h b/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mecs.h
new file mode 100755
index 00000000..c328e585
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mecs.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2010 MEMSIC, Inc.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * Definitions for ECOMPASS magnetic sensor chip.
+ */
+#ifndef __ECOMPASS_H__
+#define __ECOMPASS_H__
+
+#include <linux/ioctl.h>
+
+/* Use 'e' as magic number */
+#define ECOMPASS_IOM 'e'
+
+/* IOCTLs for ECOMPASS device */
+#define ECOMPASS_IOC_SET_MODE _IOW(ECOMPASS_IOM, 0x00, short)
+#define ECOMPASS_IOC_SET_DELAY _IOW(ECOMPASS_IOM, 0x01, short)
+#define ECOMPASS_IOC_GET_DELAY _IOR(ECOMPASS_IOM, 0x02, short)
+
+#define ECOMPASS_IOC_SET_AFLAG _IOW(ECOMPASS_IOM, 0x10, short)
+#define ECOMPASS_IOC_GET_AFLAG _IOR(ECOMPASS_IOM, 0x11, short)
+#define ECOMPASS_IOC_SET_MFLAG _IOW(ECOMPASS_IOM, 0x12, short)
+#define ECOMPASS_IOC_GET_MFLAG _IOR(ECOMPASS_IOM, 0x13, short)
+#define ECOMPASS_IOC_SET_OFLAG _IOW(ECOMPASS_IOM, 0x14, short)
+#define ECOMPASS_IOC_GET_OFLAG _IOR(ECOMPASS_IOM, 0x15, short)
+
+#define ECOMPASS_IOC_SET_APARMS _IOW(ECOMPASS_IOM, 0x20, int[4])
+#define ECOMPASS_IOC_GET_APARMS _IOR(ECOMPASS_IOM, 0x21, int[4])
+#define ECOMPASS_IOC_SET_MPARMS _IOW(ECOMPASS_IOM, 0x22, int[4])
+#define ECOMPASS_IOC_GET_MPARMS _IOR(ECOMPASS_IOM, 0x23, int[4])
+#define ECOMPASS_IOC_SET_OPARMS_YAW _IOW(ECOMPASS_IOM, 0x24, int[4])
+#define ECOMPASS_IOC_GET_OPARMS_YAW _IOR(ECOMPASS_IOM, 0x25, int[4])
+#define ECOMPASS_IOC_SET_OPARMS_PITCH _IOW(ECOMPASS_IOM, 0x26, int[4])
+#define ECOMPASS_IOC_GET_OPARMS_PITCH _IOR(ECOMPASS_IOM, 0x27, int[4])
+#define ECOMPASS_IOC_SET_OPARMS_ROLL _IOW(ECOMPASS_IOM, 0x28, int[4])
+#define ECOMPASS_IOC_GET_OPARMS_ROLL _IOR(ECOMPASS_IOM, 0x29, int[4])
+
+#define ECOMPASS_IOC_SET_YPR _IOW(ECOMPASS_IOM, 0x30, int[12])
+
+#define WMTGSENSOR_IOCTL_MAGIC 0x09
+#define WMT_IOCTL_SENSOR_GET_DRVID _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x04, unsigned int)
+#endif /* __ECOMPASS_H__ */
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mmc328x.c b/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mmc328x.c
new file mode 100755
index 00000000..4148b5f1
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mmc328x.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright (C) 2011 MEMSIC, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/sysctl.h>
+#include <asm/uaccess.h>
+#include <linux/input.h>
+//#include <linux/mmc328x.h>
+#include "mmc328x.h"
+#define DEBUG 0
+#define MAX_FAILURE_COUNT 3
+#define READMD 0
+
+#define MMC328X_DELAY_TM 10 /* ms */
+#define MMC328X_DELAY_RM 10 /* ms */
+#define MMC328X_DELAY_STDN 1 /* ms */
+#define MMC328X_DELAY_RRM 1 /* ms */
+
+#define MMC328X_RETRY_COUNT 3
+#define MMC328X_RRM_INTV 100
+
+
+//******************************* move from memsicd 2013-4-26
+#define MMC328X_OFFSET_X 4096
+#define MMC328X_OFFSET_Y 4096
+#define MMC328X_OFFSET_Z 4096
+//******************************************
+
+#define MMC328X_DEV_NAME "mmc328x"
+#define CONFIG_SENSORS_MMC328xMA_MAG //add rambo 2013-4-20
+struct i2c_client *g_client;
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static u32 read_idx = 0;
+
+static struct i2c_client *this_client;
+
+static struct wmt_msensor_data l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .samp = 5,
+ .xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },
+ .sensor_proc = NULL,
+ .isdbg = 0,
+ .sensor_samp = 10, // 1 sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ .offset={0,0,0},
+};
+
+static int get_axisset(void)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.msensor328x", varbuf, &varlen)) {
+ printk("Can't get gsensor config in u-boot!!!!\n");
+ //return -1;
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d",
+
+ &(l_sensorconfig.xyz_axis[0][0]),
+ &(l_sensorconfig.xyz_axis[0][1]),
+ &(l_sensorconfig.xyz_axis[1][0]),
+ &(l_sensorconfig.xyz_axis[1][1]),
+ &(l_sensorconfig.xyz_axis[2][0]),
+ &(l_sensorconfig.xyz_axis[2][1])
+
+ );
+ if (n != 6) {
+ printk("gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+ l_sensorconfig.sensor_samp = l_sensorconfig.samp;
+
+ printk("get the sensor config: %d:%d:%d:%d:%d:%d\n",
+
+ l_sensorconfig.xyz_axis[0][0],
+ l_sensorconfig.xyz_axis[0][1],
+ l_sensorconfig.xyz_axis[1][0],
+ l_sensorconfig.xyz_axis[1][1],
+ l_sensorconfig.xyz_axis[2][0],
+ l_sensorconfig.xyz_axis[2][1]
+ );
+ }
+ return 0;
+}
+
+
+static int mmc328x_i2c_rx_data(char *buf, int len)
+{
+ uint8_t i;
+ struct i2c_msg msgs[] = {
+ {
+ .addr = this_client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = buf,
+ },
+ {
+ .addr = this_client->addr,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = buf,
+ }
+ };
+
+ for (i = 0; i < MMC328X_RETRY_COUNT; i++) {
+ if (i2c_transfer(this_client->adapter, msgs, 2) >= 0) {
+ break;
+ }
+ mdelay(10);
+ }
+
+ if (i >= MMC328X_RETRY_COUNT) {
+ pr_err("%s: retry over %d\n", __FUNCTION__, MMC328X_RETRY_COUNT);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int mmc328x_i2c_tx_data(char *buf, int len)
+{
+ uint8_t i;
+ struct i2c_msg msg[] = {
+ {
+ .addr = this_client->addr,
+ .flags = 0,
+ .len = len,
+ .buf = buf,
+ }
+ };
+
+ for (i = 0; i < MMC328X_RETRY_COUNT; i++) {
+ if (i2c_transfer(this_client->adapter, msg, 1) >= 0) {
+ break;
+ }
+ mdelay(10);
+ }
+
+ if (i >= MMC328X_RETRY_COUNT) {
+ pr_err("%s: retry over %d\n", __FUNCTION__, MMC328X_RETRY_COUNT);
+ return -EIO;
+ }
+ return 0;
+}
+
+static int mmc328x_open(struct inode *inode, struct file *file)
+{
+ return nonseekable_open(inode, file);
+}
+
+static int mmc328x_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int mmc328x_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ void __user *pa = (void __user *)arg;
+ unsigned char data[16] = {0};
+ int vec[3] = {0};
+ int tmp[3] = {0};
+
+ int MD_times = 0;
+
+ switch (cmd) {
+ case MMC328X_IOC_TM:
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_TM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ return -EFAULT;
+ }
+ /* wait TM done for coming data read */
+ msleep(MMC328X_DELAY_TM);
+ break;
+ case MMC328X_IOC_RM:
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_RM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ return -EFAULT;
+ }
+ /* wait external capacitor charging done for next SET*/
+ msleep(MMC328X_DELAY_RM);
+ break;
+ case MMC328X_IOC_RRM:
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_RRM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ return -EFAULT;
+ }
+ /* wait external capacitor charging done for next RRM */
+ msleep(MMC328X_DELAY_RM);
+ break;
+ case MMC328X_IOC_READ:
+ data[0] = MMC328X_REG_DATA;
+ if (mmc328x_i2c_rx_data(data, 6) < 0) {
+ return -EFAULT;
+ }
+ tmp[0] = data[1] << 8 | data[0];
+ tmp[1] = data[3] << 8 | data[2];
+ tmp[2] = data[5] << 8 | data[4];
+ tmp[2] = 8192 - tmp[2] ;
+ //add 2013-4-26
+ tmp[0] -= MMC328X_OFFSET_X;
+ tmp[1] -= MMC328X_OFFSET_Y;
+ tmp[2] -= MMC328X_OFFSET_Z;
+ //add end
+ vec[0] = tmp[l_sensorconfig.xyz_axis[0][0]]*l_sensorconfig.xyz_axis[0][1];
+
+ vec[1] = tmp[l_sensorconfig.xyz_axis[1][0]]*l_sensorconfig.xyz_axis[1][1];
+
+ vec[2] = tmp[l_sensorconfig.xyz_axis[2][0]]*l_sensorconfig.xyz_axis[2][1];
+
+ #if DEBUG
+ printk("[X - %04x] [Y - %04x] [Z - %04x]\n",
+ vec[0], vec[1], vec[2]);
+ #endif
+ if (copy_to_user(pa, vec, sizeof(vec))) {
+ return -EFAULT;
+ }
+ break;
+ case MMC328X_IOC_READXYZ:
+ /* do RM every MMC328X_RRM_INTV times read */
+ if (!(read_idx % MMC328X_RRM_INTV)) {
+#ifdef CONFIG_SENSORS_MMC328xMA_MAG
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_RRM;
+ mmc328x_i2c_tx_data(data, 2);
+ msleep(MMC328X_DELAY_RRM);
+#endif
+ /* RM */
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_RM;
+ /* not check return value here, assume it always OK */
+ mmc328x_i2c_tx_data(data, 2);
+ /* wait external capacitor charging done for next RM */
+ msleep(MMC328X_DELAY_RM);
+ }
+ read_idx++;
+
+ /* send TM cmd before read */
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_TM;
+ /* not check return value here, assume it always OK */
+ mmc328x_i2c_tx_data(data, 2);
+ /* wait TM done for coming data read */
+ msleep(MMC328X_DELAY_TM);
+#if READMD
+ /* Read MD */
+ data[0] = MMC328X_REG_DS;
+ if (mmc328x_i2c_rx_data(data, 1) < 0) {
+ return -EFAULT;
+ }
+ while (!(data[0] & 0x01)) {
+ msleep(1);
+ /* Read MD again*/
+ data[0] = MMC328X_REG_DS;
+ if (mmc328x_i2c_rx_data(data, 1) < 0) {
+ return -EFAULT;
+ }
+
+ if (data[0] & 0x01) break;
+ MD_times++;
+ if (MD_times > 2) {
+ #if DEBUG
+ printk("TM not work!!");
+ #endif
+ return -EFAULT;
+ }
+ }
+#endif
+ /* read xyz raw data */
+ data[0] = MMC328X_REG_DATA;
+ if (mmc328x_i2c_rx_data(data, 6) < 0) {
+ return -EFAULT;
+ }
+ tmp[0] = data[1] << 8 | data[0];
+ tmp[1] = data[3] << 8 | data[2];
+ tmp[2] = data[5] << 8 | data[4];
+ tmp[2] = 8192 - tmp[2];
+ //add 2013-4-26
+ tmp[0] -= MMC328X_OFFSET_X;
+ tmp[1] -= MMC328X_OFFSET_Y;
+ tmp[2] -= MMC328X_OFFSET_Z;
+ //add
+ vec[0] = tmp[l_sensorconfig.xyz_axis[0][0]]*l_sensorconfig.xyz_axis[0][1];
+
+ vec[1] = tmp[l_sensorconfig.xyz_axis[1][0]]*l_sensorconfig.xyz_axis[1][1];
+
+ vec[2] = tmp[l_sensorconfig.xyz_axis[2][0]]*l_sensorconfig.xyz_axis[2][1];
+
+
+
+ #if DEBUG
+ printk("[X - %04x] [Y - %04x] [Z - %04x]\n",
+ vec[0], vec[1], vec[2]);
+ #endif
+ if (copy_to_user(pa, vec, sizeof(vec))) {
+ return -EFAULT;
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static ssize_t mmc328x_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+
+ sprintf(buf, "MMC328X");//!!!
+ ret = strlen(buf) + 1;
+
+ return ret;
+}
+
+static DEVICE_ATTR(mmc328x, S_IRUGO, mmc328x_show, NULL);
+
+static struct file_operations mmc328x_fops = {
+ .owner = THIS_MODULE,
+ .open = mmc328x_open,
+ .release = mmc328x_release,
+ .unlocked_ioctl = mmc328x_ioctl,
+};
+
+static struct miscdevice mmc328x_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = MMC328X_DEV_NAME,
+ .fops = &mmc328x_fops,
+};
+
+static int mmc328x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ unsigned char data[16] = {0};
+ int res = 0;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("%s: functionality check failed\n", __FUNCTION__);
+ res = -ENODEV;
+ goto out;
+ }
+ this_client = client;
+
+ res = misc_register(&mmc328x_device);//
+ if (res) {
+ pr_err("%s: mmc328x_device register failed\n", __FUNCTION__);
+ goto out;
+ }
+ res = device_create_file(&client->dev, &dev_attr_mmc328x);//
+ if (res) {
+ pr_err("%s: device_create_file failed\n", __FUNCTION__);
+ goto out_deregister;
+ }
+
+ /* send RM/RRM cmd to mag sensor first of all */
+#ifdef CONFIG_SENSORS_MMC328xMA_MAG
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_RRM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ }
+ msleep(MMC328X_DELAY_RRM);
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_TM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ }
+ msleep(5*MMC328X_DELAY_TM);
+#endif
+
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_RM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ /* assume RM always success */
+ }
+#ifndef CONFIG_SENSORS_MMC328xMA_MAG
+ /* wait external capacitor charging done for next RM */
+ msleep(MMC328X_DELAY_RM);
+#else
+ msleep(10*MMC328X_DELAY_RM);
+ data[0] = MMC328X_REG_CTRL;
+ data[1] = MMC328X_CTRL_TM;
+ if (mmc328x_i2c_tx_data(data, 2) < 0) {
+ }
+#endif
+
+ return 0;
+
+out_deregister:
+ misc_deregister(&mmc328x_device);
+out:
+ return res;
+}
+
+static int mmc328x_remove(struct i2c_client *client)
+{
+ device_remove_file(&client->dev, &dev_attr_mmc328x);
+ misc_deregister(&mmc328x_device);
+
+ return 0;
+}
+
+static const struct i2c_device_id mmc328x_id[] = {
+ { MMC328X_I2C_NAME, 0 },
+ { }
+};
+
+static struct i2c_driver mmc328x_driver = {
+ .probe = mmc328x_probe,
+ .remove = mmc328x_remove,
+ .id_table = mmc328x_id,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = MMC328X_I2C_NAME,
+ },
+};
+
+//****************************add by rambo to create i2c client 2013-4-18
+static struct i2c_board_info mmc328x_board_info =
+{
+ .type = MMC328X_I2C_NAME,
+ .addr = MMC328X_I2C_ADDR,
+};
+
+//******************************************
+
+static int __init mmc328x_init(void)
+{
+ int ret;
+ pr_info("mmc328x driver: init\n");
+
+ ret = get_axisset();
+ struct i2c_adapter *adapter;
+ adapter = i2c_get_adapter(0);
+ if (!adapter)
+ {
+ printk("<<<<<%s i2c get adapter fail!\n", __FUNCTION__);
+ return -1;
+ }
+ g_client = i2c_new_device(adapter, &mmc328x_board_info);
+ if (!g_client)
+ {
+ printk("<<<<%s i2c new device fail!\n", __FUNCTION__);
+ i2c_put_adapter(adapter);
+ return -1;
+ }
+ i2c_put_adapter(adapter);
+
+ return i2c_add_driver(&mmc328x_driver);
+}
+
+static void __exit mmc328x_exit(void)
+{
+ if (g_client != NULL)
+ {
+ i2c_unregister_device(g_client);
+ }
+ pr_info("mmc328x driver: exit\n");
+ i2c_del_driver(&mmc328x_driver);
+}
+
+module_init(mmc328x_init);
+module_exit(mmc328x_exit);
+
+MODULE_DESCRIPTION("MEMSIC MMC328X Magnetic Sensor Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mmc328x.h b/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mmc328x.h
new file mode 100755
index 00000000..f272ea1d
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mmc328x_msensor/mmc328x.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2010 MEMSIC, Inc.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/*
+ * Definitions for mmc328x magnetic sensor chip.
+ */
+#ifndef __MMC328X_H__
+#define __MMC328X_H__
+
+#include <linux/ioctl.h>
+
+#define MMC328X_I2C_NAME "mmc328x"
+
+/*
+ * This address comes must match the part# on your target.
+ * Address to the sensor part# support as following list:
+ * MMC3280MS - 0110000b
+ * MMC3281MS - 0110001b
+ * MMC3282MS - 0110010b
+ * MMC3283MS - 0110011b
+ * MMC3284MS - 0110100b
+ * MMC3285MS - 0110101b
+ * MMC3286MS - 0110110b
+ * MMC3287MS - 0110111b
+ * Please refer to sensor datasheet for detail.
+ */
+ struct wmt_msensor_data{
+ // for control
+ int int_gpio; //0-3
+ int op;
+ int samp;
+ int xyz_axis[3][2]; // (axis,direction)
+ struct proc_dir_entry* sensor_proc;
+ struct input_dev *input_dev;
+ //struct work_struct work;
+ struct delayed_work work; // for polling
+ struct workqueue_struct *queue;
+ int isdbg;
+ int sensor_samp; //
+ int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor
+ int test_pass;
+ int offset[3];
+ struct i2c_client *client;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend earlysuspend;
+#endif
+
+};
+#define MMC328X_I2C_ADDR 0x30
+
+/* MMC328X register address */
+#define MMC328X_REG_CTRL 0x07
+#define MMC328X_REG_DATA 0x00
+#define MMC328X_REG_DS 0x06
+
+/* MMC328X control bit */
+#define MMC328X_CTRL_TM 0x01
+#define MMC328X_CTRL_RM 0x20
+#define MMC328X_CTRL_RRM 0x40
+#define MMC328X_CTRL_NOBOOST 0x10
+
+/* Use 'm' as magic number */
+#define MMC328X_IOM 'm'
+
+/* IOCTLs for MMC328X device */
+#define MMC328X_IOC_TM _IO (MMC328X_IOM, 0x00)
+#define MMC328X_IOC_RM _IO (MMC328X_IOM, 0x01)
+#define MMC328X_IOC_READ _IOR(MMC328X_IOM, 0x02, int[3])
+#define MMC328X_IOC_READXYZ _IOR(MMC328X_IOM, 0x03, int[3])
+#define MMC328X_IOC_RRM _IO (MMC328X_IOM, 0x04)
+#define MMC328X_IOC_NOBOOST _IO (MMC328X_IOM, 0x05)
+
+#endif /* __MMC328X_H__ */
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mxc622x_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/mxc622x_gsensor/Makefile
new file mode 100755
index 00000000..16baea79
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mxc622x_gsensor/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_gsensor_mxc622x
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := mxc622x.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mxc622x_gsensor/mxc622x.c b/ANDROID_3.4.5/drivers/input/sensor/mxc622x_gsensor/mxc622x.c
new file mode 100755
index 00000000..9c94b6ed
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mxc622x_gsensor/mxc622x.c
@@ -0,0 +1,1151 @@
+/******************** (C) COPYRIGHT 2010 STMicroelectronics ********************
+ *
+ * File Name : mxc622x_acc.c
+ * Description : MXC622X accelerometer sensor API
+ *
+ *******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
+ * OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
+ * PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
+ * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+ * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+ * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ *
+ * THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
+ *
+
+ ******************************************************************************/
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/i2c.h>
+
+#include <linux/input.h>
+#include <linux/input-polldev.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+
+#include <linux/workqueue.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/platform_device.h>
+
+#include "mxc622x.h"
+#include "../sensor.h"
+#ifdef CONFIG_ARCH_SC8810
+#include <mach/eic.h>
+#endif
+
+#define G_MAX 16000 /** Maximum polled-device-reported g value */
+#define WHOAMI_MXC622X_ACC 0x25 /* Expctd content for WAI */
+
+/* CONTROL REGISTERS */
+#define WHO_AM_I 0x08 /* WhoAmI register */
+
+#define FUZZ 32
+#define FLAT 32
+#define I2C_RETRY_DELAY 5
+#define I2C_RETRIES 5
+#define I2C_AUTO_INCREMENT 0x80
+
+/* RESUME STATE INDICES */
+
+#define RESUME_ENTRIES 20
+#define DEVICE_INFO "Memsic, MXC622X"
+#define DEVICE_INFO_LEN 32
+
+/* end RESUME STATE INDICES */
+
+#define DEBUG
+//#define MXC622X_DEBUG
+
+#define MAX_INTERVAL 50
+
+#ifdef __KERNEL__
+static struct mxc622x_acc_platform_data mxc622x_plat_data = {
+ .poll_interval = 20,
+ .min_interval = 10,
+};
+#endif
+
+#ifdef I2C_BUS_NUM_STATIC_ALLOC
+static struct i2c_board_info mxc622x_i2c_boardinfo = {
+ I2C_BOARD_INFO(MXC622X_ACC_I2C_NAME, MXC622X_ACC_I2C_ADDR),
+#ifdef __KERNEL__
+ .platform_data = &mxc622x_plat_data
+#endif
+};
+#endif
+
+struct mxc622x_acc_data {
+ struct i2c_client *client;
+ struct mxc622x_acc_platform_data *pdata;
+
+ struct mutex lock;
+ struct delayed_work input_work;
+
+ struct input_dev *input_dev;
+
+ int hw_initialized;
+ /* hw_working=-1 means not tested yet */
+ int hw_working;
+ atomic_t enabled;
+ int on_before_suspend;
+
+ u8 resume_state[RESUME_ENTRIES];
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend early_suspend;
+#endif
+};
+
+/*
+ * Because misc devices can not carry a pointer from driver register to
+ * open, we keep this global. This limits the driver to a single instance.
+ */
+struct mxc622x_acc_data *mxc622x_acc_misc_data;
+struct i2c_client *mxc622x_i2c_client = NULL;
+static struct class* l_dev_class = NULL;
+struct i2c_client *this_client = NULL;
+//////////////////////////////////////////////////////
+struct mx622x_sensordata{
+ // for control
+ int int_gpio; //0-3
+ int op;
+ int samp;
+ int xyz_axis[3][3]; // (axis,direction)
+ struct proc_dir_entry* sensor_proc;
+ struct input_dev *input_dev;
+ //struct work_struct work;
+ struct delayed_work work; // for polling
+ struct workqueue_struct *queue;
+ int isdbg;
+ int sensor_samp; //
+ int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor
+ int test_pass;
+ //int offset[3];
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend earlysuspend;
+#endif
+ s16 offset[3+1]; /*+1: for 4-byte alignment*/
+
+
+};
+
+static struct mx622x_sensordata l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .samp = 16,
+ .xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },
+ .sensor_proc = NULL,
+ .isdbg = 0,
+ .sensor_samp = 1, // 1 sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ //.offset={0,0,0},
+};
+
+//////////////////////////////////////////////////////
+
+
+static int mxc622x_acc_i2c_read(struct mxc622x_acc_data *acc, u8 * buf, int len)
+{
+ int err;
+ int tries = 0;
+
+ struct i2c_msg msgs[] = {
+ {
+ .addr = acc->client->addr,
+ .flags = acc->client->flags & I2C_M_TEN,
+ .len = 1,
+ .buf = buf, },
+ {
+ .addr = acc->client->addr,
+ .flags = (acc->client->flags & I2C_M_TEN) | I2C_M_RD,
+ .len = len,
+ .buf = buf, },
+ };
+
+ do {
+ err = i2c_transfer(acc->client->adapter, msgs, 2);
+ if (err != 2)
+ msleep_interruptible(I2C_RETRY_DELAY);
+ } while ((err != 2) && (++tries < I2C_RETRIES));
+
+ if (err != 2) {
+ dev_err(&acc->client->dev, "read transfer error\n");
+ err = -EIO;
+ } else {
+ err = 0;
+ }
+
+ return err;
+}
+
+static int mxc622x_acc_i2c_write(struct mxc622x_acc_data *acc, u8 * buf, int len)
+{
+ int err;
+ int tries = 0;
+
+ struct i2c_msg msgs[] = { { .addr = acc->client->addr,
+ .flags = acc->client->flags & I2C_M_TEN,
+ .len = len + 1, .buf = buf, }, };
+ do {
+ err = i2c_transfer(acc->client->adapter, msgs, 1);
+ if (err != 1)
+ msleep_interruptible(I2C_RETRY_DELAY);
+ } while ((err != 1) && (++tries < I2C_RETRIES));
+
+ if (err != 1) {
+ dev_err(&acc->client->dev, "write transfer error\n");
+ err = -EIO;
+ } else {
+ err = 0;
+ }
+
+ return err;
+}
+
+static int mxc622x_acc_hw_init(struct mxc622x_acc_data *acc)
+{
+ int err = -1;
+ u8 buf[7];
+
+ printk(KERN_INFO "%s: hw init start\n", MXC622X_ACC_DEV_NAME);
+
+ buf[0] = WHO_AM_I;
+ err = mxc622x_acc_i2c_read(acc, buf, 1);
+ if (err < 0)
+ goto error_firstread;
+ else
+ acc->hw_working = 1;
+ if ((buf[0] & 0x3F) != WHOAMI_MXC622X_ACC) {
+ err = -1; /* choose the right coded error */
+ goto error_unknown_device;
+ }
+
+ acc->hw_initialized = 1;
+ printk(KERN_INFO "%s: hw init done\n", MXC622X_ACC_DEV_NAME);
+ return 0;
+
+error_firstread:
+ acc->hw_working = 0;
+ dev_warn(&acc->client->dev, "Error reading WHO_AM_I: is device "
+ "available/working?\n");
+ goto error1;
+error_unknown_device:
+ dev_err(&acc->client->dev,
+ "device unknown. Expected: 0x%x,"
+ " Replies: 0x%x\n", WHOAMI_MXC622X_ACC, buf[0]);
+error1:
+ acc->hw_initialized = 0;
+ dev_err(&acc->client->dev, "hw init error 0x%x,0x%x: %d\n", buf[0],
+ buf[1], err);
+ return err;
+}
+
+static void mxc622x_acc_device_power_off(struct mxc622x_acc_data *acc)
+{
+ int err;
+ u8 buf[2] = { MXC622X_REG_CTRL, MXC622X_CTRL_PWRDN };
+
+ err = mxc622x_acc_i2c_write(acc, buf, 1);
+ if (err < 0)
+ dev_err(&acc->client->dev, "soft power off failed: %d\n", err);
+}
+
+static int mxc622x_acc_device_power_on(struct mxc622x_acc_data *acc)
+{
+ int err = -1;
+ u8 buf[2] = { MXC622X_REG_CTRL, MXC622X_CTRL_PWRON };
+
+ err = mxc622x_acc_i2c_write(acc, buf, 1);
+ if (err < 0)
+ dev_err(&acc->client->dev, "soft power on failed: %d\n", err);
+
+ if (!acc->hw_initialized) {
+ err = mxc622x_acc_hw_init(acc);
+ if (acc->hw_working == 1 && err < 0) {
+ mxc622x_acc_device_power_off(acc);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+
+/* */
+
+static int mxc622x_acc_register_write(struct mxc622x_acc_data *acc, u8 *buf,
+ u8 reg_address, u8 new_value)
+{
+ int err = -1;
+
+ if (atomic_read(&acc->enabled)) {
+ /* Sets configuration register at reg_address
+ * NOTE: this is a straight overwrite */
+ buf[0] = reg_address;
+ buf[1] = new_value;
+ err = mxc622x_acc_i2c_write(acc, buf, 1);
+ if (err < 0)
+ return err;
+ }
+ return err;
+}
+
+static int mxc622x_acc_register_read(struct mxc622x_acc_data *acc, u8 *buf,
+ u8 reg_address)
+{
+
+ int err = -1;
+ buf[0] = (reg_address);
+ err = mxc622x_acc_i2c_read(acc, buf, 1);
+ return err;
+}
+
+static int mxc622x_acc_register_update(struct mxc622x_acc_data *acc, u8 *buf,
+ u8 reg_address, u8 mask, u8 new_bit_values)
+{
+ int err = -1;
+ u8 init_val;
+ u8 updated_val;
+ err = mxc622x_acc_register_read(acc, buf, reg_address);
+ if (!(err < 0)) {
+ init_val = buf[1];
+ updated_val = ((mask & new_bit_values) | ((~mask) & init_val));
+ err = mxc622x_acc_register_write(acc, buf, reg_address,
+ updated_val);
+ }
+ return err;
+}
+
+/* */
+
+static int mxc622x_acc_get_acceleration_data(struct mxc622x_acc_data *acc,
+ int *xyz)
+{
+ int err = -1;
+ /* Data bytes from hardware x, y */
+ u8 acc_data[2];
+
+ acc_data[0] = MXC622X_REG_DATA;
+ err = mxc622x_acc_i2c_read(acc, acc_data, 2);
+
+ if (err < 0)
+ {
+ #ifdef DEBUG
+ printk(KERN_INFO "%s I2C read error %d\n", MXC622X_ACC_I2C_NAME, err);
+ #endif
+ return err;
+ }
+
+ xyz[0] = (signed char)acc_data[0];
+ xyz[1] = (signed char)acc_data[1];
+ xyz[2] = 8; //32;
+
+ #ifdef MXC622X_DEBUG
+ printk("x = %d, y = %d\n", xyz[0], xyz[1]);
+ #endif
+
+ #ifdef MXC622X_DEBUG
+
+ printk(KERN_INFO "%s read x=%d, y=%d, z=%d\n",
+ MXC622X_ACC_DEV_NAME, xyz[0], xyz[1], xyz[2]);
+ printk(KERN_INFO "%s poll interval %d\n", MXC622X_ACC_DEV_NAME, acc->pdata->poll_interval);
+
+ #endif
+ return err;
+}
+
+static void mxc622x_acc_report_values(struct mxc622x_acc_data *acc, int *xyz)
+{
+ int txyz,tx,ty,tz = 0;
+ static int suf=0; // To report every merging value
+
+ tx = xyz[l_sensorconfig.xyz_axis[0][0]]*l_sensorconfig.xyz_axis[0][1];
+ ty = xyz[l_sensorconfig.xyz_axis[1][0]]*l_sensorconfig.xyz_axis[1][1];
+ tz = xyz[l_sensorconfig.xyz_axis[2][0]]*l_sensorconfig.xyz_axis[2][1];
+ suf++;
+ if (suf > 5)
+ {
+ suf = 0;
+ }
+
+ // packet the x,y,z
+ txyz = (tx&0x00FF) | ((ty&0xFF)<<8) | ((tz&0xFF)<<16) | ((suf&0xFF)<<24);
+ input_report_abs(acc->input_dev, ABS_X, txyz);
+ /*input_report_abs(acc->input_dev, ABS_Y, xyz[1]);
+ input_report_abs(acc->input_dev, ABS_Z, xyz[2]);*/
+ input_sync(acc->input_dev);
+}
+
+static int mxc622x_acc_enable(struct mxc622x_acc_data *acc)
+{
+ int err;
+
+ if (!atomic_cmpxchg(&acc->enabled, 0, 1)) {
+ err = mxc622x_acc_device_power_on(acc);
+ if (err < 0) {
+ atomic_set(&acc->enabled, 0);
+ return err;
+ }
+
+ schedule_delayed_work(&acc->input_work, msecs_to_jiffies(
+ acc->pdata->poll_interval));
+ }
+
+ return 0;
+}
+
+static int mxc622x_acc_disable(struct mxc622x_acc_data *acc)
+{
+ if (atomic_cmpxchg(&acc->enabled, 1, 0)) {
+ cancel_delayed_work_sync(&acc->input_work);
+ mxc622x_acc_device_power_off(acc);
+ }
+
+ return 0;
+}
+
+static int mxc622x_acc_misc_open(struct inode *inode, struct file *file)
+{
+ int err;
+ err = nonseekable_open(inode, file);
+ if (err < 0)
+ return err;
+
+ file->private_data = mxc622x_acc_misc_data;
+
+ return 0;
+}
+
+static /*int*/long mxc622x_acc_misc_ioctl(/*struct inode *inode, */struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ //u8 buf[4];
+ //u8 mask;
+ //u8 reg_address;
+ //u8 bit_values;
+ int err;
+ int interval;
+ int xyz[3] = {0};
+ struct mxc622x_acc_data *acc = file->private_data;
+ unsigned int uval = 0;
+
+// printk(KERN_INFO "%s: %s call with cmd 0x%x and arg 0x%x\n",
+// MXC622X_ACC_DEV_NAME, __func__, cmd, (unsigned int)arg);
+
+ switch (cmd) {
+ case MXC622X_ACC_IOCTL_GET_DELAY:
+ interval = acc->pdata->poll_interval;
+ if (copy_to_user(argp, &interval, sizeof(interval)))
+ return -EFAULT;
+ break;
+
+ //case MXC622X_ACC_IOCTL_SET_DELAY:
+ case ECS_IOCTL_APP_SET_DELAY:
+ if (copy_from_user(&interval, argp, sizeof(interval)))
+ return -EFAULT;
+ if (interval < 0 || interval > 1000)
+ return -EINVAL;
+ //if(interval > MAX_INTERVAL)
+ //interval = MAX_INTERVAL;
+ acc->pdata->poll_interval = max(interval,
+ acc->pdata->min_interval);
+ break;
+
+ //case MXC622X_ACC_IOCTL_SET_ENABLE:
+ case ECS_IOCTL_APP_SET_AFLAG:
+ if (copy_from_user(&interval, argp, sizeof(interval)))
+ return -EFAULT;
+ if (interval > 1)
+ return -EINVAL;
+ if (interval)
+ err = mxc622x_acc_enable(acc);
+ else
+ err = mxc622x_acc_disable(acc);
+ return err;
+ break;
+
+ case MXC622X_ACC_IOCTL_GET_ENABLE:
+ interval = atomic_read(&acc->enabled);
+ if (copy_to_user(argp, &interval, sizeof(interval)))
+ return -EINVAL;
+ break;
+ case MXC622X_ACC_IOCTL_GET_COOR_XYZ:
+ err = mxc622x_acc_get_acceleration_data(acc, xyz);
+ if (err < 0)
+ return err;
+ #ifdef DEBUG
+ // printk(KERN_ALERT "%s Get coordinate xyz:[%d, %d, %d]\n",
+ // __func__, xyz[0], xyz[1], xyz[2]);
+ #endif
+ if (copy_to_user(argp, xyz, sizeof(xyz))) {
+ printk(KERN_ERR " %s %d error in copy_to_user \n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ break;
+ case MXC622X_ACC_IOCTL_GET_CHIP_ID:
+ {
+ u8 devid = 0;
+ u8 devinfo[DEVICE_INFO_LEN] = {0};
+ err = mxc622x_acc_register_read(acc, &devid, WHO_AM_I);
+ if (err < 0) {
+ printk("%s, error read register WHO_AM_I\n", __func__);
+ return -EAGAIN;
+ }
+ sprintf(devinfo, "%s, %#x", DEVICE_INFO, devid);
+
+ if (copy_to_user(argp, devinfo, sizeof(devinfo))) {
+ printk("%s error in copy_to_user(IOCTL_GET_CHIP_ID)\n", __func__);
+ return -EINVAL;
+ }
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+ uval = MXC622X_DRVID;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("mxc622x_driver_id:%d\n",uval);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mxc622x_acc_misc_close(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+
+static const struct file_operations mxc622x_acc_misc_fops = {
+ .owner = THIS_MODULE,
+ .open = mxc622x_acc_misc_open,
+ .unlocked_ioctl = mxc622x_acc_misc_ioctl,
+ .release = mxc622x_acc_misc_close,
+};
+
+static struct miscdevice mxc622x_acc_misc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = GSENSOR_DEV_NODE,//MXC622X_ACC_DEV_NAME,
+ .fops = &mxc622x_acc_misc_fops,
+};
+
+static void mxc622x_acc_input_work_func(struct work_struct *work)
+{
+ struct mxc622x_acc_data *acc;
+
+ int xyz[3] = { 0 };
+ int err;
+
+ acc = mxc622x_acc_misc_data; /*container_of((struct delayed_work *)work,
+ struct mxc622x_acc_data, input_work); */
+
+ mutex_lock(&acc->lock);
+ err = mxc622x_acc_get_acceleration_data(acc, xyz);
+ if (err < 0)
+ dev_err(&acc->client->dev, "get_acceleration_data failed\n");
+ else
+ mxc622x_acc_report_values(acc, xyz);
+
+ schedule_delayed_work(&acc->input_work, msecs_to_jiffies(
+ acc->pdata->poll_interval));
+ mutex_unlock(&acc->lock);
+}
+
+#ifdef MXC622X_OPEN_ENABLE
+int mxc622x_acc_input_open(struct input_dev *input)
+{
+ struct mxc622x_acc_data *acc = input_get_drvdata(input);
+
+ return mxc622x_acc_enable(acc);
+}
+
+void mxc622x_acc_input_close(struct input_dev *dev)
+{
+ struct mxc622x_acc_data *acc = input_get_drvdata(dev);
+
+ mxc622x_acc_disable(acc);
+}
+#endif
+
+static int mxc622x_acc_validate_pdata(struct mxc622x_acc_data *acc)
+{
+ acc->pdata->poll_interval = max(acc->pdata->poll_interval,
+ acc->pdata->min_interval);
+
+ /* Enforce minimum polling interval */
+ if (acc->pdata->poll_interval < acc->pdata->min_interval) {
+ dev_err(&acc->client->dev, "minimum poll interval violated\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mxc622x_acc_input_init(struct mxc622x_acc_data *acc)
+{
+ int err;
+ // Polling rx data when the interrupt is not used.
+ if (1/*acc->irq1 == 0 && acc->irq1 == 0*/) {
+ INIT_DELAYED_WORK(&acc->input_work, mxc622x_acc_input_work_func);
+ }
+
+ acc->input_dev = input_allocate_device();
+ if (!acc->input_dev) {
+ err = -ENOMEM;
+ dev_err(&acc->client->dev, "input device allocate failed\n");
+ goto err0;
+ }
+
+#ifdef MXC622X_ACC_OPEN_ENABLE
+ acc->input_dev->open = mxc622x_acc_input_open;
+ acc->input_dev->close = mxc622x_acc_input_close;
+#endif
+
+ input_set_drvdata(acc->input_dev, acc);
+
+ set_bit(EV_ABS, acc->input_dev->evbit);
+
+ input_set_abs_params(acc->input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
+ input_set_abs_params(acc->input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
+ input_set_abs_params(acc->input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
+
+ acc->input_dev->name = GSENSOR_INPUT_NAME;//MXC622X_ACC_INPUT_NAME;
+
+ err = input_register_device(acc->input_dev);
+ if (err) {
+ dev_err(&acc->client->dev,
+ "unable to register input polled device %s\n",
+ acc->input_dev->name);
+ goto err1;
+ }
+
+ return 0;
+
+err1:
+ input_free_device(acc->input_dev);
+err0:
+ return err;
+}
+
+static void mxc622x_acc_input_cleanup(struct mxc622x_acc_data *acc)
+{
+ input_unregister_device(acc->input_dev);
+ input_free_device(acc->input_dev);
+}
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void mxc622x_early_suspend (struct early_suspend* es);
+static void mxc622x_early_resume (struct early_suspend* es);
+#endif
+
+static int is_mxc622x(struct i2c_client *client)
+{
+ int tempvalue;
+
+ /* read chip id */
+ tempvalue = i2c_smbus_read_word_data(client, WHO_AM_I);
+ if ((tempvalue & 0x003F) == WHOAMI_MXC622X_ACC) {
+ //printk(KERN_INFO "%s I2C driver registered!\n",
+ // MXC622X_ACC_DEV_NAME);
+ return 1;
+ }
+ return 0;
+}
+
+static int mxc622x_acc_probe(struct i2c_client *client)
+{
+
+ struct mxc622x_acc_data *acc;
+
+ int err = -1;
+ int tempvalue;
+
+ pr_info("%s: probe start.\n", MXC622X_ACC_DEV_NAME);
+
+ /*if (client->dev.platform_data == NULL) {
+ dev_err(&client->dev, "platform data is NULL. exiting.\n");
+ err = -ENODEV;
+ goto exit_check_functionality_failed;
+ }*/
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ dev_err(&client->dev, "client not i2c capable\n");
+ err = -ENODEV;
+ goto exit_check_functionality_failed;
+ }
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA |
+ I2C_FUNC_SMBUS_WORD_DATA)) {
+ dev_err(&client->dev, "client not smb-i2c capable:2\n");
+ err = -EIO;
+ goto exit_check_functionality_failed;
+ }
+
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_I2C_BLOCK)){
+ dev_err(&client->dev, "client not smb-i2c capable:3\n");
+ err = -EIO;
+ goto exit_check_functionality_failed;
+ }
+ /*
+ * OK. From now, we presume we have a valid client. We now create the
+ * client structure, even though we cannot fill it completely yet.
+ */
+
+ acc = kzalloc(sizeof(struct mxc622x_acc_data), GFP_KERNEL);
+ if (acc == NULL) {
+ err = -ENOMEM;
+ dev_err(&client->dev,
+ "failed to allocate memory for module data: "
+ "%d\n", err);
+ goto exit_alloc_data_failed;
+ }
+
+ mutex_init(&acc->lock);
+ mutex_lock(&acc->lock);
+
+ acc->client = client;
+ mxc622x_i2c_client = client;
+ i2c_set_clientdata(client, acc);
+
+ /* read chip id */
+ tempvalue = i2c_smbus_read_word_data(client, WHO_AM_I);
+
+ if ((tempvalue & 0x003F) == WHOAMI_MXC622X_ACC) {
+ printk(KERN_INFO "%s I2C driver registered!\n",
+ MXC622X_ACC_DEV_NAME);
+ } else {
+ acc->client = NULL;
+ printk(KERN_INFO "I2C driver not registered!"
+ " Device unknown 0x%x\n", tempvalue);
+ goto err_mutexunlockfreedata;
+ }
+ acc->pdata = kzalloc(sizeof(struct mxc622x_acc_platform_data), GFP_KERNEL);
+ if (acc->pdata == NULL) {
+ err = -ENOMEM;
+ dev_err(&client->dev,
+ "failed to allocate memory for pdata: %d\n",
+ err);
+ goto exit_kfree_pdata;
+ }
+
+ //memcpy(acc->pdata, client->dev.platform_data, sizeof(*acc->pdata));
+ acc->pdata->poll_interval = 20;
+ acc->pdata->min_interval = 10;
+
+ err = mxc622x_acc_validate_pdata(acc);
+ if (err < 0) {
+ dev_err(&client->dev, "failed to validate platform data\n");
+ goto exit_kfree_pdata;
+ }
+
+ i2c_set_clientdata(client, acc);
+
+
+ /*if (acc->pdata->init) {
+ err = acc->pdata->init();
+ if (err < 0) {
+ dev_err(&client->dev, "init failed: %d\n", err);
+ goto err2;
+ }
+ }*/
+
+ err = mxc622x_acc_device_power_on(acc);
+ if (err < 0) {
+ dev_err(&client->dev, "power on failed: %d\n", err);
+ goto err2;
+ }
+
+ atomic_set(&acc->enabled, 1);
+
+ err = mxc622x_acc_input_init(acc);
+ if (err < 0) {
+ dev_err(&client->dev, "input init failed\n");
+ goto err_power_off;
+ }
+ mxc622x_acc_misc_data = acc;
+
+ err = misc_register(&mxc622x_acc_misc_device);
+ if (err < 0) {
+ dev_err(&client->dev,
+ "misc MXC622X_ACC_DEV_NAME register failed\n");
+ goto err_input_cleanup;
+ }
+
+ mxc622x_acc_device_power_off(acc);
+
+ /* As default, do not report information */
+ atomic_set(&acc->enabled, 0);
+
+ acc->on_before_suspend = 0;
+
+ #ifdef CONFIG_HAS_EARLYSUSPEND
+ acc->early_suspend.suspend = mxc622x_early_suspend;
+ acc->early_suspend.resume = mxc622x_early_resume;
+ acc->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
+ register_early_suspend(&acc->early_suspend);
+#endif
+
+ mutex_unlock(&acc->lock);
+
+ dev_info(&client->dev, "%s: probed\n", MXC622X_ACC_DEV_NAME);
+
+ return 0;
+
+err_input_cleanup:
+ mxc622x_acc_input_cleanup(acc);
+err_power_off:
+ mxc622x_acc_device_power_off(acc);
+err2:
+ if (acc->pdata->exit) acc->pdata->exit();
+exit_kfree_pdata:
+ kfree(acc->pdata);
+err_mutexunlockfreedata:
+ kfree(acc);
+ mutex_unlock(&acc->lock);
+ i2c_set_clientdata(client, NULL);
+ mxc622x_acc_misc_data = NULL;
+exit_alloc_data_failed:
+exit_check_functionality_failed:
+ printk(KERN_ERR "%s: Driver Init failed\n", MXC622X_ACC_DEV_NAME);
+ return err;
+}
+
+static int __devexit mxc622x_acc_remove(struct i2c_client *client)
+{
+ /* TODO: revisit ordering here once _probe order is finalized */
+ struct mxc622x_acc_data *acc = mxc622x_acc_misc_data;//i2c_get_clientdata(client);
+
+ misc_deregister(&mxc622x_acc_misc_device);
+ mxc622x_acc_input_cleanup(acc);
+ mxc622x_acc_device_power_off(acc);
+ if (acc->pdata->exit)
+ acc->pdata->exit();
+ kfree(acc->pdata);
+ kfree(acc);
+
+ return 0;
+}
+
+static int mxc622x_acc_resume(struct platform_device *pdev)
+{
+ struct mxc622x_acc_data *acc = mxc622x_acc_misc_data;
+
+ if (acc != NULL && acc->on_before_suspend) {
+ acc->on_before_suspend = 0;
+ acc->hw_initialized = 0;
+ return mxc622x_acc_enable(acc);
+ }
+ return 0;
+}
+
+static int mxc622x_acc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct mxc622x_acc_data *acc = mxc622x_acc_misc_data;
+ if (acc != NULL) {
+ if (atomic_read(&acc->enabled)) {
+ acc->on_before_suspend = 1;
+ return mxc622x_acc_disable(acc);
+ }
+ }
+ return 0;
+}
+
+static int mxc622x_probe(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int mxc622x_remove(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct platform_driver mxc622x_driver = {
+ .probe = mxc622x_probe,
+ .remove = mxc622x_remove,
+ .suspend = mxc622x_acc_suspend,
+ .resume = mxc622x_acc_resume,
+ .driver = {
+ .name = GSENSOR_I2C_NAME,
+ },
+};
+
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+
+static void mxc622x_early_suspend (struct early_suspend* es)
+{
+ struct mxc622x_acc_data *acc = mxc622x_acc_misc_data; //i2c_get_clientdata(client);
+#ifdef MXC622X_DEBUG
+ printk("%s.\n", __func__);
+#endif
+ if (acc != NULL) {
+ if (atomic_read(&acc->enabled)) {
+ acc->on_before_suspend = 1;
+ return mxc622x_acc_disable(acc);
+ }
+ }
+}
+
+static void mxc622x_early_resume (struct early_suspend* es)
+{
+ struct mxc622x_acc_data *acc = mxc622x_acc_misc_data; //i2c_get_clientdata(client);
+#ifdef MXC622X_DEBUG
+ printk("%s.\n", __func__);
+#endif
+
+ if (acc != NULL && acc->on_before_suspend) {
+ acc->on_before_suspend = 0;
+ acc->hw_initialized = 0;
+ return mxc622x_acc_enable(acc);
+ }
+
+}
+
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+
+static const struct i2c_device_id mxc622x_acc_id[]
+ = { { MXC622X_ACC_DEV_NAME, 0 }, { }, };
+
+MODULE_DEVICE_TABLE(i2c, mxc622x_acc_id);
+
+#if 0
+static struct i2c_driver mxc622x_acc_driver = {
+ .driver = {
+ .name = MXC622X_ACC_I2C_NAME,
+ },
+ .probe = mxc622x_acc_probe,
+ .remove = __devexit_p(mxc622x_acc_remove),
+ .resume = mxc622x_acc_resume,
+ .suspend = mxc622x_acc_suspend,
+ .id_table = mxc622x_acc_id,
+};
+#endif
+
+#ifdef I2C_BUS_NUM_STATIC_ALLOC
+
+int i2c_static_add_device(struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter;
+ struct i2c_client *client;
+ int err;
+
+ adapter = i2c_get_adapter(I2C_STATIC_BUS_NUM);
+ if (!adapter) {
+ pr_err("%s: can't get i2c adapter\n", __FUNCTION__);
+ err = -ENODEV;
+ goto i2c_err;
+ }
+
+ client = i2c_new_device(adapter, info);
+ if (!client) {
+ pr_err("%s: can't add i2c device at 0x%x\n",
+ __FUNCTION__, (unsigned int)info->addr);
+ err = -ENODEV;
+ goto i2c_err;
+ }
+
+ i2c_put_adapter(adapter);
+
+ return 0;
+
+i2c_err:
+ return err;
+}
+
+#endif /*I2C_BUS_NUM_STATIC_ALLOC*/
+
+static void mxc622x_platform_release(struct device *device)
+{
+ dbg("...\n");
+ return;
+}
+
+
+static struct platform_device mxc622x_device = {
+ .name = GSENSOR_I2C_NAME,
+ .id = 0,
+ .dev = {
+ .release = mxc622x_platform_release,
+ },
+};
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static int get_axisset(void* param)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+
+ int tmp_offset[3] = {0};
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.mxc622xsensor", varbuf, &varlen)) {
+ errlog("Can't get gsensor config in u-boot!!!!\n");
+ return -1;
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &l_sensorconfig.op,
+ &l_sensorconfig.int_gpio,
+ &l_sensorconfig.samp,
+ &(l_sensorconfig.xyz_axis[0][0]),
+ &(l_sensorconfig.xyz_axis[0][1]),
+ &(l_sensorconfig.xyz_axis[1][0]),
+ &(l_sensorconfig.xyz_axis[1][1]),
+ &(l_sensorconfig.xyz_axis[2][0]),
+ &(l_sensorconfig.xyz_axis[2][1]),
+ &tmp_offset[0],
+ &tmp_offset[1],
+ &tmp_offset[2]
+ );
+ if (n != 12) {
+ printk(KERN_ERR "gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+ l_sensorconfig.offset[0] = tmp_offset[0];
+ l_sensorconfig.offset[1] = tmp_offset[1];
+ l_sensorconfig.offset[2] = tmp_offset[2];
+ l_sensorconfig.sensor_samp = l_sensorconfig.samp;
+
+ dbg("get the sensor config: %d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ l_sensorconfig.op,
+ l_sensorconfig.int_gpio,
+ l_sensorconfig.samp,
+ l_sensorconfig.xyz_axis[0][0],
+ l_sensorconfig.xyz_axis[0][1],
+ l_sensorconfig.xyz_axis[1][0],
+ l_sensorconfig.xyz_axis[1][1],
+ l_sensorconfig.xyz_axis[2][0],
+ l_sensorconfig.xyz_axis[2][1],
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+ }
+ return 0;
+}
+
+
+static int __init mxc622x_acc_init(void)
+{
+ int ret = 0;
+
+ printk(KERN_INFO "%s accelerometer driver: init\n",
+ MXC622X_ACC_I2C_NAME);
+ ret = get_axisset(NULL);
+ if (ret < 0)
+ {
+ printk("<<<<<%s user choose to no sensor chip!\n", __func__);
+ return ret;
+ }
+
+ if (!(this_client = sensor_i2c_register_device(0, GSENSOR_I2C_ADDR, GSENSOR_I2C_NAME)))
+ {
+ printk(KERN_EMERG"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+ if(!is_mxc622x(this_client))
+ {
+ dbg("isn't mxc622x gsensor!\n");
+ return -1;
+ }
+ // parse g-sensor u-boot arg
+
+ /*if (ret)
+ {
+ errlog("only for test!\n");
+ return -1;
+ }*/
+#ifdef I2C_BUS_NUM_STATIC_ALLOC
+ ret = i2c_static_add_device(&mxc622x_i2c_boardinfo);
+ if (ret < 0) {
+ pr_err("%s: add i2c device error %d\n", __FUNCTION__, ret);
+ goto init_err;
+ }
+#endif
+ ret = mxc622x_acc_probe(this_client);
+ if (ret)
+ {
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+ }
+ // create the platform device
+ l_dev_class = class_create(THIS_MODULE, GSENSOR_I2C_NAME);
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create gsensor device !!\n");
+ return ret;
+ }
+ if((ret = platform_device_register(&mxc622x_device)))
+ {
+ klog("Can't register mc3230 platform devcie!!!\n");
+ return ret;
+ }
+ if ((ret = platform_driver_register(&mxc622x_driver)) != 0)
+ {
+ errlog("Can't register mc3230 platform driver!!!\n");
+ return ret;
+ }
+
+ //return i2c_add_driver(&mxc622x_acc_driver);
+
+init_err:
+ return ret;
+}
+
+static void __exit mxc622x_acc_exit(void)
+{
+ //printk(KERN_INFO "%s accelerometer driver exit\n", MXC622X_ACC_DEV_NAME);
+
+ platform_driver_unregister(&mxc622x_driver);
+ platform_device_unregister(&mxc622x_device);
+ class_destroy(l_dev_class);
+ mxc622x_acc_remove(mxc622x_i2c_client);
+ sensor_i2c_unregister_device(this_client);
+ #ifdef I2C_BUS_NUM_STATIC_ALLOC
+ i2c_unregister_device(mxc622x_i2c_client);
+ #endif
+
+ //i2c_del_driver(&mxc622x_acc_driver);
+ return;
+}
+
+module_init(mxc622x_acc_init);
+module_exit(mxc622x_acc_exit);
+
+MODULE_DESCRIPTION("mxc622x accelerometer misc driver");
+MODULE_AUTHOR("Memsic");
+MODULE_LICENSE("GPL");
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/mxc622x_gsensor/mxc622x.h b/ANDROID_3.4.5/drivers/input/sensor/mxc622x_gsensor/mxc622x.h
new file mode 100755
index 00000000..2b83bb7b
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/mxc622x_gsensor/mxc622x.h
@@ -0,0 +1,83 @@
+
+/******************** (C) COPYRIGHT 2010 STMicroelectronics ********************
+*
+* File Name : mxc622x.h
+* Authors : MH - C&I BU - Application Team
+*
+********************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
+* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
+* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*
+* THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
+*
+*******************************************************************************/
+
+
+#ifndef __MXC622X_H__
+#define __MXC622X_H__
+
+#include <linux/ioctl.h> /* For IOCTL macros */
+#include <linux/input.h>
+
+#ifndef DEBUG
+#define DEBUG
+#endif
+
+#define GSENSOR_I2C_NAME "mxc622x"
+#define GSENSOR_I2C_ADDR 0x15
+
+#define MXC622X_ACC_IOCTL_BASE 77
+/** The following define the IOCTL command values via the ioctl macros */
+#define MXC622X_ACC_IOCTL_SET_DELAY _IOW(MXC622X_ACC_IOCTL_BASE, 0, int)
+#define MXC622X_ACC_IOCTL_GET_DELAY _IOR(MXC622X_ACC_IOCTL_BASE, 1, int)
+#define MXC622X_ACC_IOCTL_SET_ENABLE _IOW(MXC622X_ACC_IOCTL_BASE, 2, int)
+#define MXC622X_ACC_IOCTL_GET_ENABLE _IOR(MXC622X_ACC_IOCTL_BASE, 3, int)
+#define MXC622X_ACC_IOCTL_GET_COOR_XYZ _IOW(MXC622X_ACC_IOCTL_BASE, 22, int)
+#define MXC622X_ACC_IOCTL_GET_CHIP_ID _IOR(MXC622X_ACC_IOCTL_BASE, 255, char[32])
+
+/************************************************/
+/* Accelerometer defines section */
+/************************************************/
+#define MXC622X_ACC_DEV_NAME "mxc622x"
+#define MXC622X_ACC_INPUT_NAME "accelerometer"
+#define MXC622X_ACC_I2C_ADDR 0x15
+#define MXC622X_ACC_I2C_NAME MXC622X_ACC_DEV_NAME
+
+/* MXC622X register address */
+#define MXC622X_REG_CTRL 0x04
+#define MXC622X_REG_DATA 0x00
+
+/* MXC622X control bit */
+#define MXC622X_CTRL_PWRON 0x00 /* power on */
+#define MXC622X_CTRL_PWRDN 0x80 /* power donw */
+
+//#if defined(CONFIG_MACH_SP6810A)
+//#define I2C_BUS_NUM_STATIC_ALLOC
+#define I2C_STATIC_BUS_NUM ( 0) // Need to be modified according to actual setting
+//#endif
+
+struct mxc622x_acc_platform_data {
+ int poll_interval;
+ int min_interval;
+
+ int (*init)(void);
+ void (*exit)(void);
+ int (*power_on)(void);
+ int (*power_off)(void);
+
+};
+
+#endif /* __MXC622X_H__ */
+
+
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/sensor.c b/ANDROID_3.4.5/drivers/input/sensor/sensor.c
new file mode 100755
index 00000000..5a82a9fb
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/sensor.c
@@ -0,0 +1,114 @@
+#include <linux/i2c.h>
+#include <linux/export.h>
+//#include <linux/mutex.h>
+#include "sensor.h"
+//DEFINE_MUTEX(mutex_client);
+//static struct i2c_client *sensor_client=NULL;
+struct i2c_client *sensor_i2c_register_device(int bus_no, int client_addr, const char *client_name)
+{
+ struct i2c_adapter *adapter = NULL;
+ struct i2c_client *sensor_client=NULL;
+
+ struct i2c_board_info sensor_i2c_board_info = {
+ .type = "unused",
+ .flags = 0x00,
+ .addr = 0xff,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+ };
+
+ if ((bus_no<0) || (client_addr>0x7f) || (client_addr<0)|| (!client_name))
+ {
+ printk(KERN_ERR "%s param error! pls check out!\n", __FUNCTION__);
+ return NULL;
+ }
+ printk(KERN_INFO "%s busno %d client_addr 0x%x client_name %s \n", __FUNCTION__, \
+ bus_no, client_addr, client_name);
+
+ sensor_i2c_board_info.addr = client_addr;
+ //sensor_i2c_board_info.type = client_name;
+ strcpy(sensor_i2c_board_info.type, client_name);
+
+ adapter = i2c_get_adapter(bus_no);/*in bus NR*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return NULL;
+ }
+
+ //mutex_lock(&mutex_client);
+ sensor_client = i2c_new_device(adapter, &sensor_i2c_board_info);
+
+
+ if (sensor_client == NULL) {
+ printk("allocate i2c client failed\n");
+ //mutex_unlock(&mutex_client);
+ return NULL;
+ }
+ i2c_put_adapter(adapter);
+ //mutex_unlock(&mutex_client);
+
+ return sensor_client;
+}
+EXPORT_SYMBOL(sensor_i2c_register_device);
+
+struct i2c_client *sensor_i2c_register_device2(int bus_no, int client_addr, const char *client_name,void *pdata)
+{
+ struct i2c_adapter *adapter = NULL;
+ struct i2c_client *sensor_client=NULL;
+
+ struct i2c_board_info sensor_i2c_board_info = {
+ .type = "unused",
+ .flags = 0x00,
+ .addr = 0xff,
+ .platform_data = NULL,
+ .archdata = NULL,
+ .irq = -1,
+ };
+
+ if ((bus_no<0) || (client_addr>0x7f) || (client_addr<0)|| (!client_name))
+ {
+ printk(KERN_ERR "%s param error! pls check out!\n", __FUNCTION__);
+ return NULL;
+ }
+ printk(KERN_INFO "%s busno %d client_addr 0x%x client_name %s \n", __FUNCTION__, \
+ bus_no, client_addr, client_name);
+
+ sensor_i2c_board_info.addr = client_addr;
+ sensor_i2c_board_info.platform_data = pdata;
+ //sensor_i2c_board_info.type = client_name;
+ strcpy(sensor_i2c_board_info.type, client_name);
+
+ adapter = i2c_get_adapter(bus_no);/*in bus NR*/
+
+ if (NULL == adapter) {
+ printk("can not get i2c adapter, client address error\n");
+ return NULL;
+ }
+
+ //mutex_lock(&mutex_client);
+ sensor_client = i2c_new_device(adapter, &sensor_i2c_board_info);
+
+
+ if (sensor_client == NULL) {
+ printk("allocate i2c client failed\n");
+ //mutex_unlock(&mutex_client);
+ return NULL;
+ }
+ i2c_put_adapter(adapter);
+ //mutex_unlock(&mutex_client);
+
+ return sensor_client;
+}
+EXPORT_SYMBOL(sensor_i2c_register_device2);
+
+void sensor_i2c_unregister_device(struct i2c_client *client)
+{
+ if (client != NULL)
+ {
+ i2c_unregister_device(client);
+ }
+}
+EXPORT_SYMBOL(sensor_i2c_unregister_device);
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/sensor.h b/ANDROID_3.4.5/drivers/input/sensor/sensor.h
new file mode 100755
index 00000000..9a51433d
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/sensor.h
@@ -0,0 +1,91 @@
+#ifndef __SENSOR_H__
+#define __SENSOR_H__
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/proc_fs.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+
+
+//#define GSENSOR_I2C_NAME "unused"
+//#define GSENSOR_I2C_ADDR 0xff
+
+
+#define GSENSOR_PROC_NAME "gsensor_config"
+#define GSENSOR_INPUT_NAME "g-sensor"
+#define GSENSOR_DEV_NODE "sensor_ctrl"
+
+#define SENSOR_PROC_NAME "lsensor_config"
+#define SENSOR_INPUT_NAME "l-sensor"
+#define SENSOR_DEV_NODE "lsensor_ctrl"
+
+#undef dbg
+#define dbg(fmt, args...) if (l_sensorconfig.isdbg) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk(KERN_ERR "[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+enum gsensor_id
+{
+ MMA7660_DRVID = 0,
+ MC3230_DRVID ,
+ DMARD08_DRVID ,
+ DMARD06_DRVID ,
+ DMARD10_DRVID ,
+ MXC622X_DRVID ,
+ MMA8452Q_DRVID ,
+ STK8312_DRVID ,
+ KIONIX_DRVID,
+ DMARD09_DRVID ,
+ //add new gsensor id here, must be in order
+};
+
+#define ISL29023_DRVID 0
+
+struct wmt_gsensor_data{
+ // for control
+ int int_gpio; //0-3
+ int op;
+ int samp;
+ int xyz_axis[3][2]; // (axis,direction)
+ struct proc_dir_entry* sensor_proc;
+ struct input_dev *input_dev;
+ //struct work_struct work;
+ struct delayed_work work; // for polling
+ struct workqueue_struct *queue;
+ int isdbg;
+ int sensor_samp; //
+ int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor
+ int test_pass;
+ int offset[3];
+ struct i2c_client *client;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend earlysuspend;
+#endif
+
+};
+
+///////////////////////// ioctrl cmd ////////////////////////
+#define WMTGSENSOR_IOCTL_MAGIC 0x09
+#define WMT_IOCTL_SENSOR_CAL_OFFSET _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x01, int) //offset calibration
+#define ECS_IOCTL_APP_SET_AFLAG _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x02, short)
+#define ECS_IOCTL_APP_SET_DELAY _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x03, short)
+#define WMT_IOCTL_SENSOR_GET_DRVID _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x04, unsigned int)
+#define WMT_IOCTL_SENOR_GET_RESOLUTION _IOR(WMTGSENSOR_IOCTL_MAGIC, 0x05, short)
+
+#define WMT_LSENSOR_IOCTL_MAGIC 0x10
+#define LIGHT_IOCTL_SET_ENABLE _IOW(WMT_LSENSOR_IOCTL_MAGIC, 0x01, short)
+
+/* Function prototypes */
+extern struct i2c_client *sensor_i2c_register_device (int bus_no, int client_addr, const char *client_name);
+extern struct i2c_client *sensor_i2c_register_device2(int bus_no, int client_addr, const char *client_name,void *pdata);
+extern void sensor_i2c_unregister_device(struct i2c_client *client);
+
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/sensor/stk3310/Makefile b/ANDROID_3.4.5/drivers/input/sensor/stk3310/Makefile
new file mode 100755
index 00000000..19a79f84
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/stk3310/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_lsensor_stk3310
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := stk3310.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/stk3310/stk3310.c b/ANDROID_3.4.5/drivers/input/sensor/stk3310/stk3310.c
new file mode 100755
index 00000000..4e9fde10
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/stk3310/stk3310.c
@@ -0,0 +1,644 @@
+/*
+ * stk3310.c - stk3310 ALS & Proximity Driver
+ *
+ * By Intersil Corp
+ * Michael DiGioia
+ *
+ * Based on isl29011.c
+ * by Mike DiGioia <mdigioia@intersil.com>
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/hwmon.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/pm_runtime.h>
+#include <linux/input-polldev.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+//#include <linux/earlysuspend.h>
+#include <linux/platform_device.h>
+#include "../sensor.h"
+#define SENSOR_I2C_NAME "stk3310"
+#define SENSOR_I2C_ADDR 0x48
+
+#undef dbg
+#define dbg(fmt, args...)
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk(KERN_ERR "[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+/* Insmod parameters */
+//I2C_CLIENT_INSMOD_1(stk3310);
+
+#define MODULE_NAME "stk3310"
+
+
+struct stk_device {
+ struct input_polled_dev* input_poll_devl;
+ struct input_polled_dev* input_poll_devp;
+ struct i2c_client* client;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend earlysuspend;
+#endif
+
+};
+
+static struct stk_device* l_sensorconfig = NULL;
+static int l_enable = 1; // 0:don't report data
+static int p_enable = 1; // 0:don't report data
+
+static struct i2c_client *this_client = NULL;
+
+static DEFINE_MUTEX(mutex);
+
+static int isl_get_lux_datal(struct i2c_client* client)
+{
+ __u16 resH, resL;
+ resL = i2c_smbus_read_byte_data(client, 0x14);
+ resH = i2c_smbus_read_byte_data(client, 0x13);
+ if ((resL < 0) || (resH < 0))
+ {
+ errlog("Error to read lux_data!\n");
+ return -1;
+ }
+ return (resH <<8 | resL) ;//* idev->range / idev->resolution;
+}
+
+
+static int isl_get_lux_datap(struct i2c_client* client)
+{
+ __u16 resH, resL;
+ resL = i2c_smbus_read_byte_data(client, 0x12);
+ resH = i2c_smbus_read_byte_data(client, 0x11);
+ if ((resL < 0) || (resH < 0))
+ {
+ errlog("Error to read lux_data!\n");
+ return -1;
+ }
+ //return (resH <<8 | resL) ;//* idev->range / idev->resolution;
+ if(resH>0)
+ return 0;
+ else
+ return 6;
+}
+
+//#define PXM 0
+static int isl_set_default_config(struct i2c_client *client)
+{
+ int ret=0;
+ unsigned char regval;
+//#if PXM
+ ret = i2c_smbus_write_byte_data(client, 0, (1 << 1));
+ if(p_enable)
+ {
+ regval = i2c_smbus_read_byte_data(l_sensorconfig->client, 0);
+ regval |= (1 << 0);
+ i2c_smbus_write_byte_data(l_sensorconfig->client, 0, regval);
+ }
+ //ret = i2c_smbus_write_byte_data(client, 0, (1 << 0));
+//#else
+//#endif
+ if (ret < 0)
+ return -EINVAL;
+ return 0;
+}
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int stk3310_detect(struct i2c_client *client/*, int kind,
+ struct i2c_board_info *info*/)
+{
+ int device;
+
+ device= i2c_smbus_read_byte_data(client, 0x3e);
+ if(0x13==device)
+ {
+ printk(KERN_ALERT "stk3310 detected OK\n");
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int isl_input_open(struct input_dev* input)
+{
+ return 0;
+}
+
+void isl_input_close(struct input_dev* input)
+{
+}
+
+static void isl_input_lux_poll_l(struct input_polled_dev *dev)
+{
+ struct stk_device* idev = dev->private;
+ struct input_dev* input = idev->input_poll_devl->input;
+ struct i2c_client* client = idev->client;
+ if (l_enable != 0)
+ {
+ mutex_lock(&mutex);
+ //printk(KERN_ALERT "by flashchen val is %x",val);
+ input_report_abs(input, ABS_MISC, isl_get_lux_datal(client));
+ input_sync(input);
+ mutex_unlock(&mutex);
+ }
+}
+
+static void isl_input_lux_poll_p(struct input_polled_dev *dev)
+{
+ struct stk_device* idev = dev->private;
+ struct input_dev* input = idev->input_poll_devp->input;
+ struct i2c_client* client = idev->client;
+ if (p_enable != 0)
+ {
+ mutex_lock(&mutex);
+ //printk(KERN_ALERT "by flashchen val is %x",val);
+ input_report_abs(input, ABS_MISC, isl_get_lux_datap(client));
+ input_sync(input);
+ mutex_unlock(&mutex);
+ }
+}
+
+static struct i2c_device_id stk3310_id[] = {
+ {"stk3310", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, stk3310_id);
+
+
+static int mmad_open(struct inode *inode, struct file *file)
+{
+ dbg("Open the l-sensor node...\n");
+ return 0;
+}
+
+static int mmad_release(struct inode *inode, struct file *file)
+{
+ dbg("Close the l-sensor node...\n");
+ return 0;
+}
+
+static ssize_t mmadl_read(struct file *fl, char __user *buf, size_t cnt, loff_t *lf)
+{
+ int lux_data = 0;
+
+ mutex_lock(&mutex);
+ lux_data = isl_get_lux_datal(l_sensorconfig->client);
+ mutex_unlock(&mutex);
+ if (lux_data < 0)
+ {
+ errlog("Failed to read lux data!\n");
+ return -1;
+ }
+ printk(KERN_ALERT "lux_data is %x\n",lux_data);
+ return 0;
+ copy_to_user(buf, &lux_data, sizeof(lux_data));
+ return sizeof(lux_data);
+}
+
+
+static ssize_t mmadp_read(struct file *fl, char __user *buf, size_t cnt, loff_t *lf)
+{
+ int lux_data = 0;
+
+ mutex_lock(&mutex);
+ lux_data = isl_get_lux_datap(l_sensorconfig->client);
+ mutex_unlock(&mutex);
+ if (lux_data < 0)
+ {
+ errlog("Failed to read lux data!\n");
+ return -1;
+ }
+ printk(KERN_ALERT "lux_data is %x\n",lux_data);
+ return 0;
+ copy_to_user(buf, &lux_data, sizeof(lux_data));
+ return sizeof(lux_data);
+}
+
+static long
+mmadl_ioctl(/*struct inode *inode,*/ struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ //char rwbuf[5];
+ short enable; //amsr = -1;
+ unsigned int uval;
+
+ dbg("l-sensor ioctr...\n");
+ //memset(rwbuf, 0, sizeof(rwbuf));
+ switch (cmd) {
+ case LIGHT_IOCTL_SET_ENABLE:
+ // enable/disable sensor
+ if (copy_from_user(&enable, argp, sizeof(short)))
+ {
+ printk(KERN_ERR "Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ dbg("enable=%d\n",enable);
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor.\n", enable);
+
+ //l_sensorconfig.sensor_enable = enable;
+ dbg("Should to implement d/e the light sensor!\n");
+ l_enable = enable;
+
+ } else {
+ printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+#define DRVID 0
+ uval = DRVID ;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("stk3310_driver_id:%d\n",uval);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+static long
+mmadp_ioctl(/*struct inode *inode,*/ struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ //char rwbuf[5];
+ short enable; //amsr = -1;
+ unsigned int uval;
+ unsigned char regval;
+
+ dbg("l-sensor ioctr...\n");
+ //memset(rwbuf, 0, sizeof(rwbuf));
+ switch (cmd) {
+ case LIGHT_IOCTL_SET_ENABLE:
+ // enable/disable sensor
+ if (copy_from_user(&enable, argp, sizeof(short)))
+ {
+ printk(KERN_ERR "Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ dbg("enable=%d\n",enable);
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor.\n", enable);
+
+ //l_sensorconfig.sensor_enable = enable;
+ dbg("Should to implement d/e the light sensor!\n");
+ p_enable = enable;
+ if(p_enable)
+ {
+ regval = i2c_smbus_read_byte_data(l_sensorconfig->client, 0);
+ regval |= (1 << 0);
+ i2c_smbus_write_byte_data(l_sensorconfig->client, 0, regval);
+ }
+ else
+ {
+ regval = i2c_smbus_read_byte_data(l_sensorconfig->client, 0);
+ regval &= ~(1 << 0);
+ i2c_smbus_write_byte_data(l_sensorconfig->client, 0, regval);
+ }
+
+ } else {
+ printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+#define DRVID 0
+ uval = DRVID ;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("stk3310_driver_id:%d\n",uval);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+static struct file_operations mmadl_fops = {
+ .owner = THIS_MODULE,
+ .open = mmad_open,
+ .release = mmad_release,
+ .read = mmadl_read,
+ .unlocked_ioctl = mmadl_ioctl,
+};
+
+static struct miscdevice mmadl_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "lsensor_ctrl",
+ .fops = &mmadl_fops,
+};
+
+static struct file_operations mmadp_fops = {
+ .owner = THIS_MODULE,
+ .open = mmad_open,
+ .release = mmad_release,
+ .read = mmadp_read,
+ .unlocked_ioctl = mmadp_ioctl,
+};
+
+static struct miscdevice mmadp_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "psensor_ctrl",
+ .fops = &mmadp_fops,
+};
+#if 0
+static void stk3310_early_suspend(struct early_suspend *h)
+{
+ dbg("start\n");
+ mutex_lock(&mutex);
+ //pm_runtime_get_sync(dev);
+ //isl_set_mod(client, ISL_MOD_POWERDOWN);
+ //pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ dbg("exit\n");
+}
+
+static void stk3310_late_resume(struct early_suspend *h)
+{
+ struct i2c_client *client = l_sensorconfig->client;
+
+ dbg("start\n");
+ mutex_lock(&mutex);
+ //pm_runtime_get_sync(dev);
+ //isl_set_mod(client, last_mod);
+ isl_set_default_config(client);
+ //pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ dbg("exit\n");
+}
+#endif
+
+static int
+stk3310_probe(struct i2c_client *client/*, const struct i2c_device_id *id*/)
+{
+ int res=0;
+
+ struct stk_device* idev = kzalloc(sizeof(struct stk_device), GFP_KERNEL);
+ if(!idev)
+ return -ENOMEM;
+
+ l_sensorconfig = idev;
+
+/* last mod is ALS continuous */
+ //pm_runtime_enable(&client->dev);
+ idev->input_poll_devl = input_allocate_polled_device();
+ if(!idev->input_poll_devl)
+ {
+ res = -ENOMEM;
+ goto err_input_allocate_device;
+ }
+ idev->input_poll_devp = input_allocate_polled_device();
+ if(!idev->input_poll_devp)
+ {
+ res = -ENOMEM;
+ goto err_input_allocate_device;
+ }
+ idev->client = client;
+
+ idev->input_poll_devl->private = idev;
+ idev->input_poll_devl->poll = isl_input_lux_poll_l;
+ idev->input_poll_devl->poll_interval = 100;//50;
+ idev->input_poll_devl->input->open = isl_input_open;
+ idev->input_poll_devl->input->close = isl_input_close;
+ idev->input_poll_devl->input->name = "lsensor_lux";
+ idev->input_poll_devl->input->id.bustype = BUS_I2C;
+ idev->input_poll_devl->input->dev.parent = &client->dev;
+
+ input_set_drvdata(idev->input_poll_devl->input, idev);
+ input_set_capability(idev->input_poll_devl->input, EV_ABS, ABS_MISC);
+ input_set_abs_params(idev->input_poll_devl->input, ABS_MISC, 0, 16000, 0, 0);
+
+ idev->input_poll_devp->private = idev;
+ idev->input_poll_devp->poll = isl_input_lux_poll_p;
+ idev->input_poll_devp->poll_interval = 100;//50;
+ idev->input_poll_devp->input->open = isl_input_open;
+ idev->input_poll_devp->input->close = isl_input_close;
+ idev->input_poll_devp->input->name = "psensor_lux";
+ idev->input_poll_devp->input->id.bustype = BUS_I2C;
+ idev->input_poll_devp->input->dev.parent = &client->dev;
+
+ input_set_drvdata(idev->input_poll_devp->input, idev);
+ input_set_capability(idev->input_poll_devp->input, EV_ABS, ABS_MISC);
+ input_set_abs_params(idev->input_poll_devp->input, ABS_MISC, 0, 16000, 0, 0);
+ i2c_set_clientdata(client, idev);
+ /* set default config after set_clientdata */
+ res = isl_set_default_config(client);
+ res = misc_register(&mmadl_device);
+ if (res) {
+ errlog("mmad_device register failed\n");
+ goto err_misc_registerl;
+ }
+ res = misc_register(&mmadp_device);
+ if (res) {
+ errlog("mmad_device register failed\n");
+ goto err_misc_registerp;
+ }
+ res = input_register_polled_device(idev->input_poll_devl);
+ if(res < 0)
+ goto err_input_register_devicel;
+ res = input_register_polled_device(idev->input_poll_devp);
+ if(res < 0)
+ goto err_input_register_devicep;
+ // suspend/resume register
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ idev->earlysuspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ idev->earlysuspend.suspend = stk3310_early_suspend;
+ idev->earlysuspend.resume = stk3310_late_resume;
+ register_early_suspend(&(idev->earlysuspend));
+#endif
+
+ dbg("stk3310 probe succeed!\n");
+ return 0;
+err_input_register_devicep:
+ input_free_polled_device(idev->input_poll_devp);
+err_input_register_devicel:
+ input_free_polled_device(idev->input_poll_devl);
+err_misc_registerp:
+ misc_deregister(&mmadp_device);
+err_misc_registerl:
+ misc_deregister(&mmadl_device);
+err_input_allocate_device:
+ //__pm_runtime_disable(&client->dev, false);
+ kfree(idev);
+ return res;
+}
+
+static int stk3310_remove(struct i2c_client *client)
+{
+ struct stk_device* idev = i2c_get_clientdata(client);
+
+ //unregister_early_suspend(&(idev->earlysuspend));
+ misc_deregister(&mmadl_device);
+ misc_deregister(&mmadp_device);
+ input_unregister_polled_device(idev->input_poll_devl);
+ input_unregister_polled_device(idev->input_poll_devp);
+ input_free_polled_device(idev->input_poll_devl);
+ input_free_polled_device(idev->input_poll_devp);
+ //__pm_runtime_disable(&client->dev, false);
+ kfree(idev);
+ printk(KERN_INFO MODULE_NAME ": %s stk3310 remove call, \n", __func__);
+ return 0;
+}
+
+//****************add platform_device & platform_driver for suspend &resume 2013-7-2
+static int ls_probe(struct platform_device *pdev){
+ //printk("<<<%s\n", __FUNCTION__);
+ return 0;
+}
+static int ls_remove(struct platform_device *pdev){
+ //printk("<<<%s\n", __FUNCTION__);
+ return 0;
+}
+static int ls_suspend(struct platform_device *pdev, pm_message_t state){
+ printk("<<<%s\n", __FUNCTION__);
+
+ return 0;
+}
+
+static int ls_resume(struct platform_device *pdev){
+ //return 0;
+ int ret = 0;
+ int count = 0;
+
+ struct i2c_client *client = l_sensorconfig->client;
+ printk("<<<%s\n", __FUNCTION__);
+
+RETRY:
+ mutex_lock(&mutex);
+
+ ret = isl_set_default_config(client);
+
+ mutex_unlock(&mutex);
+ if (ret < 0){
+ printk("%s isl_set_default_config fail!\n", __FUNCTION__);
+ count++;
+ if (count < 5){
+ mdelay(2);
+ goto RETRY;
+ }
+ else
+ return ret;
+ }
+ return 0;
+
+}
+static void lsdev_release(struct device *dev)
+{
+ return;
+}
+static struct platform_device lsdev = {
+ .name = "lsdevice",
+ .id = -1,
+ .dev = {
+ .release = lsdev_release,
+ },
+};
+static struct platform_driver lsdrv = {
+ .probe = ls_probe,
+ .remove = ls_remove,
+ .suspend = ls_suspend,
+ .resume = ls_resume,
+ .driver = {
+ .name = "lsdevice",
+ },
+};
+//********************************************************************
+
+
+static int __init sensor_stk3310_init(void)
+{
+ int ret = 0;
+ printk(KERN_INFO MODULE_NAME ": %s stk3310 init call, \n", __func__);
+ /*
+ * Force device to initialize: i2c-15 0x44
+ * If i2c_new_device is not called, even stk3310_detect will not run
+ * TODO: rework to automatically initialize the device
+ */
+ //i2c_new_device(i2c_get_adapter(15), &isl_info);
+ //return i2c_add_driver(&stk3310_driver);
+ if (!(this_client = sensor_i2c_register_device(2, SENSOR_I2C_ADDR, SENSOR_I2C_NAME)))
+ {
+ printk(KERN_EMERG"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+ if (stk3310_detect(this_client))
+ {
+ errlog("Can't find light sensor stk3310!\n");
+ goto detect_fail;
+ }
+ if(stk3310_probe(this_client))
+ {
+ errlog("Erro for probe!\n");
+ goto detect_fail;
+ }
+
+ ret = platform_device_register(&lsdev);
+ if (ret){
+ printk("<<<platform_device_register fail!\n");
+ return ret;
+ }
+ ret = platform_driver_register(&lsdrv);
+ if (ret){
+ printk("<<<platform_driver_register fail!\n");
+ platform_device_unregister(&lsdev);
+ return ret;
+ }
+ return 0;
+
+detect_fail:
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+}
+
+static void __exit sensor_stk3310_exit(void)
+{
+ printk(KERN_INFO MODULE_NAME ": %s stk3310 exit call \n", __func__);
+ stk3310_remove(this_client);
+ sensor_i2c_unregister_device(this_client);
+ platform_driver_unregister(&lsdrv);
+ platform_device_unregister(&lsdev);
+ //i2c_del_driver(&stk3310_driver);
+}
+
+module_init(sensor_stk3310_init);
+module_exit(sensor_stk3310_exit);
+
+MODULE_AUTHOR("flash");
+MODULE_ALIAS("stk3310 ALS");
+MODULE_DESCRIPTION("Stk3310 Driver");
+MODULE_LICENSE("GPL v2");
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/Makefile
new file mode 100755
index 00000000..ba1a46b1
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_gsensor_stk8312
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := stk831x.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/stk8312.h b/ANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/stk8312.h
new file mode 100755
index 00000000..c4b25cdc
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/stk8312.h
@@ -0,0 +1,51 @@
+/*
+ * Definitions for Sensortek stk8312 accelerometer
+ */
+#ifndef _STK831X_H_
+#define _STK831X_H_
+
+#include <linux/ioctl.h>
+#define STK831X_I2C_NAME "stk831x"
+#define ACC_IDEVICE_NAME "sensor_ctrl"
+#define STKDIR 0x3D
+#define STK_LSB_1G 21
+/* registers for stk8312 registers */
+
+#define STK831X_XOUT 0x00 /* x-axis acceleration*/
+#define STK831X_YOUT 0x01 /* y-axis acceleration*/
+#define STK831X_ZOUT 0x02 /* z-axis acceleration*/
+#define STK831X_TILT 0x03 /* Tilt Status */
+#define STK831X_SRST 0x04 /* Sampling Rate Status */
+#define STK831X_SPCNT 0x05 /* Sleep Count */
+#define STK831X_INTSU 0x06 /* Interrupt setup*/
+#define STK831X_MODE 0x07
+#define STK831X_SR 0x08 /* Sample rate */
+#define STK831X_PDET 0x09 /* Tap Detection */
+#define STK831X_DEVID 0x0B /* Device ID */
+#define STK831X_OFSX 0x0C /* X-Axis offset */
+#define STK831X_OFSY 0x0D /* Y-Axis offset */
+#define STK831X_OFSZ 0x0E /* Z-Axis offset */
+#define STK831X_PLAT 0x0F /* Tap Latency */
+#define STK831X_PWIN 0x10 /* Tap Window */
+#define STK831X_FTH 0x11 /* Free-Fall Threshold */
+#define STK831X_FTM 0x12 /* Free-Fall Time */
+#define STK831X_STH 0x13 /* Shake Threshold */
+#define STK831X_CTRL 0x14 /* Control Register */
+#define STK831X_RESET 0x20 /*software reset*/
+
+/* IOCTLs*/
+#define STK_IOCTL_WRITE _IOW(STKDIR, 0x01, char[8])
+#define STK_IOCTL_READ _IOWR(STKDIR, 0x02, char[8])
+#define STK_IOCTL_SET_ENABLE _IOW(STKDIR, 0x03, char)
+#define STK_IOCTL_GET_ENABLE _IOR(STKDIR, 0x04, char)
+#define STK_IOCTL_SET_DELAY _IOW(STKDIR, 0x05, char)
+#define STK_IOCTL_GET_DELAY _IOR(STKDIR, 0x06, char)
+#define STK_IOCTL_SET_OFFSET _IOW(STKDIR, 0x07, char[3])
+#define STK_IOCTL_GET_OFFSET _IOR(STKDIR, 0x08, char[3])
+#define STK_IOCTL_GET_ACCELERATION _IOR(STKDIR, 0x09, int[3])
+#define STK_IOCTL_SET_RANGE _IOW(STKDIR, 0x10, char)
+#define STK_IOCTL_GET_RANGE _IOR(STKDIR, 0x11, char)
+#define STK_IOCTL_SET_CALI _IOW(STKDIR, 0x12, char)
+
+
+#endif
diff --git a/ANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/stk8313.h b/ANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/stk8313.h
new file mode 100755
index 00000000..66536ac7
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/stk8313.h
@@ -0,0 +1,52 @@
+/*
+ * Definitions for Sensortek stk8313 accelerometer
+ */
+#ifndef _STK831X_H_
+#define _STK831X_H_
+
+#include <linux/ioctl.h>
+#define STK831X_I2C_NAME "stk831x"
+#define ACC_IDEVICE_NAME "accelerometer"
+#define STKDIR 0x3D
+#define STK_LSB_1G 256
+/* register for stk8313 registers */
+
+#define STK831X_XOUT 0x00
+#define STK831X_YOUT 0x02
+#define STK831X_ZOUT 0x04
+#define STK831X_TILT 0x06 /* Tilt Status */
+#define STK831X_SRST 0x07 /* Sampling Rate Status */
+#define STK831X_SPCNT 0x08 /* Sleep Count */
+#define STK831X_INTSU 0x09 /* Interrupt setup*/
+#define STK831X_MODE 0x0A
+#define STK831X_SR 0x0B /* Sample rate */
+#define STK831X_PDET 0x0C /* Tap Detection */
+#define STK831X_DEVID 0x0E /* Device ID */
+#define STK831X_OFSX 0x0F /* X-Axis offset */
+#define STK831X_OFSY 0x10 /* Y-Axis offset */
+#define STK831X_OFSZ 0x11 /* Z-Axis offset */
+#define STK831X_PLAT 0x12 /* Tap Latency */
+#define STK831X_PWIN 0x13 /* Tap Window */
+#define STK831X_FTH 0x14 /* Fre e-Fall Threshold */
+#define STK831X_FTM 0x15 /* Free-Fall Time */
+#define STK831X_STH 0x16 /* Shake Threshold */
+#define STK831X_ISTMP 0x17 /* Interrupt Setup */
+#define STK831X_INTMAP 0x18 /*Interrupt Map*/
+#define STK831X_RESET 0x20 /*software reset*/
+
+/* IOCTLs*/
+#define STK_IOCTL_WRITE _IOW(STKDIR, 0x01, char[8])
+#define STK_IOCTL_READ _IOWR(STKDIR, 0x02, char[8])
+#define STK_IOCTL_SET_ENABLE _IOW(STKDIR, 0x03, char)
+#define STK_IOCTL_GET_ENABLE _IOR(STKDIR, 0x04, char)
+#define STK_IOCTL_SET_DELAY _IOW(STKDIR, 0x05, char)
+#define STK_IOCTL_GET_DELAY _IOR(STKDIR, 0x06, char)
+#define STK_IOCTL_SET_OFFSET _IOW(STKDIR, 0x07, char[3])
+#define STK_IOCTL_GET_OFFSET _IOR(STKDIR, 0x08, char[3])
+#define STK_IOCTL_GET_ACCELERATION _IOR(STKDIR, 0x09, int[3])
+#define STK_IOCTL_SET_RANGE _IOW(STKDIR, 0x10, char)
+#define STK_IOCTL_GET_RANGE _IOR(STKDIR, 0x11, char)
+#define STK_IOCTL_SET_CALI _IOW(STKDIR, 0x12, char)
+
+
+#endif \ No newline at end of file
diff --git a/ANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/stk831x.c b/ANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/stk831x.c
new file mode 100755
index 00000000..68952f9c
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/stk8312_gsensor/stk831x.c
@@ -0,0 +1,3590 @@
+/*
+ * stk831x.c - Linux kernel modules for sensortek stk8311/stk8312/stk8313 accelerometer
+ *
+ * Copyright (C) 2011~2013 Lex Hsieh / sensortek <lex_hsieh@sensortek.com.tw>
+ *
+ * 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/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+#include <linux/input.h>
+#include <asm/gpio.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/kthread.h>
+#include <linux/version.h>
+#include <linux/pm_runtime.h>
+#include <linux/fs.h>
+#include <linux/workqueue.h>
+#include <linux/fcntl.h>
+#include <linux/syscalls.h>
+
+
+#include "../sensor.h"
+
+
+//#define STK_ALLWINNER_PLATFORM
+#define STK_ACC_DRIVER_VERSION "1.6.1"
+/*choose polling or interrupt mode*/
+#define STK_ACC_POLLING_MODE 1
+#if (!STK_ACC_POLLING_MODE)
+ #define ADDITIONAL_GPIO_CFG 1
+ #define STK_INT_PIN 39
+#endif
+//#define STK_PERMISSION_THREAD
+#define STK_RESUME_RE_INIT
+//#define STK_DEBUG_PRINT
+//#define STK_DEBUG_RAWDATA
+//#define STK_LOWPASS
+#define STK_FIR_LEN 4
+
+///////////////////////////////////////
+#define CONFIG_SENSORS_STK8312////////
+/////////////////////////////////////
+#define STK_ZG_FILTER
+#ifdef CONFIG_SENSORS_STK8312
+ #define STK_ZG_COUNT 1
+#elif defined (CONFIG_SENSORS_STK8313)
+ #define STK_ZG_COUNT 4
+#endif
+
+#define STK_TUNE
+#ifdef CONFIG_SENSORS_STK8312
+ #define STK_TUNE_XYOFFSET 3
+ #define STK_TUNE_ZOFFSET 6
+ #define STK_TUNE_NOISE 5
+#elif defined (CONFIG_SENSORS_STK8313)
+ #define STK_TUNE_XYOFFSET 35
+ #define STK_TUNE_ZOFFSET 75
+ #define STK_TUNE_NOISE 20
+#endif
+#define STK_TUNE_NUM 125
+#define STK_TUNE_DELAY 125
+//Flourtise - Kevin
+#define STK_WMT_PLATFORM
+#ifdef STK_WMT_PLATFORM
+ //#define STK8312_DRVID 7
+ ///////////////////////// ioctrl cmd ////////////////////////^M
+ #define WMTGSENSOR_IOCTL_MAGIC 0x09
+ #define WMT_IOCTL_SENSOR_CAL_OFFSET _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x01, int) //offset calibration^M
+ #define ECS_IOCTL_APP_SET_AFLAG _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x02, short)
+ #define ECS_IOCTL_APP_SET_DELAY _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x03, short)
+ #define WMT_IOCTL_SENSOR_GET_DRVID _IOW(WMTGSENSOR_IOCTL_MAGIC, 0x04, unsigned int)
+ #define WMT_IOCTL_SENOR_GET_RESOLUTION _IOR(WMTGSENSOR_IOCTL_MAGIC, 0x05, short)
+
+#endif
+//Flourise - Kevin
+#ifndef STK_WMT_PLATFORM
+ #ifdef CONFIG_SENSORS_STK8313
+ #include <linux/stk8313.h>
+ #elif defined CONFIG_SENSORS_STK8312
+ #include <linux/stk8312.h>
+ #else
+ #error "What's your stk accelerometer?"
+ #endif
+#else
+ #ifdef CONFIG_SENSORS_STK8313
+ #include "stk8313.h"
+ #elif defined CONFIG_SENSORS_STK8312
+ #include "stk8312.h"
+ #else
+ #error "What's your stk accelerometer?"
+ #endif
+#endif /* #ifndef STK_ALLWINNER_PLATFORM */
+
+SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename, mode_t, mode);
+
+static struct i2c_client *this_client = NULL;
+
+//add 2013-6-24
+#define GSENSOR_NAME "stk8312"
+static struct class* l_dev_class = NULL;
+struct stk8312_config
+{
+ int op;
+ int int_gpio; //0-3
+ int xyz_axis[3][2]; // (axis,direction)
+ int rxyz_axis[3][2];
+ int irq;
+ struct proc_dir_entry* sensor_proc;
+ int sensorlevel;
+ int shake_enable; // 1--enable shake, 0--disable shake
+ int manual_rotation; // 0--landance, 90--vertical
+ struct input_dev *input_dev;
+ //struct work_struct work;
+ struct delayed_work work; // for polling
+ struct workqueue_struct *queue;
+ int isdbg; // 0-- no debug log, 1--show debug log
+ int sensor_samp; // 1,2,4,8,16,32,64,120
+ int sensor_enable; // 0 --> disable sensor, 1 --> enable sensor
+ int test_pass;
+ spinlock_t spinlock;
+ int pollcnt; // the counts of polling
+ int offset[3];
+};
+
+static struct stk8312_config l_sensorconfig = {
+ .op = 0,
+ .int_gpio = 3,
+ .xyz_axis = {
+ {ABS_X, -1},
+ {ABS_Y, 1},
+ {ABS_Z, -1},
+ },
+ .irq = 6,
+ .int_gpio = 3,
+ .sensor_proc = NULL,
+ .sensorlevel = 0,
+ .shake_enable = 0, // default enable shake
+ .isdbg = 0,
+ .sensor_samp = 10, // 4sample/second
+ .sensor_enable = 1, // enable sensor
+ .test_pass = 0, // for test program
+ .pollcnt = 0, // Don't report the x,y,z when the driver is loaded until 2~3 seconds
+ .offset = {0,0,0},
+};
+//******************************************
+
+#if defined(STK_LOWPASS)
+#define MAX_FIR_LEN 32
+struct data_filter {
+ s16 raw[MAX_FIR_LEN][3];
+ int sum[3];
+ int num;
+ int idx;
+};
+#endif
+
+struct stk831x_data
+{
+ struct input_dev *input_dev;
+ struct work_struct stk_work;
+ int irq;
+ int raw_data[3];
+ atomic_t enabled;
+ unsigned char delay;
+ struct mutex write_lock;
+ bool first_enable;
+ bool re_enable;
+ char recv_reg;
+#if STK_ACC_POLLING_MODE
+ struct hrtimer acc_timer;
+ struct work_struct stk_acc_work;
+ struct workqueue_struct *stk_acc_wq;
+ ktime_t acc_poll_delay;
+#endif //#if STK_ACC_POLLING_MODE
+ atomic_t cali_status;
+#if defined(STK_LOWPASS)
+ atomic_t firlength;
+ atomic_t fir_en;
+ struct data_filter fir;
+#endif
+};
+
+#define STK831X_HOLD_ODR
+#define STK831X_INIT_ODR 1//2 //2:100Hz, 3:50Hz, 4:25Hz
+#define STK831X_SAMPLE_TIME_MIN_NO 2
+#define STK831X_SAMPLE_TIME_NO 5
+const static int STK831X_SAMPLE_TIME[STK831X_SAMPLE_TIME_NO] = {2500, 5000, 10000, 20000, 40000};
+static struct stk831x_data *stk831x_data_ptr;
+static int event_since_en = 0;
+static int event_since_en_limit = 20;
+#if (!STK_ACC_POLLING_MODE)
+static struct workqueue_struct *stk_mems_work_queue = NULL;
+#endif //#if STK_ACC_POLLING_MODE
+
+#define STK_DEBUG_CALI
+#define STK_SAMPLE_NO 10
+#define STK_ACC_CALI_VER0 0x3D
+#define STK_ACC_CALI_VER1 0x01
+#define STK_ACC_CALI_FILE "/data/misc/stkacccali.conf"
+#define STK_ACC_CALI_FILE_SIZE 10
+
+#define STK_K_SUCCESS_TUNE 0x04
+#define STK_K_SUCCESS_FT2 0x03
+#define STK_K_SUCCESS_FT1 0x02
+#define STK_K_SUCCESS_FILE 0x01
+#define STK_K_NO_CALI 0xFF
+#define STK_K_RUNNING 0xFE
+#define STK_K_FAIL_LRG_DIFF 0xFD
+#define STK_K_FAIL_OPEN_FILE 0xFC
+#define STK_K_FAIL_W_FILE 0xFB
+#define STK_K_FAIL_R_BACK 0xFA
+#define STK_K_FAIL_R_BACK_COMP 0xF9
+#define STK_K_FAIL_I2C 0xF8
+#define STK_K_FAIL_K_PARA 0xF7
+#define STK_K_FAIL_OTP_OUT_RG 0xF6
+#define STK_K_FAIL_ENG_I2C 0xF5
+#define STK_K_FAIL_FT1_USD 0xF4
+#define STK_K_FAIL_FT2_USD 0xF3
+#define STK_K_FAIL_WRITE_NOFST 0xF2
+#define STK_K_FAIL_OTP_5T 0xF1
+#define STK_K_FAIL_PLACEMENT 0xF0
+
+
+#define POSITIVE_Z_UP 0
+#define NEGATIVE_Z_UP 1
+#define POSITIVE_X_UP 2
+#define NEGATIVE_X_UP 3
+#define POSITIVE_Y_UP 4
+#define NEGATIVE_Y_UP 5
+static unsigned char stk831x_placement = POSITIVE_Z_UP;
+#ifdef STK_TUNE
+static char stk_tune_offset_record[3] = {0};
+static int stk_tune_offset[3] = {0};
+static int stk_tune_sum[3] = {0};
+static int stk_tune_max[3] = {0};
+static int stk_tune_min[3] = {0};
+static int stk_tune_index = 0;
+static int stk_tune_done = 0;
+#endif
+
+static int stk_store_in_ic( struct stk831x_data *stk, char otp_offset[], char FT_index, uint32_t delay_ms);
+static int32_t stk_get_file_content(char * r_buf, int8_t buf_size);
+static int stk_store_in_file(char offset[], char mode);
+static int STK831x_ReadByteOTP(char rReg, char *value);
+static int STK831x_SetEnable(struct stk831x_data *stk, char en);
+static int STK831x_SetCali(struct stk831x_data *stk, char sstate);
+static int32_t stk_get_ic_content(struct stk831x_data *stk);
+static int STK831x_SetOffset(char buf[]);
+static void stk_handle_first_en(struct stk831x_data *stk);
+static int STK831x_GetDelay(struct stk831x_data *stk, uint32_t* gdelay_ns);
+static int STK831x_SetDelay(struct stk831x_data *stk, uint32_t sdelay_ns);
+
+#ifdef STK_ALLWINNER_PLATFORM
+static int gsensor_direct_x = 0;
+static int gsensor_direct_y = 0;
+static int gsensor_direct_z = 0;
+static int gsensor_xy_revert = 0;
+
+enum {
+ DEBUG_INIT = 1U << 0,
+ DEBUG_CONTROL_INFO = 1U << 1,
+ DEBUG_DATA_INFO = 1U << 2,
+ DEBUG_SUSPEND = 1U << 3,
+};
+static u32 debug_mask = 0;
+#define dprintk(level_mask, fmt, arg...) if (unlikely(debug_mask & level_mask)) \
+ printk(KERN_DEBUG fmt , ## arg)
+
+module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
+#endif /* #ifdef STK_ALLWINNER_PLATFORM */
+
+#ifdef STK_ALLWINNER_PLATFORM
+/* Addresses to scan */
+static union
+{
+ unsigned short dirty_addr_buf[2];
+ const unsigned short normal_i2c[2];
+}u_i2c_addr = {{0x00},};
+static __u32 twi_id = 1;
+#endif /* #ifdef STK_ALLWINNER_PLATFORM */
+
+/**
+ * gsensor_fetch_sysconfig_para - get config info from sysconfig.fex file.
+ * return value:
+ * = 0; success;
+ * < 0; err
+ */
+#ifdef STK_ALLWINNER_A20_A31
+static int gsensor_fetch_sysconfig_para(void)
+{
+ int ret = -1;
+ int device_used = -1;
+ script_item_u val;
+ script_item_value_type_e type;
+
+ dprintk(DEBUG_INIT, "========%s===================\n", __func__);
+
+ type = script_get_item("gsensor_para", "gsensor_used", &val);
+
+ if (SCIRPT_ITEM_VALUE_TYPE_INT != type) {
+ pr_err("%s: type err device_used = %d. \n", __func__, val.val);
+ goto script_get_err;
+ }
+ device_used = val.val;
+
+ if (1 == device_used) {
+ type = script_get_item("gsensor_para", "gsensor_twi_id", &val);
+ if(SCIRPT_ITEM_VALUE_TYPE_INT != type){
+ pr_err("%s: type err twi_id = %d. \n", __func__, val.val);
+ goto script_get_err;
+ }
+ twi_id = val.val;
+
+ dprintk(DEBUG_INIT, "%s: twi_id is %d. \n", __func__, twi_id);
+
+ if(SCIRPT_ITEM_VALUE_TYPE_INT != script_get_item("gsensor_para", "gsensor_direct_x", &val)){
+ pr_err("%s: line: %d: script_get_item err. \n", __FILE__, __LINE__);
+ goto script_get_err;
+ }
+ gsensor_direct_x = val.val;
+
+ if(SCIRPT_ITEM_VALUE_TYPE_INT != script_get_item("gsensor_para", "gsensor_direct_y", &val)){
+ pr_err("%s: line: %d: script_get_item err. \n", __FILE__, __LINE__);
+ goto script_get_err;
+ }
+ gsensor_direct_y = val.val;
+ if(SCIRPT_ITEM_VALUE_TYPE_INT != script_get_item("gsensor_para", "gsensor_direct_z", &val)){
+ pr_err("%s: line: %d: script_get_item err. \n", __FILE__, __LINE__);
+ goto script_get_err;
+ }
+ gsensor_direct_z = val.val;
+
+ if(SCIRPT_ITEM_VALUE_TYPE_INT != script_get_item("gsensor_para", "gsensor_xy_revert", &val)){
+ pr_err("%s: line: %d: script_get_item err. \n", __FILE__, __LINE__);
+ goto script_get_err;
+ }
+ gsensor_xy_revert = val.val;
+
+ ret = 0;
+
+ } else {
+ pr_err("%s: gsensor_unused. \n", __func__);
+ ret = -1;
+ }
+
+ return ret;
+
+script_get_err:
+ pr_notice("=========script_get_err============\n");
+ return ret;
+}
+#endif /* #ifdef STK_ALLWINNER_A20_A31 */
+
+#ifdef STK_ALLWINNER_A13
+static int gsensor_fetch_sysconfig_para(void)
+{
+ int ret = -1;
+ int device_used = -1;
+
+ printk("========%s===================\n", __func__);
+
+ if(SCRIPT_PARSER_OK != (ret = script_parser_fetch("gsensor_para", "gsensor_used", &device_used, 1))){
+ pr_err("%s: script_parser_fetch err.ret = %d. \n", __func__, ret);
+ goto script_parser_fetch_err;
+ }
+ if(1 == device_used){
+ if(SCRIPT_PARSER_OK != script_parser_fetch("gsensor_para", "gsensor_twi_id", &twi_id, 1)){
+ pr_err("%s: script_parser_fetch err. \n",__func__);
+ goto script_parser_fetch_err;
+ }
+ printk("%s: twi_id is %d. \n", __func__, twi_id);
+
+ stk8313_pin_hd = gpio_request_ex("gsensor_para",NULL);
+ if (stk8313_pin_hd==-1) {
+ printk("stk8313_pin_hd pin request error!\n");
+ }
+ ret = 0;
+
+ }else{
+ pr_err("%s: gsensor_unused. \n", __func__);
+ ret = -1;
+ }
+
+ return ret;
+
+ script_parser_fetch_err:
+ pr_notice("=========script_parser_fetch_err============\n");
+ return ret;
+}
+#endif /* #ifdef STK_ALLWINNER_A13 */
+
+
+
+static int STK_i2c_Rx(char *rxData, int length)
+{
+ uint8_t retry;
+ struct i2c_msg msgs[] =
+ {
+ {
+ .addr = this_client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = rxData,
+ },
+ {
+ .addr = this_client->addr,
+ .flags = I2C_M_RD,
+ .len = length,
+ .buf = rxData,
+ },
+ };
+
+ for (retry = 0; retry <= 3; retry++)
+ {
+ if (i2c_transfer(this_client->adapter, msgs, 2) > 0)
+ break;
+ else
+ mdelay(10);
+ }
+
+ if (retry > 3)
+ {
+ printk(KERN_ERR "%s: retry over 3\n", __func__);
+ return -EIO;
+ }
+ else
+ return 0;
+}
+
+static int STK_i2c_Tx(char *txData, int length)
+{
+ int retry;
+ struct i2c_msg msg[] =
+ {
+ {
+ .addr = this_client->addr,
+ .flags = 0,
+ .len = length,
+ .buf = txData,
+ },
+ };
+
+ for (retry = 0; retry <= 3; retry++)
+ {
+ if (i2c_transfer(this_client->adapter, msg, 1) > 0)
+ break;
+ else
+ mdelay(10);
+ }
+
+ if(*txData >= 0x21 && *txData <= 0x3E)
+ {
+ for (retry = 0; retry <= 3; retry++)
+ {
+ if (i2c_transfer(this_client->adapter, msg, 1) > 0)
+ break;
+ else
+ mdelay(10);
+ }
+ }
+
+ if (retry > 3)
+ {
+ printk(KERN_ERR "%s: i2c error, retry over 3\n", __func__);
+ return -EIO;
+ }
+ else
+ return 0;
+}
+
+
+static int STK831X_SetVD(struct stk831x_data *stk)
+{
+ int result;
+ char buffer[2] = "";
+ char reg24;
+
+ msleep(2);
+ result = STK831x_ReadByteOTP(0x70, &reg24);
+ if(result < 0)
+ {
+ printk(KERN_ERR "%s: read back error, result=%d\n", __func__, result);
+ return result;
+ }
+
+ if(reg24 != 0)
+ {
+ buffer[0] = 0x24;
+ buffer[1] = reg24;
+ //printk(KERN_INFO "%s:write 0x%x to 0x24\n", __func__, buffer[1]);
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return result;
+ }
+ }
+ else
+ {
+ //printk(KERN_INFO "%s: reg24=0, do nothing\n", __func__);
+ return 0;
+ }
+
+ buffer[0] = 0x24;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return result;
+ }
+ if(buffer[0] != reg24)
+ {
+ printk(KERN_ERR "%s: error, reg24=0x%x, read=0x%x\n", __func__, reg24, buffer[0]);
+ return -1;
+ }
+ //printk(KERN_INFO "%s: successfully", __func__);
+ return 0;
+}
+
+#ifdef STK_TUNE
+static void STK831x_ResetPara(void)
+{
+ int ii;
+ for(ii=0;ii<3;ii++)
+ {
+ stk_tune_sum[ii] = 0;
+ stk_tune_min[ii] = 4096;
+ stk_tune_max[ii] = -4096;
+ }
+ return;
+}
+
+static void STK831x_Tune(struct stk831x_data *stk, int acc[])
+{
+ int ii;
+ char offset[3];
+ char mode_reg;
+ int result;
+ char buffer[2] = "";
+
+ if (stk_tune_done==0)
+ {
+ if( event_since_en >= STK_TUNE_DELAY)
+ {
+ if ((abs(acc[0]) <= STK_TUNE_XYOFFSET) && (abs(acc[1]) <= STK_TUNE_XYOFFSET)
+ && (abs(abs(acc[2])-STK_LSB_1G) <= STK_TUNE_ZOFFSET))
+ stk_tune_index++;
+ else
+ stk_tune_index = 0;
+
+ if (stk_tune_index==0)
+ STK831x_ResetPara();
+ else
+ {
+ for(ii=0;ii<3;ii++)
+ {
+ stk_tune_sum[ii] += acc[ii];
+ if(acc[ii] > stk_tune_max[ii])
+ stk_tune_max[ii] = acc[ii];
+ if(acc[ii] < stk_tune_min[ii])
+ stk_tune_min[ii] = acc[ii];
+ }
+ }
+
+ if(stk_tune_index == STK_TUNE_NUM)
+ {
+ for(ii=0;ii<3;ii++)
+ {
+ if((stk_tune_max[ii] - stk_tune_min[ii]) > STK_TUNE_NOISE)
+ {
+ stk_tune_index = 0;
+ STK831x_ResetPara();
+ return;
+ }
+ }
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed, result=0x%x\n", __func__, result);
+ return;
+ }
+ mode_reg = buffer[0];
+ buffer[1] = mode_reg & 0xF8;
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed, result=0x%x\n", __func__, result);
+ return;
+ }
+
+ stk_tune_offset[0] = stk_tune_sum[0]/STK_TUNE_NUM;
+ stk_tune_offset[1] = stk_tune_sum[1]/STK_TUNE_NUM;
+ if (acc[2] > 0)
+ stk_tune_offset[2] = stk_tune_sum[2]/STK_TUNE_NUM - STK_LSB_1G;
+ else
+ stk_tune_offset[2] = stk_tune_sum[2]/STK_TUNE_NUM - (-STK_LSB_1G);
+
+ offset[0] = (char) (-stk_tune_offset[0]);
+ offset[1] = (char) (-stk_tune_offset[1]);
+ offset[2] = (char) (-stk_tune_offset[2]);
+ STK831x_SetOffset(offset);
+ stk_tune_offset_record[0] = offset[0];
+ stk_tune_offset_record[1] = offset[1];
+ stk_tune_offset_record[2] = offset[2];
+
+ buffer[1] = mode_reg | 0x1;
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed, result=0x%x\n", __func__, result);
+ return;
+ }
+
+ STK831X_SetVD(stk);
+ stk_store_in_file(offset, STK_K_SUCCESS_TUNE);
+ stk_tune_done = 1;
+ atomic_set(&stk->cali_status, STK_K_SUCCESS_TUNE);
+ event_since_en = 0;
+ printk(KERN_INFO "%s:TUNE done, %d,%d,%d\n", __func__, offset[0], offset[1],offset[2]);
+ }
+ }
+ }
+ /*
+ else
+ {
+ if(atomic_read(&stk->enabled))
+ {
+ acc[0] -= stk_tune_offset[0];
+ acc[1] -= stk_tune_offset[1];
+ acc[2] -= stk_tune_offset[2];
+ }
+ }
+ */
+ // printk(KERN_INFO "%s:TUNE %4d,%4d,%4d [%d,%d,%d] %d\n", __func__, acc[0], acc[1], acc[2], stk_tune_offset[0], stk_tune_offset[1],stk_tune_offset[2],stk_tune_done);
+ return;
+}
+#endif
+
+#ifdef CONFIG_SENSORS_STK8312
+static int STK831x_CheckReading(int acc[], bool clear)
+{
+ static int check_result = 0;
+
+ if(acc[0] == 127 || acc[0] == -128 || acc[1] == 127 || acc[1] == -128 ||
+ acc[2] == 127 || acc[2] == -128)
+ {
+ printk(KERN_INFO "%s: acc:%o,%o,%o\n", __func__, acc[0], acc[1], acc[2]);
+ check_result++;
+ }
+ if(clear)
+ {
+ if(check_result == 3)
+ {
+ event_since_en_limit = 10000;
+ printk(KERN_INFO "%s: incorrect reading\n", __func__);
+ check_result = 0;
+ return 1;
+ }
+ check_result = 0;
+ }
+ return 0;
+}
+static inline int STK831x_ReadSensorData(struct stk831x_data *stk)
+{
+ int result;
+ char buffer[3] = {0};
+ int acc_xyz[3] = {0};
+#ifdef STK_ZG_FILTER
+ s16 zero_fir = 0;
+#endif
+#ifdef STK_LOWPASS
+ int idx, firlength = atomic_read(&stk->firlength);
+#endif
+ int k_status = atomic_read(&stk->cali_status);
+ memset(buffer, 0, 3);
+
+ buffer[0] = STK831X_XOUT;
+ result = STK_i2c_Rx(buffer, 3);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:i2c transfer error\n", __func__);
+ return result;
+ }
+
+ if (buffer[0] & 0x80)
+ acc_xyz[0] = buffer[0] - 256;
+ else
+ acc_xyz[0] = buffer[0];
+ if (buffer[1] & 0x80)
+ acc_xyz[1] = buffer[1] - 256;
+ else
+ acc_xyz[1] = buffer[1];
+ if (buffer[2] & 0x80)
+ acc_xyz[2] = buffer[2] - 256;
+ else
+ acc_xyz[2] = buffer[2];
+
+#ifdef STK_DEBUG_RAWDATA
+ printk(KERN_INFO "%s:RAW %4d,%4d,%4d\n", __func__, stk->raw_data[0], stk->raw_data[1], stk->raw_data[2]);
+#endif
+
+ if(event_since_en == 16 || event_since_en == 17)
+ STK831x_CheckReading(acc_xyz, false);
+ else if(event_since_en == 18)
+ STK831x_CheckReading(acc_xyz, true);
+
+ if(k_status == STK_K_RUNNING)
+ {
+ stk->raw_data[0] = acc_xyz[0];
+ stk->raw_data[1] = acc_xyz[1];
+ stk->raw_data[2] = acc_xyz[2];
+ return 0;
+ }
+
+#ifdef STK_LOWPASS //not define 2013-7-12
+ if(atomic_read(&stk->fir_en))
+ {
+ if(stk->fir.num < firlength)
+ {
+ stk->fir.raw[stk->fir.num][0] = acc_xyz[0];
+ stk->fir.raw[stk->fir.num][1] = acc_xyz[1];
+ stk->fir.raw[stk->fir.num][2] = acc_xyz[2];
+ stk->fir.sum[0] += acc_xyz[0];
+ stk->fir.sum[1] += acc_xyz[1];
+ stk->fir.sum[2] += acc_xyz[2];
+ stk->fir.num++;
+ stk->fir.idx++;
+ }
+ else
+ {
+ idx = stk->fir.idx % firlength;
+ stk->fir.sum[0] -= stk->fir.raw[idx][0];
+ stk->fir.sum[1] -= stk->fir.raw[idx][1];
+ stk->fir.sum[2] -= stk->fir.raw[idx][2];
+ stk->fir.raw[idx][0] = acc_xyz[0];
+ stk->fir.raw[idx][1] = acc_xyz[1];
+ stk->fir.raw[idx][2] = acc_xyz[2];
+ stk->fir.sum[0] += acc_xyz[0];
+ stk->fir.sum[1] += acc_xyz[1];
+ stk->fir.sum[2] += acc_xyz[2];
+ stk->fir.idx++;
+ acc_xyz[0] = stk->fir.sum[0]/firlength;
+ acc_xyz[1] = stk->fir.sum[1]/firlength;
+ acc_xyz[2] = stk->fir.sum[2]/firlength;
+ }
+ }
+#ifdef STK_DEBUG_RAWDATA
+ printk(KERN_INFO "%s:After FIR %4d,%4d,%4d\n", __func__, stk->raw_data[0], stk->raw_data[1], stk->raw_data[2]);
+#endif
+
+#endif /* #ifdef STK_LOWPASS */
+
+
+
+#ifdef STK_TUNE //define
+ if((k_status&0xF0) != 0)
+ STK831x_Tune(stk, acc_xyz);
+#endif
+
+#ifdef STK_ZG_FILTER //define
+ if( abs(acc_xyz[0]) <= STK_ZG_COUNT) // 1
+ acc_xyz[0] = (acc_xyz[0]*zero_fir);
+ if( abs(acc_xyz[1]) <= STK_ZG_COUNT)
+ acc_xyz[1] = (acc_xyz[1]*zero_fir);
+ if( abs(acc_xyz[2]) <= STK_ZG_COUNT)
+ acc_xyz[2] = (acc_xyz[2]*zero_fir);
+#endif /* #ifdef STK_ZG_FILTER */
+
+ stk->raw_data[0] = acc_xyz[0];
+ stk->raw_data[1] = acc_xyz[1];
+ stk->raw_data[2] = acc_xyz[2];
+
+ return 0;
+}
+
+#elif defined CONFIG_SENSORS_STK8313
+static int STK831x_CheckReading(int acc[], bool clear)
+{
+ static int check_result = 0;
+
+ if(acc[0] == 2047 || acc[0] == -2048 || acc[1] == 2047 || acc[1] == -2048 ||
+ acc[2] == 2047 || acc[2] == -2048)
+ {
+ printk(KERN_INFO "%s: acc:%o,%o,%o\n", __func__, acc[0], acc[1], acc[2]);
+ check_result++;
+ }
+ if(clear)
+ {
+ if(check_result == 3)
+ {
+ event_since_en_limit = 10000;
+ printk(KERN_INFO "%s: incorrect reading\n", __func__);
+ check_result = 0;
+ return 1;
+ }
+ check_result = 0;
+ }
+ return 0;
+}
+static int STK831x_ReadSensorData(struct stk831x_data *stk)
+{
+ int result;
+ char buffer[6] = "";
+ int acc_xyz[3] = {0};
+#ifdef STK_ZG_FILTER
+ s16 zero_fir = 0;
+#endif
+#ifdef STK_LOWPASS
+ int idx, firlength = atomic_read(&stk->firlength);
+#endif
+ int k_status = atomic_read(&stk->cali_status);
+
+ memset(buffer, 0, 6);
+ buffer[0] = STK831X_XOUT;
+ result = STK_i2c_Rx(buffer, 6);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:i2c transfer error\n", __func__);
+ return result;
+ }
+
+ if (buffer[0] & 0x80)
+ acc_xyz[0] = ((int)buffer[0]<<4) + (buffer[1]>>4) - 4096;
+ else
+ acc_xyz[0] = ((int)buffer[0]<<4) + (buffer[1]>>4);
+ if (buffer[2] & 0x80)
+ acc_xyz[1] = ((int)buffer[2]<<4) + (buffer[3]>>4) - 4096;
+ else
+ acc_xyz[1] = ((int)buffer[2]<<4) + (buffer[3]>>4);
+ if (buffer[4] & 0x80)
+ acc_xyz[2] = ((int)buffer[4]<<4) + (buffer[5]>>4) - 4096;
+ else
+ acc_xyz[2] = ((int)buffer[4]<<4) + (buffer[5]>>4);
+
+#ifdef STK_DEBUG_RAWDATA
+ printk(KERN_INFO "%s:RAW %4d,%4d,%4d\n", __func__, stk->raw_data[0], stk->raw_data[1], stk->raw_data[2]);
+#endif
+
+ if(event_since_en == 16 || event_since_en == 17)
+ STK831x_CheckReading(acc_xyz, false);
+ else if(event_since_en == 18)
+ STK831x_CheckReading(acc_xyz, true);
+ if(k_status == STK_K_RUNNING)
+ {
+ stk->raw_data[0] = acc_xyz[0];
+ stk->raw_data[1] = acc_xyz[1];
+ stk->raw_data[2] = acc_xyz[2];
+ return 0;
+ }
+
+#ifdef STK_LOWPASS
+ if(atomic_read(&stk->fir_en))
+ {
+ if(stk->fir.num < firlength)
+ {
+ stk->fir.raw[stk->fir.num][0] = acc_xyz[0];
+ stk->fir.raw[stk->fir.num][1] = acc_xyz[1];
+ stk->fir.raw[stk->fir.num][2] = acc_xyz[2];
+ stk->fir.sum[0] += acc_xyz[0];
+ stk->fir.sum[1] += acc_xyz[1];
+ stk->fir.sum[2] += acc_xyz[2];
+ stk->fir.num++;
+ stk->fir.idx++;
+ }
+ else
+ {
+ idx = stk->fir.idx % firlength;
+ stk->fir.sum[0] -= stk->fir.raw[idx][0];
+ stk->fir.sum[1] -= stk->fir.raw[idx][1];
+ stk->fir.sum[2] -= stk->fir.raw[idx][2];
+ stk->fir.raw[idx][0] = acc_xyz[0];
+ stk->fir.raw[idx][1] = acc_xyz[1];
+ stk->fir.raw[idx][2] = acc_xyz[2];
+ stk->fir.sum[0] += acc_xyz[0];
+ stk->fir.sum[1] += acc_xyz[1];
+ stk->fir.sum[2] += acc_xyz[2];
+ stk->fir.idx++;
+ acc_xyz[0] = stk->fir.sum[0]/firlength;
+ acc_xyz[1] = stk->fir.sum[1]/firlength;
+ acc_xyz[2] = stk->fir.sum[2]/firlength;
+ }
+ }
+#ifdef STK_DEBUG_RAWDATA
+ printk(KERN_INFO "%s:After FIR %4d,%4d,%4d\n", __func__, stk->raw_data[0], stk->raw_data[1], stk->raw_data[2]);
+#endif
+
+#endif /* #ifdef STK_LOWPASS */
+
+
+#ifdef STK_TUNE
+ if((k_status&0xF0) != 0)
+ STK831x_Tune(stk, acc_xyz);
+#endif
+
+#ifdef STK_ZG_FILTER
+ if( abs(acc_xyz[0]) <= STK_ZG_COUNT)
+ acc_xyz[0] = (acc_xyz[0]*zero_fir);
+ if( abs(acc_xyz[1]) <= STK_ZG_COUNT)
+ acc_xyz[1] = (acc_xyz[1]*zero_fir);
+ if( abs(acc_xyz[2]) <= STK_ZG_COUNT)
+ acc_xyz[2] = (acc_xyz[2]*zero_fir);
+#endif /* #ifdef STK_ZG_FILTER */
+
+ stk->raw_data[0] = acc_xyz[0];
+ stk->raw_data[1] = acc_xyz[1];
+ stk->raw_data[2] = acc_xyz[2];
+
+ return 0;
+}
+#endif
+
+static int STK831x_ReportValue(struct stk831x_data *stk)
+{
+ //int tmp = 0;
+ int rxyz[3] = {0};
+#if 1//comment 2013-8-15
+ if(event_since_en < 1200)
+ {
+ event_since_en++;
+ if(event_since_en < 12)
+ return 0;
+ }
+#endif
+//add by gandy
+ //gsensor_direct_x = 0;
+#if 0
+ if (gsensor_direct_x == 1)
+ stk->raw_data[0] = -stk->raw_data[0];
+
+ //gsensor_direct_y = 1;
+ if (gsensor_direct_y == 1)
+ stk->raw_data[1] = -stk->raw_data[1];
+
+ gsensor_direct_z = 1;
+ if (gsensor_direct_z == 1)
+ stk->raw_data[2] = -stk->raw_data[2];
+
+ if (gsensor_xy_revert == 1)
+ {
+ tmp = stk->raw_data[0];
+ stk->raw_data[0] = stk->raw_data[1];
+ stk->raw_data[1] = tmp;
+ }
+#endif
+//end add
+ //add coord
+ //printk("x,y,z(%d,%d,%d)\n", stk->raw_data[0], stk->raw_data[1], stk->raw_data[2]);
+ rxyz[0] = stk->raw_data[0];
+ rxyz[1] = stk->raw_data[1];
+ rxyz[2] = stk->raw_data[2];
+ stk->raw_data[0] = rxyz[l_sensorconfig.xyz_axis[0][0]]*l_sensorconfig.xyz_axis[0][1];
+ stk->raw_data[1] = rxyz[l_sensorconfig.xyz_axis[1][0]]*l_sensorconfig.xyz_axis[1][1];
+ stk->raw_data[2] = rxyz[l_sensorconfig.xyz_axis[2][0]]*l_sensorconfig.xyz_axis[2][1];
+
+
+#if 0
+ stk->raw_data[0] = stk->raw_data[0]*9800*100/2133; //add for stk8132 21.34
+ stk->raw_data[1] = stk->raw_data[1]*9800*100/2133;
+ stk->raw_data[2] = stk->raw_data[2]*9800*100/2133;
+#endif
+
+
+#ifdef STK_DEBUG_PRINT
+ printk(KERN_INFO "%s:%4d,%4d,%4d\n", __func__, stk->raw_data[0], stk->raw_data[1], stk->raw_data[2]);
+#endif
+ input_report_abs(stk->input_dev, ABS_X, stk->raw_data[0]);
+ input_report_abs(stk->input_dev, ABS_Y, stk->raw_data[1]);
+ input_report_abs(stk->input_dev, ABS_Z, stk->raw_data[2]);
+
+ //printk(" after x,y,z(%d,%d,%d)\n", stk->raw_data[0], stk->raw_data[1], stk->raw_data[2]);
+ input_sync(stk->input_dev);
+ return 0;
+}
+
+static int STK831x_SetOffset(char buf[])
+{
+ int result;
+ char buffer[4] = "";
+
+ buffer[0] = STK831X_OFSX;
+ buffer[1] = buf[0];
+ buffer[2] = buf[1];
+ buffer[3] = buf[2];
+ result = STK_i2c_Tx(buffer, 4);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return result;
+ }
+ return 0;
+}
+
+static int STK831x_GetOffset(char buf[])
+{
+ int result;
+ char buffer[3] = "";
+
+ buffer[0] = STK831X_OFSX;
+ result = STK_i2c_Rx(buffer, 3);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return result;
+ }
+ buf[0] = buffer[0];
+ buf[1] = buffer[1];
+ buf[2] = buffer[2];
+ return 0;
+}
+
+static int STK831x_SetEnable(struct stk831x_data *stk, char en)
+{
+ int result;
+ char buffer[2] = "";
+ int new_enabled = (en)?1:0;
+ int k_status = atomic_read(&stk->cali_status);
+
+ if(new_enabled == atomic_read(&stk->enabled))
+ return 0;
+ printk(KERN_INFO "%s:%x\n", __func__, en);
+
+ //mutex_lock(&stk->write_lock);
+ if(stk->first_enable && k_status != STK_K_RUNNING)
+ stk_handle_first_en(stk);
+
+ mutex_lock(&stk->write_lock);
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ goto e_err_i2c;
+ }
+ if(en)
+ {
+ buffer[1] = (buffer[0] & 0xF8) | 0x01;
+ event_since_en = 0;
+#ifdef STK_TUNE
+ if((k_status&0xF0) != 0 && stk_tune_done == 0)
+ {
+ stk_tune_index = 0;
+ STK831x_ResetPara();
+ }
+#endif
+ }
+ else
+ buffer[1] = (buffer[0] & 0xF8);
+
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ goto e_err_i2c;
+ }
+ mutex_unlock(&stk->write_lock);
+
+ if(stk->first_enable && k_status != STK_K_RUNNING)
+ {
+ stk->first_enable = false;
+ msleep(2);
+ result = stk_get_ic_content(stk);
+ }
+ if(en)
+ {
+ STK831X_SetVD(stk);
+#if STK_ACC_POLLING_MODE
+ hrtimer_start(&stk->acc_timer, stk->acc_poll_delay, HRTIMER_MODE_REL);
+#else
+ enable_irq((unsigned int)stk->irq);
+#endif //#if STK_ACC_POLLING_MODE
+ }
+ else
+ {
+#if STK_ACC_POLLING_MODE
+ hrtimer_cancel(&stk->acc_timer);
+ cancel_work_sync(&stk->stk_acc_work);
+#else
+ disable_irq((unsigned int)stk->irq);
+#endif //#if STK_ACC_POLLING_MODE
+ }
+ //mutex_unlock(&stk->write_lock);
+ atomic_set(&stk->enabled, new_enabled);
+ return 0;
+
+e_err_i2c:
+ mutex_unlock(&stk->write_lock);
+ return result;
+}
+
+static int STK831x_GetEnable(struct stk831x_data *stk, char* gState)
+{
+ *gState = atomic_read(&stk->enabled);
+ return 0;
+}
+
+static int STK831x_SetDelay(struct stk831x_data *stk, uint32_t sdelay_ns)
+{
+ unsigned char sr_no;
+ int result;
+ char buffer[2] = "";
+ uint32_t sdelay_us = sdelay_ns / 1000;
+
+ for(sr_no=(STK831X_SAMPLE_TIME_NO-1);sr_no>0;sr_no--)
+ {
+ if(sdelay_us >= STK831X_SAMPLE_TIME[sr_no])
+ break;
+ }
+ if(sr_no < STK831X_SAMPLE_TIME_MIN_NO)
+ sr_no = STK831X_SAMPLE_TIME_MIN_NO;
+
+#ifdef STK831X_HOLD_ODR
+ sr_no = STK831X_INIT_ODR;
+#endif
+
+#ifdef STK_DEBUG_PRINT
+#ifdef STK831X_HOLD_ODR
+ printk(KERN_INFO "%s:sdelay_us=%d, Hold delay = %d\n", __func__, sdelay_us, STK831X_SAMPLE_TIME[STK831X_INIT_ODR]);
+#else
+ printk(KERN_INFO "%s:sdelay_us=%d\n", __func__, sdelay_us);
+#endif
+#endif
+ mutex_lock(&stk->write_lock);
+ if(stk->delay == sr_no)
+ {
+ mutex_unlock(&stk->write_lock);
+ return 0;
+ }
+ buffer[0] = STK831X_SR;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ goto d_err_i2c;
+ }
+
+ buffer[1] = (buffer[0] & 0xF8) | ((sr_no & 0x07));
+ buffer[0] = STK831X_SR;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ goto d_err_i2c;
+ }
+ stk->delay = sr_no;
+#if STK_ACC_POLLING_MODE
+ stk->acc_poll_delay = ns_to_ktime(STK831X_SAMPLE_TIME[sr_no]*USEC_PER_MSEC);
+#endif
+
+#if defined(STK_LOWPASS)
+ stk->fir.num = 0;
+ stk->fir.idx = 0;
+ stk->fir.sum[0] = 0;
+ stk->fir.sum[1] = 0;
+ stk->fir.sum[2] = 0;
+#endif
+ mutex_unlock(&stk->write_lock);
+
+ return 0;
+d_err_i2c:
+ mutex_unlock(&stk->write_lock);
+ return result;
+}
+
+static int STK831x_GetDelay(struct stk831x_data *stk, uint32_t *gdelay_ns)
+{
+ int result;
+ char buffer[2] = "";
+
+ mutex_lock(&stk->write_lock);
+ buffer[0] = STK831X_SR;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ mutex_unlock(&stk->write_lock);
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return result;
+ }
+ mutex_unlock(&stk->write_lock);
+ *gdelay_ns = (uint32_t) STK831X_SAMPLE_TIME[(int)buffer[0]] * 1000;
+ return 0;
+}
+
+
+static int STK831x_SetRange(char srange)
+{
+ int result;
+ char buffer[2] = "";
+#ifdef STK_DEBUG_PRINT
+ printk(KERN_INFO "%s:range=0x%x\n", __func__, srange);
+#endif
+
+ if(srange >= 3)
+ {
+ printk(KERN_ERR "%s:parameter out of range\n", __func__);
+ return -1;
+ }
+
+ buffer[0] = STK831X_STH;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return result;
+ }
+
+ buffer[1] = (buffer[0] & 0x3F) | srange<<6;
+ buffer[0] = STK831X_STH;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return result;
+ }
+ return 0;
+}
+
+static int STK831x_GetRange(char* grange)
+{
+ int result;
+ char buffer = 0;
+
+ buffer = STK831X_STH;
+ result = STK_i2c_Rx(&buffer, 1);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return result;
+ }
+ *grange = buffer >> 6;
+ return 0;
+}
+
+static int STK831x_ReadByteOTP(char rReg, char *value)
+{
+ int redo = 0;
+ int result;
+ char buffer[2] = "";
+ *value = 0;
+
+ buffer[0] = 0x3D;
+ buffer[1] = rReg;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ goto eng_i2c_r_err;
+ }
+ buffer[0] = 0x3F;
+ buffer[1] = 0x02;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ goto eng_i2c_r_err;
+ }
+
+ do {
+ msleep(2);
+ buffer[0] = 0x3F;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ goto eng_i2c_r_err;
+ }
+ if(buffer[0]& 0x80)
+ {
+ break;
+ }
+ redo++;
+ }while(redo < 10);
+
+ if(redo == 10)
+ {
+ printk(KERN_ERR "%s:OTP read repeat read 10 times! Failed!\n", __func__);
+ return -STK_K_FAIL_OTP_5T;
+ }
+ buffer[0] = 0x3E;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ goto eng_i2c_r_err;
+ }
+ *value = buffer[0];
+#ifdef STK_DEBUG_CALI
+ printk(KERN_INFO "%s: read 0x%x=0x%x\n", __func__, rReg, *value);
+#endif
+ return 0;
+
+eng_i2c_r_err:
+ return -STK_K_FAIL_ENG_I2C;
+}
+
+static int STK831x_WriteByteOTP(char wReg, char value)
+{
+ int finish_w_check = 0;
+ int result;
+ char buffer[2] = "";
+ char read_back, value_xor = value;
+ int re_write = 0;
+
+ do
+ {
+ finish_w_check = 0;
+ buffer[0] = 0x3D;
+ buffer[1] = wReg;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed, err=0x%x\n", __func__, result);
+ goto eng_i2c_w_err;
+ }
+ buffer[0] = 0x3E;
+ buffer[1] = value_xor;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed, err=0x%x\n", __func__, result);
+ goto eng_i2c_w_err;
+ }
+ buffer[0] = 0x3F;
+ buffer[1] = 0x01;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed, err=0x%x\n", __func__, result);
+ goto eng_i2c_w_err;
+ }
+
+ do
+ {
+ msleep(1);
+ buffer[0] = 0x3F;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed, err=0x%x\n", __func__, result);
+ goto eng_i2c_w_err;
+ }
+ if(buffer[0]& 0x80)
+ {
+ result = STK831x_ReadByteOTP(wReg, &read_back);
+ if(result < 0)
+ {
+ printk(KERN_ERR "%s: read back error, result=%d\n", __func__, result);
+ goto eng_i2c_w_err;
+ }
+
+ if(read_back == value)
+ {
+#ifdef STK_DEBUG_CALI
+ printk(KERN_INFO "%s: write 0x%x=0x%x successfully\n", __func__, wReg, value);
+#endif
+ re_write = 0xFF;
+ break;
+ }
+ else
+ {
+ printk(KERN_ERR "%s: write 0x%x=0x%x, read 0x%x=0x%x, try again\n", __func__, wReg, value_xor, wReg, read_back);
+ value_xor = read_back ^ value;
+ re_write++;
+ break;
+ }
+ }
+ finish_w_check++;
+ } while (finish_w_check < 5);
+ } while(re_write < 10);
+
+ if(re_write == 10)
+ {
+ printk(KERN_ERR "%s: write 0x%x fail, read=0x%x, write=0x%x, target=0x%x\n", __func__, wReg, read_back, value_xor, value);
+ return -STK_K_FAIL_OTP_5T;
+ }
+
+ return 0;
+
+eng_i2c_w_err:
+ return -STK_K_FAIL_ENG_I2C;
+}
+
+static int STK831x_WriteOffsetOTP(struct stk831x_data *stk, int FT, char offsetData[])
+{
+ char regR[6], reg_comp[3];
+ char mode;
+ int result;
+ char buffer[2] = "";
+ int ft_pre_trim = 0;
+
+ if(FT==1)
+ {
+ result = STK831x_ReadByteOTP(0x7F, &regR[0]);
+ if(result < 0)
+ goto eng_i2c_err;
+
+ if(regR[0]&0x10)
+ {
+ printk(KERN_ERR "%s: 0x7F=0x%x\n", __func__, regR[0]);
+ return -STK_K_FAIL_FT1_USD;
+ }
+ }
+ else if (FT == 2)
+ {
+ result = STK831x_ReadByteOTP(0x7F, &regR[0]);
+ if(result < 0)
+ goto eng_i2c_err;
+
+ if(regR[0]&0x20)
+ {
+ printk(KERN_ERR "%s: 0x7F=0x%x\n", __func__, regR[0]);
+ return -STK_K_FAIL_FT2_USD;
+ }
+ }
+//Check End
+
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ goto common_i2c_error;
+ }
+ mode = buffer[0];
+ buffer[1] = (mode | 0x01);
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ goto common_i2c_error;
+ }
+ msleep(2);
+
+
+ if(FT == 1)
+ {
+ result = STK831x_ReadByteOTP(0x40, &reg_comp[0]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_ReadByteOTP(0x41, &reg_comp[1]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_ReadByteOTP(0x42, &reg_comp[2]);
+ if(result < 0)
+ goto eng_i2c_err;
+ }
+ else if (FT == 2)
+ {
+ result = STK831x_ReadByteOTP(0x50, &reg_comp[0]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_ReadByteOTP(0x51, &reg_comp[1]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_ReadByteOTP(0x52, &reg_comp[2]);
+ if(result < 0)
+ goto eng_i2c_err;
+ }
+
+ result = STK831x_ReadByteOTP(0x30, &regR[0]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_ReadByteOTP(0x31, &regR[1]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_ReadByteOTP(0x32, &regR[2]);
+ if(result < 0)
+ goto eng_i2c_err;
+
+ if(reg_comp[0] == regR[0] && reg_comp[1] == regR[1] && reg_comp[2] == regR[2])
+ {
+ printk(KERN_INFO "%s: ft pre-trimmed\n", __func__);
+ ft_pre_trim = 1;
+ }
+
+ if(!ft_pre_trim)
+ {
+ if(FT == 1)
+ {
+ result = STK831x_WriteByteOTP(0x40, regR[0]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_WriteByteOTP(0x41, regR[1]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_WriteByteOTP(0x42, regR[2]);
+ if(result < 0)
+ goto eng_i2c_err;
+ }
+ else if (FT == 2)
+ {
+ result = STK831x_WriteByteOTP(0x50, regR[0]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_WriteByteOTP(0x51, regR[1]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_WriteByteOTP(0x52, regR[2]);
+ if(result < 0)
+ goto eng_i2c_err;
+ }
+ }
+#ifdef STK_DEBUG_CALI
+ printk(KERN_INFO "%s:OTP step1 Success!\n", __func__);
+#endif
+ buffer[0] = 0x2A;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ goto common_i2c_error;
+ }
+ else
+ {
+ regR[0] = buffer[0];
+ }
+ buffer[0] = 0x2B;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ goto common_i2c_error;
+ }
+ else
+ {
+ regR[1] = buffer[0];
+ }
+ buffer[0] = 0x2E;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ goto common_i2c_error;
+ }
+ else
+ {
+ regR[2] = buffer[0];
+ }
+ buffer[0] = 0x2F;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ goto common_i2c_error;
+ }
+ else
+ {
+ regR[3] = buffer[0];
+ }
+ buffer[0] = 0x32;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ goto common_i2c_error;
+ }
+ else
+ {
+ regR[4] = buffer[0];
+ }
+ buffer[0] = 0x33;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ goto common_i2c_error;
+ }
+ else
+ {
+ regR[5] = buffer[0];
+ }
+
+ regR[1] = offsetData[0];
+ regR[3] = offsetData[2];
+ regR[5] = offsetData[1];
+ if(FT==1)
+ {
+ result = STK831x_WriteByteOTP(0x44, regR[1]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_WriteByteOTP(0x46, regR[3]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_WriteByteOTP(0x48, regR[5]);
+ if(result < 0)
+ goto eng_i2c_err;
+
+ if(!ft_pre_trim)
+ {
+ result = STK831x_WriteByteOTP(0x43, regR[0]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_WriteByteOTP(0x45, regR[2]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_WriteByteOTP(0x47, regR[4]);
+ if(result < 0)
+ goto eng_i2c_err;
+ }
+ }
+ else if (FT == 2)
+ {
+ result = STK831x_WriteByteOTP(0x54, regR[1]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_WriteByteOTP(0x56, regR[3]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_WriteByteOTP(0x58, regR[5]);
+ if(result < 0)
+ goto eng_i2c_err;
+
+ if(!ft_pre_trim)
+ {
+ result = STK831x_WriteByteOTP(0x53, regR[0]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_WriteByteOTP(0x55, regR[2]);
+ if(result < 0)
+ goto eng_i2c_err;
+ result = STK831x_WriteByteOTP(0x57, regR[4]);
+ if(result < 0)
+ goto eng_i2c_err;
+ }
+ }
+#ifdef STK_DEBUG_CALI
+ printk(KERN_INFO "%s:OTP step2 Success!\n", __func__);
+#endif
+ result = STK831x_ReadByteOTP(0x7F, &regR[0]);
+ if(result < 0)
+ goto eng_i2c_err;
+
+ if(FT==1)
+ regR[0] = regR[0]|0x10;
+ else if(FT==2)
+ regR[0] = regR[0]|0x20;
+
+ result = STK831x_WriteByteOTP(0x7F, regR[0]);
+ if(result < 0)
+ goto eng_i2c_err;
+#ifdef STK_DEBUG_CALI
+ printk(KERN_INFO "%s:OTP step3 Success!\n", __func__);
+#endif
+ return 0;
+
+eng_i2c_err:
+ printk(KERN_ERR "%s: read/write eng i2c error, result=0x%x\n", __func__, result);
+ return result;
+
+common_i2c_error:
+ printk(KERN_ERR "%s: read/write common i2c error, result=0x%x\n", __func__, result);
+ return result;
+}
+
+static int STK831X_VerifyCali(struct stk831x_data *stk, unsigned char en_dis, uint32_t delay_ms)
+{
+ unsigned char axis, state;
+ int acc_ave[3] = {0, 0, 0};
+ const unsigned char verify_sample_no = 3;
+#ifdef CONFIG_SENSORS_STK8313
+ const unsigned char verify_diff = 25;
+#elif defined CONFIG_SENSORS_STK8312
+ const unsigned char verify_diff = 2;
+#endif
+ int result;
+ char buffer[2] = "";
+ int ret = 0;
+
+ if(en_dis)
+ {
+ STK831x_SetDelay(stk, 10000000);
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed, result=0x%x\n", __func__, result);
+ return -STK_K_FAIL_I2C;
+ }
+ buffer[1] = (buffer[0] & 0xF8) | 0x01;
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed, result=0x%x\n", __func__, result);
+ return -STK_K_FAIL_I2C;
+ }
+ STK831X_SetVD(stk);
+ msleep(delay_ms*15);
+ }
+
+ for(state=0;state<verify_sample_no;state++)
+ {
+ STK831x_ReadSensorData(stk);
+ for(axis=0;axis<3;axis++)
+ acc_ave[axis] += stk->raw_data[axis];
+#ifdef STK_DEBUG_CALI
+ printk(KERN_INFO "%s: acc=%d,%d,%d\n", __func__, stk->raw_data[0], stk->raw_data[1], stk->raw_data[2]);
+#endif
+ msleep(delay_ms);
+ }
+
+ for(axis=0;axis<3;axis++)
+ acc_ave[axis] /= verify_sample_no;
+
+ switch(stk831x_placement)
+ {
+ case POSITIVE_X_UP:
+ acc_ave[0] -= STK_LSB_1G;
+ break;
+ case NEGATIVE_X_UP:
+ acc_ave[0] += STK_LSB_1G;
+ break;
+ case POSITIVE_Y_UP:
+ acc_ave[1] -= STK_LSB_1G;
+ break;
+ case NEGATIVE_Y_UP:
+ acc_ave[1] += STK_LSB_1G;
+ break;
+ case POSITIVE_Z_UP:
+ acc_ave[2] -= STK_LSB_1G;
+ break;
+ case NEGATIVE_Z_UP:
+ acc_ave[2] += STK_LSB_1G;
+ break;
+ default:
+ printk("%s: invalid stk831x_placement=%d\n", __func__, stk831x_placement);
+ ret = -STK_K_FAIL_PLACEMENT;
+ break;
+ }
+ if(abs(acc_ave[0]) > verify_diff || abs(acc_ave[1]) > verify_diff || abs(acc_ave[2]) > verify_diff)
+ {
+ printk(KERN_INFO "%s:Check data x:%d, y:%d, z:%d\n", __func__,acc_ave[0],acc_ave[1],acc_ave[2]);
+ printk(KERN_ERR "%s:Check Fail, Calibration Fail\n", __func__);
+ ret = -STK_K_FAIL_LRG_DIFF;
+ }
+#ifdef STK_DEBUG_CALI
+ else
+ printk(KERN_INFO "%s:Check data pass\n", __func__);
+#endif
+ if(en_dis)
+ {
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed, result=0x%x\n", __func__, result);
+ return -STK_K_FAIL_I2C;
+ }
+ buffer[1] = (buffer[0] & 0xF8);
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed, result=0x%x\n", __func__, result);
+ return -STK_K_FAIL_I2C;
+ }
+ }
+
+ return ret;
+}
+
+
+static int STK831x_SetCali(struct stk831x_data *stk, char sstate)
+{
+ char org_enable;
+ int acc_ave[3] = {0, 0, 0};
+ int state, axis;
+ int new_offset[3];
+ char char_offset[3] = {0};
+ int result;
+ char buffer[2] = "";
+ char reg_offset[3] = {0};
+ char store_location = sstate;
+ uint32_t gdelay_ns, real_delay_ms;
+ char offset[3];
+
+ atomic_set(&stk->cali_status, STK_K_RUNNING);
+ //sstate=1, STORE_OFFSET_IN_FILE
+ //sstate=2, STORE_OFFSET_IN_IC
+#ifdef STK_DEBUG_CALI
+ printk(KERN_INFO "%s:store_location=%d\n", __func__, store_location);
+#endif
+ if((store_location != 3 && store_location != 2 && store_location != 1) || (stk831x_placement < 0 || stk831x_placement > 5) )
+ {
+ printk(KERN_ERR "%s, invalid parameters\n", __func__);
+ atomic_set(&stk->cali_status, STK_K_FAIL_K_PARA);
+ return -STK_K_FAIL_K_PARA;
+ }
+ STK831x_GetDelay(stk, &gdelay_ns);
+ STK831x_GetEnable(stk, &org_enable);
+ if(org_enable)
+ STK831x_SetEnable(stk, 0);
+ STK831x_SetDelay(stk, 10000000);
+ msleep(1);
+ STK831x_GetDelay(stk, &real_delay_ms);
+ real_delay_ms = (real_delay_ms + (NSEC_PER_MSEC / 2)) / NSEC_PER_MSEC;
+ printk(KERN_INFO "%s: delay =%d ms\n", __func__, real_delay_ms);
+
+ STK831x_SetOffset(reg_offset);
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ goto err_i2c_rw;
+ }
+ buffer[1] = (buffer[0] & 0xF8) | 0x01;
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ goto err_i2c_rw;
+ }
+
+ STK831X_SetVD(stk);
+ if(store_location >= 2)
+ {
+ buffer[0] = 0x2B;
+ buffer[1] = 0x0;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ goto err_i2c_rw;
+ }
+ buffer[0] = 0x2F;
+ buffer[1] = 0x0;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ goto err_i2c_rw;
+ }
+ buffer[0] = 0x33;
+ buffer[1] = 0x0;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ goto err_i2c_rw;
+ }
+ }
+
+ msleep(real_delay_ms*20);
+ for(state=0;state<STK_SAMPLE_NO;state++)
+ {
+ STK831x_ReadSensorData(stk);
+ for(axis=0;axis<3;axis++)
+ acc_ave[axis] += stk->raw_data[axis];
+#ifdef STK_DEBUG_CALI
+ printk(KERN_INFO "%s: acc=%d,%d,%d\n", __func__, stk->raw_data[0], stk->raw_data[1], stk->raw_data[2]);
+#endif
+ msleep(real_delay_ms);
+ }
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ goto err_i2c_rw;
+ }
+ buffer[1] = (buffer[0] & 0xF8);
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ goto err_i2c_rw;
+ }
+
+ for(axis=0;axis<3;axis++)
+ {
+ if(acc_ave[axis] >= 0)
+ acc_ave[axis] = (acc_ave[axis] + STK_SAMPLE_NO / 2) / STK_SAMPLE_NO;
+ else
+ acc_ave[axis] = (acc_ave[axis] - STK_SAMPLE_NO / 2) / STK_SAMPLE_NO;
+
+ }
+ if(acc_ave[2] <= -1)
+ stk831x_placement = NEGATIVE_Z_UP;
+ else if((acc_ave[2] >= 1))
+ stk831x_placement = POSITIVE_Z_UP;
+#ifdef STK_DEBUG_CALI
+ printk(KERN_INFO "%s:stk831x_placement=%d\n", __func__, stk831x_placement);
+#endif
+
+ switch(stk831x_placement)
+ {
+ case POSITIVE_X_UP:
+ acc_ave[0] -= STK_LSB_1G;
+ break;
+ case NEGATIVE_X_UP:
+ acc_ave[0] += STK_LSB_1G;
+ break;
+ case POSITIVE_Y_UP:
+ acc_ave[1] -= STK_LSB_1G;
+ break;
+ case NEGATIVE_Y_UP:
+ acc_ave[1] += STK_LSB_1G;
+ break;
+ case POSITIVE_Z_UP:
+ acc_ave[2] -= STK_LSB_1G;
+ break;
+ case NEGATIVE_Z_UP:
+ acc_ave[2] += STK_LSB_1G;
+ break;
+ default:
+ printk("%s: invalid stk831x_placement=%d\n", __func__, stk831x_placement);
+ atomic_set(&stk->cali_status, STK_K_FAIL_PLACEMENT);
+ return -STK_K_FAIL_K_PARA;
+ break;
+ }
+
+ for(axis=0;axis<3;axis++)
+ {
+ acc_ave[axis] = -acc_ave[axis];
+ new_offset[axis] = acc_ave[axis];
+ char_offset[axis] = new_offset[axis];
+ }
+#ifdef STK_DEBUG_CALI
+ printk(KERN_INFO "%s: New offset:%d,%d,%d\n", __func__, new_offset[0], new_offset[1], new_offset[2]);
+#endif
+ if(store_location == 1)
+ {
+ STK831x_SetOffset(char_offset);
+ msleep(1);
+ STK831x_GetOffset(reg_offset);
+ for(axis=0;axis<3;axis++)
+ {
+ if(char_offset[axis] != reg_offset[axis])
+ {
+ printk(KERN_ERR "%s: set offset to register fail!, char_offset[%d]=%d,reg_offset[%d]=%d\n",
+ __func__, axis,char_offset[axis], axis, reg_offset[axis]);
+ atomic_set(&stk->cali_status, STK_K_FAIL_WRITE_NOFST);
+ return -STK_K_FAIL_WRITE_NOFST;
+ }
+ }
+
+
+ result = STK831X_VerifyCali(stk, 1, real_delay_ms);
+ if(result)
+ {
+ printk(KERN_ERR "%s: calibration check fail, result=0x%x\n", __func__, result);
+ atomic_set(&stk->cali_status, -result);
+ }
+ else
+ {
+ result = stk_store_in_file(char_offset, STK_K_SUCCESS_FILE);
+ if(result)
+ {
+ printk(KERN_INFO "%s:write calibration failed\n", __func__);
+ atomic_set(&stk->cali_status, -result);
+ }
+ else
+ {
+ printk(KERN_INFO "%s successfully\n", __func__);
+ atomic_set(&stk->cali_status, STK_K_SUCCESS_FILE);
+ }
+
+ }
+ }
+ else if(store_location >= 2)
+ {
+ for(axis=0; axis<3; axis++)
+ {
+#ifdef CONFIG_SENSORS_STK8313
+ new_offset[axis]>>=2;
+#endif
+ char_offset[axis] = (char)new_offset[axis];
+ if( (char_offset[axis]>>7)==0)
+ {
+ if(char_offset[axis] >= 0x20 )
+ {
+ printk(KERN_ERR "%s: offset[%d]=0x%x is too large, limit to 0x1f\n",
+ __func__, axis, char_offset[axis] );
+ char_offset[axis] = 0x1F;
+ //atomic_set(&stk->cali_status, STK_K_FAIL_OTP_OUT_RG);
+ //return -STK_K_FAIL_OTP_OUT_RG;
+ }
+ }
+ else
+ {
+ if(char_offset[axis] <= 0xDF)
+ {
+ printk(KERN_ERR "%s: offset[%d]=0x%x is too large, limit to 0x20\n",
+ __func__, axis, char_offset[axis]);
+ char_offset[axis] = 0x20;
+ //atomic_set(&stk->cali_status, STK_K_FAIL_OTP_OUT_RG);
+ //return -STK_K_FAIL_OTP_OUT_RG;
+ }
+ else
+ char_offset[axis] = char_offset[axis] & 0x3f;
+ }
+ }
+
+ printk(KERN_INFO "%s: OTP offset:0x%x,0x%x,0x%x\n", __func__, char_offset[0], char_offset[1], char_offset[2]);
+ if(store_location == 2)
+ {
+ result = stk_store_in_ic( stk, char_offset, 1, real_delay_ms);
+ if(result == 0)
+ {
+ printk(KERN_INFO "%s successfully\n", __func__);
+ atomic_set(&stk->cali_status, STK_K_SUCCESS_FT1);
+ }
+ else
+ {
+ printk(KERN_ERR "%s fail, result=%d\n", __func__, result);
+ }
+ }
+ else if(store_location == 3)
+ {
+ result = stk_store_in_ic( stk, char_offset, 2, real_delay_ms);
+ if(result == 0)
+ {
+ printk(KERN_INFO "%s successfully\n", __func__);
+ atomic_set(&stk->cali_status, STK_K_SUCCESS_FT2);
+ }
+ else
+ {
+ printk(KERN_ERR "%s fail, result=%d\n", __func__, result);
+ }
+ }
+ offset[0] = offset[1] = offset[2] = 0;
+ stk_store_in_file(offset, store_location);
+ }
+#ifdef STK_TUNE
+ stk_tune_offset_record[0] = 0;
+ stk_tune_offset_record[1] = 0;
+ stk_tune_offset_record[2] = 0;
+ stk_tune_done = 1;
+#endif
+ stk->first_enable = false;
+ STK831x_SetDelay(stk, gdelay_ns);
+
+ if(org_enable)
+ STK831x_SetEnable(stk, 1);
+ return 0;
+
+err_i2c_rw:
+ stk->first_enable = false;
+ if(org_enable)
+ STK831x_SetEnable(stk, 1);
+ printk(KERN_ERR "%s: i2c read/write error, err=0x%x\n", __func__, result);
+ atomic_set(&stk->cali_status, STK_K_FAIL_I2C);
+ return result;
+}
+
+
+static int STK831x_GetCali(struct stk831x_data *stk)
+{
+ char r_buf[STK_ACC_CALI_FILE_SIZE] = {0};
+ char offset[3], mode;
+ int cnt, result;
+ char regR[6];
+
+#ifdef STK_TUNE
+ printk(KERN_INFO "%s: stk_tune_done=%d, stk_tune_index=%d, stk_tune_offset=%d,%d,%d\n", __func__,
+ stk_tune_done, stk_tune_index, stk_tune_offset_record[0], stk_tune_offset_record[1],
+ stk_tune_offset_record[2]);
+#endif
+ if ((stk_get_file_content(r_buf, STK_ACC_CALI_FILE_SIZE)) == 0)
+ {
+ if(r_buf[0] == STK_ACC_CALI_VER0 && r_buf[1] == STK_ACC_CALI_VER1)
+ {
+ offset[0] = r_buf[2];
+ offset[1] = r_buf[3];
+ offset[2] = r_buf[4];
+ mode = r_buf[5];
+ printk(KERN_INFO "%s:file offset:%#02x,%#02x,%#02x,%#02x\n",
+ __func__, offset[0], offset[1], offset[2], mode);
+ }
+ else
+ {
+ printk(KERN_ERR "%s: cali version number error! r_buf=0x%x,0x%x,0x%x,0x%x,0x%x\n",
+ __func__, r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4]);
+ }
+ }
+ else
+ printk(KERN_INFO "%s: No file offset\n", __func__);
+
+ for(cnt=0x43;cnt<0x49;cnt++)
+ {
+ result = STK831x_ReadByteOTP(cnt, &(regR[cnt-0x43]));
+ if(result < 0)
+ printk(KERN_ERR "%s: STK831x_ReadByteOTP failed, ret=%d\n", __func__, result);
+ }
+ printk(KERN_INFO "%s: OTP 0x43-0x49:%#02x,%#02x,%#02x,%#02x,%#02x,%#02x\n", __func__, regR[0],
+ regR[1], regR[2],regR[3], regR[4], regR[5]);
+
+ for(cnt=0x53;cnt<0x59;cnt++)
+ {
+ result = STK831x_ReadByteOTP(cnt, &(regR[cnt-0x53]));
+ if(result < 0)
+ printk(KERN_ERR "%s: STK831x_ReadByteOTP failed, ret=%d\n", __func__, result);
+ }
+ printk(KERN_INFO "%s: OTP 0x53-0x59:%#02x,%#02x,%#02x,%#02x,%#02x,%#02x\n", __func__, regR[0],
+ regR[1], regR[2],regR[3], regR[4], regR[5]);
+
+ return 0;
+}
+
+static int STK831x_Init(struct stk831x_data *stk, struct i2c_client *client)
+{
+ int result;
+ char buffer[2] = "";
+
+#ifdef CONFIG_SENSORS_STK8312
+ printk(KERN_INFO "%s: Initialize stk8312\n", __func__);
+#elif defined CONFIG_SENSORS_STK8313
+ printk(KERN_INFO "%s: Initialize stk8313\n", __func__);
+#endif
+
+ buffer[0] = STK831X_RESET;
+ buffer[1] = 0x00;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return result;
+ }
+
+ /* int pin is active high, psuh-pull */
+ buffer[0] = STK831X_MODE;
+ buffer[1] = 0xC0;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return result;
+ }
+
+ /* 50 Hz ODR */
+ stk->delay = STK831X_INIT_ODR;
+ buffer[0] = STK831X_SR;
+ buffer[1] = stk->delay /*+ STK831X_SAMPLE_TIME_BASE*//*2*/; //debug for rotate slowly 2013-8-15
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return result;
+ }
+
+#if (!STK_ACC_POLLING_MODE)
+ /* enable GINT, int after every measurement */
+ buffer[0] = STK831X_INTSU;
+ buffer[1] = 0x10;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:interrupt init failed\n", __func__);
+ return result;
+ }
+#endif
+ /* +- 6g mode */
+ buffer[0] = STK831X_STH;
+#ifdef CONFIG_SENSORS_STK8312
+ buffer[1] = 0x42;
+#elif defined CONFIG_SENSORS_STK8313
+ buffer[1] = 0x82;
+#endif
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ printk(KERN_ERR "%s:set range failed\n", __func__);
+ return result;
+ }
+
+ atomic_set(&stk->enabled, 0);
+ event_since_en = 0;
+
+#ifdef STK_LOWPASS
+ memset(&stk->fir, 0x00, sizeof(stk->fir));
+ atomic_set(&stk->firlength, STK_FIR_LEN);
+ atomic_set(&stk->fir_en, 1);
+#endif
+
+#ifdef STK_TUNE
+ stk_tune_offset[0] = 0;
+ stk_tune_offset[1] = 0;
+ stk_tune_offset[2] = 0;
+ stk_tune_done = 0;
+#endif
+ return 0;
+}
+
+static void stk_handle_first_en(struct stk831x_data *stk)
+{
+ char r_buf[STK_ACC_CALI_FILE_SIZE] = {0};
+ char offset[3];
+ char mode;
+
+ if ((stk_get_file_content(r_buf, STK_ACC_CALI_FILE_SIZE)) == 0)
+ {
+ if(r_buf[0] == STK_ACC_CALI_VER0 && r_buf[1] == STK_ACC_CALI_VER1)
+ {
+ offset[0] = r_buf[2];
+ offset[1] = r_buf[3];
+ offset[2] = r_buf[4];
+ mode = r_buf[5];
+ STK831x_SetOffset(offset);
+#ifdef STK_TUNE
+ stk_tune_offset_record[0] = offset[0];
+ stk_tune_offset_record[1] = offset[1];
+ stk_tune_offset_record[2] = offset[2];
+#endif
+ printk(KERN_INFO "%s: set offset:%d,%d,%d, mode=%d\n", __func__, offset[0], offset[1], offset[2], mode);
+ atomic_set(&stk->cali_status, mode);
+ }
+ else
+ {
+ printk(KERN_ERR "%s: cali version number error! r_buf=0x%x,0x%x,0x%x,0x%x,0x%x\n",
+ __func__, r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4]);
+ //return -EINVAL;
+ }
+ }
+#ifdef STK_TUNE
+ else if(stk_tune_offset_record[0]!=0 || stk_tune_offset_record[1]!=0 || stk_tune_offset_record[2]!=0)
+ {
+ STK831x_SetOffset(stk_tune_offset_record);
+ stk_tune_done = 1;
+ atomic_set(&stk->cali_status, STK_K_SUCCESS_TUNE);
+ printk(KERN_INFO "%s: set offset:%d,%d,%d\n", __func__, stk_tune_offset_record[0],
+ stk_tune_offset_record[1],stk_tune_offset_record[2]);
+ }
+#endif
+ else
+ {
+ offset[0] = offset[1] = offset[2] = 0;
+ stk_store_in_file(offset, STK_K_NO_CALI);
+ atomic_set(&stk->cali_status, STK_K_NO_CALI);
+ }
+ printk(KERN_INFO "%s: finish, cali_status = 0x%x\n", __func__, atomic_read(&stk->cali_status));
+ return;
+}
+
+static int32_t stk_get_ic_content(struct stk831x_data *stk)
+{
+ int result;
+ char regR;
+
+ result = STK831x_ReadByteOTP(0x7F, &regR);
+ if(result < 0)
+ {
+ printk(KERN_ERR "%s: read/write eng i2c error, result=0x%x\n", __func__, result);
+ return result;
+ }
+
+ if(regR&0x20)
+ {
+ atomic_set(&stk->cali_status, STK_K_SUCCESS_FT2);
+ printk(KERN_INFO "%s: OTP 2 used\n", __func__);
+ return 2;
+ }
+ if(regR&0x10)
+ {
+ atomic_set(&stk->cali_status, STK_K_SUCCESS_FT1);
+ printk(KERN_INFO "%s: OTP 1 used\n", __func__);
+ return 1;
+ }
+ return 0;
+}
+
+static int stk_store_in_ic( struct stk831x_data *stk, char otp_offset[], char FT_index, uint32_t delay_ms)
+{
+ int result;
+ char buffer[2] = "";
+
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ goto ic_err_i2c_rw;
+ }
+ buffer[1] = (buffer[0] & 0xF8) | 0x01;
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ goto ic_err_i2c_rw;
+ }
+ STK831X_SetVD(stk);
+
+ buffer[0] = 0x2B;
+ buffer[1] = otp_offset[0];
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ goto ic_err_i2c_rw;
+ }
+ buffer[0] = 0x2F;
+ buffer[1] = otp_offset[2];
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ goto ic_err_i2c_rw;
+ }
+ buffer[0] = 0x33;
+ buffer[1] = otp_offset[1];
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ goto ic_err_i2c_rw;
+ }
+
+
+#ifdef STK_DEBUG_CALI
+ //printk(KERN_INFO "%s:Check All OTP Data after write 0x2B 0x2F 0x33\n", __func__);
+ //STK831x_ReadAllOTP();
+#endif
+
+ msleep(delay_ms*15);
+ result = STK831X_VerifyCali(stk, 0, 0);
+ if(result)
+ {
+ printk(KERN_ERR "%s: calibration check1 fail, FT_index=%d\n", __func__, FT_index);
+ goto ic_err_misc;
+ }
+#ifdef STK_DEBUG_CALI
+ //printk(KERN_INFO "\n%s:Check All OTP Data before write OTP\n", __func__);
+
+#endif
+ //Write OTP
+ printk(KERN_INFO "\n%s:Write offset data to FT%d OTP\n", __func__, FT_index);
+ result = STK831x_WriteOffsetOTP(stk, FT_index, otp_offset);
+ if(result < 0)
+ {
+ printk(KERN_INFO "%s: write OTP%d fail\n", __func__, FT_index);
+ goto ic_err_misc;
+ }
+
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Rx(buffer, 1);
+ if (result < 0)
+ {
+ goto ic_err_i2c_rw;
+ }
+ buffer[1] = (buffer[0] & 0xF8);
+ buffer[0] = STK831X_MODE;
+ result = STK_i2c_Tx(buffer, 2);
+ if (result < 0)
+ {
+ goto ic_err_i2c_rw;
+ }
+
+ msleep(1);
+ STK831x_Init(stk, this_client);
+#ifdef STK_DEBUG_CALI
+ //printk(KERN_INFO "\n%s:Check All OTP Data after write OTP and reset\n", __func__);
+#endif
+
+ result = STK831X_VerifyCali(stk, 1, delay_ms);
+ if(result)
+ {
+ printk(KERN_ERR "%s: calibration check2 fail\n", __func__);
+ goto ic_err_misc;
+ }
+ return 0;
+
+ic_err_misc:
+ STK831x_Init(stk, this_client);
+ msleep(1);
+ atomic_set(&stk->cali_status, -result);
+ return result;
+
+ic_err_i2c_rw:
+ printk(KERN_ERR "%s: i2c read/write error, err=0x%x\n", __func__, result);
+ msleep(1);
+ STK831x_Init(stk, this_client);
+ atomic_set(&stk->cali_status, STK_K_FAIL_I2C);
+ return result;
+}
+
+static int32_t stk_get_file_content(char * r_buf, int8_t buf_size)
+{
+ struct file *cali_file;
+ mm_segment_t fs;
+ ssize_t ret;
+
+ cali_file = filp_open(STK_ACC_CALI_FILE, O_RDONLY,0);
+ if(IS_ERR(cali_file))
+ {
+ printk(KERN_ERR "%s: filp_open error, no offset file!\n", __func__);
+ return -ENOENT;
+ }
+ else
+ {
+ fs = get_fs();
+ set_fs(get_ds());
+ ret = cali_file->f_op->read(cali_file,r_buf, STK_ACC_CALI_FILE_SIZE,&cali_file->f_pos);
+ if(ret < 0)
+ {
+ printk(KERN_ERR "%s: read error, ret=%d\n", __func__, ret);
+ filp_close(cali_file,NULL);
+ return -EIO;
+ }
+ set_fs(fs);
+ }
+
+ filp_close(cali_file,NULL);
+ return 0;
+}
+
+#ifdef STK_PERMISSION_THREAD
+static struct task_struct *STKPermissionThread = NULL;
+
+static int stk_permission_thread(void *data)
+{
+ int ret = 0;
+ int retry = 0;
+ mm_segment_t fs = get_fs();
+ set_fs(KERNEL_DS);
+ msleep(20000);
+ do{
+ msleep(5000);
+ ret = sys_fchmodat(AT_FDCWD, "/sys/class/input/input0/driver/cali" , 0666);
+ ret = sys_fchmodat(AT_FDCWD, "/sys/class/input/input1/driver/cali" , 0666);
+ ret = sys_fchmodat(AT_FDCWD, "/sys/class/input/input2/driver/cali" , 0666);
+ ret = sys_fchmodat(AT_FDCWD, "/sys/class/input/input3/driver/cali" , 0666);
+ ret = sys_fchmodat(AT_FDCWD, "/sys/class/input/input4/driver/cali" , 0666);
+ ret = sys_fchmodat(AT_FDCWD, "/sys/class/input/input0/cali" , 0666);
+ ret = sys_fchmodat(AT_FDCWD, "/sys/class/input/input1/cali" , 0666);
+ ret = sys_fchmodat(AT_FDCWD, "/sys/class/input/input2/cali" , 0666);
+ ret = sys_fchmodat(AT_FDCWD, "/sys/class/input/input3/cali" , 0666);
+ ret = sys_fchmodat(AT_FDCWD, "/sys/class/input/input4/cali" , 0666);
+ ret = sys_chmod(STK_ACC_CALI_FILE , 0666);
+ ret = sys_fchmodat(AT_FDCWD, STK_ACC_CALI_FILE , 0666);
+ //if(ret < 0)
+ // printk("fail to execute sys_fchmodat, ret = %d\n", ret);
+ if(retry++ > 10)
+ break;
+ }while(ret == -ENOENT);
+ set_fs(fs);
+ printk(KERN_INFO "%s exit, retry=%d\n", __func__, retry);
+ return 0;
+}
+#endif /* #ifdef STK_PERMISSION_THREAD */
+
+static int stk_store_in_file(char offset[], char mode)
+{
+ struct file *cali_file;
+ char r_buf[STK_ACC_CALI_FILE_SIZE] = {0};
+ char w_buf[STK_ACC_CALI_FILE_SIZE] = {0};
+ mm_segment_t fs;
+ ssize_t ret;
+ int8_t i;
+
+ w_buf[0] = STK_ACC_CALI_VER0;
+ w_buf[1] = STK_ACC_CALI_VER1;
+ w_buf[2] = offset[0];
+ w_buf[3] = offset[1];
+ w_buf[4] = offset[2];
+ w_buf[5] = mode;
+
+ cali_file = filp_open(STK_ACC_CALI_FILE, O_CREAT | O_RDWR,0666);
+
+ if(IS_ERR(cali_file))
+ {
+ printk(KERN_ERR "%s: filp_open error!\n", __func__);
+ return -STK_K_FAIL_OPEN_FILE;
+ }
+ else
+ {
+ fs = get_fs();
+ set_fs(get_ds());
+
+ ret = cali_file->f_op->write(cali_file,w_buf,STK_ACC_CALI_FILE_SIZE,&cali_file->f_pos);
+ if(ret != STK_ACC_CALI_FILE_SIZE)
+ {
+ printk(KERN_ERR "%s: write error!\n", __func__);
+ filp_close(cali_file,NULL);
+ return -STK_K_FAIL_W_FILE;
+ }
+ cali_file->f_pos=0x00;
+ ret = cali_file->f_op->read(cali_file,r_buf, STK_ACC_CALI_FILE_SIZE,&cali_file->f_pos);
+ if(ret < 0)
+ {
+ printk(KERN_ERR "%s: read error!\n", __func__);
+ filp_close(cali_file,NULL);
+ return -STK_K_FAIL_R_BACK;
+ }
+ set_fs(fs);
+
+ //printk(KERN_INFO "%s: read ret=%d!\n", __func__, ret);
+ for(i=0;i<STK_ACC_CALI_FILE_SIZE;i++)
+ {
+ if(r_buf[i] != w_buf[i])
+ {
+ printk(KERN_ERR "%s: read back error, r_buf[%x](0x%x) != w_buf[%x](0x%x)\n",
+ __func__, i, r_buf[i], i, w_buf[i]);
+ filp_close(cali_file,NULL);
+ return -STK_K_FAIL_R_BACK_COMP;
+ }
+ }
+ }
+ filp_close(cali_file,NULL);
+
+#ifdef STK_PERMISSION_THREAD
+ fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_chmod(STK_ACC_CALI_FILE , 0666);
+ ret = sys_fchmodat(AT_FDCWD, STK_ACC_CALI_FILE , 0666);
+ set_fs(fs);
+#endif
+ //printk(KERN_INFO "%s successfully\n", __func__);
+ return 0;
+}
+
+static int stk_open(struct inode *inode, struct file *file)
+{
+ int ret;
+ ret = nonseekable_open(inode, file);
+ if(ret < 0)
+ return ret;
+ file->private_data = stk831x_data_ptr;
+ return 0;
+}
+
+static int stk_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,36))
+static long stk_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+#else
+static int stk_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+#endif
+{
+ void __user *argp = (void __user *)arg;
+ int retval = 0;
+ char state = 0, restore_state = 0;
+ char rwbuf[8] = "";
+ uint32_t delay_ns;
+ char char3_buffer[3];
+ int result;
+ int int3_buffer[3];
+ struct stk831x_data *stk = file->private_data;
+ unsigned int uval = -1;
+/* printk(KERN_INFO "%s: cmd = 0x%x\n", __func__, cmd); */
+
+ if(cmd == ECS_IOCTL_APP_SET_DELAY || cmd == STK_IOCTL_SET_DELAY || cmd == STK_IOCTL_SET_OFFSET || cmd == STK_IOCTL_SET_RANGE || cmd == STK_IOCTL_WRITE || cmd == STK_IOCTL_SET_CALI)
+ {
+ STK831x_GetEnable(stk, &restore_state);
+ if(restore_state)
+ STK831x_SetEnable(stk, 0);
+ }
+
+ switch (cmd)
+ {
+ case STK_IOCTL_SET_OFFSET:
+ if(copy_from_user(&char3_buffer, argp, sizeof(char3_buffer)))
+ return -EFAULT;
+ break;
+ case ECS_IOCTL_APP_SET_DELAY:
+ case STK_IOCTL_SET_DELAY:
+ if(copy_from_user(&delay_ns, argp, sizeof(uint32_t)))
+ return -EFAULT;
+ break;
+ case STK_IOCTL_WRITE:
+ case STK_IOCTL_READ:
+ if (copy_from_user(&rwbuf, argp, sizeof(rwbuf)))
+ return -EFAULT;
+ break;
+ case ECS_IOCTL_APP_SET_AFLAG:
+ case STK_IOCTL_SET_ENABLE:
+ case STK_IOCTL_SET_RANGE:
+ case STK_IOCTL_SET_CALI:
+ if(copy_from_user(&state, argp, sizeof(char)))
+ return -EFAULT;
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+
+ uval = STK8312_DRVID;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ printk("<<<<<<<driver_id:%d\n",uval);
+ break;
+ case WMT_IOCTL_SENOR_GET_RESOLUTION:
+ uval = (8<<8) | 12; // 8bit:12g 0xxx xx
+
+ if (copy_to_user((unsigned int *)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ printk("<<<<<<<resolution:0x%x\n",uval);
+ default:
+ break;
+ }
+
+ switch (cmd)
+ {
+ case STK_IOCTL_WRITE:
+ if (rwbuf[0] < 2)
+ return -EINVAL;
+ result = STK_i2c_Tx(&rwbuf[1], rwbuf[0]);
+ if (result < 0)
+ return result;
+ break;
+ case STK_IOCTL_SET_OFFSET:
+ STK831x_SetOffset(char3_buffer);
+ break;
+ case ECS_IOCTL_APP_SET_DELAY:
+ case STK_IOCTL_SET_DELAY:
+ STK831x_SetDelay(stk, delay_ns);
+ break;
+ case STK_IOCTL_READ:
+ if (rwbuf[0] < 1)
+ return -EINVAL;
+ result = STK_i2c_Rx(&rwbuf[1], rwbuf[0]);
+ if (result < 0)
+ return result;
+ break;
+ case STK_IOCTL_GET_DELAY:
+ STK831x_GetDelay(stk, &delay_ns);
+ break;
+ case STK_IOCTL_GET_OFFSET:
+ STK831x_GetOffset(char3_buffer);
+ break;
+ case STK_IOCTL_GET_ACCELERATION:
+ STK831x_ReadSensorData(stk);
+ int3_buffer[0] = stk->raw_data[0];
+ int3_buffer[1] = stk->raw_data[1];
+ int3_buffer[2] = stk->raw_data[2];
+ break;
+ case ECS_IOCTL_APP_SET_AFLAG:
+ case STK_IOCTL_SET_ENABLE:
+ STK831x_SetEnable(stk, state);
+ break;
+ case STK_IOCTL_GET_ENABLE:
+ STK831x_GetEnable(stk, &state);
+ break;
+ case STK_IOCTL_SET_RANGE:
+ STK831x_SetRange(state);
+ break;
+ case STK_IOCTL_GET_RANGE:
+ STK831x_GetRange(&state);
+ break;
+ case STK_IOCTL_SET_CALI:
+ STK831x_SetCali(stk, state);
+ break;
+ default:
+ //retval = -ENOTTY;
+ break;
+ }
+
+ if(cmd == ECS_IOCTL_APP_SET_DELAY || cmd == STK_IOCTL_SET_DELAY || cmd == STK_IOCTL_SET_OFFSET || cmd == STK_IOCTL_SET_RANGE || cmd == STK_IOCTL_WRITE || cmd == STK_IOCTL_SET_CALI)
+ {
+ if(restore_state)
+ STK831x_SetEnable(stk, restore_state);
+ }
+ switch (cmd)
+ {
+ case STK_IOCTL_GET_ACCELERATION:
+ if(copy_to_user(argp, &int3_buffer, sizeof(int3_buffer)))
+ return -EFAULT;
+ break;
+ case STK_IOCTL_READ:
+ if(copy_to_user(argp, &rwbuf, sizeof(rwbuf)))
+ return -EFAULT;
+ break;
+ case STK_IOCTL_GET_DELAY:
+ if(copy_to_user(argp, &delay_ns, sizeof(delay_ns)))
+ return -EFAULT;
+ break;
+ case STK_IOCTL_GET_OFFSET:
+ if(copy_to_user(argp, &char3_buffer, sizeof(char3_buffer)))
+ return -EFAULT;
+ break;
+ case STK_IOCTL_GET_RANGE:
+ case STK_IOCTL_GET_ENABLE:
+ if(copy_to_user(argp, &state, sizeof(char)))
+ return -EFAULT;
+ break;
+ default:
+ break;
+ }
+
+ return retval;
+}
+
+
+static struct file_operations stk_fops = {
+ .owner = THIS_MODULE,
+ .open = stk_open,
+ .release = stk_release,
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,36))
+ .unlocked_ioctl = stk_ioctl,
+#else
+ .ioctl = stk_ioctl,
+#endif
+};
+
+static struct miscdevice stk_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+#ifndef STK_WMT_PLATFORM
+ .name = "stk831x",
+#else
+ .name = "sensor_ctrl",
+#endif
+ .fops = &stk_fops,
+};
+
+
+#if STK_ACC_POLLING_MODE
+static enum hrtimer_restart stk_acc_timer_func(struct hrtimer *timer)
+{
+ struct stk831x_data *stk = container_of(timer, struct stk831x_data, acc_timer);
+ queue_work(stk->stk_acc_wq, &stk->stk_acc_work);
+ hrtimer_forward_now(&stk->acc_timer, stk->acc_poll_delay);
+ return HRTIMER_RESTART;
+}
+
+static void stk_acc_poll_work_func(struct work_struct *work)
+{
+ struct stk831x_data *stk = container_of(work, struct stk831x_data, stk_acc_work);
+ STK831x_ReadSensorData(stk);
+ STK831x_ReportValue(stk);
+ return;
+}
+
+#else
+
+static irqreturn_t stk_mems_irq_handler(int irq, void *data)
+{
+ struct stk831x_data *pData = data;
+ disable_irq_nosync(pData->irq);
+ queue_work(stk_mems_work_queue,&pData->stk_work);
+ return IRQ_HANDLED;
+}
+
+
+static void stk_mems_wq_function(struct work_struct *work)
+{
+ struct stk831x_data *stk = container_of(work, struct stk831x_data, stk_work);
+ STK831x_ReadSensorData(stk);
+ STK831x_ReportValue(stk);
+ enable_irq(stk->irq);
+}
+
+static int stk831x_irq_setup(struct i2c_client *client, struct stk831x_data *stk_int)
+{
+ int error;
+ int irq= -1;
+#if ADDITIONAL_GPIO_CFG
+ if (gpio_request(STK_INT_PIN, "EINT"))
+ {
+ printk(KERN_ERR "%s:gpio_request() failed\n",__func__);
+ return -1;
+ }
+ gpio_direction_input(STK_INT_PIN);
+
+ irq = gpio_to_irq(STK_INT_PIN);
+ if ( irq < 0 )
+ {
+ printk(KERN_ERR "%s:gpio_to_irq() failed\n",__func__);
+ return -1;
+ }
+ client->irq = irq;
+ stk_int->irq = irq;
+#endif //#if ADDITIONAL_GPIO_CFG
+ printk(KERN_INFO "%s: irq # = %d\n", __func__, irq);
+ if(irq < 0)
+ printk(KERN_ERR "%s: irq number was not specified!\n", __func__);
+ error = request_irq(client->irq, stk_mems_irq_handler, IRQF_TRIGGER_RISING , "stk-mems", stk_int);
+ if (error < 0)
+ {
+ printk(KERN_ERR "%s: request_irq(%d) failed for (%d)\n", __func__, client->irq, error);
+ return -1;
+ }
+ disable_irq(irq);
+ return irq;
+}
+
+#endif //#if STK_ACC_POLLING_MODE
+
+static ssize_t stk831x_enable_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stk831x_data *stk = i2c_get_clientdata(this_client);
+ return scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&stk->enabled));
+}
+
+static ssize_t stk831x_enable_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+
+ struct stk831x_data *stk = i2c_get_clientdata(this_client);
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ {
+ printk(KERN_ERR "%s: strict_strtoul failed, error=0x%x\n", __func__, error);
+ return error;
+ }
+ if ((data == 0)||(data==1))
+ STK831x_SetEnable(stk,data);
+ else
+ printk(KERN_ERR "%s: invalud argument, data=%ld\n", __func__, data);
+ return count;
+}
+
+static ssize_t stk831x_value_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stk831x_data *stk = i2c_get_clientdata(this_client);
+ int ddata[3];
+
+ printk(KERN_INFO "driver version:%s\n",STK_ACC_DRIVER_VERSION);
+ STK831x_ReadSensorData(stk);
+ ddata[0]= stk->raw_data[0];
+ ddata[1]= stk->raw_data[1];
+ ddata[2]= stk->raw_data[2];
+ return scnprintf(buf, PAGE_SIZE, "%d %d %d\n", ddata[0], ddata[1], ddata[2]);
+}
+
+static ssize_t stk831x_delay_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stk831x_data *stk = i2c_get_clientdata(this_client);
+ uint32_t gdelay_ns;
+
+ STK831x_GetDelay(stk, &gdelay_ns);
+ return scnprintf(buf, PAGE_SIZE, "%d\n", gdelay_ns/1000000);
+}
+
+static ssize_t stk831x_delay_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct stk831x_data *stk = i2c_get_clientdata(this_client);
+ char restore_state = 0;
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ {
+ printk(KERN_ERR "%s: strict_strtoul failed, error=0x%x\n", __func__, error);
+ return error;
+ }
+
+ STK831x_GetEnable(stk, &restore_state);
+ if(restore_state)
+ STK831x_SetEnable(stk, 0);
+
+ STK831x_SetDelay(stk, data*1000000); // ms to ns
+
+ if(restore_state)
+ STK831x_SetEnable(stk, restore_state);
+ return count;
+}
+
+static ssize_t stk831x_cali_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stk831x_data *stk = i2c_get_clientdata(this_client);
+ int status = atomic_read(&stk->cali_status);
+
+ if(status != STK_K_RUNNING)
+ STK831x_GetCali(stk);
+ return scnprintf(buf, PAGE_SIZE, "%02x\n", status);
+}
+
+static ssize_t stk831x_cali_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned long data;
+ int error;
+ struct stk831x_data *stk = i2c_get_clientdata(this_client);
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ {
+ printk(KERN_ERR "%s: strict_strtoul failed, error=0x%x\n", __func__, error);
+ return error;
+ }
+ STK831x_SetCali(stk, data);
+ return count;
+}
+
+static ssize_t stk831x_send_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int error, i;
+ char *token[2];
+ int w_reg[2];
+ char buffer[2] = "";
+
+ for (i = 0; i < 2; i++)
+ token[i] = strsep((char **)&buf, " ");
+ if((error = strict_strtoul(token[0], 16, (unsigned long *)&(w_reg[0]))) < 0)
+ {
+ printk(KERN_ERR "%s:strict_strtoul failed, error=0x%x\n", __func__, error);
+ return error;
+ }
+ if((error = strict_strtoul(token[1], 16, (unsigned long *)&(w_reg[1]))) < 0)
+ {
+ printk(KERN_ERR "%s:strict_strtoul failed, error=0x%x\n", __func__, error);
+ return error;
+ }
+ printk(KERN_INFO "%s: reg[0x%x]=0x%x\n", __func__, w_reg[0], w_reg[1]);
+ buffer[0] = w_reg[0];
+ buffer[1] = w_reg[1];
+ error = STK_i2c_Tx(buffer, 2);
+ if (error < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return error;
+ }
+ return count;
+}
+
+static ssize_t stk831x_recv_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct stk831x_data *stk = i2c_get_clientdata(this_client);
+ return scnprintf(buf, PAGE_SIZE, "%02x\n", stk->recv_reg);
+}
+
+static ssize_t stk831x_recv_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ char buffer[2] = "";
+ unsigned long data;
+ int error;
+ struct stk831x_data *stk = i2c_get_clientdata(this_client);
+
+ error = strict_strtoul(buf, 16, &data);
+ if (error)
+ {
+ printk(KERN_ERR "%s: strict_strtoul failed, error=0x%x\n", __func__, error);
+ return error;
+ }
+
+ buffer[0] = data;
+ error = STK_i2c_Rx(buffer, 2);
+ if (error < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return error;
+ }
+ stk->recv_reg = buffer[0];
+ printk(KERN_INFO "%s: reg[0x%x]=0x%x\n", __func__, (int)data , (int)buffer[0]);
+ return count;
+}
+
+static ssize_t stk831x_allreg_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int error;
+ char buffer[16] = "";
+ char show_buffer[14] = "";
+ int aa,bb, no, show_no = 0;
+
+ for(bb=0;bb<4;bb++)
+ {
+ buffer[0] = bb * 0x10;
+ error = STK_i2c_Rx(buffer, 16);
+ if (error < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return error;
+ }
+ for(aa=0;aa<16;aa++)
+ {
+ no = bb*0x10+aa;
+ printk(KERN_INFO "stk reg[0x%x]=0x%x\n", no, buffer[aa]);
+ switch(no)
+ {
+ case 0x0:
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case STK831X_INTSU:
+ case STK831X_MODE:
+ case STK831X_SR:
+ case STK831X_OFSX:
+ case STK831X_OFSY:
+ case STK831X_OFSZ:
+ case STK831X_STH:
+ case 0x24:
+ show_buffer[show_no] = buffer[aa];
+ show_no++;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return scnprintf(buf, PAGE_SIZE, "0x0=%02x,0x1=%02x,0x2=%02x,0x3=%02x,0x4=%02x,0x5=%02x,INTSU=%02x,MODE=%02x,SR=%02x,OFSX=%02x,OFSY=%02x,OFSZ=%02x,STH=%02x,0x24=%02x\n",
+ show_buffer[0], show_buffer[1], show_buffer[2], show_buffer[3], show_buffer[4],
+ show_buffer[5], show_buffer[6], show_buffer[7], show_buffer[8], show_buffer[9],
+ show_buffer[10], show_buffer[11], show_buffer[12], show_buffer[13]);
+}
+
+static ssize_t stk831x_sendo_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int error, i;
+ char *token[2];
+ int w_reg[2];
+ char buffer[2] = "";
+
+ for (i = 0; i < 2; i++)
+ token[i] = strsep((char **)&buf, " ");
+ if((error = strict_strtoul(token[0], 16, (unsigned long *)&(w_reg[0]))) < 0)
+ {
+ printk(KERN_ERR "%s:strict_strtoul failed, error=0x%x\n", __func__, error);
+ return error;
+ }
+ if((error = strict_strtoul(token[1], 16, (unsigned long *)&(w_reg[1]))) < 0)
+ {
+ printk(KERN_ERR "%s:strict_strtoul failed, error=0x%x\n", __func__, error);
+ return error;
+ }
+ printk(KERN_INFO "%s: reg[0x%x]=0x%x\n", __func__, w_reg[0], w_reg[1]);
+
+ buffer[0] = w_reg[0];
+ buffer[1] = w_reg[1];
+ error = STK831x_WriteByteOTP(buffer[0], buffer[1]);
+ if (error < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return error;
+ }
+ return count;
+}
+
+
+static ssize_t stk831x_recvo_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ char buffer[2] = "";
+ unsigned long data;
+ int error;
+
+ error = strict_strtoul(buf, 16, &data);
+ if (error)
+ {
+ printk(KERN_ERR "%s: strict_strtoul failed, error=0x%x\n", __func__, error);
+ return error;
+ }
+
+ buffer[0] = data;
+ error = STK831x_ReadByteOTP(buffer[0], &buffer[1]);
+ if (error < 0)
+ {
+ printk(KERN_ERR "%s:failed\n", __func__);
+ return error;
+ }
+ printk(KERN_INFO "%s: reg[0x%x]=0x%x\n", __func__, buffer[0] , buffer[1]);
+ return count;
+}
+
+static ssize_t stk831x_firlen_show(struct device *dev,
+struct device_attribute *attr, char *buf)
+{
+#ifdef STK_LOWPASS
+ struct stk831x_data *stk = i2c_get_clientdata(this_client);
+ int len = atomic_read(&stk->firlength);
+
+ if(atomic_read(&stk->firlength))
+ {
+ printk(KERN_INFO "len = %2d, idx = %2d\n", stk->fir.num, stk->fir.idx);
+ printk(KERN_INFO "sum = [%5d %5d %5d]\n", stk->fir.sum[0], stk->fir.sum[1], stk->fir.sum[2]);
+ printk(KERN_INFO "avg = [%5d %5d %5d]\n", stk->fir.sum[0]/len, stk->fir.sum[1]/len, stk->fir.sum[2]/len);
+ }
+ return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&stk->firlength));
+#else
+ return snprintf(buf, PAGE_SIZE, "not support\n");
+#endif
+}
+
+static ssize_t stk831x_firlen_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+#ifdef STK_LOWPASS
+ struct stk831x_data *stk = i2c_get_clientdata(this_client);
+ int error;
+ unsigned long data;
+
+ error = strict_strtoul(buf, 10, &data);
+ if (error)
+ {
+ printk(KERN_ERR "%s: strict_strtoul failed, error=%d\n", __func__, error);
+ return error;
+ }
+
+ if(data > MAX_FIR_LEN)
+ {
+ printk(KERN_ERR "%s: firlen exceed maximum filter length\n", __func__);
+ }
+ else if (data < 1)
+ {
+ atomic_set(&stk->firlength, 1);
+ atomic_set(&stk->fir_en, 0);
+ memset(&stk->fir, 0x00, sizeof(stk->fir));
+ }
+ else
+ {
+ atomic_set(&stk->firlength, data);
+ memset(&stk->fir, 0x00, sizeof(stk->fir));
+ atomic_set(&stk->fir_en, 1);
+ }
+#else
+ printk(KERN_ERR "%s: firlen is not supported\n", __func__);
+#endif
+ return count;
+}
+
+
+static DEVICE_ATTR(enable, 0644, stk831x_enable_show, stk831x_enable_store);
+static DEVICE_ATTR(value, 0444, stk831x_value_show, NULL);
+static DEVICE_ATTR(delay, 0644, stk831x_delay_show, stk831x_delay_store);
+static DEVICE_ATTR(cali, 0644, stk831x_cali_show, stk831x_cali_store);
+static DEVICE_ATTR(send, 0200, NULL, stk831x_send_store);
+static DEVICE_ATTR(recv, 0644, stk831x_recv_show, stk831x_recv_store);
+static DEVICE_ATTR(allreg, 0444, stk831x_allreg_show, NULL);
+static DEVICE_ATTR(sendo, 0200, NULL, stk831x_sendo_store);
+static DEVICE_ATTR(recvo, 0200, NULL, stk831x_recvo_store);
+static DEVICE_ATTR(firlen, 0644, stk831x_firlen_show, stk831x_firlen_store);
+
+static struct attribute *stk831x_attributes[] = {
+ &dev_attr_enable.attr,
+ &dev_attr_value.attr,
+ &dev_attr_delay.attr,
+ &dev_attr_cali.attr,
+ &dev_attr_send.attr,
+ &dev_attr_recv.attr,
+ &dev_attr_allreg.attr,
+ &dev_attr_sendo.attr,
+ &dev_attr_recvo.attr,
+ &dev_attr_firlen.attr,
+ NULL
+};
+
+static struct attribute_group stk831x_attribute_group = {
+#ifndef STK_ALLWINNER_PLATFORM
+ .name = "driver",
+#endif
+ .attrs = stk831x_attributes,
+};
+static int stk831x_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int error;
+ struct stk831x_data *stk;
+
+ printk(KERN_INFO "stk831x_probe: driver version:%s\n",STK_ACC_DRIVER_VERSION);
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ {
+ printk(KERN_ERR "%s:i2c_check_functionality error\n", __func__);
+ error = -ENODEV;
+ goto exit_i2c_check_functionality_error;
+ }
+
+ stk = kzalloc(sizeof(struct stk831x_data),GFP_KERNEL);
+ if (!stk)
+ {
+ printk(KERN_ERR "%s:memory allocation error\n", __func__);
+ error = -ENOMEM;
+ goto exit_kzalloc_error;
+ }
+ stk831x_data_ptr = stk;
+ mutex_init(&stk->write_lock);
+
+#if (STK_ACC_POLLING_MODE)
+ stk->stk_acc_wq = create_singlethread_workqueue("stk_acc_wq");
+ INIT_WORK(&stk->stk_acc_work, stk_acc_poll_work_func);
+ hrtimer_init(&stk->acc_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+// stk->acc_poll_delay = ns_to_ktime(40 * NSEC_PER_MSEC);
+ stk->acc_poll_delay = ns_to_ktime(STK831X_SAMPLE_TIME[STK831X_INIT_ODR]*USEC_PER_MSEC);
+ stk->acc_timer.function = stk_acc_timer_func;
+#else
+ stk_mems_work_queue = create_workqueue("stk_mems_wq");
+ if(stk_mems_work_queue)
+ INIT_WORK(&stk->stk_work, stk_mems_wq_function);
+ else
+ {
+ printk(KERN_ERR "%s:create_workqueue error\n", __func__);
+ error = -EPERM;
+ goto exit_create_workqueue_error;
+ }
+
+ error = stk831x_irq_setup(client, stk);
+ if(!error)
+ {
+ goto exit_irq_setup_error;
+ }
+#endif //#if STK_ACC_POLLING_MODE
+
+ i2c_set_clientdata(client, stk);
+ this_client = client;
+
+ error = STK831x_Init(stk, client);
+ if (error)
+ {
+ printk(KERN_ERR "%s:stk831x initialization failed\n", __func__);
+ goto exit_stk_init_error;
+ }
+ atomic_set(&stk->cali_status, STK_K_NO_CALI);
+ stk->first_enable = true;
+ stk->re_enable = false;
+ event_since_en_limit = 20;
+
+ stk->input_dev = input_allocate_device();
+ if (!stk->input_dev)
+ {
+ error = -ENOMEM;
+ printk(KERN_ERR "%s:input_allocate_device failed\n", __func__);
+ goto exit_input_dev_alloc_error;
+ }
+#ifndef STK_WMT_PLATFORM
+ stk->input_dev->name = ACC_IDEVICE_NAME;
+#else
+ stk->input_dev->name = "g-sensor";
+#endif
+ set_bit(EV_ABS, stk->input_dev->evbit);
+
+ input_set_abs_params(stk->input_dev, ABS_X, -65532, 65532, 0, 0);
+ input_set_abs_params(stk->input_dev, ABS_Y, -65532, 65532, 0, 0);
+ input_set_abs_params(stk->input_dev, ABS_Z, -65532, 65532, 0, 0);
+
+
+ error = input_register_device(stk->input_dev);
+ if (error)
+ {
+ printk(KERN_ERR "%s:Unable to register input device: %s\n", __func__, stk->input_dev->name);
+ goto exit_input_register_device_error;
+ }
+
+ error = misc_register(&stk_device);
+ if (error)
+ {
+ printk(KERN_ERR "%s: misc_register failed\n", __func__);
+ goto exit_misc_device_register_error;
+ }
+ error = sysfs_create_group(&stk_device.this_device->kobj, &stk831x_attribute_group);
+ if (error)
+ {
+ printk(KERN_ERR "%s: sysfs_create_group failed\n", __func__);
+ goto exit_sysfs_create_group_error;
+ }
+
+ printk(KERN_INFO "%s successfully\n", __func__);
+ return 0;
+exit_sysfs_create_group_error:
+ //sysfs_remove_group(&stk->input_dev->dev.kobj, &stk831x_attribute_group);
+ sysfs_remove_group(&stk_device.this_device->kobj, &stk831x_attribute_group);
+exit_misc_device_register_error:
+ misc_deregister(&stk_device);
+exit_input_register_device_error:
+ input_unregister_device(stk->input_dev);
+exit_input_dev_alloc_error:
+exit_stk_init_error:
+#if (STK_ACC_POLLING_MODE)
+ hrtimer_try_to_cancel(&stk->acc_timer);
+ destroy_workqueue(stk->stk_acc_wq);
+#else
+ free_irq(client->irq, stk);
+#if ADDITIONAL_GPIO_CFG
+exit_irq_setup_error:
+ gpio_free( STK_INT_PIN );
+#endif //#if ADDITIONAL_GPIO_CFG
+ destroy_workqueue(stk_mems_work_queue);
+exit_create_workqueue_error:
+#endif //#if (!STK_ACC_POLLING_MODE)
+ mutex_destroy(&stk->write_lock);
+ kfree(stk);
+ stk = NULL;
+exit_kzalloc_error:
+exit_i2c_check_functionality_error:
+ return error;
+}
+
+static int stk831x_remove(struct i2c_client *client)
+{
+ struct stk831x_data *stk = i2c_get_clientdata(client);
+
+ //sysfs_remove_group(&stk->input_dev->dev.kobj, &stk831x_attribute_group);
+ sysfs_remove_group(&stk_device.this_device->kobj, &stk831x_attribute_group);
+ misc_deregister(&stk_device);
+ input_unregister_device(stk->input_dev);
+ cancel_work_sync(&stk->stk_work);
+#if (STK_ACC_POLLING_MODE)
+ hrtimer_try_to_cancel(&stk->acc_timer);
+ destroy_workqueue(stk->stk_acc_wq);
+#else
+ free_irq(client->irq, stk);
+#if ADDITIONAL_GPIO_CFG
+ gpio_free( STK_INT_PIN );
+#endif //#if ADDITIONAL_GPIO_CFG
+ if (stk_mems_work_queue)
+ destroy_workqueue(stk_mems_work_queue);
+#endif //#if (!STK_ACC_POLLING_MODE)
+ mutex_destroy(&stk->write_lock);
+ kfree(stk);
+ stk = NULL;
+ return 0;
+}
+
+static const struct i2c_device_id stk831x[] = {
+ { STK831X_I2C_NAME, 0 },
+ { }
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int stk831x_suspend(struct device *dev)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct stk831x_data *stk = i2c_get_clientdata(client);
+ printk(KERN_INFO "%s\n", __func__);
+ if(atomic_read(&stk->enabled))
+ {
+ STK831x_SetEnable(stk, 0);
+ stk->re_enable = true;
+ }
+ return 0;
+}
+
+
+static int stk831x_resume(struct device *dev)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct stk831x_data *stk = i2c_get_clientdata(client);
+#ifdef STK_RESUME_RE_INIT
+ int error;
+#endif
+
+ printk(KERN_INFO "%s\n", __func__);
+#ifdef STK_RESUME_RE_INIT
+ error = STK831x_Init(stk, this_client);
+ if (error)
+ {
+ printk(KERN_ERR "%s:stk831x initialization failed\n", __func__);
+ return error;
+ }
+ stk->first_enable = true;
+#endif
+ if(stk->re_enable)
+ {
+ stk->re_enable = false;
+ STK831x_SetEnable(stk, 1);
+ }
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+
+#ifdef CONFIG_PM_RUNTIME
+static int stk831x_runtime_suspend(struct device *dev)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct stk831x_data *stk = i2c_get_clientdata(client);
+ printk(KERN_INFO "%s\n", __func__);
+ if(atomic_read(&stk->enabled))
+ {
+ STK831x_SetEnable(stk, 0);
+ stk->re_enable = true;
+ }
+ return 0;
+}
+
+
+static int stk831x_runtime_resume(struct device *dev)
+{
+ struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+ struct stk831x_data *stk = i2c_get_clientdata(client);
+ printk(KERN_INFO "%s\n", __func__);
+ stk->first_enable = true;
+ if(stk->re_enable)
+ {
+ stk->re_enable = false;
+ STK831x_SetEnable(stk, 1);
+ }
+ return 0;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+static const struct dev_pm_ops stk831x_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(stk831x_suspend, stk831x_resume)
+ SET_RUNTIME_PM_OPS(stk831x_runtime_suspend, stk831x_runtime_resume, NULL)
+};
+
+static void stk831x_shutdown(struct i2c_client *client)
+{
+ struct stk831x_data *stk = NULL;
+
+ stk = i2c_get_clientdata(client);
+ hrtimer_cancel(&stk->acc_timer);
+ cancel_work_sync(&stk->stk_acc_work);
+}
+
+static struct i2c_driver stk831x_driver = {
+ .probe = stk831x_probe,
+ .remove = stk831x_remove,
+ .id_table = stk831x,
+ .shutdown = stk831x_shutdown,
+// .suspend = stk831x_suspend,
+// .resume = stk831x_resume,
+ .driver = {
+ .name = STK831X_I2C_NAME,
+ .pm = &stk831x_pm_ops,
+ },
+};
+
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static int get_axisset(void* param)
+{
+ char varbuf[64];
+ int n;
+ int varlen;
+ //int tmpoff[3] = {0};
+ memset(varbuf, 0, sizeof(varbuf));
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara("wmt.io.stk8312sensor", varbuf, &varlen)) {
+ errlog("Can't get gsensor config in u-boot!!!!\n");
+ return -1;
+ } else {
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
+ &l_sensorconfig.op,
+ &(l_sensorconfig.xyz_axis[0][0]),
+ &(l_sensorconfig.xyz_axis[0][1]),
+ &(l_sensorconfig.xyz_axis[1][0]),
+ &(l_sensorconfig.xyz_axis[1][1]),
+ &(l_sensorconfig.xyz_axis[2][0]),
+ &(l_sensorconfig.xyz_axis[2][1]),
+ &(l_sensorconfig.offset[0]),
+ &(l_sensorconfig.offset[1]),
+ &(l_sensorconfig.offset[2]));
+ if (n != 10) {
+ printk(KERN_ERR "gsensor format is error in u-boot!!!\n");
+ return -1;
+ }
+
+ printk("get the sensor config: %d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n",
+ l_sensorconfig.op,
+ l_sensorconfig.xyz_axis[0][0],
+ l_sensorconfig.xyz_axis[0][1],
+ l_sensorconfig.xyz_axis[1][0],
+ l_sensorconfig.xyz_axis[1][1],
+ l_sensorconfig.xyz_axis[2][0],
+ l_sensorconfig.xyz_axis[2][1],
+ l_sensorconfig.offset[0],
+ l_sensorconfig.offset[1],
+ l_sensorconfig.offset[2]
+ );
+ }
+ return 0;
+}
+
+static int is_stk8312(void)
+{
+ struct i2c_client *client = NULL;
+ int ret = 0;
+ char wbuf[1] = {0x0b};
+ char rbuf[1] = {0x0};
+ //int devid = 0;
+ client = this_client;
+ if (!client)
+ {
+ return 0;
+ }
+#if 0
+
+ devid = i2c_smbus_read_byte_data(client, 0x0b); //fail!!!
+#endif
+
+ ret = i2c_master_send(client, wbuf, 1);
+ ret = i2c_master_recv(client, rbuf, 1);
+ printk("<<<%s devid 0x%x\n", __FUNCTION__ ,rbuf[0]);
+#if 0 //also ok!!
+ struct i2c_msg msg[2] = {
+ {.addr = client->addr,
+ .flags = 0,
+ .len = 1,
+ .buf = wbuf,
+ },
+ { .addr = client->addr,
+ .flags = I2C_M_RD,
+ .len = 1,
+ .buf = rbuf,
+ },
+ };
+
+ ret = i2c_transfer(client->adapter, msg, 2);
+
+ printk("ret %d, id 0x%x\n", ret, rbuf[0]);
+#endif
+ if (rbuf[0] == 0x58)
+ return 1;
+ else
+ return 0;
+
+
+}
+
+static int __init stk831x_init(void)
+{
+ int ret = 0;
+ printk(KERN_EMERG"%d:%s",__LINE__,__func__);
+
+ ret = get_axisset(NULL);
+ if (ret < 0)
+ {
+ printk("<<<<<%s user choose to no sensor chip!\n", __func__);
+ return ret;
+ }
+
+ if (!(this_client = sensor_i2c_register_device(0, STKDIR, STK831X_I2C_NAME)))
+ {
+ printk(KERN_EMERG"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+ ret = is_stk8312();
+ if (!ret)
+ {
+ printk("%s not find stk8312\n", __FUNCTION__);
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+
+ }
+
+
+ l_dev_class = class_create(THIS_MODULE, GSENSOR_NAME);
+ //for S40 module to judge whether insmod is ok
+ if (IS_ERR(l_dev_class)){
+ ret = PTR_ERR(l_dev_class);
+ printk(KERN_ERR "Can't class_create gsensor device !!\n");
+ return ret;
+ }
+
+ ret = i2c_add_driver(&stk831x_driver);
+ if (ret!=0)
+ {
+ printk(KERN_EMERG"======stk831x init fail, ret=0x%x======\n", ret);
+ i2c_del_driver(&stk831x_driver);
+ return ret;
+ }
+#ifdef STK_PERMISSION_THREAD
+ STKPermissionThread = kthread_run(
+ ,"stk","Permissionthread");
+ if(IS_ERR(STKPermissionThread))
+ STKPermissionThread = NULL;
+#endif // STK_PERMISSION_THREAD
+ printk(KERN_EMERG"%d:%s",__LINE__,__func__);
+
+ return ret;
+}
+
+static void __exit stk831x_exit(void)
+{
+ //sensor_i2c_unregister_device(this_client);
+ i2c_del_driver(&stk831x_driver);
+ class_destroy(l_dev_class);
+#ifdef STK_PERMISSION_THREAD
+ if(STKPermissionThread)
+ STKPermissionThread = NULL;
+#endif // STK_PERMISSION_THREAD
+ sensor_i2c_unregister_device(this_client);
+}
+
+module_init(stk831x_init);
+module_exit(stk831x_exit);
+
+MODULE_AUTHOR("Lex Hsieh / Sensortek");
+MODULE_DESCRIPTION("stk831x 3-Axis accelerometer driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(STK_ACC_DRIVER_VERSION);
diff --git a/ANDROID_3.4.5/drivers/input/sensor/us5182_lpsensor/Makefile b/ANDROID_3.4.5/drivers/input/sensor/us5182_lpsensor/Makefile
new file mode 100755
index 00000000..1f89e698
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/us5182_lpsensor/Makefile
@@ -0,0 +1,34 @@
+KERNELDIR=../../../../
+#KERNELDIR=/home/hangyan/android8850/kernel/ANDROID_3.0.8
+CROSS = arm_1103_le-
+CC= $(CROSS)gcc
+LD= $(CROSS)ld
+STRIP = $(CROSS)strip
+
+DEBUG = n
+
+# Add your debugging flag (or not) to EXTRA_CFLAGS
+ifeq ($(DEBUG),y)
+# DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+DEBFLAGS = -O0 -g -DSCULL_DEBUG # "-O" is needed to expand inlines
+
+else
+ DEBFLAGS = -O2 -Wall
+endif
+
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+
+MY_MODULE_NAME=s_wmt_lsensor_us5182
+
+obj-m := $(MY_MODULE_NAME).o
+$(MY_MODULE_NAME)-objs := us5182.o
+
+default:
+ $(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
+ $(STRIP) --strip-debug $(MY_MODULE_NAME).ko
+ rm -rf *.o *~ core .depend .*.cmd *.mod.c .tmp_versions
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/us5182_lpsensor/us5182.c b/ANDROID_3.4.5/drivers/input/sensor/us5182_lpsensor/us5182.c
new file mode 100755
index 00000000..b251fb83
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/us5182_lpsensor/us5182.c
@@ -0,0 +1,1098 @@
+/*
+ * us5182.c - us5182 ALS & Proximity Driver
+ *
+ * By Intersil Corp
+ * Michael DiGioia
+ *
+ * Based on isl29011.c
+ * by Mike DiGioia <mdigioia@intersil.com>
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/kernel.h>
+#include <linux/hwmon.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/pm_runtime.h>
+#include <linux/input-polldev.h>
+#include <linux/miscdevice.h>
+#include <asm/uaccess.h>
+//#include <linux/earlysuspend.h>
+#include <linux/types.h>
+#include "../sensor.h"
+#include "us5182.h"
+/* Insmod parameters */
+//I2C_CLIENT_INSMOD_1(us5182);
+
+#define MODULE_NAME "us5182"
+
+#undef dbg
+#define dbg(fmt, args...)
+
+#undef errlog
+#undef klog
+#define errlog(fmt, args...) printk(KERN_ERR "[%s]: " fmt, __FUNCTION__, ## args)
+#define klog(fmt, args...) printk(KERN_ALERT "[%s]: " fmt, __FUNCTION__, ## args)
+
+struct us_device {
+ struct input_polled_dev* input_poll_devl;
+ struct input_polled_dev* input_poll_devp;
+ struct i2c_client* client;
+ struct class* class;
+ struct device *lsdev;
+ dev_t devno;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ struct early_suspend earlysuspend;
+#endif
+ u8 enable_id;
+
+};
+static int psh_l8th = 90;
+static int psh_h8th = 0;
+
+static int psl_l8th = 50;
+static int psl_h8th = 0;
+
+static struct i2c_client *this_client = NULL;
+/*=====Global variable===============================*/
+static u8 error_flag, debounces;
+static int previous_value, this_value;
+static struct i2c_client *gclient = NULL;
+/*===================================================*/
+static u8 reg_cache[us5182_NUM_CACHABLE_REGS];
+
+static struct us_device* l_sensorconfig = NULL;
+static int l_enable = 0; // 0:don't report data
+static int p_enable = 0; // 0:don't report data
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static int no_adc_map = 1;
+
+static DEFINE_MUTEX(mutex);
+
+static int us5182_i2c_read(struct i2c_client *client,u8 reg)
+{
+#if 0
+ int val;
+ val = i2c_smbus_read_byte_data(client, reg);
+ if (val < 0)
+ printk("%s %d i2c transfer error\n", __func__, __LINE__);
+ return val;
+#endif
+//in default our i2c controller, will not send repeatStart signal in read process.(stop-start)
+//well this sensor must have the repeatStart signal to work normally
+//so we have to pass I2C_M_NOSTART flag to controller 2013-7-5
+ char rdData[2] = {0};
+
+ struct i2c_msg msgs[2] =
+ {
+ {.addr = client->addr, .flags = 0|I2C_M_NOSTART, .len = 1, .buf = rdData,},
+ {.addr = client->addr, .flags = I2C_M_RD, .len = 1, .buf = rdData,},
+ };
+ rdData[0] = reg;
+
+ if (i2c_transfer(client->adapter, msgs, 2) < 0) {
+ printk( "%s: transfer failed.", __func__);
+ return -EIO;
+ }
+
+ return rdData[0];
+}
+
+static int get_als_resolution(struct i2c_client *client)
+{
+ return (us5182_i2c_read(client,REGS_CR01) & 0x18) >> 3;
+}
+
+
+static int isl_get_lux_datal(struct i2c_client* client)
+{
+
+ int lsb, msb, bitdepth;
+
+ mutex_lock(&mutex);
+ lsb = us5182_i2c_read(client, REGS_LSB_SENSOR);//
+
+ if (lsb < 0) {
+ mutex_unlock(&mutex);
+ return lsb;
+ }
+
+ msb = us5182_i2c_read(client, REGS_MSB_SENSOR);//
+ mutex_unlock(&mutex);
+
+ if (msb < 0)
+ return msb;
+
+ bitdepth = get_als_resolution(client);//?????
+ switch(bitdepth){
+ case 0:
+ lsb &= 0xF0; // 12bit??
+ lsb >>= 4; //add
+ return ((msb << 4) | lsb);
+ break;
+ case 1:
+ lsb &= 0xFC; //?? 14bit
+ lsb >>= 2;
+ return ((msb << 6) | lsb);
+ break;
+ }
+
+ return ((msb << 8) | lsb);
+}
+
+
+static int get_ps_resolution(struct i2c_client *client)
+{
+ u8 data;
+
+ data = (us5182_i2c_read(client,REGS_CR02) & 0x18) >> 3;
+
+ return data;
+}
+
+static int isl_get_lux_datap(struct i2c_client* client)
+{
+
+ int lsb, msb, bitdepth;
+
+ mutex_lock(&mutex);
+ lsb = us5182_i2c_read(client, REGS_LSB_SENSOR_PS);
+
+ if (lsb < 0) {
+ mutex_unlock(&mutex);
+ return lsb;
+ }
+
+ msb = us5182_i2c_read(client, REGS_MSB_SENSOR_PS);
+ mutex_unlock(&mutex);
+
+ if (msb < 0)
+ return msb;
+
+ bitdepth = get_ps_resolution(client);
+ switch(bitdepth){
+ case 0:
+ lsb &= 0xF0; // 12bit ??
+ lsb >>= 4;
+ return ((msb << 4) | lsb);
+ break;
+ case 1:
+ lsb &= 0xFC; // 14bit ??
+ lsb >>= 2;
+ return ((msb << 6) | lsb);
+ break;
+ }
+
+ return ((msb << 8) | lsb); //we use 16bit now
+}
+
+
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int us5182_detect(struct i2c_client *client/*, int kind,
+ struct i2c_board_info *info*/)
+{
+
+ char rxData[2] = {0xb2, 0};
+ int ret = 0;
+
+#if 1
+ //rxData[0] = 0xb2;
+
+ struct i2c_msg msgs[2] = {
+
+ {.addr = client->addr, .flags = 0|I2C_M_NOSTART, .len = 1, .buf = rxData,},
+ {.addr = client->addr, .flags = I2C_M_RD, .len = 1, .buf = rxData,}
+ };
+ ret = i2c_transfer(client->adapter, msgs, 2);
+ if (ret < 0){
+ printk(KERN_ERR "%s i2c_transfer error!\n", __FUNCTION__);
+ return -EIO;
+ }
+
+#endif
+
+ if(0x26 == rxData[0])
+ {
+ printk(KERN_ALERT "us5182 detected OK\n");
+ return 0;
+ }
+ else
+ return -1;
+}
+
+int isl_input_open(struct input_dev* input)
+{
+ return 0;
+}
+
+void isl_input_close(struct input_dev* input)
+{
+}
+
+//Fixme plan to transfer the adc value to the config.xml lux 2013-5-10
+static __u16 uadc[8] = {2, 8, 100, 400, 900, 1000, 1500, 1900};//customize
+static __u16 ulux[9] = {128, 200, 1300, 2000, 3000, 4000, 5000, 6000, 7000};
+static __u16 adc_to_lux(__u16 adc)
+{
+ static long long var = 0;
+ int i = 0; //length of array is 8,9
+ for (i=0; i<8; i++) {
+ if ( adc < uadc[i]){
+ break;
+ }
+ }
+ if ( i<9)
+ {
+ var++;
+ if (var%2)
+ return ulux[i]+0;
+ else
+ return ulux[i]-1;
+ }
+ return ulux[4];
+}
+
+static void isl_input_lux_poll_l(struct input_polled_dev *dev)
+{
+ struct us_device* idev = dev->private;
+ struct input_dev* input = idev->input_poll_devl->input;
+ struct i2c_client* client = idev->client;
+ int ret_val = 0;
+
+ if (client == NULL){
+ printk("%s client NULL!\n", __FUNCTION__);
+ return;
+ }
+
+ //printk("%s\n", __FUNCTION__);
+ if (l_enable != 0)
+ {
+ //mutex_lock(&mutex); //dead lock!! 2013-7-9!!!
+ //printk(KERN_ALERT "by flashchen val is %x",val);
+ ret_val = isl_get_lux_datal(client); //adc
+ if (ret_val < 0)
+ return;
+ if (!no_adc_map)
+ ret_val = adc_to_lux(ret_val);
+
+ input_report_abs(input, ABS_MISC, ret_val);
+ //printk("%s %d\n", __FUNCTION__, ret_val);
+ input_sync(input);
+ //mutex_unlock(&mutex);
+ }
+}
+
+static void isl_input_lux_poll_p(struct input_polled_dev *dev)
+{
+ struct us_device* idev = dev->private;
+ struct input_dev* input = idev->input_poll_devp->input;
+ struct i2c_client* client = idev->client;
+
+ int tmp_val = 0, debounce = 0;
+ int ret_val = 0;
+
+ //printk("%s\n", __FUNCTION__);
+ if (p_enable != 0)
+ {
+ //mutex_lock(&mutex);
+ //printk(KERN_ALERT "by flashchen val is %x",val);
+
+ #if 0 //just read raw data out 2013-7-18
+ for (debounce=0; debounce<10; debounce++){
+ ret_val = isl_get_lux_datap(client);
+ if (ret_val < 0)
+ return;
+
+ tmp_val += ret_val;
+ msleep(1);
+ }
+ tmp_val /= 10;
+ //add for near/far detection!
+ if (tmp_val > 0x00ff)
+ tmp_val = 6;
+ else
+ tmp_val = 0;
+ input_report_abs(input, ABS_MISC, tmp_val);
+ input_sync(input);
+ #endif
+
+ tmp_val = us5182_i2c_read(client, REGS_CR00);
+
+ if (tmp_val & CR0_PROX_MASK) //approach
+ input_report_abs(input, ABS_MISC, 0);
+ else
+ input_report_abs(input, ABS_MISC, 6);
+
+ input_sync(input);
+ //printk("%s %d\n", __FUNCTION__, tmp_val);
+ //mutex_unlock(&mutex);
+ }
+}
+
+#if 0
+static struct i2c_device_id us5182_id[] = {
+ {"us5182", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, us5182_id);
+#endif // 2013-7-9
+
+static int mmad_open(struct inode *inode, struct file *file)
+{
+ dbg("Open the l-sensor node...\n");
+ return 0;
+}
+
+static int mmad_release(struct inode *inode, struct file *file)
+{
+ dbg("Close the l-sensor node...\n");
+ return 0;
+}
+
+static ssize_t mmadl_read(struct file *fl, char __user *buf, size_t cnt, loff_t *lf)
+{
+ int lux_data = 0;
+ //printk("%s try to mutex_lock \n", __FUNCTION__);
+ //mutex_lock(&mutex);
+ //printk("lock ok!\n");
+ lux_data = isl_get_lux_datal(l_sensorconfig->client);
+ //mutex_unlock(&mutex);
+ if (lux_data < 0)
+ {
+ printk("Failed to read lux data!\n");
+ return -1;
+ }
+ printk(KERN_ALERT "lux_data is %x\n",lux_data);
+ //return 0;
+ copy_to_user(buf, &lux_data, sizeof(lux_data));
+ return sizeof(lux_data);
+}
+
+
+static ssize_t mmadp_read(struct file *fl, char __user *buf, size_t cnt, loff_t *lf)
+{
+ int lux_data = 0;
+
+ //mutex_lock(&mutex);
+ lux_data = isl_get_lux_datap(l_sensorconfig->client);
+ //mutex_unlock(&mutex);
+ if (lux_data < 0)
+ {
+ errlog("Failed to read lux data!\n");
+ return -1;
+ }
+ printk(KERN_ALERT "lux_data is %x\n",lux_data);
+ //return 0;
+ copy_to_user(buf, &lux_data, sizeof(lux_data));
+ return sizeof(lux_data);
+}
+
+static long
+mmadl_ioctl(/*struct inode *inode,*/ struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ //char rwbuf[5];
+ short enable; //amsr = -1;
+ unsigned int uval;
+
+ //printk("l-sensor ioctr... cmd 0x%x arg %d\n", cmd, arg);
+ //memset(rwbuf, 0, sizeof(rwbuf));
+ switch (cmd) {
+ case LIGHT_IOCTL_SET_ENABLE:
+ // enable/disable sensor
+ if (copy_from_user(&enable, argp, sizeof(short)))
+ {
+ printk(KERN_ERR "Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ dbg("enable=%d\n",enable);
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor.\n", enable);
+
+ //l_sensorconfig.sensor_enable = enable;
+ dbg("Should to implement d/e the light sensor!\n");
+ l_enable = enable;
+
+ } else {
+ printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+#define DRVID 0
+ uval = DRVID ;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("us5182_driver_id:%d\n",uval);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+static long
+mmadp_ioctl(/*struct inode *inode,*/ struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ void __user *argp = (void __user *)arg;
+ //char rwbuf[5];
+ short enable; //amsr = -1;
+ unsigned int uval;
+ unsigned char regval;
+
+ dbg("l-sensor ioctr...\n");
+ //memset(rwbuf, 0, sizeof(rwbuf));
+ switch (cmd) {
+ case LIGHT_IOCTL_SET_ENABLE:
+ // enable/disable sensor
+ if (copy_from_user(&enable, argp, sizeof(short)))
+ {
+ printk(KERN_ERR "Can't get enable flag!!!\n");
+ return -EFAULT;
+ }
+ dbg("enable=%d\n",enable);
+ if ((enable >=0) && (enable <=1))
+ {
+ dbg("driver: disable/enable(%d) gsensor.\n", enable);
+
+ //l_sensorconfig.sensor_enable = enable;
+ dbg("Should to implement d/e the light sensor!\n");
+ p_enable = enable;
+ #if 1
+ if(p_enable)
+ {
+ regval = us5182_i2c_read(l_sensorconfig->client, 0);
+ regval &= ~(3 << 4);
+ i2c_smbus_write_byte_data(l_sensorconfig->client, 0, regval);
+ }
+ else
+ {
+ regval = us5182_i2c_read(l_sensorconfig->client, 0);
+ regval &= ~(3 << 4);
+ regval |= (1 << 4);
+ i2c_smbus_write_byte_data(l_sensorconfig->client, 0, regval);
+ }
+ #endif
+
+ } else {
+ printk(KERN_ERR "Wrong enable argument in %s !!!\n", __FUNCTION__);
+ return -EINVAL;
+ }
+ break;
+ case WMT_IOCTL_SENSOR_GET_DRVID:
+#define DRVID 0
+ uval = DRVID ;
+ if (copy_to_user((unsigned int*)arg, &uval, sizeof(unsigned int)))
+ {
+ return -EFAULT;
+ }
+ dbg("us5182_driver_id:%d\n",uval);
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+static struct file_operations mmadl_fops = {
+ .owner = THIS_MODULE,
+ .open = mmad_open,
+ .release = mmad_release,
+ .read = mmadl_read,
+ .unlocked_ioctl = mmadl_ioctl,
+};
+
+static struct miscdevice mmadl_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "lsensor_ctrl",
+ .fops = &mmadl_fops,
+};
+
+static struct file_operations mmadp_fops = {
+ .owner = THIS_MODULE,
+ .open = mmad_open,
+ .release = mmad_release,
+ .read = mmadp_read,
+ .unlocked_ioctl = mmadp_ioctl,
+};
+
+static struct miscdevice mmadp_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "psensor_ctrl",
+ .fops = &mmadp_fops,
+};
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void us5182_early_suspend(struct early_suspend *h)
+{
+ dbg("start\n");
+ mutex_lock(&mutex);
+ //pm_runtime_get_sync(dev);
+ //isl_set_mod(client, ISL_MOD_POWERDOWN);
+ //pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ dbg("exit\n");
+}
+
+static void us5182_late_resume(struct early_suspend *h)
+{
+ struct i2c_client *client = l_sensorconfig->client;
+
+ dbg("start\n");
+ mutex_lock(&mutex);
+ //pm_runtime_get_sync(dev);
+ //isl_set_mod(client, last_mod);
+ //isl_set_default_config(client);
+ //pm_runtime_put_sync(dev);
+ mutex_unlock(&mutex);
+ dbg("exit\n");
+}
+#endif
+
+int us5182_i2c_write(struct i2c_client *client, u8 reg,u8 mask, u8 shift, int val ) {
+ //struct us5182_data *data = i2c_get_clientdata(client);
+ int err;
+ u8 tmp;
+ mutex_lock(&mutex);
+
+ tmp = reg_cache[reg];
+ tmp &= ~mask;
+ tmp |= val << shift;
+
+ err = i2c_smbus_write_byte_data(client, reg, tmp);
+ if (!err)
+ reg_cache[reg] = tmp;
+
+ mutex_unlock(&mutex);
+ if (err >= 0) return 0;
+
+ printk("%s %d i2c transfer error\n", __func__, __LINE__);
+ return err;
+}
+
+
+static int set_word_mode(struct i2c_client *client, int mode)
+{
+ //
+ return us5182_i2c_write(client, REGS_CR00,
+ CR0_WORD_MASK, CR0_WORD_SHIFT, mode);
+}
+
+
+static int set_oneshotmode(struct i2c_client *client, int mode)
+{
+ return us5182_i2c_write(client,REGS_CR00,CR0_ONESHOT_MASK, CR0_ONESHOT_SHIFT, mode);
+}
+
+
+static int set_opmode(struct i2c_client *client, int mode)
+{
+ return us5182_i2c_write(client,REGS_CR00,CR0_OPMODE_MASK,
+ CR0_OPMODE_SHIFT, mode);
+}
+
+/* power_status */
+static int set_power_status(struct i2c_client *client, int status)
+{
+ if(status == CR0_SHUTDOWN_EN )
+ return us5182_i2c_write(client,REGS_CR00,CR0_SHUTDOWN_MASK,
+ CR0_SHUTDOWN_SHIFT,CR0_SHUTDOWN_EN);
+ else
+ return us5182_i2c_write(client,REGS_CR00,CR0_SHUTDOWN_MASK,
+ CR0_SHUTDOWN_SHIFT, CR0_OPERATION);
+}
+
+
+static int us5182_init_client(struct i2c_client *client)
+{
+
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+ int i = 0;
+ int v = -1;
+ if ( !i2c_check_functionality(adapter,I2C_FUNC_SMBUS_BYTE_DATA) ) {
+ printk(KERN_INFO "byte op is not permited.\n");
+ return -EIO;
+ }
+
+ /* read all the registers once to fill the cache.
+ * if one of the reads fails, we consider the init failed */
+
+ for (i = 0; i < ARRAY_SIZE(reg_cache); i++) {
+ v = us5182_i2c_read(client, i);
+ printk("reg 0x%x value 0x%x \n", i, v);
+ if (v < 0)
+ return -ENODEV;
+ reg_cache[i] = v;
+ }
+
+ /*Set Default*/
+ set_word_mode(client, 0);//word enable? //just byte one time
+ set_power_status(client,CR0_OPERATION); //power on?
+ set_opmode(client,CR0_OPMODE_ALSONLY); //CR0_OPMODE_ALSANDPS CR0_OPMODE_ALSONLY
+ set_oneshotmode(client, CR0_ONESHOT_DIS);
+
+ us5182_i2c_write(client, REGS_CR03, CR3_LEDDR_MASK, CR3_LEDDR_SHIFT, CR3_LEDDR_50);
+
+ //set als gain
+ us5182_i2c_write(client, REGS_CR01, CR1_ALS_GAIN_MASK, CR1_ALS_GAIN_SHIFT, CR1_ALS_GAIN_X8);
+
+ //set ps threshold --> lth, hth
+ us5182_i2c_write(client, REGS_INT_LSB_TH_HI_PS, 0xff, 0, psh_l8th); //
+ us5182_i2c_write(client, REGS_INT_MSB_TH_HI_PS, 0xff, 0, psh_h8th); //0 default
+
+ us5182_i2c_write(client, REGS_INT_LSB_TH_LO_PS, 0xff, 0, psl_l8th); //
+ us5182_i2c_write(client, REGS_INT_MSB_TH_LO_PS, 0xff, 0, psl_h8th); // 0 default
+ //set_resolution(client,us5182_RES_16);
+ //set_range(client,3);
+ //set_int_ht(client,0x3E8); //1000 lux
+ //set_int_lt(client,0x8); //8 lux
+ //dev_info(&data->client->dev, "us5182 ver. %s found.\n",DRIVER_VERSION);
+
+ /*init global variable*/
+ error_flag = 0;
+ previous_value = 0;
+ this_value = 0;
+ debounces = 2;//debounces 5 times
+ return 0;
+}
+//******add for sys debug devic_attribute
+static ssize_t reg_show(struct device *dev, struct device_attribute *attr, char *buf) {
+
+ int i = 0, val = 0;
+ printk("<<<<<<<<<reg dump\n");
+
+ for (i=0; i<=0x1f; i++) {
+ val = us5182_i2c_read(gclient, i);
+ printk("reg 0x%x: val 0x%x \n", i, val);
+
+ }
+ printk("\n");
+ printk("<<<<<<<<<<<<<<<<<<<<dump end\n");
+ return 0;
+}
+
+static ssize_t reg_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
+
+ int reg = 0, val = 0;
+ int ret = 0;
+ int res = 0;
+
+ printk("buf is %s\n", buf);
+
+ ret = sscanf(buf, "%x:%x", &reg, &val);
+ printk("reg:val is 0x%x:0x%x\n", reg, val);
+
+ if (reg<0 || val<0) {
+ printk("param error!\n");
+ return -1;
+ }
+
+ res = us5182_i2c_read(gclient, reg);
+ i2c_smbus_write_byte_data(gclient, reg, val);
+ printk(KERN_ERR "reg 0x%x 0x%x -->0x%x\n", reg, res, val);
+
+ return count;
+}
+//struct device_attribute dev_attr_reg = __ATTR(reg, 0644, reg_show, reg_store);
+//DEVICE_ATTR(reg, 0644, reg_show, reg_store);
+
+static ssize_t adc_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+
+ int i;
+ int size = sizeof(uadc)/sizeof(uadc[0]);
+ printk("<<<%s\n", __FUNCTION__);
+ for (i=0; i<size; i++)
+ {
+ printk(" %5d ", uadc[i]);
+ //sprintf(buf, "%d " &uadc[i]);
+ }
+ printk("\n");
+
+ return sizeof(uadc);
+ //printk(" %s \n", buf);
+}
+
+static ssize_t adc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ __u32 tmp;
+ int index;
+ int n;
+ int size = sizeof(uadc)/sizeof(uadc[0]);
+
+ printk("<<<%s\n", __FUNCTION__);
+ printk("<< %s >>>\n", buf);
+ n = sscanf(buf, "%d:%d", &index, &tmp);
+ printk("<<<<int n %d %d:%d \n", n, index, tmp);
+ if ( n==2 && index>=0 && index<size){
+
+ uadc[index] = tmp;
+ no_adc_map = 0;
+ }
+ else {
+ printk("<<<param error!\n");
+ no_adc_map = 1;
+ }
+ return count;
+}
+
+static struct device_attribute us5182_attr[] =
+{
+ __ATTR(reg, 0644, reg_show, reg_store),
+ __ATTR(adc, 0644, adc_show, adc_store),
+ __ATTR_NULL,
+};
+
+static int device_create_attribute(struct device *dev, struct device_attribute *attr)
+{
+ int err = 0, i;
+ for (i=0; NULL != attr[i].attr.name; i++)
+ {
+ err = device_create_file(dev, &attr[i]); //&attr[i].attr
+ if (err)
+ break;
+ }
+ if (err)
+ {
+ for (; i>=0; i--)
+ device_remove_file(dev, &attr[i]);//&attr[i].attr
+ }
+ return err;
+}
+
+static void device_remove_attribute(struct device *dev, struct device_attribute *attr)
+{
+ int i;
+ for (i=0; attr[i].attr.name != NULL; i++)
+ device_remove_file(dev, &attr[i]); //&attr[i].attr
+}
+//add end
+static int
+us5182_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ int res=0;
+
+ struct us_device* idev = kzalloc(sizeof(struct us_device), GFP_KERNEL);
+ if(!idev)
+ return -ENOMEM;
+
+ l_sensorconfig = idev;
+
+ /*initial enable device id*/
+ idev->enable_id = 0x00;
+
+ gclient = client;
+ /* initialize the us5182 chip */
+ res = us5182_init_client(client);//
+
+ if (res != 0)
+ goto err_input_allocate_device;
+/* last mod is ALS continuous */
+ //pm_runtime_enable(&client->dev);
+ idev->input_poll_devl = input_allocate_polled_device();
+ if(!idev->input_poll_devl)
+ {
+ res = -ENOMEM;
+ goto err_input_allocate_device;
+ }
+ idev->input_poll_devp = input_allocate_polled_device();
+ if(!idev->input_poll_devp)
+ {
+ res = -ENOMEM;
+ goto err_input_allocate_device;
+ }
+ idev->client = client;
+
+ idev->input_poll_devl->private = idev;
+ idev->input_poll_devl->poll = isl_input_lux_poll_l;
+ idev->input_poll_devl->poll_interval = 100;//50;
+ idev->input_poll_devl->input->open = isl_input_open;
+ idev->input_poll_devl->input->close = isl_input_close;
+ idev->input_poll_devl->input->name = "lsensor_lux";
+ idev->input_poll_devl->input->id.bustype = BUS_I2C;
+ idev->input_poll_devl->input->dev.parent = &client->dev;
+
+ input_set_drvdata(idev->input_poll_devl->input, idev);
+ input_set_capability(idev->input_poll_devl->input, EV_ABS, ABS_MISC);
+ input_set_abs_params(idev->input_poll_devl->input, ABS_MISC, 0, 16000, 0, 0);
+
+ idev->input_poll_devp->private = idev;
+ idev->input_poll_devp->poll = isl_input_lux_poll_p;
+ idev->input_poll_devp->poll_interval = 10;//100; 50ms
+ idev->input_poll_devp->input->open = isl_input_open;
+ idev->input_poll_devp->input->close = isl_input_close;
+ idev->input_poll_devp->input->name = "psensor_lux";
+ idev->input_poll_devp->input->id.bustype = BUS_I2C;
+ idev->input_poll_devp->input->dev.parent = &client->dev;
+
+ input_set_drvdata(idev->input_poll_devp->input, idev);
+ input_set_capability(idev->input_poll_devp->input, EV_ABS, ABS_MISC);
+ input_set_abs_params(idev->input_poll_devp->input, ABS_MISC, 0, 16000, 0, 0);
+ i2c_set_clientdata(client, idev);
+ /* set default config after set_clientdata */
+ //res = isl_set_default_config(client);
+ res = misc_register(&mmadl_device);
+ if (res) {
+ errlog("mmad_device register failed\n");
+ goto err_misc_registerl;
+ }
+ res = misc_register(&mmadp_device);
+ if (res) {
+ errlog("mmad_device register failed\n");
+ goto err_misc_registerp;
+ }
+ res = input_register_polled_device(idev->input_poll_devl);
+ if(res < 0)
+ goto err_input_register_devicel;
+ res = input_register_polled_device(idev->input_poll_devp);
+ if(res < 0)
+ goto err_input_register_devicep;
+ // suspend/resume register
+#ifdef CONFIG_HAS_EARLYSUSPEND
+ idev->earlysuspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+ idev->earlysuspend.suspend = us5182_early_suspend;
+ idev->earlysuspend.resume = us5182_late_resume;
+ register_early_suspend(&(idev->earlysuspend));
+#endif
+
+ dbg("us5182 probe succeed!\n");
+ res = alloc_chrdev_region(&idev->devno, 0, 1, "us5182");
+ if(res)
+ {
+ printk("can't allocate chrdev\n");
+ return 0;
+ }
+ idev->class = class_create(THIS_MODULE, "us5182-lsensor");
+ if (IS_ERR(idev->class)) {
+ printk("<<< %s class_create() error!\n", __FUNCTION__);
+ return 0;
+ }
+ idev->lsdev = device_create(idev->class, NULL, idev->devno, NULL, "us5182");
+ if (IS_ERR(idev->lsdev)) {
+ printk("<<< %s device_create() error!\n", __FUNCTION__);
+ return 0;
+ }
+ res = device_create_attribute(idev->lsdev, us5182_attr);
+ return 0;
+err_input_register_devicep:
+ input_free_polled_device(idev->input_poll_devp);
+err_input_register_devicel:
+ input_free_polled_device(idev->input_poll_devl);
+err_misc_registerp:
+ misc_deregister(&mmadp_device);
+err_misc_registerl:
+ misc_deregister(&mmadl_device);
+err_input_allocate_device:
+ //__pm_runtime_disable(&client->dev, false);
+ kfree(idev);
+ return res;
+}
+
+static int us5182_remove(struct i2c_client *client)
+{
+ int i = 0;
+ struct us_device* idev = i2c_get_clientdata(client);
+#if 1
+ //device_remove_file(idev->lsdev, &dev_attr_reg);
+ device_remove_attribute(idev->lsdev, us5182_attr);
+ unregister_chrdev_region(idev->devno, 1);
+ device_destroy(idev->class, idev->devno);
+ class_destroy(idev->class);
+#endif
+ printk("%s %d\n", __FUNCTION__, i++); // 0
+ //unregister_early_suspend(&(idev->earlysuspend));
+ misc_deregister(&mmadl_device);
+ printk("%s %d\n", __FUNCTION__, i++);
+ misc_deregister(&mmadp_device);
+ printk("%s %d\n", __FUNCTION__, i++);
+ input_unregister_polled_device(idev->input_poll_devl);//here block??
+ printk("%s %d\n", __FUNCTION__, i++);
+ input_unregister_polled_device(idev->input_poll_devp);
+ printk("%s %d\n", __FUNCTION__, i++);
+ input_free_polled_device(idev->input_poll_devl);
+ printk("%s %d\n", __FUNCTION__, i++);
+ input_free_polled_device(idev->input_poll_devp);
+ printk("%s %d\n", __FUNCTION__, i++);
+ //__pm_runtime_disable(&client->dev, false);
+
+ kfree(idev);
+ printk(KERN_INFO MODULE_NAME ": %s us5182 remove call, \n", __func__);
+ return 0;
+}
+static void us5182_shutdown(struct i2c_client *client)
+{
+ l_enable = 0;
+ p_enable = 0;
+}
+
+static int us5182_suspend(struct i2c_client *client, pm_message_t message)
+{
+ return 0;
+}
+static int us5182_resume(struct i2c_client *client)
+{
+ int res = 0;
+ res = us5182_init_client(client);//
+ return 0;
+}
+
+static const struct i2c_device_id us5182_id[] = {
+ { SENSOR_I2C_NAME , 0 },
+ {},
+};
+
+
+static struct i2c_driver us5182_i2c_driver =
+{
+ .probe = us5182_probe,
+ .remove = us5182_remove,
+ .suspend = us5182_suspend,
+ .resume = us5182_resume,
+ .shutdown = us5182_shutdown,
+ .driver = {
+ .name = SENSOR_I2C_NAME,
+ .owner = THIS_MODULE,
+ },
+ .id_table = us5182_id,
+};
+
+static int get_adc_val(void)
+{
+ int i=0, varlen=0, n=0;
+ __u32 buf[8] = {0};
+ char varbuf[50] ={0};
+ char *name = "wmt.io.lsensor";
+ char *psth = "wmt.io.psensor";
+ int thbuf[4] = {0};
+
+ varlen = sizeof(varbuf);
+ if (wmt_getsyspara(psth, varbuf, &varlen))
+ {
+ printk("<<<<fail to wmt_syspara %s\n", "wmt.io.psensor");
+
+ }
+ else
+ {
+ n = sscanf(varbuf, "%d:%d:%d:%d", &thbuf[0], &thbuf[1], &thbuf[2], &thbuf[3]);
+ if (n == 4)
+ {
+ psh_h8th = thbuf[0];
+ psh_l8th = thbuf[1];
+ psl_h8th = thbuf[2];
+ psl_l8th = thbuf[3];
+ }
+ else
+ printk("wmt.io.psensor error!\n");
+ }
+ if (wmt_getsyspara(name, varbuf, &varlen))
+ {
+ printk("<<<<fail to wmt_syspara %s\n", "wmt.io.lsensor");
+ no_adc_map = 1;
+ return -1;
+ }
+ n = sscanf(varbuf, "%d:%d:%d:%d:%d:%d:%d:%d", &buf[0], &buf[1], &buf[2], &buf[3], &buf[4], &buf[5], \
+ &buf[6], &buf[7]);
+ //printk("<<< n %d \n", n);
+ if (n != 8)
+ {
+ printk("<<<<<%s uboot env wmt.io.lsensor param error!\n", __FUNCTION__);
+ return -1;
+ }
+ for (i=0; i<8; i++)
+ {
+ //printk("<<<< %5d ", buf[i]);
+ uadc[i] = buf[i];
+ }
+ no_adc_map = 0;
+ //printk("\n");
+ return 0;
+}
+
+static int __init sensor_us5182_init(void)
+{
+ printk(KERN_INFO MODULE_NAME ": %s us5182 init call, \n", __func__);
+ /*
+ * Force device to initialize: i2c-15 0x44
+ * If i2c_new_device is not called, even us5182_detect will not run
+ * TODO: rework to automatically initialize the device
+ */
+ //i2c_new_device(i2c_get_adapter(15), &isl_info);
+ //return i2c_add_driver(&us5182_driver);
+ if (!(this_client = sensor_i2c_register_device(4, SENSOR_I2C_ADDR, SENSOR_I2C_NAME)))
+ {
+ printk(KERN_EMERG"Can't register gsensor i2c device!\n");
+ return -1;
+ }
+ if (us5182_detect(this_client)) //
+ {
+ errlog("Can't find light sensor us5182!\n");
+ goto detect_fail;
+ }
+
+ get_adc_val();
+/*
+ if(us5182_probe(this_client))
+ {
+ errlog("Erro for probe!\n");
+ goto detect_fail;
+ }
+*/
+ if(i2c_add_driver(&us5182_i2c_driver) < 0)
+ {
+ errlog("Erro for i2c_add_driver()!\n");
+ goto detect_fail;
+ }
+ return 0;
+
+detect_fail:
+ sensor_i2c_unregister_device(this_client);
+ return -1;
+}
+
+static void __exit sensor_us5182_exit(void)
+{
+ printk(KERN_INFO MODULE_NAME ": %s us5182 exit call \n", __func__);
+ //us5182_remove(this_client);
+ i2c_del_driver(&us5182_i2c_driver);
+ sensor_i2c_unregister_device(this_client);
+
+}
+
+module_init(sensor_us5182_init);
+module_exit(sensor_us5182_exit);
+
+MODULE_AUTHOR("rambo");
+MODULE_ALIAS("us5182 ALS");
+MODULE_DESCRIPTION("us5182 Driver");
+MODULE_LICENSE("GPL v2");
+
diff --git a/ANDROID_3.4.5/drivers/input/sensor/us5182_lpsensor/us5182.h b/ANDROID_3.4.5/drivers/input/sensor/us5182_lpsensor/us5182.h
new file mode 100755
index 00000000..361d91e8
--- /dev/null
+++ b/ANDROID_3.4.5/drivers/input/sensor/us5182_lpsensor/us5182.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2012 UPI finley_huang <finley_huang@upi-semi.com>. All Rights Reserved.
+ * us5182 Light Sensor Driver for Linux 2.6
+ */
+
+/*
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __us5182_H__
+#define __us5182_H__
+
+#include <linux/types.h>
+
+#define SENSOR_I2C_NAME "us5182"
+#define SENSOR_I2C_ADDR (0x72>>1) //0x72 //7bit 0x39
+/*us5182 Slave Addr*/
+#define LIGHT_ADDR 0x39 //0x72 //7bit 0x39
+
+/*Interrupt PIN for S3C6410*/
+//#define IRQ_LIGHT_INT IRQ_EINT(6) //comment for compile error
+
+/*Register Set*/
+#define REGS_CR00 0x00
+#define REGS_CR01 0x01
+#define REGS_CR02 0x02
+#define REGS_CR03 0x03
+//ALS
+#define REGS_INT_LSB_TH_LO 0x04
+#define REGS_INT_MSB_TH_LO 0x05
+#define REGS_INT_LSB_TH_HI 0x06
+#define REGS_INT_MSB_TH_HI 0x07
+//PS
+#define REGS_INT_LSB_TH_LO_PS 0x08
+#define REGS_INT_MSB_TH_LO_PS 0x09
+#define REGS_INT_LSB_TH_HI_PS 0x0A
+#define REGS_INT_MSB_TH_HI_PS 0x0B
+//ALS data
+#define REGS_LSB_SENSOR 0x0C
+#define REGS_MSB_SENSOR 0x0D
+//PS data
+#define REGS_LSB_SENSOR_PS 0x0E
+#define REGS_MSB_SENSOR_PS 0x0F
+
+#define REGS_CR10 0x10
+#define REGS_CR11 0x11
+#define REGS_CR16 0x16
+#define REGS_CR20 0x20
+#define REGS_CR21 0x21
+#define REGS_CR22 0x22
+#define REGS_CR29 0x29
+#define REGS_CR2A 0x2A
+#define REGS_CR2B 0x2B
+#define REGS_VERSION_ID 0x1F
+#define REGS_CHIP_ID 0xB2
+
+/*ShutDown_EN*/
+#define CR0_OPERATION 0x0
+#define CR0_SHUTDOWN_EN 0x1
+
+#define CR0_SHUTDOWN_SHIFT (7)
+#define CR0_SHUTDOWN_MASK (0x1 << CR0_SHUTDOWN_SHIFT)
+
+/*OneShot_EN*/
+#define CR0_ONESHOT_EN 0x01
+#define CR0_ONESHOT_DIS 0x00
+#define CR0_ONESHOT_SHIFT (6)
+#define CR0_ONESHOT_MASK (0x1 << CR0_ONESHOT_SHIFT)
+
+/*Operation Mode*/
+#define CR0_OPMODE_ALSANDPS 0x0
+#define CR0_OPMODE_ALSONLY 0x1
+#define CR0_OPMODE_IRONLY 0x2
+
+#define CR0_OPMODE_SHIFT (4)
+#define CR0_OPMODE_MASK (0x3 << CR0_OPMODE_SHIFT)
+
+/*all int flag (PROX, INT_A, INT_P)*/
+#define CR0_ALL_INT_CLEAR 0x0
+
+#define CR0_ALL_INT_SHIFT (1)
+#define CR0_ALL_INT_MASK (0x7 << CR0_ALL_INT_SHIFT)
+
+
+/*indicator of object proximity detection*/
+#define CR0_PROX_CLEAR 0x0
+
+#define CR0_PROX_SHIFT (3)
+#define CR0_PROX_MASK (0x1 << CR0_PROX_SHIFT)
+
+/*interrupt status of proximity sensor*/
+#define CR0_INTP_CLEAR 0x0
+
+#define CR0_INTP_SHIFT (2)
+#define CR0_INTP_MASK (0x1 << CR0_INTP_SHIFT)
+
+/*interrupt status of ambient sensor*/
+#define CR0_INTA_CLEAR 0x0
+
+#define CR0_INTA_SHIFT (1)
+#define CR0_INTA_MASK (0x1 << CR0_INTA_SHIFT)
+
+/*Word mode enable*/
+#define CR0_WORD_EN 0x1
+
+#define CR0_WORD_SHIFT (0)
+#define CR0_WORD_MASK (0x1 << CR0_WORD_SHIFT)
+
+
+/*ALS fault queue depth for interrupt enent output*/
+#define CR1_ALS_FQ_1 0x0
+#define CR1_ALS_FQ_4 0x1
+#define CR1_ALS_FQ_8 0x2
+#define CR1_ALS_FQ_16 0x3
+#define CR1_ALS_FQ_24 0x4
+#define CR1_ALS_FQ_32 0x5
+#define CR1_ALS_FQ_48 0x6
+#define CR1_ALS_FQ_63 0x7
+
+#define CR1_ALS_FQ_SHIFT (5)
+#define CR1_ALS_FQ_MASK (0x7 << CR1_ALS_FQ_SHIFT)
+
+/*resolution for ALS*/
+#define CR1_ALS_RES_12BIT 0x0
+#define CR1_ALS_RES_14BIT 0x1
+#define CR1_ALS_RES_16BIT 0x2
+#define CR1_ALS_RES_16BIT_2 0x3
+
+#define CR1_ALS_RES_SHIFT (3)
+#define CR1_ALS_RES_MASK (0x3 << CR1_ALS_RES_SHIFT)
+
+/*sensing amplifier selection for ALS*/
+#define CR1_ALS_GAIN_X1 0x0
+#define CR1_ALS_GAIN_X2 0x1
+#define CR1_ALS_GAIN_X4 0x2
+#define CR1_ALS_GAIN_X8 0x3
+#define CR1_ALS_GAIN_X16 0x4
+#define CR1_ALS_GAIN_X32 0x5
+#define CR1_ALS_GAIN_X64 0x6
+#define CR1_ALS_GAIN_X128 0x7
+
+#define CR1_ALS_GAIN_SHIFT (0)
+#define CR1_ALS_GAIN_MASK (0x7 << CR1_ALS_GAIN_SHIFT)
+
+
+/*PS fault queue depth for interrupt event output*/
+#define CR2_PS_FQ_1 0x0
+#define CR2_PS_FQ_4 0x1
+#define CR2_PS_FQ_8 0x2
+#define CR2_PS_FQ_15 0x3
+
+#define CR2_PS_FQ_SHIFT (6)
+#define CR2_PS_FQ_MASK (0x3 << CR2_PS_FQ_SHIFT)
+
+/*interrupt type setting */
+/*low active*/
+#define CR2_INT_LEVEL 0x0
+/*low pulse*/
+#define CR2_INT_PULSE 0x1
+
+#define CR2_INT_SHIFT (5)
+#define CR2_INT_MASK (0x1 << CR2_INT_SHIFT)
+
+/*resolution for PS*/
+#define CR2_PS_RES_12 0x0
+#define CR2_PS_RES_14 0x1
+#define CR2_PS_RES_16 0x2
+#define CR2_PS_RES_16_2 0x3
+
+#define CR2_PS_RES_SHIFT (3)
+#define CR2_PS_RES_MASK (0x3 << CR2_PS_RES_SHIFT)
+
+/*sensing amplifier selection for PS*/
+#define CR2_PS_GAIN_1 0x0
+#define CR2_PS_GAIN_2 0x1
+#define CR2_PS_GAIN_4 0x2
+#define CR2_PS_GAIN_8 0x3
+#define CR2_PS_GAIN_16 0x4
+#define CR2_PS_GAIN_32 0x5
+#define CR2_PS_GAIN_64 0x6
+#define CR2_PS_GAIN_128 0x7
+
+#define CR2_PS_GAIN_SHIFT (0)
+#define CR2_PS_GAIN_MASK (0x7 << CR2_PS_GAIN_SHIFT)
+
+/*wait-time slot selection*/
+#define CR3_WAIT_SEL_0 0x0
+#define CR3_WAIT_SEL_4 0x1
+#define CR3_WAIT_SEL_8 0x2
+#define CR3_WAIT_SEL_16 0x3
+
+#define CR3_WAIT_SEL_SHIFT (6)
+#define CR3_WAIT_SEL_MASK (0x3 << CR3_WAIT_SEL_SHIFT)
+
+/*IR-LED drive peak current setting*/
+#define CR3_LEDDR_12_5 0x0
+#define CR3_LEDDR_25 0x1
+#define CR3_LEDDR_50 0x2
+#define CR3_LEDDR_100 0x3
+
+#define CR3_LEDDR_SHIFT (4)
+#define CR3_LEDDR_MASK (0x3 << CR3_LEDDR_SHIFT)
+
+/*INT pin source selection*/
+#define CR3_INT_SEL_BATH 0x0
+#define CR3_INT_SEL_ALS 0x1
+#define CR3_INT_SEL_PS 0x2
+#define CR3_INT_SEL_PSAPP 0x3
+
+#define CR3_INT_SEL_SHIFT (2)
+#define CR3_INT_SEL_MASK (0x3 << CR3_INT_SEL_SHIFT)
+
+/*software reset for register and core*/
+#define CR3_SOFTRST_EN 0x1
+
+#define CR3_SOFTRST_SHIFT (0)
+#define CR3_SOFTRST_MASK (0x1 << CR3_SOFTRST_SHIFT)
+
+/*modulation frequency of LED driver*/
+#define CR10_FREQ_DIV2 0x0
+#define CR10_FREQ_DIV4 0x1
+#define CR10_FREQ_DIV8 0x2
+#define CR10_FREQ_DIV16 0x3
+
+#define CR10_FREQ_SHIFT (1)
+#define CR10_FREQ_MASK (0x3 << CR10_FREQ_SHIFT)
+
+/*50/60 Rejection enable*/
+#define CR10_REJ_5060_DIS 0x00
+#define CR10_REJ_5060_EN 0x01
+
+#define CR10_REJ_5060_SHIFT (0)
+#define CR10_REJ_5060_MASK (0x1 << CR10_REJ_5060_SHIFT)
+
+#define us5182_NUM_CACHABLE_REGS 0x12
+
+/*enable sensor*/
+#define ID_LIGHT 0
+#define ID_PROXIMITY 1
+
+#define DEVICE_LIGHT (1 << ID_LIGHT)
+#define DEVICE_PROXIMITY (1 << ID_PROXIMITY)
+#endif