diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /drivers/input/sensor/dmard09_gsensor | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'drivers/input/sensor/dmard09_gsensor')
-rwxr-xr-x | drivers/input/sensor/dmard09_gsensor/Makefile | 35 | ||||
-rwxr-xr-x | drivers/input/sensor/dmard09_gsensor/dmt09.c | 1685 | ||||
-rwxr-xr-x | drivers/input/sensor/dmard09_gsensor/dmt09.h | 183 |
3 files changed, 1903 insertions, 0 deletions
diff --git a/drivers/input/sensor/dmard09_gsensor/Makefile b/drivers/input/sensor/dmard09_gsensor/Makefile new file mode 100755 index 00000000..d9242020 --- /dev/null +++ b/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/drivers/input/sensor/dmard09_gsensor/dmt09.c b/drivers/input/sensor/dmard09_gsensor/dmt09.c new file mode 100755 index 00000000..90b03aa3 --- /dev/null +++ b/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/drivers/input/sensor/dmard09_gsensor/dmt09.h b/drivers/input/sensor/dmard09_gsensor/dmt09.h new file mode 100755 index 00000000..d30e606a --- /dev/null +++ b/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 |