原创在:https://blog.csdn.net/wangjun7121/article/details/61916427
发现很多转的没有注明出处,这里添加出处,感谢作者。
/*MTK sensor 经过了一个中间层,数据上报数据为:应用层: /dev/input/xxx ----------------------------------------------------------------------------------内核:[Input 子系统]/\||[MTK 添加的 hwmsen 层] [轮询传感器上报或传感器中断自己上报]/\||--------------------------------------[sensor 1] [sensor 2] ..... [sensor n]【传感器驱动调用接口】:hwmsen_attach(int sensor, struct hwmsen_object *obj)// 创建一个 hwmsen_context 添加全局数组 dev_context// 这样 hwmsen 模块就会轮询检查上报此传感器的值mcxt->cxt[sensor] = kzalloc(sizeof(struct hwmsen_context), GFP_KERNEL)memcpy(&mcxt->cxt[sensor]->obj, obj, sizeof(*obj));hwmsen_detach(int sensor) kfree(mcxt->cxt[sensor]);mcxt->cxt[sensor] = NULL;【应用程序操作入口流程】:hwmsen_unlocked_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)switch(cmd){case HWM_IO_SET_DELAY:copy_from_user(&delayPara, argp, sizeof(delayPara))hwmsen_set_delay(delayPara.delay,delayPara.handle);//modified for android2.3// 获得操作上下文,上下文是在初始化流程中做的struct hwmsen_context *cxt = NULL;cxt = hwm_obj->dc->cxt[handle];// 调用具体 sensor 驱动中注册的函数cxt->obj.sensor_operate(cxt->obj.self, SENSOR_DELAY, &delay,sizeof(int), NULL, 0, NULL)update_workqueue_polling_rate(delayPara.delay);//use the fastest sensor polling delay as work queue polling delay base time//upadate all sensors delayCountSetcase HWM_IO_SET_WAKE:hwmsen_wakeup(hwm_obj);input_event(obj->idev, EV_SYN, SYN_CONFIG, 0);case HWM_IO_ENABLE_SENSOR:copy_from_user(&flag, argp, sizeof(flag))hwmsen_enable(hwm_obj, flag, 1);if(enable == 1)// 上电使能传感器cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL)// Need to complete the interrupt sensor work///// 打开定时器,让其定时轮询传感器数据obj->dc->polling_running = 1;mod_timer(&obj->timer, jiffies + atomic_read(&obj->delay)/(1000/HZ)); else cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL)update_workqueue_polling_rate(200);// re-update workqueue polling rate///// 取消定时器,关闭轮询传感器数据obj->dc->polling_running = 0;del_timer_sync(&obj->timer);cancel_work_sync(&obj->report);// 传感器数据设置为无效obj_data.sensors_data[sensor].values[0] = SENSOR_INVALID_VALUE;obj_data.sensors_data[sensor].values[1] = SENSOR_INVALID_VALUE;obj_data.sensors_data[sensor].values[2] = SENSOR_INVALID_VALUE;case HWM_IO_DISABLE_SENSOR:copy_from_user(&flag, argp, sizeof(flag))hwmsen_enable(hwm_obj, flag, 0);case HWM_IO_GET_SENSORS_DATA:copy_from_user(&hwm_sensors_data, argp, sizeof(hwm_sensors_data))case HWM_IO_ENABLE_SENSOR_NODATA:copy_from_user(&flag, argp, sizeof(flag))hwmsen_enable_nodata(hwm_obj, flag, 1)if(enable == 1)cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable, sizeof(int), NULL, 0, NULL)elsecxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL)case HWM_IO_DISABLE_SENSOR_NODATA:hwmsen_enable_nodata(hwm_obj, flag, 0);case HWM_IO_DISABLE_SENSOR_NODATA:hwmsen_enable_nodata(hwm_obj, flag, 0);【模块初始化流程总结】 :module_init(hwmsen_init);hwmsen_init(void) // 注册平台设备 platform_driver_register(&hwmsen_driver)// 匹配设备后调用 hwmsen_probe(struct platform_device *pdev) // 初始化静态数组init_static_data();   // 主要用两个数组:hwmsen_data 与 dev_context 数据结构的数组// -------------Sensor daa-----------------------------------------------------// struct hwmsen_data{//  hwm_sensor_data sensors_data[MAX_ANDROID_SENSOR_NUM+1];//                      typedef struct {//                          int     sensor;             // 传感器识别    sensor identifier//                             int values[3];              // 传感器值     sensor values//                             uint32_t value_divide;      // sensor values divide//                           int8_t status;              // sensor accuracy//                            int update;                 // whether updata?//                            int64_t time;               // time is in nanosecond//                          uint32_t    reserved;//                         }hwm_sensor_data;//     int data_updata[MAX_ANDROID_SENSOR_NUM+1];//   struct mutex lock;// };// ----------------------------------------------------------------------------// struct dev_context {//     int     polling_running;//     struct mutex lock;//     struct hwmsen_context* cxt[MAX_ANDROID_SENSOR_NUM+1];//                struct hwmsen_context { // sensor context//                     atomic_t                enable;//                   atomic_t delay;//                   uint32_t delayCountSet;//                   uint32_t delayCount;//                  //                  struct hwmsen_object    obj;//                                  struct hwmsen_object {//                                        void *self;//                                       int polling;          // 上传数据方式:轮询还是中断/                                       // 被 hwmsen 模块回调的函数,用于获得上报数据等,与传感器交互使用//                                         int (*sensor_operate)(void* self, uint32_t command, void* buff_in, int size_in,//                                           void* buff_out, int size_out, int* actualout);//                                    };//                };// };hwm_obj = hwmsen_alloc_object();struct hwmdev_object *obj = kzalloc(sizeof(*obj), GFP_KERNEL); obj->dc = &dev_cxt;obj->active_data_sensor = 0;obj->active_sensor = 0;atomic_set(&obj->delay, 200); // 5Hz // set work queue delay time 200msatomic_set(&obj->wake, 0);//// 创建单线程工作队列sensor_workqueue = create_singlethread_workqueue("sensor_polling");INIT_WORK(&obj->report, hwmsen_work_func);init_timer(&obj->timer);obj->timer.expires  = jiffies + atomic_read(&obj->delay)/(1000/HZ);//// 用于轮询obj->timer.function = hwmsen_poll;obj->timer.data       = (unsigned long)obj;/// 轮询函数:是在 ioctl() 中打开定时器轮询的/hwmsen_poll(unsigned long data)// 调用上面注册的工作队列处理函数queue_work(sensor_workqueue, &obj->report);hwmsen_work_func()input_event(obj->idev, EV_SYN, SYN_CONFIG, 0);// 设置时间戳memset(&sensor_data, 0, sizeof(sensor_data));  time.tv_sec = time.tv_nsec = 0;    time = get_monotonic_coarse(); nt = time.tv_sec*1000000000LL+time.tv_nsec;/// 遍历注册的传感器【 hwmsen_attach() 注册 】for(idx = 0; idx < MAX_ANDROID_SENSOR_NUM; idx++)// Interrupt sensor///// 如果查看的传感器是中断模式上报数据的,跳过,不需要轮询// 因为传感感会在自己的中断函数内主动上报数据if(cxt->obj.polling == 0)if(obj_data.data_updata[idx] == 1)event_type |= (1 << idx);obj_data.data_updata[idx] = 0;continue;/// 对于非中断上报数据的传感器进行轮询上报数据// 添加具体 sensor 数据的延时上报支持//added to surpport set delay to specified sensorif(cxt->delayCount > 0)cxt->delayCount--;if(0 == cxt->delayCount)cxt->delayCount = cxt->delayCountSet;else continue;//// 调用具体的传感器驱动函数获取数据cxt->obj.sensor_operate(cxt->obj.self,SENSOR_GET_DATA, NULL, 0, &sensor_data, sizeof(hwm_sensor_data), &out_size);///// 如果是光感、压力、距离或温度传感器,数据保存在 sensor_data.values[0]if((idx == ID_LIGHT) ||(idx == ID_PRESSURE) ||(idx == ID_PROXIMITY) || (idx == ID_TEMPRERATURE))// data changed, update the dataif(sensor_data.values[0] != obj_data.sensors_data[idx].values[0])obj_data.sensors_data[idx].values[0] = sensor_data.values[0];obj_data.sensors_data[idx].value_divide = sensor_data.value_divide;obj_data.sensors_data[idx].status = sensor_data.status;obj_data.sensors_data[idx].time = nt;event_type |= (1 << idx);else // 获得其他传感器数据// data changed, update the dataif((sensor_data.values[0] != obj_data.sensors_data[idx].values[0]) || (sensor_data.values[1] != obj_data.sensors_data[idx].values[1])|| (sensor_data.values[2] != obj_data.sensors_data[idx].values[2]))if( 0 == sensor_data.values[0] && 0==sensor_data.values[1] && 0 == sensor_data.values[2])continue;obj_data.sensors_data[idx].values[0] = sensor_data.values[0];obj_data.sensors_data[idx].values[1] = sensor_data.values[1];obj_data.sensors_data[idx].values[2] = sensor_data.values[2];obj_data.sensors_data[idx].value_divide = sensor_data.value_divide;obj_data.sensors_data[idx].status = sensor_data.status;obj_data.sensors_data[idx].time = nt;event_type |= (1 << idx);// 如果是再次使能,判断是不是第一次,先过滤掉第一个无效数据if(enable_again == true)  。。。///// 如果数据有更新,通过 Input 更新数据if(event_type != 0)   input_report_rel(obj->idev, EVENT_TYPE_SENSOR, event_type);input_sync(obj->idev);//modified//// 如果是轮询模式,则重置定时器if(obj->dc->polling_running == 1)mod_timer(&obj->timer, jiffies + atomic_read(&obj->delay)/(1000/HZ));// 分配输入设备hwm_obj->idev = input_allocate_device();// 设置输入上报事件类型set_bit(EV_REL, hwm_obj->idev->evbit);set_bit(EV_SYN, hwm_obj->idev->evbit);input_set_capability(hwm_obj->idev, EV_REL, EVENT_TYPE_SENSOR);// 注册输入设备 input_register_device(hwm_obj->idev)// 注册杂项设备 hwm_obj->mdev.minor = MISC_DYNAMIC_MINOR;hwm_obj->mdev.name  = HWM_SENSOR_DEV_NAME;hwm_obj->mdev.fops  = &hwmsen_fops;misc_register(&hwm_obj->mdev)// 注册 sys 系统入口 hwmsen_create_attr(hwm_obj->mdev.this_device)// 注册电源管理atomic_set(&(hwm_obj->early_suspend), 0);hwm_obj->early_drv.level    = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 1,hwm_obj->early_drv.suspend  = hwmsen_early_suspend,hwm_obj->early_drv.resume   = hwmsen_late_resume,    register_early_suspend(&hwm_obj->early_drv);// 自动检测加速度传感器#if defined(MTK_AUTO_DETECT_ACCELEROMETER)platform_driver_register(&gsensor_driver)#endif// 自动检测陀螺仪#if defined(MTK_AUTO_DETECT_MAGNETOMETER)platform_driver_register(&msensor_driver)#endif// 自动检测光感#if defined(MTK_AUTO_DETECT_ALSPS)platform_driver_register(&alsps_sensor_driver)// 实现方式:上同static struct platform_driver alsps_sensor_driver = {.probe      = alsps_sensor_probe,.remove     = hwmsen_alsps_sensor_remove,    .driver     = {.name  = "als_ps",}};// 匹配后执行static int alsps_sensor_probe(struct platform_device *pdev) {int i =0;int err=0;HWM_LOG(" als_ps sensor_probe +\n");for(i = 0; i < MAX_CHOOSE_G_NUM; i++){if(NULL != alsps_init_list[i]){// 核心:调用所有传感器的初始化程序,返回第一个初始化成功的err = alsps_init_list[i]->init();if(0 == err){strcpy(alsps_name,alsps_init_list[i]->name);HWM_LOG(" alsps sensor %s probe ok\n", alsps_name);break;}}}return 0;}#endif*/
/* alps/ALPS_SW/TRUNK/MAIN/alps/kernel/drivers/hwmon/mt6516/hwmsen_dev.c** (C) Copyright 2009 * MediaTek <www.MediaTek.com>** Sensor devices** 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/miscdevice.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/workqueue.h>
#include <linux/wait.h>
#include <linux/slab.h>#include <linux/hwmsensor.h>
#include <linux/hwmsen_helper.h>
#include <linux/hwmsen_dev.h>
//add for fix resume issue
#include <linux/earlysuspend.h>
#include <linux/wakelock.h>
//add for fix resume issue end#include <cust_alsps.h>#define SENSOR_INVALID_VALUE -1
#define MAX_CHOOSE_G_NUM 5
#define MAX_CHOOSE_M_NUM 5static void hwmsen_early_suspend(struct early_suspend *h);
static void hwmsen_late_resume(struct early_suspend *h);
static void update_workqueue_polling_rate(int newDelay);static struct workqueue_struct * sensor_workqueue = NULL;/******************************************************************************* structure / enumeration / macro / definition*****************************************************************************/struct sensor_delay
{int handle;uint32_t delay;
};struct hwmsen_context { /*sensor context*/atomic_t                enable;atomic_t delay;uint32_t delayCountSet;uint32_t delayCount;struct hwmsen_object    obj;
};#if defined(MTK_AUTO_DETECT_ACCELEROMETER)
static char gsensor_name[25];
static struct sensor_init_info* gsensor_init_list[MAX_CHOOSE_G_NUM]= {0}; //modified
#endif
#if defined(MTK_AUTO_DETECT_MAGNETOMETER)
static char msensor_name[25];
static struct sensor_init_info* msensor_init_list[MAX_CHOOSE_G_NUM]= {0}; //modified
#endif
#if defined(MTK_AUTO_DETECT_ALSPS)
static char alsps_name[25];
static struct sensor_init_info* alsps_init_list[MAX_CHOOSE_G_NUM]= {0}; //modified
#endif/*----------------------------------------------------------------------------*/
struct dev_context {int     polling_running;struct mutex lock;struct hwmsen_context* cxt[MAX_ANDROID_SENSOR_NUM+1];
};
/*-------------Sensor daa-----------------------------------------------------*/
struct hwmsen_data{hwm_sensor_data sensors_data[MAX_ANDROID_SENSOR_NUM+1];int data_updata[MAX_ANDROID_SENSOR_NUM+1];struct mutex lock;
};
/*----------------------------------------------------------------------------*/
typedef enum {HWM_TRC_REPORT_NUM = 0x0001,HWM_TRC_REPORT_EVT = 0x0002, HWM_TRC_REPORT_INF = 0X0004,
} HWM_TRC;
/*----------------------------------------------------------------------------*/
#define C_MAX_OBJECT_NUM 1
struct hwmdev_object {struct input_dev   *idev;struct miscdevice   mdev;struct dev_context *dc;struct work_struct  report;atomic_t            delay; /*polling period for reporting input event*/atomic_t            wake;  /*user-space request to wake-up, used with stop*/struct timer_list   timer;  /* polling timer */atomic_t            trace;uint32_t          active_sensor;          // Active, but hwmsen don't need data sensor. Maybe other need it's data.uint32_t         active_data_sensor;     // Active and hwmsen need data sensor.//add for fix resume issuestruct early_suspend    early_drv;struct wake_lock        read_data_wake_lock;atomic_t                early_suspend;//add for fix resume end
};static bool enable_again = false;
static struct hwmdev_object *hwm_obj = NULL;
/******************************************************************************* static variables*****************************************************************************/static struct hwmsen_data obj_data ={.lock =__MUTEX_INITIALIZER(obj_data.lock),
};
static struct dev_context dev_cxt = {.lock = __MUTEX_INITIALIZER(dev_cxt.lock),
};
/*----------------------------------------------------------------------------*//******************************************************************************* Local functions*****************************************************************************/
static void hwmsen_work_func(struct work_struct *work)
{//HWM_LOG("+++++++++++++++++++++++++hwmsen_work_func workqueue performed!+++++++++++++++++++++++++++++\n");//struct hwmdev_object *obj = container_of(work, struct hwmdev_object, report);struct hwmdev_object *obj = hwm_obj;struct hwmsen_context *cxt = NULL;int out_size;hwm_sensor_data sensor_data;uint32_t event_type = 0;int64_t  nt;struct timespec time; int err, idx;   //int trc = atomic_read(&obj->trace);if (obj == NULL){HWM_ERR("obj point is NULL!\n");return;}if(atomic_read(&obj->wake)){input_event(obj->idev, EV_SYN, SYN_CONFIG, 0);atomic_set(&obj->wake, 0);     return;}memset(&sensor_data, 0, sizeof(sensor_data));   time.tv_sec = time.tv_nsec = 0;    time = get_monotonic_coarse(); nt = time.tv_sec*1000000000LL+time.tv_nsec;//mutex_lock(&obj_data.lock);for(idx = 0; idx < MAX_ANDROID_SENSOR_NUM; idx++){cxt = obj->dc->cxt[idx];if((cxt == NULL) || (cxt->obj.sensor_operate == NULL)|| !(obj->active_data_sensor&(0x01<<idx))){continue;}// Interrupt sensorif(cxt->obj.polling == 0){if(obj_data.data_updata[idx] == 1){mutex_lock(&obj_data.lock);event_type |= (1 << idx);obj_data.data_updata[idx] = 0;mutex_unlock(&obj_data.lock);}continue;}//added to surpport set delay to specified sensorif(cxt->delayCount > 0){//HWM_LOG("sensor(%d) delayCount = %d\n",idx,cxt->delayCount);cxt->delayCount--;if(0 == cxt->delayCount){cxt->delayCount = cxt->delayCountSet;//HWM_LOG("sensor(%d) go to get data\n",idx);}else{ //HWM_LOG("sensor(%d) wait for next work\n",idx);continue;}}err = cxt->obj.sensor_operate(cxt->obj.self,SENSOR_GET_DATA, NULL, 0, &sensor_data, sizeof(hwm_sensor_data), &out_size);if(err){HWM_ERR("get data from sensor (%d) fails!!\n", idx);continue;}else{if((idx == ID_LIGHT) ||(idx == ID_PRESSURE) ||(idx == ID_PROXIMITY) || (idx == ID_TEMPRERATURE)){// data changed, update the dataif(sensor_data.values[0] != obj_data.sensors_data[idx].values[0]){mutex_lock(&obj_data.lock);obj_data.sensors_data[idx].values[0] = sensor_data.values[0];obj_data.sensors_data[idx].value_divide = sensor_data.value_divide;obj_data.sensors_data[idx].status = sensor_data.status;obj_data.sensors_data[idx].time = nt;event_type |= (1 << idx);mutex_unlock(&obj_data.lock);//HWM_LOG("get %d sensor, values: %d!\n", idx, sensor_data.values[0]);}}else{// data changed, update the dataif((sensor_data.values[0] != obj_data.sensors_data[idx].values[0]) || (sensor_data.values[1] != obj_data.sensors_data[idx].values[1])|| (sensor_data.values[2] != obj_data.sensors_data[idx].values[2])){  if( 0 == sensor_data.values[0] && 0==sensor_data.values[1] && 0 == sensor_data.values[2]){continue;}mutex_lock(&obj_data.lock);obj_data.sensors_data[idx].values[0] = sensor_data.values[0];obj_data.sensors_data[idx].values[1] = sensor_data.values[1];obj_data.sensors_data[idx].values[2] = sensor_data.values[2];obj_data.sensors_data[idx].value_divide = sensor_data.value_divide;obj_data.sensors_data[idx].status = sensor_data.status;obj_data.sensors_data[idx].time = nt;event_type |= (1 << idx);mutex_unlock(&obj_data.lock);//HWM_LOG("get %d sensor, values: %d, %d, %d!\n", idx, //sensor_data.values[0], sensor_data.values[1], sensor_data.values[2]);}}}           }////mutex_unlock(&obj_data.lock);if(enable_again == true){event_type = obj->active_data_sensor;enable_again = false;//filter -1 valuefor(idx = 0; idx <= MAX_ANDROID_SENSOR_NUM; idx++){if(ID_ACCELEROMETER==idx || ID_MAGNETIC==idx || ID_ORIENTATION==idx||ID_GYROSCOPE==idx || ID_TEMPRERATURE==idx||ID_LINEAR_ACCELERATION==idx || ID_ROTATION_VECTOR==idx||ID_GRAVITY==idx){if(SENSOR_INVALID_VALUE == obj_data.sensors_data[idx].values[0] ||SENSOR_INVALID_VALUE == obj_data.sensors_data[idx].values[1] ||SENSOR_INVALID_VALUE == obj_data.sensors_data[idx].values[2]){event_type &= ~(1 << idx);//HWM_LOG("idx=%d,obj->active_sensor after clear: %d\n",idx);}}if(ID_PROXIMITY==idx || ID_LIGHT==idx || ID_PRESSURE==idx){if(SENSOR_INVALID_VALUE == obj_data.sensors_data[idx].values[0]){event_type &= ~(1 << idx);//HWM_LOG("idx=%d,obj->active_sensor after clear: %d\n",idx);}}}//HWM_LOG("event type after enable: %d\n", event_type);}if((event_type&(1 << ID_PROXIMITY))&& SENSOR_INVALID_VALUE == obj_data.sensors_data[ID_PROXIMITY].values[0]){event_type &= ~(1 << ID_PROXIMITY);   //HWM_LOG("remove ps event!!!!!!!!!!!\n");}if(event_type != 0){        input_report_rel(obj->idev, EVENT_TYPE_SENSOR, event_type);input_sync(obj->idev);//modified//HWM_LOG("event type: %d\n", event_type);}else{//HWM_LOG("no available sensor!!\n");}if(obj->dc->polling_running == 1){mod_timer(&obj->timer, jiffies + atomic_read(&obj->delay)/(1000/HZ)); }
}/******************************************************************************* export functions*****************************************************************************/
int hwmsen_get_interrupt_data(int sensor, hwm_sensor_data *data)
{//HWM_LOG("++++++++++++++++++++++++++++hwmsen_get_interrupt_data function sensor = %d\n",sensor);struct dev_context *mcxt = &dev_cxt;struct hwmdev_object *obj = hwm_obj;int64_t  nt;struct timespec time; if((sensor > MAX_ANDROID_SENSOR_NUM) || (mcxt->cxt[sensor] == NULL) || (mcxt->cxt[sensor]->obj.polling != 0)){HWM_ERR("sensor %d!\n", sensor);return -EINVAL;}else{       time.tv_sec = time.tv_nsec = 0;    time = get_monotonic_coarse(); nt = time.tv_sec*1000000000LL+time.tv_nsec;  if((sensor == ID_LIGHT) ||(sensor == ID_PRESSURE) ||(sensor == ID_PROXIMITY) || (sensor == ID_TEMPRERATURE)){// data changed, update the dataif(data->values[0] != obj_data.sensors_data[sensor].values[0]){mutex_lock(&obj_data.lock);obj_data.data_updata[sensor] = 1;obj_data.sensors_data[sensor].values[0] = data->values[0];obj_data.sensors_data[sensor].time = nt;obj_data.sensors_data[sensor].value_divide = data->value_divide;mutex_unlock(&obj_data.lock);}}else{// data changed, update the dataif((data->values[0] != obj_data.sensors_data[sensor].values[0]) || (data->values[1] != obj_data.sensors_data[sensor].values[1])|| (data->values[2] != obj_data.sensors_data[sensor].values[2])){mutex_lock(&obj_data.lock);obj_data.sensors_data[sensor].values[0] = data->values[0];obj_data.sensors_data[sensor].values[1] = data->values[1];obj_data.sensors_data[sensor].values[2] = data->values[2];obj_data.sensors_data[sensor].value_divide = data->value_divide;obj_data.data_updata[sensor] = 1;obj_data.sensors_data[sensor].time = nt;mutex_unlock(&obj_data.lock);}}if(obj->dc->polling_running == 1){hwmsen_work_func(NULL);}return 0;}
}
/*----------------------------------------------------------------------------*/
EXPORT_SYMBOL_GPL(hwmsen_get_interrupt_data);/*----------------------------------------------------------------------------*/
static void hwmsen_poll(unsigned long data)
{struct hwmdev_object *obj = (struct hwmdev_object *)data;if(obj != NULL){queue_work(sensor_workqueue, &obj->report);}
}
/*----------------------------------------------------------------------------*/
static struct hwmdev_object *hwmsen_alloc_object(void)
{struct hwmdev_object *obj = kzalloc(sizeof(*obj), GFP_KERNEL); HWM_FUN(f);if(!obj){HWM_ERR("Alloc hwmsen object error!\n");return NULL;}    obj->dc = &dev_cxt;obj->active_data_sensor = 0;obj->active_sensor = 0;atomic_set(&obj->delay, 200); /*5Hz*/// set work queue delay time 200msatomic_set(&obj->wake, 0);sensor_workqueue = create_singlethread_workqueue("sensor_polling");INIT_WORK(&obj->report, hwmsen_work_func);init_timer(&obj->timer);obj->timer.expires    = jiffies + atomic_read(&obj->delay)/(1000/HZ);obj->timer.function  = hwmsen_poll;obj->timer.data       = (unsigned long)obj;return obj;
}/*Sensor device driver attach to hwmsen device------------------------------------------------*/
int hwmsen_attach(int sensor, struct hwmsen_object *obj)
{struct dev_context *mcxt = &dev_cxt;int err = 0;HWM_FUN(f);if((mcxt == NULL) || (sensor > MAX_ANDROID_SENSOR_NUM)){err = -EINVAL;goto err_exit;}mutex_lock(&mcxt->lock);if(mcxt->cxt[sensor] != NULL){err = -EEXIST;goto err_exit;}else{mcxt->cxt[sensor] = kzalloc(sizeof(struct hwmsen_context), GFP_KERNEL);if(mcxt->cxt[sensor] == NULL){err = -EPERM;goto err_exit;}                atomic_set(&mcxt->cxt[sensor]->enable, 0);memcpy(&mcxt->cxt[sensor]->obj, obj, sizeof(*obj));// add for android2.3 set  sensors default polling delay time is 200msatomic_set(&mcxt->cxt[sensor]->delay, 200);}err_exit:mutex_unlock(&mcxt->lock); return err;
}
/*----------------------------------------------------------------------------*/
EXPORT_SYMBOL_GPL(hwmsen_attach);
/*----------------------------------------------------------------------------*/
int hwmsen_detach(int sensor)
{int err = 0;struct dev_context *mcxt = &dev_cxt; HWM_FUN(f);if ((sensor > MAX_ANDROID_SENSOR_NUM) || (mcxt->cxt[sensor] == NULL)){err = -EINVAL;goto err_exit;}mutex_lock(&mcxt->lock);kfree(mcxt->cxt[sensor]);mcxt->cxt[sensor] = NULL;err_exit:mutex_unlock(&mcxt->lock);return 0;
}
/*----------------------------------------------------------------------------*/
EXPORT_SYMBOL_GPL(hwmsen_detach);
/*----------------------------------------------------------------------------*/
static int hwmsen_enable(struct hwmdev_object *obj, int sensor, int enable)
{struct hwmsen_context *cxt = NULL;int err = 0;uint32_t sensor_type;sensor_type = 1 << sensor;if(!obj){HWM_ERR("hwmdev obj pointer is NULL!\n");return -EINVAL;}else if(obj->dc->cxt[sensor] == NULL){HWM_ERR("the sensor (%d) is not attached!!\n", sensor);return -ENODEV;}mutex_lock(&obj->dc->lock);cxt = obj->dc->cxt[sensor];    if(enable == 1){
//{@for mt6582 blocking issue work around      if(sensor == 7){HWM_LOG("P-sensor disable LDO low power\n");pmic_ldo_suspend_enable(0);}
//@}enable_again = true;obj->active_data_sensor |= sensor_type;if((obj->active_sensor & sensor_type) == 0)   // no no-data active{       if (cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL) != 0){if (cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL) != 0){if (cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL) != 0){HWM_ERR("activate sensor(%d) 3 times err = %d\n", sensor, err);err = -EINVAL;goto exit;}}}atomic_set(&cxt->enable, 1);          }// Need to complete the interrupt sensor workif((0 == obj->dc->polling_running) && (obj->active_data_sensor != 0)){obj->dc->polling_running = 1;//obj->timer.expires = jiffies + atomic_read(&obj->delay)/(1000/HZ);//add_timer(&obj->timer);mod_timer(&obj->timer, jiffies + atomic_read(&obj->delay)/(1000/HZ)); }}else{
//{@for mt6582 blocking issue work aroundif(sensor == 7){HWM_LOG("P-sensor enable LDO low power\n");pmic_ldo_suspend_enable(1);}
//@}obj->active_data_sensor &= ~sensor_type;if((obj->active_sensor & sensor_type) == 0)   // no no-data active{if(cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL) != 0){HWM_ERR("deactiva sensor(%d) err = %d\n", sensor, err);err = -EINVAL;goto exit;}atomic_set(&cxt->enable, 0);update_workqueue_polling_rate(200);// re-update workqueue polling rate}       if((1 == obj->dc->polling_running) && (obj->active_data_sensor == 0)){obj->dc->polling_running = 0;del_timer_sync(&obj->timer);cancel_work_sync(&obj->report);}obj_data.sensors_data[sensor].values[0] = SENSOR_INVALID_VALUE;obj_data.sensors_data[sensor].values[1] = SENSOR_INVALID_VALUE;obj_data.sensors_data[sensor].values[2] = SENSOR_INVALID_VALUE;}  HWM_LOG("sensor(%d), flag(%d)\n", sensor, enable);exit:mutex_unlock(&obj->dc->lock); return err;
}/*-------------no data sensor enable/disable--------------------------------------*/
static int hwmsen_enable_nodata(struct hwmdev_object *obj, int sensor, int enable)
{struct hwmsen_context *cxt = NULL;int err = 0;uint32_t sensor_type;HWM_FUN(f);sensor_type = 1 << sensor;if(NULL == obj){HWM_ERR("hwmdev obj pointer is NULL!\n");return -EINVAL;}else if(obj->dc->cxt[sensor] == NULL){HWM_ERR("the sensor (%d) is not attached!!\n", sensor);return -ENODEV;}mutex_lock(&obj->dc->lock);cxt = obj->dc->cxt[sensor];if(enable == 1){obj->active_sensor |= sensor_type;if((obj->active_data_sensor & sensor_type) == 0)  // no data active{if(cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable, sizeof(int), NULL, 0, NULL) != 0){HWM_ERR("activate sensor(%d) err = %d\n", sensor, err);err = -EINVAL;goto exit;}atomic_set(&cxt->enable, 1);}}else{obj->active_sensor &= ~sensor_type;if((obj->active_data_sensor & sensor_type) == 0) // no data active{if(cxt->obj.sensor_operate(cxt->obj.self, SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL) != 0){HWM_ERR("Deactivate sensor(%d) err = %d\n", sensor, err);err = -EINVAL;goto exit;}atomic_set(&cxt->enable, 0);}}exit:mutex_unlock(&obj->dc->lock);return err;
}
/*------------set delay--------------------------------------------------------*/
static int hwmsen_set_delay(int delay, int handle )
{int err = 0;struct hwmsen_context *cxt = NULL;cxt = hwm_obj->dc->cxt[handle];if(NULL == cxt ||(cxt->obj.sensor_operate == NULL)){HWM_ERR("have no this sensor %d or operator point is null!\r\n", handle);}else if(atomic_read(&cxt->enable) != 0){if(cxt->obj.sensor_operate(cxt->obj.self, SENSOR_DELAY, &delay,sizeof(int), NULL, 0, NULL) != 0){HWM_ERR("%d sensor's sensor_operate function error %d!\r\n",handle,err);return err;}//record sensor delayatomic_set(&cxt->delay, delay);}return err;
}
/*----------------------------------------------------------------------------*/
static int hwmsen_wakeup(struct hwmdev_object *obj)
{HWM_FUN(f);if(obj == NULL){HWM_ERR("null pointer!!\n");return -EINVAL;}input_event(obj->idev, EV_SYN, SYN_CONFIG, 0);return 0;
}
/*----------------------------------------------------------------------------*/
static ssize_t hwmsen_show_hwmdev(struct device* dev, struct device_attribute *attr, char *buf)
{//struct hwmdev_object *devobj = (struct hwmdev_object*)dev_get_drvdata(dev);int len = 0;printk("sensor test: hwmsen_show_hwmdev function!\n");
/*if (!devobj || !devobj->dc) {HWM_ERR("null pointer: %p, %p", devobj, (!devobj) ? (NULL) : (devobj->dc));return 0;}for (idx = 0; idx < C_MAX_HWMSEN_NUM; idx++) len += snprintf(buf+len, PAGE_SIZE-len, "    %d", idx);len += snprintf(buf+len, PAGE_SIZE-len, "\n");for (idx = 0; idx < C_MAX_HWMSEN_NUM; idx++)len += snprintf(buf+len, PAGE_SIZE-len, "    %d", atomic_read(&devobj->dc->cxt[idx].enable));len += snprintf(buf+len, PAGE_SIZE-len, "\n");*/return len;
}
/*----------------------------------------------------------------------------*/
static ssize_t hwmsen_store_active(struct device* dev, struct device_attribute *attr,const char *buf, size_t count)
{
/*printk("sensor test: hwmsen_store_active function!\n");struct hwmdev_object *devobj = (struct hwmdev_object*)dev_get_drvdata(dev);int sensor, enable, err, idx;if (!devobj || !devobj->dc) {HWM_ERR("null pointer!!\n");return count;}if (!strncmp(buf, "all-start", 9)) {for (idx = 0; idx < C_MAX_HWMSEN_NUM; idx++)hwmsen_enable(devobj, idx, 1);} else if (!strncmp(buf, "all-stop", 8)) {for (idx = 0; idx < C_MAX_HWMSEN_NUM; idx++)hwmsen_enable(devobj, idx, 0);    } else if (2 == sscanf(buf, "%d %d", &sensor, &enable)) {if ((err = hwmsen_enable(devobj, sensor, enable)))HWM_ERR("sensor enable failed: %d\n", err);}
*/return count;
}
/*----------------------------------------------------------------------------*/
static ssize_t hwmsen_show_delay(struct device* dev, struct device_attribute *attr, char *buf)
{
/*struct hwmdev_object *devobj = (struct hwmdev_object*)dev_get_drvdata(dev);
printk("sensor test: hwmsen_show_delay function!\n");if (!devobj || !devobj->dc) {HWM_ERR("null pointer!!\n");return 0;}return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&devobj->delay));
*/return 0;}
/*----------------------------------------------------------------------------*/
static ssize_t hwmsen_store_delay(struct device* dev, struct device_attribute *attr,const char *buf, size_t count)
{
/*struct hwmdev_object *devobj = (struct hwmdev_object*)dev_get_drvdata(dev);int delay;
printk("sensor test: hwmsen_show_delay function!\n");if (!devobj || !devobj->dc) {HWM_ERR("null pointer!!\n");return count;}if (1 != sscanf(buf, "%d", &delay)) {HWM_ERR("invalid format!!\n");return count;}atomic_set(&devobj->delay, delay);*/return count;
}
/*----------------------------------------------------------------------------*/
static ssize_t hwmsen_show_wake(struct device* dev, struct device_attribute *attr, char *buf)
{
/*printk("sensor test: hwmsen_show_wake function!\n");struct hwmdev_object *devobj = (struct hwmdev_object*)dev_get_drvdata(dev);if (!devobj || !devobj->dc) {HWM_ERR("null pointer!!\n");return 0;}return snprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&devobj->wake));    */return 0;
}
/*----------------------------------------------------------------------------*/
static ssize_t hwmsen_store_wake(struct device* dev, struct device_attribute *attr,const char *buf, size_t count)
{
/*struct hwmdev_object *devobj = (struct hwmdev_object*)dev_get_drvdata(dev);int wake, err;
printk("sensor test: hwmsen_store_wake function!\n");if (!devobj || !devobj->dc) {HWM_ERR("null pointer!!\n");return count;}if (1 != sscanf(buf, "%d", &wake)) {HWM_ERR("invalid format!!\n");return count;}if ((err = hwmsen_wakeup(devobj))) {HWM_ERR("wakeup sensor fail, %d\n", err);return count;}*/ return count;
}  /*----------------------------------------------------------------------------*/
static ssize_t hwmsen_show_trace(struct device *dev, struct device_attribute *attr, char *buf)
{struct i2c_client *client = to_i2c_client(dev);struct hwmdev_object *obj = i2c_get_clientdata(client);HWM_FUN(f);return snprintf(buf, PAGE_SIZE, "0x%08X\n", atomic_read(&obj->trace));
}
/*----------------------------------------------------------------------------*/
static ssize_t hwmsen_store_trace(struct device* dev, struct device_attribute *attr, const char *buf, size_t count)
{struct i2c_client *client = to_i2c_client(dev);struct hwmdev_object *obj = i2c_get_clientdata(client);    int trc;HWM_FUN(f);if (1 == sscanf(buf, "0x%x\n", &trc)){atomic_set(&obj->trace, trc);}else{HWM_ERR("set trace level fail!!\n");}return count;
}
/*----------------------------------------------------------------------------*/
DEVICE_ATTR(hwmdev,     S_IWUSR | S_IRUGO, hwmsen_show_hwmdev, NULL);
DEVICE_ATTR(active,     S_IWUSR | S_IRUGO, hwmsen_show_hwmdev, hwmsen_store_active);
DEVICE_ATTR(delay,      S_IWUSR | S_IRUGO, hwmsen_show_delay,  hwmsen_store_delay);
DEVICE_ATTR(wake,       S_IWUSR | S_IRUGO, hwmsen_show_wake,   hwmsen_store_wake);
DEVICE_ATTR(trace,      S_IWUSR | S_IRUGO, hwmsen_show_trace,  hwmsen_store_trace);
/*----------------------------------------------------------------------------*/
static struct device_attribute *hwmsen_attr_list[] =
{&dev_attr_hwmdev,&dev_attr_active,&dev_attr_delay,&dev_attr_wake,&dev_attr_trace,
};/*----------------------------------------------------------------------------*/
static int hwmsen_create_attr(struct device *dev)
{int idx, err = 0;int num = (int)(sizeof(hwmsen_attr_list)/sizeof(hwmsen_attr_list[0]));HWM_FUN();if(!dev){return -EINVAL;}   for(idx = 0; idx < num; idx++){if((err = device_create_file(dev, hwmsen_attr_list[idx]))){            HWM_ERR("device_create_file (%s) = %d\n", hwmsen_attr_list[idx]->attr.name, err);        break;}}return err;
}
/*----------------------------------------------------------------------------*/
static int hwmsen_delete_attr(struct device *dev)
{int idx ,err = 0;int num = (int)(sizeof(hwmsen_attr_list)/sizeof(hwmsen_attr_list[0]));HWM_FUN(f);if (!dev){return -EINVAL;}for (idx = 0; idx < num; idx++){device_remove_file(dev, hwmsen_attr_list[idx]);}   return err;
}/*----------------------------------------------------------------*/
static int init_static_data(void)
{int i = 0;
//  memset(&obj_data, 0, sizeof(struct hwmsen_data));
//  obj_data.lock = __MUTEX_INITIALIZER(obj_data.lock);    for(i=0; i < MAX_ANDROID_SENSOR_NUM; i++){dev_cxt.cxt[i] = NULL;     memset(&obj_data.sensors_data[i], SENSOR_INVALID_VALUE, sizeof(hwm_sensor_data));obj_data.sensors_data[i].sensor = i;}return 0;
}
/*----------------------------------------------------------------*/
static int hwmsen_open(struct inode *node , struct file *fp)
{HWM_FUN(f);//struct file_private* data = kzalloc(sizeof(struct file_private), GFP_KERNEL);
//  fp->private_data = data;fp->private_data = NULL;return nonseekable_open(node,fp);
}
/*----------------------------------------------------------------------------*/
static int hwmsen_release(struct inode *node, struct file *fp)
{HWM_FUN(f);kfree(fp->private_data);fp->private_data = NULL;return 0;
}
/*----------------------------------------------------------------------------*/
static void update_workqueue_polling_rate(int newDelay)
{atomic_t delaytemp;int i=0;int idx=0;struct hwmsen_context *cxt = NULL;struct hwmdev_object *obj = hwm_obj;HWM_FUN(f);atomic_set(&delaytemp, 200);//used to finding fastest sensor polling ratefor(i = 0; i < MAX_ANDROID_SENSOR_NUM; i++){if(hwm_obj->active_data_sensor & 1<<i){if(atomic_read(&delaytemp) > atomic_read(&(hwm_obj->dc->cxt[i]->delay))){atomic_set(&delaytemp, atomic_read(&(hwm_obj->dc->cxt[i]->delay)));// work queue polling delay base time}}}//use the fastest sensor polling delay as work queue polling delay base timeif(atomic_read(&delaytemp) > newDelay){atomic_set(&hwm_obj->delay, newDelay);// work queue polling delay base timeHWM_LOG("set new workqueue base time=%d\n",atomic_read(&hwm_obj->delay));}else{atomic_set(&hwm_obj->delay, atomic_read(&delaytemp));HWM_LOG("set old fastest sensor delay as workqueue base time=%d\n",atomic_read(&hwm_obj->delay));}//upadate all sensors delayCountSetfor(idx = 0; idx < MAX_ANDROID_SENSOR_NUM; idx++){cxt = obj->dc->cxt[idx];if((cxt == NULL) || (cxt->obj.sensor_operate == NULL)|| !(obj->active_data_sensor&(0x01<<idx))){continue;}if(0 == atomic_read(&cxt->delay)){cxt->delayCount = cxt->delayCountSet = 0;HWM_LOG("%s,set delayCountSet=0 delay =%d handle=%d\r\n",__func__, atomic_read(&cxt->delay), idx);}if(atomic_read(&cxt->delay) <= atomic_read(&hwm_obj->delay)){cxt->delayCount = cxt->delayCountSet = 0;HWM_LOG("%s,set delayCountSet=0 delay =%d handle=%d\r\n",__func__, atomic_read(&cxt->delay), idx);}else{i= atomic_read(&cxt->delay)/atomic_read(&hwm_obj->delay);cxt->delayCount = cxt->delayCountSet = i;HWM_LOG("%s:set delayCountSet=%d delay =%d handle=%d\r\n",__func__, i, atomic_read(&cxt->delay), idx);#if 0switch(i){case 3:// 200/60 ;60/20cxt->delayCount = cxt->delayCountSet = 3;HWM_LOG("%s:set delayCountSet=3 delay =%d handle=%d\r\n",__func__,atomic_read(&cxt->delay), idx);break;case 10:// 200/20cxt->delayCount = cxt->delayCountSet = 10;HWM_LOG("%s:set delayCountSet=10 delay =%d handle=%d\r\n",__func__, atomic_read(&cxt->delay), idx);break;}#endif}}
}//static int hwmsen_ioctl(struct inode *node, struct file *fp,
//                        unsigned int cmd, unsigned long arg)
static long hwmsen_unlocked_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
{//HWM_LOG("IO parament %d!\r\n", cmd);   void __user *argp = (void __user*)arg;uint32_t flag;struct sensor_delay delayPara;hwm_trans_data hwm_sensors_data; int i = 0;atomic_t delaytemp;atomic_set(&delaytemp, 200);//used to finding fastest sensor polling rate//int delaytemp=200;//used to finding fastest sensor polling rateif(!hwm_obj){HWM_ERR("null pointer!!\n");return -EINVAL;}switch(cmd){case HWM_IO_SET_DELAY:// android2.3 sensor system has 4 sample delay 0ms 20ms 60ms 200msif(copy_from_user(&delayPara, argp, sizeof(delayPara))){HWM_ERR("copy_from_user fail!!\n");return -EFAULT;}HWM_LOG("ioctl delay handle=%d,delay =%d\n",delayPara.handle,delayPara.delay);hwmsen_set_delay(delayPara.delay,delayPara.handle);//modified for android2.3update_workqueue_polling_rate(delayPara.delay);break;case HWM_IO_SET_WAKE:hwmsen_wakeup(hwm_obj);break;case HWM_IO_ENABLE_SENSOR:if(copy_from_user(&flag, argp, sizeof(flag))){HWM_ERR("copy_from_user fail!!\n");return -EFAULT;}hwmsen_enable(hwm_obj, flag, 1);break;case HWM_IO_DISABLE_SENSOR:if(copy_from_user(&flag, argp, sizeof(flag))){HWM_ERR("copy_from_user fail!!\n");return -EFAULT;}hwmsen_enable(hwm_obj, flag, 0);break;case HWM_IO_GET_SENSORS_DATA:          if(copy_from_user(&hwm_sensors_data, argp, sizeof(hwm_sensors_data))){HWM_ERR("copy_from_user fail!!\n");return -EFAULT;}mutex_lock(&obj_data.lock);          memcpy(hwm_sensors_data.data, &(obj_data.sensors_data),sizeof(hwm_sensor_data) * MAX_ANDROID_SENSOR_NUM);for(i = 0; i < MAX_ANDROID_SENSOR_NUM; i++){if(hwm_sensors_data.date_type & 1<<i){                 hwm_sensors_data.data[i].update = 1;}else{hwm_sensors_data.data[i].update = 0;}}mutex_unlock(&obj_data.lock);if(copy_to_user(argp, &hwm_sensors_data, sizeof(hwm_sensors_data))){HWM_ERR("copy_to_user fail!!\n");return -EFAULT;}break;case HWM_IO_ENABLE_SENSOR_NODATA:if(copy_from_user(&flag, argp, sizeof(flag))){HWM_ERR("copy_from_user fail!!\n");return -EFAULT;}hwmsen_enable_nodata(hwm_obj, flag, 1);break;case HWM_IO_DISABLE_SENSOR_NODATA:if(copy_from_user(&flag, argp, sizeof(flag))){HWM_ERR("copy_from_user fail!!\n");return -EFAULT;}hwmsen_enable_nodata(hwm_obj, flag, 0);break;default:HWM_ERR("have no this paramenter %d!!\n", cmd);return -ENOIOCTLCMD;}return 0;
}
/*----------------------------------------------------------------------------*/
static struct file_operations hwmsen_fops = {
//  .owner  = THIS_MODULE,.open   = hwmsen_open,.release = hwmsen_release,
//  .ioctl  = hwmsen_ioctl,.unlocked_ioctl = hwmsen_unlocked_ioctl,
};
/*----------------------------------------------------------------------------*/
static int hwmsen_probe(struct platform_device *pdev)
{int err;//HWM_LOG("+++++++++++++++++hwmsen_probe!!\n");HWM_FUN(f);init_static_data();   hwm_obj = hwmsen_alloc_object();if (!hwm_obj){err = -ENOMEM;HWM_ERR("unable to allocate devobj!\n");goto exit_alloc_data_failed;}hwm_obj->idev = input_allocate_device();if (!hwm_obj->idev){err = -ENOMEM;HWM_ERR("unable to allocate input device!\n");goto exit_alloc_input_dev_failed;}set_bit(EV_REL, hwm_obj->idev->evbit);set_bit(EV_SYN, hwm_obj->idev->evbit);input_set_capability(hwm_obj->idev, EV_REL, EVENT_TYPE_SENSOR);hwm_obj->idev->name = HWM_INPUTDEV_NAME;if((err = input_register_device(hwm_obj->idev))){HWM_ERR("unable to register input device!\n");goto exit_input_register_device_failed;}input_set_drvdata(hwm_obj->idev, hwm_obj);hwm_obj->mdev.minor = MISC_DYNAMIC_MINOR;hwm_obj->mdev.name  = HWM_SENSOR_DEV_NAME;hwm_obj->mdev.fops  = &hwmsen_fops;if((err = misc_register(&hwm_obj->mdev))){HWM_ERR("unable to register sensor device!!\n");goto exit_misc_register_failed;}dev_set_drvdata(hwm_obj->mdev.this_device, hwm_obj);if(hwmsen_create_attr(hwm_obj->mdev.this_device) != 0){HWM_ERR("unable to create attributes!!\n");goto exit_hwmsen_create_attr_failed;}// add for fix resume bugatomic_set(&(hwm_obj->early_suspend), 0);hwm_obj->early_drv.level    = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 1,hwm_obj->early_drv.suspend  = hwmsen_early_suspend,hwm_obj->early_drv.resume   = hwmsen_late_resume,    register_early_suspend(&hwm_obj->early_drv);wake_lock_init(&(hwm_obj->read_data_wake_lock),WAKE_LOCK_SUSPEND,"read_data_wake_lock");// add for fix resume bug endreturn 0;exit_hwmsen_create_attr_failed:exit_misc_register_failed:
//  exit_get_hwmsen_info_failed:exit_input_register_device_failed:input_free_device(hwm_obj->idev);exit_alloc_input_dev_failed:    kfree(hwm_obj);exit_alloc_data_failed:return err;
}
/*----------------------------------------------------------------------------*/
static int hwmsen_remove(struct platform_device *pdev)
{HWM_FUN(f);input_unregister_device(hwm_obj->idev);        hwmsen_delete_attr(hwm_obj->mdev.this_device);misc_deregister(&hwm_obj->mdev);kfree(hwm_obj);return 0;
}
static void hwmsen_early_suspend(struct early_suspend *h)
{//HWM_FUN(f);atomic_set(&(hwm_obj->early_suspend), 1);HWM_LOG(" hwmsen_early_suspend ok------->hwm_obj->early_suspend=%d \n",atomic_read(&hwm_obj->early_suspend));return ;
}
/*----------------------------------------------------------------------------*/
static void hwmsen_late_resume(struct early_suspend *h)
{//HWM_FUN(f);atomic_set(&(hwm_obj->early_suspend), 0);HWM_LOG(" hwmsen_late_resume ok------->hwm_obj->early_suspend=%d \n",atomic_read(&hwm_obj->early_suspend));return ;
}
/*----------------------------------------------------------------------------*/
static int hwmsen_suspend(struct platform_device *dev, pm_message_t state)
{//HWM_FUN(f);return 0;
}
/*----------------------------------------------------------------------------*/
static int hwmsen_resume(struct platform_device *dev)
{//HWM_FUN(f);return 0;
}
/*----------------------------------------------------------------------------*/
static struct platform_driver hwmsen_driver =
{.probe      = hwmsen_probe,.remove     = hwmsen_remove,    .suspend    = hwmsen_suspend,.resume     = hwmsen_resume,.driver     = {.name = HWM_SENSOR_DEV_NAME,
//      .owner = THIS_MODULE,}
};/*----------------------------------------------------------------------------*/#if defined(MTK_AUTO_DETECT_MAGNETOMETER)int hwmsen_msensor_remove(struct platform_device *pdev)
{int err =0;int i=0;for(i = 0; i < MAX_CHOOSE_G_NUM; i++){if(0 ==  strcmp(msensor_name,msensor_init_list[i]->name)){if(NULL == msensor_init_list[i]->uninit){HWM_LOG(" hwmsen_msensor_remove null pointer \n");return -1;}msensor_init_list[i]->uninit();}}return 0;
}static int msensor_probe(struct platform_device *pdev)
{int i =0;int err=0;HWM_LOG(" msensor_probe +\n");for(i = 0; i < MAX_CHOOSE_G_NUM; i++){if(NULL != msensor_init_list[i]){err = msensor_init_list[i]->init();if(0 == err){strcpy(msensor_name,msensor_init_list[i]->name);HWM_LOG(" msensor %s probe ok\n", msensor_name);break;}}}return 0;
}static struct platform_driver msensor_driver = {.probe      = msensor_probe,.remove     = hwmsen_msensor_remove,    .driver     = {.name  = "msensor",
//      .owner = THIS_MODULE,}
};int hwmsen_msensor_add(struct sensor_init_info* obj)
{int err=0;int i =0;HWM_FUN(f);for(i =0; i < MAX_CHOOSE_G_NUM; i++ ){if(NULL == msensor_init_list[i]){msensor_init_list[i] = kzalloc(sizeof(struct sensor_init_info), GFP_KERNEL);if(NULL == msensor_init_list[i]){HWM_ERR("kzalloc error");return -1;}obj->platform_diver_addr = &msensor_driver;msensor_init_list[i] = obj;break;}}return err;
}
EXPORT_SYMBOL_GPL(hwmsen_msensor_add);#endif#if defined(MTK_AUTO_DETECT_ACCELEROMETER)//int hwmsen_gsensor_remove(struct platform_device *pdev)
{int i=0;for(i = 0; i < MAX_CHOOSE_G_NUM; i++){if(0 ==  strcmp(gsensor_name,gsensor_init_list[i]->name)){if(NULL == gsensor_init_list[i]->uninit){HWM_LOG(" hwmsen_gsensor_remove null pointer +\n");return -1;}gsensor_init_list[i]->uninit();}}return 0;
}static int gsensor_probe(struct platform_device *pdev)
{int i =0;int err=0;HWM_LOG(" gsensor_probe +\n");//
/*for(i = 0; i < MAX_CHOOSE_G_NUM; i++){HWM_LOG(" gsensor_init_list[i]=%d\n",gsensor_init_list[i]);}
*///for(i = 0; i < MAX_CHOOSE_G_NUM; i++){HWM_LOG(" i=%d\n",i);if(0 != gsensor_init_list[i]){HWM_LOG(" !!!!!!!!\n");err = gsensor_init_list[i]->init();if(0 == err){strcpy(gsensor_name,gsensor_init_list[i]->name);HWM_LOG(" gsensor %s probe ok\n", gsensor_name);break;}}}if(i == MAX_CHOOSE_G_NUM){HWM_LOG(" gsensor probe fail\n");}return 0;
}static struct platform_driver gsensor_driver = {.probe      = gsensor_probe,.remove     = hwmsen_gsensor_remove,    .driver     = {.name  = "gsensor",
//      .owner = THIS_MODULE,}
};int hwmsen_gsensor_add(struct sensor_init_info* obj)
{int err=0;int i =0;HWM_FUN(f);for(i =0; i < MAX_CHOOSE_G_NUM; i++ ){if(NULL == gsensor_init_list[i]){gsensor_init_list[i] = kzalloc(sizeof(struct sensor_init_info), GFP_KERNEL);if(NULL == gsensor_init_list[i]){HWM_ERR("kzalloc error");return -1;}obj->platform_diver_addr = &gsensor_driver;gsensor_init_list[i] = obj;break;}}return err;
}
EXPORT_SYMBOL_GPL(hwmsen_gsensor_add);#endif#if defined(MTK_AUTO_DETECT_ALSPS)int hwmsen_alsps_sensor_remove(struct platform_device *pdev)
{int err =0;int i=0;for(i = 0; i < MAX_CHOOSE_G_NUM; i++){if(0 ==  strcmp(alsps_name,alsps_init_list[i]->name)){if(NULL == alsps_init_list[i]->uninit){HWM_LOG(" hwmsen_alsps_sensor_remove null pointer \n");return -1;}alsps_init_list[i]->uninit();}}return 0;
}static int alsps_sensor_probe(struct platform_device *pdev)
{int i =0;int err=0;HWM_LOG(" als_ps sensor_probe +\n");for(i = 0; i < MAX_CHOOSE_G_NUM; i++){if(NULL != alsps_init_list[i]){err = alsps_init_list[i]->init();if(0 == err){strcpy(alsps_name,alsps_init_list[i]->name);HWM_LOG(" alsps sensor %s probe ok\n", alsps_name);break;}}}return 0;
}static struct platform_driver alsps_sensor_driver = {.probe      = alsps_sensor_probe,.remove     = hwmsen_alsps_sensor_remove,    .driver     = {.name  = "als_ps",}
};int hwmsen_alsps_sensor_add(struct sensor_init_info* obj)
{int err=0;int i =0;HWM_FUN(f);for(i =0; i < MAX_CHOOSE_G_NUM; i++ ){if(NULL == alsps_init_list[i]){alsps_init_list[i] = kzalloc(sizeof(struct sensor_init_info), GFP_KERNEL);if(NULL == alsps_init_list[i]){HWM_ERR("kzalloc error");return -1;}obj->platform_diver_addr = &alsps_sensor_driver;alsps_init_list[i] = obj;break;}}return err;
}
EXPORT_SYMBOL_GPL(hwmsen_alsps_sensor_add);#endif/*----------------------------------------------------------------------------*/
static int __init hwmsen_init(void)
{HWM_FUN(f);if(platform_driver_register(&hwmsen_driver)){HWM_ERR("failed to register sensor driver");return -ENODEV;}    #if defined(MTK_AUTO_DETECT_ACCELEROMETER)if(platform_driver_register(&gsensor_driver)){HWM_ERR("failed to register gensor driver");return -ENODEV;}
#endif#if defined(MTK_AUTO_DETECT_MAGNETOMETER)if(platform_driver_register(&msensor_driver)){HWM_ERR("failed to register mensor driver");return -ENODEV;}
#endif#if defined(MTK_AUTO_DETECT_ALSPS)if(platform_driver_register(&alsps_sensor_driver)){HWM_ERR("failed to register alsps_sensor_driver driver");return -ENODEV;}
#endifreturn 0;
}
/*----------------------------------------------------------------------------*/
static void __exit hwmsen_exit(void)
{platform_driver_unregister(&hwmsen_driver);
}
/*----------------------------------------------------------------------------*/
module_init(hwmsen_init);
module_exit(hwmsen_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("sensor device driver");
MODULE_AUTHOR("Chunlei Wang<chunlei.wang@mediatek.com");

【转载】MTK Sensor 传感器驱动及系统框架 1. 【非常好】【mtk sensor 驱动框架】hwmsen_dev.c相关推荐

  1. V4L2视频驱动框架简述(转载)

    摘自:https://blog.csdn.net/LinuxArmbiggod/article/details/80310445 V4L2视频驱动框架简述 奶牛养殖场小马 2018-05-14 15: ...

  2. 08.音频系统:第003课_Linux音频驱动程序:第002节_ASoC音频驱动框架

    通过上小节alsa音频驱动框架的分析,知道如果要去写一个声卡驱动,我们需要分配,设置,注册snd_card结构体: 定义一个struct snd_card *card; snd_card_new // ...

  3. Linux驱动框架之misc类设备驱动框架

    1.何为misc设备 (1)misc中文名就是杂项设备\杂散设备,因为现在的硬件设备多种多样,有好些设备不好对他们进行一个单独的分类,所以就将这些设备全部归属于 杂散设备,也就是misc设备,例如像a ...

  4. V4L2视频驱动框架---v4l2_device管理模块简述

    ​ v4l2框架由4个主要的部分(数据结构)组成: v4l2_devices(包括v4l2_subdev) :v4l2_device管理所有的设备 media_device : meida_devic ...

  5. Linux V4l2驱动 -- 框架概述

    V4l2框架简述 1 硬件 常用的电脑摄像头是USB接口,主流的智能手机摄像头是MIPI接口,另外还有像树莓派等硬件使用的CSI接口的设备.常用的智能手机Camera采用的MIPI接口,电路框架以及电 ...

  6. rt-thread SDIO驱动框架分析(SD卡驱动\SD Nand驱动)

    rt-thread SDIO驱动框架分析之SD卡驱动 文章目录 rt-thread SDIO驱动框架分析之SD卡驱动 1. 前言 2. SDIO通用驱动框架介绍 3. 文件架构分析 4. SDIO设备 ...

  7. linux内核的I2C子系统详解1——I2C总线概览、驱动框架概览

    以下内容源于朱有鹏<物联网大讲堂>课程的学习,如有侵权,请告知删除. 1.I2C总线汇总概览 (1)三根通信线:SCL.SDA.GND: (2)同步.串行.电平.低速(几百k).近距离: ...

  8. linux内核按键驱动,嵌入式Linux按键驱动框架

    前言 本文将通过轮询.中断.poll机制.异步通知和同步互斥阻塞等方式编写按键驱动程序.本节的驱动框架是在<嵌入式Linux驱动框架的搭建>的基础上进行改进的,所以本文只讲解修改的部分. ...

  9. 深入学习Linux摄像头(二)v4l2驱动框架

    深入学习Linux摄像头系列 深入学习Linux摄像头(一)v4l2应用编程 深入学习Linux摄像头(二)v4l2驱动框架 深入学习Linux摄像头(三)虚拟摄像头驱动分析 深入学习Linux摄像头 ...

最新文章

  1. 图解HTTPS建立过程
  2. 33 张图详解 RSTP 、MSTP、替代技术
  3. Pytorch optimizer.step() 和loss.backward()和scheduler.step()的关系与区别 (Pytorch 代码讲解)
  4. Spring+Hibernate+c3p0连接池配置-连接无法释放的问题解决方案
  5. 基于Quartus II的在线调试方法
  6. 如何将不同类型数据导入Elaticsearch中?
  7. Android 之PackageManager框架
  8. CCIE-LAB-第三篇-VRRP+SLA
  9. 手把手带你手写SpringMVC,剑指优秀开源框架灵魂
  10. Mysql 定时备份操作
  11. python数据分析之(1)数据输入和输出
  12. 时间管理:战略时间块,缓冲时间块,逃离时间块
  13. Java一个月学到springboot_从零开始学SpringBoot如何开始使用图文详解
  14. tomcat设置编码格式utf8
  15. 大数据第三季--spark(day1)-徐培成-专题视频课程
  16. win10计算机切换用户,win10账户切换,详细教您win10怎么切换账户
  17. VirtualBox 应用程序错误
  18. 批量修改WORD文档密码
  19. git出现 [rejected]master -> master (non-fast-forward)问题怎么解决
  20. LM75AD温度传感器的应用(2)

热门文章

  1. 本本重装了win7之后不能调屏幕亮度了
  2. Android 10 适配攻略
  3. adb 连接天天模拟器端口5037被占用问题的解决
  4. 基于三层交换机--NAT、VRRP技术的综合运用
  5. 给打印机发送打印命令,打印机不反应win7
  6. 巨头入局,无人货架小玩家离场倒计时
  7. word之怎么对每节或每章使用不同的页眉或页脚?
  8. 关于SMO算法的一点点认识
  9. CAD转换成JPG图片超级方便的方法
  10. iOS13适配深色模式(Dark Mode)