aboutsummaryrefslogtreecommitdiff
path: root/drivers/misc/mediatek/shake_sensor
diff options
context:
space:
mode:
authorMeizu OpenSource <patchwork@meizu.com>2016-08-15 10:19:42 +0800
committerMeizu OpenSource <patchwork@meizu.com>2016-08-15 10:19:42 +0800
commitd2e1446d81725c351dc73a03b397ce043fb18452 (patch)
tree4dbc616b7f92aea39cd697a9084205ddb805e344 /drivers/misc/mediatek/shake_sensor
first commit
Diffstat (limited to 'drivers/misc/mediatek/shake_sensor')
-rwxr-xr-xdrivers/misc/mediatek/shake_sensor/Makefile9
-rw-r--r--drivers/misc/mediatek/shake_sensor/shake.c609
-rw-r--r--drivers/misc/mediatek/shake_sensor/shake.h105
3 files changed, 723 insertions, 0 deletions
diff --git a/drivers/misc/mediatek/shake_sensor/Makefile b/drivers/misc/mediatek/shake_sensor/Makefile
new file mode 100755
index 000000000..58370a0ab
--- /dev/null
+++ b/drivers/misc/mediatek/shake_sensor/Makefile
@@ -0,0 +1,9 @@
+include $(srctree)/drivers/misc/mediatek/Makefile.custom
+
+# In case the platform does NOT support this type of sensors
+
+obj-y += shake.o
+
+ifeq ($(CONFIG_CUSTOM_KERNEL_SHAKE_SENSOR),"OTHER_VENDOR")
+obj-y += other_vendor/
+endif
diff --git a/drivers/misc/mediatek/shake_sensor/shake.c b/drivers/misc/mediatek/shake_sensor/shake.c
new file mode 100644
index 000000000..11fe51ba2
--- /dev/null
+++ b/drivers/misc/mediatek/shake_sensor/shake.c
@@ -0,0 +1,609 @@
+#include "shake.h"
+
+static struct shk_context *shk_context_obj = NULL;
+
+static struct shk_init_info* shake_init= {0}; //modified
+static void shk_early_suspend(struct early_suspend *h);
+static void shk_late_resume(struct early_suspend *h);
+
+static int resume_enable_status = 0;
+
+static struct shk_context *shk_context_alloc_object(void)
+{
+ struct shk_context *obj = kzalloc(sizeof(*obj), GFP_KERNEL);
+ SHK_LOG("shk_context_alloc_object++++\n");
+ if(!obj)
+ {
+ SHK_ERR("Alloc shk object error!\n");
+ return NULL;
+ }
+ atomic_set(&obj->wake, 0);
+ mutex_init(&obj->shk_op_mutex);
+
+ SHK_LOG("shk_context_alloc_object----\n");
+ return obj;
+}
+
+int shk_notify()
+{
+ int err=0;
+ int value=0;
+ struct shk_context *cxt = NULL;
+ cxt = shk_context_obj;
+ SHK_LOG("shk_notify++++\n");
+
+ value = 1;
+ input_report_rel(cxt->idev, EVENT_TYPE_SHK_VALUE, value);
+ input_sync(cxt->idev);
+
+ return err;
+}
+
+static int shk_real_enable(int enable)
+{
+ int err =0;
+ struct shk_context *cxt = NULL;
+ cxt = shk_context_obj;
+
+ if(SHK_RESUME == enable)
+ {
+ enable = resume_enable_status;
+ }
+
+ if(1==enable)
+ {
+ resume_enable_status = 1;
+ if(atomic_read(&(shk_context_obj->early_suspend))) //not allow to enable under suspend
+ {
+ return 0;
+ }
+ if(false==cxt->is_active_data)
+ {
+ err = cxt->shk_ctl.open_report_data(1);
+ if(err)
+ {
+ err = cxt->shk_ctl.open_report_data(1);
+ if(err)
+ {
+ err = cxt->shk_ctl.open_report_data(1);
+ if(err)
+ {
+ SHK_ERR("enable_shake enable(%d) err 3 timers = %d\n", enable, err);
+ return err;
+ }
+ }
+ }
+ cxt->is_active_data = true;
+ SHK_LOG("enable_shake real enable \n" );
+ }
+ }
+ else if((0==enable) || (SHK_SUSPEND == enable))
+ {
+ if(0==enable)
+ resume_enable_status = 0;
+ if(true==cxt->is_active_data)
+ {
+ err = cxt->shk_ctl.open_report_data(0);
+ if(err)
+ {
+ SHK_ERR("enable_shakeenable(%d) err = %d\n", enable, err);
+ }
+ cxt->is_active_data =false;
+ SHK_LOG("enable_shake real disable \n" );
+ }
+ }
+ return err;
+}
+
+int shk_enable_nodata(int enable)
+{
+ struct shk_context *cxt = NULL;
+ cxt = shk_context_obj;
+ if(NULL == cxt->shk_ctl.open_report_data)
+ {
+ SHK_ERR("shk_enable_nodata:shk ctl path is NULL\n");
+ return -1;
+ }
+
+ if(1 == enable)
+ {
+ cxt->is_active_nodata = true;
+ }
+ if(0 == enable)
+ {
+ cxt->is_active_nodata = false;
+ }
+ shk_real_enable(enable);
+ return 0;
+}
+
+static ssize_t shk_show_enable_nodata(struct device* dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct shk_context *cxt = NULL;
+ cxt = shk_context_obj;
+
+ SHK_LOG("shk active: %d\n", cxt->is_active_nodata);
+ return snprintf(buf, PAGE_SIZE, "%d\n", cxt->is_active_nodata);
+}
+
+static ssize_t shk_store_enable_nodata(struct device* dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct shk_context *cxt = NULL;
+ SHK_LOG("shk_store_enable nodata buf=%s\n",buf);
+ mutex_lock(&shk_context_obj->shk_op_mutex);
+ cxt = shk_context_obj;
+ if(NULL == cxt->shk_ctl.open_report_data)
+ {
+ SHK_LOG("shk_ctl enable nodata NULL\n");
+ mutex_unlock(&shk_context_obj->shk_op_mutex);
+ return count;
+ }
+ if (!strncmp(buf, "1", 1))
+ {
+ shk_enable_nodata(1);
+ }
+ else if (!strncmp(buf, "0", 1))
+ {
+ shk_enable_nodata(0);
+ }
+ else
+ {
+ SHK_ERR(" shk_store enable nodata cmd error !!\n");
+ }
+ mutex_unlock(&shk_context_obj->shk_op_mutex);
+ return count;
+}
+
+static ssize_t shk_store_active(struct device* dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct shk_context *cxt = NULL;
+ int res =0;
+ int en=0;
+ SHK_LOG("shk_store_active buf=%s\n",buf);
+ mutex_lock(&shk_context_obj->shk_op_mutex);
+
+ cxt = shk_context_obj;
+ if((res = sscanf(buf, "%d", &en))!=1)
+ {
+ SHK_LOG(" shk_store_active param error: res = %d\n", res);
+ }
+ SHK_LOG(" shk_store_active en=%d\n",en);
+ if(1 == en)
+ {
+ shk_real_enable(1);
+ }
+ else if(0 == en)
+ {
+ shk_real_enable(0);
+ }
+ else
+ {
+ SHK_ERR(" shk_store_active error !!\n");
+ }
+ mutex_unlock(&shk_context_obj->shk_op_mutex);
+ SHK_LOG(" shk_store_active done\n");
+ return count;
+}
+/*----------------------------------------------------------------------------*/
+static ssize_t shk_show_active(struct device* dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct shk_context *cxt = NULL;
+ cxt = shk_context_obj;
+
+ SHK_LOG("shk active: %d\n", cxt->is_active_data);
+ return snprintf(buf, PAGE_SIZE, "%d\n", cxt->is_active_data);
+}
+
+static ssize_t shk_store_delay(struct device* dev,
+ struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+ SHK_LOG(" not support now\n");
+ return len;
+}
+
+
+static ssize_t shk_show_delay(struct device* dev,
+ struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+ SHK_LOG(" not support now\n");
+ return len;
+}
+
+
+static ssize_t shk_store_batch(struct device* dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int len = 0;
+ SHK_LOG(" not support now\n");
+ return len;
+}
+
+static ssize_t shk_show_batch(struct device* dev,
+ struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+ SHK_LOG(" not support now\n");
+ return len;
+}
+
+static ssize_t shk_store_flush(struct device* dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int len = 0;
+ SHK_LOG(" not support now\n");
+ return len;
+}
+
+static ssize_t shk_show_flush(struct device* dev,
+ struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+ SHK_LOG(" not support now\n");
+ return len;
+}
+
+static ssize_t shk_show_devnum(struct device* dev,
+ struct device_attribute *attr, char *buf)
+{
+ char *devname = NULL;
+ devname = dev_name(&shk_context_obj->idev->dev);
+ return snprintf(buf, PAGE_SIZE, "%s\n", devname+5); //TODO: why +5?
+}
+static int shake_remove(struct platform_device *pdev)
+{
+ SHK_LOG("shake_remove\n");
+ return 0;
+}
+
+static int shake_probe(struct platform_device *pdev)
+{
+ SHK_LOG("shake_probe\n");
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id shake_of_match[] = {
+ { .compatible = "mediatek,shake", },
+ {},
+};
+#endif
+
+static struct platform_driver shake_driver = {
+ .probe = shake_probe,
+ .remove = shake_remove,
+ .driver =
+ {
+ .name = "shake",
+ #ifdef CONFIG_OF
+ .of_match_table = shake_of_match,
+ #endif
+ }
+};
+
+static int shk_real_driver_init(void)
+{
+ int err=0;
+ SHK_LOG(" shk_real_driver_init +\n");
+ if(0 != shake_init)
+ {
+ SHK_LOG(" shk try to init driver %s\n", shake_init->name);
+ err = shake_init->init();
+ if(0 == err)
+ {
+ SHK_LOG(" shk real driver %s probe ok\n", shake_init->name);
+ }
+ }
+ return err;
+}
+
+int shk_driver_add(struct shk_init_info* obj)
+{
+ int err=0;
+
+ SHK_FUN();
+ SHK_LOG("register shake driver for the first time\n");
+ if(platform_driver_register(&shake_driver))
+ {
+ SHK_ERR("failed to register gensor driver already exist\n");
+ }
+ if(NULL == shake_init)
+ {
+ obj->platform_diver_addr = &shake_driver;
+ shake_init = obj;
+ }
+
+ if(NULL==shake_init)
+ {
+ SHK_ERR("SHK driver add err \n");
+ err=-1;
+ }
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(shk_driver_add);
+
+static int shk_misc_init(struct shk_context *cxt)
+{
+ int err=0;
+ //kernel-3.10\include\linux\Miscdevice.h
+ //use MISC_DYNAMIC_MINOR exceed 64
+ cxt->mdev.minor = M_SHK_MISC_MINOR;
+ cxt->mdev.name = SHK_MISC_DEV_NAME;
+ if((err = misc_register(&cxt->mdev)))
+ {
+ SHK_ERR("unable to register shk misc device!!\n");
+ }
+ return err;
+}
+
+static void shk_input_destroy(struct shk_context *cxt)
+{
+ struct input_dev *dev = cxt->idev;
+
+ input_unregister_device(dev);
+ input_free_device(dev);
+}
+
+static int shk_input_init(struct shk_context *cxt)
+{
+ struct input_dev *dev;
+ int err = 0;
+
+ dev = input_allocate_device();
+ if (NULL == dev)
+ return -ENOMEM;
+
+ dev->name = SHK_INPUTDEV_NAME;
+ input_set_capability(dev, EV_REL, EVENT_TYPE_SHK_VALUE);
+
+ input_set_drvdata(dev, cxt);
+ set_bit(EV_REL, dev->evbit);
+ err = input_register_device(dev);
+ if (err < 0) {
+ input_free_device(dev);
+ return err;
+ }
+ cxt->idev= dev;
+
+ return 0;
+}
+
+DEVICE_ATTR(shkenablenodata, S_IWUSR | S_IRUGO, shk_show_enable_nodata, shk_store_enable_nodata);
+DEVICE_ATTR(shkactive, S_IWUSR | S_IRUGO, shk_show_active, shk_store_active);
+DEVICE_ATTR(shkdelay, S_IWUSR | S_IRUGO, shk_show_delay, shk_store_delay);
+DEVICE_ATTR(shkbatch, S_IWUSR | S_IRUGO, shk_show_batch, shk_store_batch);
+DEVICE_ATTR(shkflush, S_IWUSR | S_IRUGO, shk_show_flush, shk_store_flush);
+DEVICE_ATTR(shkdevnum, S_IWUSR | S_IRUGO, shk_show_devnum, NULL);
+
+
+static struct attribute *shk_attributes[] = {
+ &dev_attr_shkenablenodata.attr,
+ &dev_attr_shkactive.attr,
+ &dev_attr_shkdelay.attr,
+ &dev_attr_shkbatch.attr,
+ &dev_attr_shkflush.attr,
+ &dev_attr_shkdevnum.attr,
+ NULL
+};
+
+static struct attribute_group shk_attribute_group = {
+ .attrs = shk_attributes
+};
+
+int shk_register_data_path(struct shk_data_path *data)
+{
+ struct shk_context *cxt = NULL;
+ cxt = shk_context_obj;
+ cxt->shk_data.get_data = data->get_data;
+ if(NULL == cxt->shk_data.get_data)
+ {
+ SHK_LOG("shk register data path fail \n");
+ return -1;
+ }
+ return 0;
+}
+
+int shk_register_control_path(struct shk_control_path *ctl)
+{
+ struct shk_context *cxt = NULL;
+ int err =0;
+ cxt = shk_context_obj;
+// cxt->shk_ctl.enable = ctl->enable;
+// cxt->shk_ctl.enable_nodata = ctl->enable_nodata;
+ cxt->shk_ctl.open_report_data = ctl->open_report_data;
+
+ if(NULL==cxt->shk_ctl.open_report_data)
+ {
+ SHK_LOG("shk register control path fail \n");
+ return -1;
+ }
+
+ //add misc dev for sensor hal control cmd
+ err = shk_misc_init(shk_context_obj);
+ if(err)
+ {
+ SHK_ERR("unable to register shk misc device!!\n");
+ return -2;
+ }
+ err = sysfs_create_group(&shk_context_obj->mdev.this_device->kobj,
+ &shk_attribute_group);
+ if (err < 0)
+ {
+ SHK_ERR("unable to create shk attribute file\n");
+ return -3;
+ }
+ kobject_uevent(&shk_context_obj->mdev.this_device->kobj, KOBJ_ADD);
+ return 0;
+}
+
+static int shk_probe(struct platform_device *pdev)
+{
+ int err;
+ SHK_LOG("+++++++++++++shk_probe!!\n");
+
+ shk_context_obj = shk_context_alloc_object();
+ if (!shk_context_obj)
+ {
+ err = -ENOMEM;
+ SHK_ERR("unable to allocate devobj!\n");
+ goto exit_alloc_data_failed;
+ }
+ //init real shk driver
+ err = shk_real_driver_init();
+ if(err)
+ {
+ SHK_ERR("shk real driver init fail\n");
+ goto real_driver_init_fail;
+ }
+
+ //init input dev
+ err = shk_input_init(shk_context_obj);
+ if(err)
+ {
+ SHK_ERR("unable to register shk input device!\n");
+ goto exit_alloc_input_dev_failed;
+ }
+
+#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_EARLYSUSPEND)
+ atomic_set(&(shk_context_obj->early_suspend), 0);
+ shk_context_obj->early_drv.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 1,
+ shk_context_obj->early_drv.suspend = shk_early_suspend,
+ shk_context_obj->early_drv.resume = shk_late_resume,
+ register_early_suspend(&shk_context_obj->early_drv);
+#endif //#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(CONFIG_EARLYSUSPEND)
+
+ SHK_LOG("----shk_probe OK !!\n");
+ return 0;
+
+
+ if (err)
+ {
+ SHK_ERR("sysfs node creation error \n");
+ shk_input_destroy(shk_context_obj);
+ }
+ real_driver_init_fail:
+ exit_alloc_input_dev_failed:
+ kfree(shk_context_obj);
+ exit_alloc_data_failed:
+ SHK_LOG("----shk_probe fail !!!\n");
+ return err;
+}
+
+static int shk_remove(struct platform_device *pdev)
+{
+ int err=0;
+ SHK_FUN(f);
+ input_unregister_device(shk_context_obj->idev);
+ sysfs_remove_group(&shk_context_obj->idev->dev.kobj,
+ &shk_attribute_group);
+
+ if((err = misc_deregister(&shk_context_obj->mdev)))
+ {
+ SHK_ERR("misc_deregister fail: %d\n", err);
+ }
+ kfree(shk_context_obj);
+ return 0;
+}
+
+static void shk_early_suspend(struct early_suspend *h)
+{
+ atomic_set(&(shk_context_obj->early_suspend), 1);
+ if(!atomic_read(&shk_context_obj->wake)) //not wake up, disable in early suspend
+ {
+ shk_real_enable(SHK_SUSPEND);
+ }
+ SHK_LOG(" shk_early_suspend ok------->hwm_obj->early_suspend=%d \n",atomic_read(&(shk_context_obj->early_suspend)));
+ return ;
+}
+/*----------------------------------------------------------------------------*/
+static void shk_late_resume(struct early_suspend *h)
+{
+ atomic_set(&(shk_context_obj->early_suspend), 0);
+ if(!atomic_read(&shk_context_obj->wake) && resume_enable_status) //not wake up, disable in early suspend
+ {
+ shk_real_enable(SHK_RESUME);
+ }
+ SHK_LOG(" shk_late_resume ok------->hwm_obj->early_suspend=%d \n",atomic_read(&(shk_context_obj->early_suspend)));
+ return ;
+}
+
+#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(USE_EARLY_SUSPEND)
+static int shk_suspend(struct platform_device *dev, pm_message_t state)
+{
+ atomic_set(&(shk_context_obj->suspend), 1);
+ if(!atomic_read(&shk_context_obj->wake)) //not wake up, disable in early suspend
+ {
+ shk_real_enable(SHK_SUSPEND);
+ }
+ SHK_LOG(" shk_early_suspend ok------->hwm_obj->suspend=%d \n",atomic_read(&(shk_context_obj->suspend)));
+ return 0;
+}
+/*----------------------------------------------------------------------------*/
+static int shk_resume(struct platform_device *dev)
+{
+ atomic_set(&(shk_context_obj->suspend), 0);
+ if(!atomic_read(&shk_context_obj->wake) && resume_enable_status) //not wake up, disable in early suspend
+ {
+ shk_real_enable(SHK_RESUME);
+ }
+ SHK_LOG(" shk_resume ok------->hwm_obj->suspend=%d \n",atomic_read(&(shk_context_obj->suspend)));
+ return 0;
+}
+#endif //#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(USE_EARLY_SUSPEND)
+
+#ifdef CONFIG_OF
+static const struct of_device_id m_shk_pl_of_match[] = {
+ { .compatible = "mediatek,m_shk_pl", },
+ {},
+};
+#endif
+
+static struct platform_driver shk_driver =
+{
+ .probe = shk_probe,
+ .remove = shk_remove,
+#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(USE_EARLY_SUSPEND)
+ .suspend = shk_suspend,
+ .resume = shk_resume,
+#endif
+ .driver =
+ {
+ .name = SHK_PL_DEV_NAME,
+ #ifdef CONFIG_OF
+ .of_match_table = m_shk_pl_of_match,
+ #endif
+ }
+};
+
+static int __init shk_init(void)
+{
+ SHK_FUN();
+
+ if(platform_driver_register(&shk_driver))
+ {
+ SHK_ERR("failed to register shk driver\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void __exit shk_exit(void)
+{
+ platform_driver_unregister(&shk_driver);
+ platform_driver_unregister(&shake_driver);
+}
+
+late_initcall(shk_init);
+//module_init(shk_init);
+//module_exit(shk_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHK device driver");
+MODULE_AUTHOR("Mediatek");
+
diff --git a/drivers/misc/mediatek/shake_sensor/shake.h b/drivers/misc/mediatek/shake_sensor/shake.h
new file mode 100644
index 000000000..46db5e6df
--- /dev/null
+++ b/drivers/misc/mediatek/shake_sensor/shake.h
@@ -0,0 +1,105 @@
+#ifndef __SHK_H__
+#define __SHK_H__
+
+
+#include <linux/wakelock.h>
+#include <linux/interrupt.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/hwmsensor.h>
+#include <linux/earlysuspend.h>
+#include <linux/hwmsen_dev.h>
+
+
+#define SHK_TAG "<SHAKE> "
+#define SHK_FUN(f) printk(SHK_TAG"%s\n", __func__)
+#define SHK_ERR(fmt, args...) printk(SHK_TAG"%s %d : "fmt, __func__, __LINE__, ##args)
+#define SHK_LOG(fmt, args...) printk(SHK_TAG fmt, ##args)
+#define SHK_VER(fmt, args...) printk(SHK_TAG"%s: "fmt, __func__, ##args) //((void)0)
+
+//#define OP_SHK_DELAY 0X01
+#define OP_SHK_ENABLE 0X02
+//#define OP_SHK_GET_DATA 0X04
+
+#define SHK_INVALID_VALUE -1
+
+#define EVENT_TYPE_SHK_VALUE REL_X
+
+#define SHK_VALUE_MAX (32767)
+#define SHK_VALUE_MIN (-32768)
+#define SHK_STATUS_MIN (0)
+#define SHK_STATUS_MAX (64)
+#define SHK_DIV_MAX (32767)
+#define SHK_DIV_MIN (1)
+
+typedef enum {
+ SHK_DEACTIVATE,
+ SHK_ACTIVATE,
+ SHK_SUSPEND,
+ SHK_RESUME
+} shk_state_e;
+
+struct shk_control_path
+{
+// int (*enable_nodata)(int en);//only enable not report event to HAL
+ int (*open_report_data)(int open);//open data rerport to HAL
+// int (*enable)(int en);
+ //bool is_support_batch;//version2.used for batch mode support flag
+};
+
+struct shk_data_path
+{
+ int (*get_data)(u16 *value, int *status);
+};
+
+struct shk_init_info
+{
+ char *name;
+ int (*init)(void);
+ int (*uninit)(void);
+ struct platform_driver* platform_diver_addr;
+};
+
+struct shk_data{
+ hwm_sensor_data shk_data ;
+ int data_updata;
+ //struct mutex lock;
+};
+
+struct shk_drv_obj {
+ void *self;
+ int polling;
+ int (*shk_operate)(void* self, uint32_t command, void* buff_in, int size_in,
+ void* buff_out, int size_out, int* actualout);
+};
+
+struct shk_context {
+ struct input_dev *idev;
+ struct miscdevice mdev;
+ struct work_struct report;
+ struct mutex shk_op_mutex;
+ atomic_t wake; /*user-space request to wake-up, used with stop*/
+ atomic_t trace;
+
+ struct early_suspend early_drv;
+ atomic_t early_suspend;
+ atomic_t suspend;
+
+ struct shk_data drv_data;
+ struct shk_control_path shk_ctl;
+ struct shk_data_path shk_data;
+ bool is_active_nodata; // Active, but HAL don't need data sensor. such as orientation need
+ bool is_active_data; // Active and HAL need data .
+ bool is_batch_enable; //version2.this is used for judging whether sensor is in batch mode
+};
+
+extern int shk_notify(void);
+extern int shk_driver_add(struct shk_init_info* obj) ;
+extern int shk_register_control_path(struct shk_control_path *ctl);
+extern int shk_register_data_path(struct shk_data_path *data);
+
+#endif