3 sensor driver
相关结构体
//Sensor device 抽象
struct hwmdev_object {
structinput_dev *idev;
structmiscdevice mdev;
structdev_context *dc;
structwork_struct report;
atomic_t delay; /*polling period for reportinginput event*/
atomic_t wake; /*user-space request to wake-up, used withstop*/
structtimer_list timer; /* polling timer */
atomic_t trace;
uint32_t active_sensor; // Active, buthwmsen don't need data sensor. //Maybeother need it's data.
uint32_t active_data_sensor; // Active and hwmsen need datasensor.
//addfor fix resume issue
structearly_suspend early_drv;
structwake_lock read_data_wake_lock;
atomic_t early_suspend;
//addfor fix resume end
};
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_tdelay;
uint32_tdelayCountSet;
uint32_tdelayCount;
structhwmsen_object obj;
};
/*------------sensorsdata----------------------------------------------------*/
typedef struct {
/*sensor identifier */
int sensor;
/*sensor values */
int values[3];
/*sensor values divide */
uint32_tvalue_divide;
/*sensor accuracy*/
int8_tstatus;
/*whether updata? */
int update;
/*time is in nanosecond */
int64_t time;
uint32_t reserved;
}hwm_sensor_data;
typedef struct {
hwm_sensor_datadata[MAX_ANDROID_SENSOR_NUM];
intdate_type;
}hwm_trans_data;
static int hwmsen_probe(structplatform_device *pdev)
{
interr;
//HWM_LOG("+++++++++++++++++hwmsen_probe!!\n");
HWM_FUN(f);
init_static_data();
hwm_obj= hwmsen_alloc_object(); //alloc& init hwmsensor obj
if(!hwm_obj)
{
err= -ENOMEM;
HWM_ERR("unableto allocate devobj!\n");
gotoexit_alloc_data_failed;
}
hwm_obj->idev= input_allocate_device(); //alloc inputdevice
if(!hwm_obj->idev)
{
err= -ENOMEM;
HWM_ERR("unableto allocate input device!\n");
gotoexit_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); ///setevent type
hwm_obj->idev->name= HWM_INPUTDEV_NAME;
if((err= input_register_device(hwm_obj->idev))) ///
{
HWM_ERR("unableto register input device!\n");
gotoexit_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))) //注册为一个杂项设备,提供ops
{
HWM_ERR("unableto register sensor device!!\n");
gotoexit_misc_register_failed;
}
dev_set_drvdata(hwm_obj->mdev.this_device,hwm_obj);
//add for fix resume bug
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);
wake_lock_init(&(hwm_obj->read_data_wake_lock),WAKE_LOCK_SUSPEND,"read_data_wake_lock");
//add for fix resume bug end
return0;
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:
returnerr;
}
static void hwmsen_poll(unsigned long data)
{
structhwmdev_object *obj = (struct hwmdev_object *)data;
if(obj!= NULL)
{
queue_work(sensor_workqueue,&obj->report);
}
}
static struct hwmdev_object*hwmsen_alloc_object(void)
{
structhwmdev_object *obj = kzalloc(sizeof(*obj), GFP_KERNEL);
HWM_FUN(f);
if(!obj)
{
HWM_ERR("Allochwmsen object error!\n");
returnNULL;
}
obj->dc= &dev_cxt;
obj->active_data_sensor= 0;
obj->active_sensor= 0;
atomic_set(&obj->delay,200); /*5Hz*/// set work queue delay time 200ms
atomic_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;
returnobj;
}
ioctrl 分析,只要提供ioctrl cmd给sensor hal
static long hwmsen_unlocked_ioctl(structfile *fp, unsigned int cmd, unsigned long arg)
{
//HWM_LOG("IOparament %d!\r\n", cmd);
void__user *argp = (void __user*)arg;
uint32_tflag;
structsensor_delay delayPara;
hwm_trans_datahwm_sensors_data;
inti = 0;
atomic_tdelaytemp;
atomic_set(&delaytemp,200);//used to finding fastest sensor polling rate
//intdelaytemp=200;//used to finding fastest sensor polling rate
if(!hwm_obj)
{
HWM_ERR("nullpointer!!\n");
return-EINVAL;
}
switch(cmd)
{
caseHWM_IO_SET_DELAY:
// android2.3 sensor system has 4 sample delay0ms 20ms 60ms 200ms
if(copy_from_user(&delayPara,argp, sizeof(delayPara)))
{
HWM_ERR("copy_from_userfail!!\n");
return-EFAULT;
}
HWM_LOG("ioctldelay handle=%d,delay =%d\n",delayPara.handle,delayPara.delay);
hwmsen_set_delay(delayPara.delay,delayPara.handle);//modifiedfor android2.3
update_workqueue_polling_rate(delayPara.delay);
break;
caseHWM_IO_SET_WAKE:
hwmsen_wakeup(hwm_obj);
break;
caseHWM_IO_ENABLE_SENSOR: //打开相应的sensor,并poll sensor数据
if(copy_from_user(&flag,argp, sizeof(flag)))
{
HWM_ERR("copy_from_userfail!!\n");
return-EFAULT;
}
hwmsen_enable(hwm_obj,flag, 1);
break;
caseHWM_IO_DISABLE_SENSOR: //关闭相应的sensor,flag 为sensor type
if(copy_from_user(&flag,argp, sizeof(flag)))
{
HWM_ERR("copy_from_userfail!!\n");
return-EFAULT;
}
hwmsen_enable(hwm_obj,flag, 0);
break;
caseHWM_IO_GET_SENSORS_DATA: //获取sensorsdata
if(copy_from_user(&hwm_sensors_data,argp, sizeof(hwm_sensors_data)))
{
HWM_ERR("copy_from_userfail!!\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_userfail!!\n");
return-EFAULT;
}
break;
caseHWM_IO_ENABLE_SENSOR_NODATA: //仅仅打开sensor
if(copy_from_user(&flag,argp, sizeof(flag)))
{
HWM_ERR("copy_from_userfail!!\n");
return -EFAULT;
}
hwmsen_enable_nodata(hwm_obj,flag, 1);
break;
caseHWM_IO_DISABLE_SENSOR_NODATA:
if(copy_from_user(&flag,argp, sizeof(flag)))
{
HWM_ERR("copy_from_userfail!!\n");
return-EFAULT;
}
hwmsen_enable_nodata(hwm_obj,flag, 0);
break;
default:
HWM_ERR("haveno this paramenter %d!!\n", cmd);
return-ENOIOCTLCMD;
}
return0;
}
static int hwmsen_enable(structhwmdev_object *obj, int sensor, int enable)
{
structhwmsen_context *cxt = NULL;
interr = 0;
uint32_tsensor_type;
sensor_type= 1 << sensor;
if(!obj)
{
HWM_ERR("hwmdevobj pointer is NULL!\n");
return-EINVAL;
}
elseif(obj->dc->cxt[sensor] == NULL)
{
HWM_ERR("thesensor (%d) is not attached!!\n", sensor);
return-ENODEV;
}
mutex_lock(&obj->dc->lock);
cxt= obj->dc->cxt[sensor];
if(enable== 1)
{
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) //通过sensor type,打开特定sensor(accelerometor、proximity etc)
{
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("activatesensor(%d) 3 times err = %d\n", sensor, err);
err= -EINVAL;
gotoexit;
}
}
}
atomic_set(&cxt->enable,1);
}
//Need to complete the interrupt sensor work
if((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)); //启动poll timer
}
}
else
{
obj->active_data_sensor&= ~sensor_type;
if((obj->active_sensor& sensor_type) == 0) // no no-dataactive
{
if(cxt->obj.sensor_operate(cxt->obj.self,SENSOR_ENABLE, &enable,sizeof(int), NULL, 0, NULL) != 0)
{
HWM_ERR("deactivasensor(%d) err = %d\n", sensor, err);
err= -EINVAL;
gotoexit;
}
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);
returnerr;
}
hwmsen_enable 打开特定sensor后,启动polltimer,timer 时间到会调用hwmsen_poll 启动sensor_workqueue ,继而进入hwmsen_work_func 获取sensor data,并上报sensor type input 时间:
static void hwmsen_work_func(structwork_struct *work)
{
//structhwmdev_object *obj = container_of(work, struct hwmdev_object, report);
structhwmdev_object *obj = hwm_obj;
structhwmsen_context *cxt = NULL;
intout_size;
hwm_sensor_datasensor_data;
uint32_tevent_type = 0;
int64_t nt;
structtimespec time;
interr, idx;
//inttrc = atomic_read(&obj->trace);
if(obj == NULL)
{
HWM_ERR("objpoint 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 sensor
if(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;
}
//addedto surpport set delay to specified sensor
if(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 nextwork\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("getdata 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 data
if(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 data
if((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]);
}
}
}
}
if(enable_again== true)
{
event_type= obj->active_data_sensor;
enable_again= false;
//filter-1 value
for(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_sensorafter 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_sensorafter clear: %d\n",idx);
}
}
}
//HWM_LOG("eventtype 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("removeps event!!!!!!!!!!!\n");
}
if(event_type!= 0)
{
input_report_rel(obj->idev,EVENT_TYPE_SENSOR, event_type);
input_sync(obj->idev);//modified
//HWM_LOG("eventtype: %d\n", event_type);
}
else
{
//HWM_LOG("noavailable sensor!!\n");
}
if(obj->dc->polling_running== 1)
{
mod_timer(&obj->timer,jiffies + atomic_read(&obj->delay)/(1000/HZ));
}
}
下面介绍几个hwmsen driver提供给特定physical sensor driver的接口:
/*Sensor device driver attach to hwmsendevice------------------------------------------------*/
int hwmsen_attach(int sensor, structhwmsen_object *obj)
{
structdev_context *mcxt = &dev_cxt;
interr = 0;
HWM_FUN(f);
if((mcxt== NULL) || (sensor > MAX_ANDROID_SENSOR_NUM))
{
err= -EINVAL;
gotoerr_exit;
}
mutex_lock(&mcxt->lock);
if(mcxt->cxt[sensor]!= NULL)
{
err= -EEXIST;
gotoerr_exit;
}
else
{
mcxt->cxt[sensor]= kzalloc(sizeof(struct hwmsen_context), GFP_KERNEL);
if(mcxt->cxt[sensor]== NULL)
{
err= -EPERM;
gotoerr_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 200ms
atomic_set(&mcxt->cxt[sensor]->delay, 200);
}
err_exit:
mutex_unlock(&mcxt->lock);
returnerr;
}
int hwmsen_detach(int sensor)
{
interr = 0;
structdev_context *mcxt = &dev_cxt;
HWM_FUN(f);
if((sensor > MAX_ANDROID_SENSOR_NUM) || (mcxt->cxt[sensor] == NULL))
{
err= -EINVAL;
gotoerr_exit;
}
mutex_lock(&mcxt->lock);
kfree(mcxt->cxt[sensor]);
mcxt->cxt[sensor]= NULL;
err_exit:
mutex_unlock(&mcxt->lock);
return0;
}
//中断模式,获取sensors data接口
int hwmsen_get_interrupt_data(int sensor,hwm_sensor_data *data)
{
//HWM_LOG("++++++++++++++++++++++++++++hwmsen_get_interrupt_datafunction sensor = %d\n",sensor);
structdev_context *mcxt = &dev_cxt;
structhwmdev_object *obj = hwm_obj;
int64_t nt;
structtimespec 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 data
if(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 data
if((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);
}
return0;
}
}
</article>
转自:https://blog.csdn.net/u013531497/article/details/38612681