static ssize_t batch_store_batch(struct device* dev, struct device_attribute *attr, const char *buf, size_t count) { int handle, flags, samplingPeriodNs, maxBatchReportLatencyNs; int res, delay; struct batch_context *cxt = NULL; cxt = batch_context_obj; BATCH_LOG("write value: buf = %s\n", buf); if((res = sscanf(buf, "%d,%d,%d,%d", &handle, &flags, &samplingPeriodNs, &maxBatchReportLatencyNs))!=4) { BATCH_ERR(" batch_store_delay param error: res = %d\n", res); } BATCH_LOG(" batch_store_delay param: handle %d, flag:%d samplingPeriodNs:%d, maxBatchReportLatencyNs: %d\n",handle, flags, samplingPeriodNs, maxBatchReportLatencyNs); if(flags & SENSORS_BATCH_DRY_RUN ) { if(cxt->dev_list.data_dev[handle].is_batch_supported != 0) { cxt->batch_result = 0; }else{ cxt->batch_result = -1; } }else if(flags & SENSORS_BATCH_WAKE_UPON_FIFO_FULL){ register_eint_unmask(); } if(maxBatchReportLatencyNs == 0){ cxt->active_sensor = cxt->active_sensor & (~(0x01 << handle));//every active_sensor bit stands for a sensor type, bit = 0 stands for batch disabled if(cxt->active_sensor == 0){ cxt->is_polling_run = false; del_timer_sync(&cxt->timer); cancel_work_sync(&cxt->report); }else{ cxt->dev_list.data_dev[handle].delay = 0; delay = batch_update_polling_rate(); atomic_set(&cxt->delay, delay); mod_timer(&cxt->timer, jiffies + atomic_read(&cxt->delay)/(1000/HZ)); cxt->is_polling_run = true; } }else if(maxBatchReportLatencyNs != 0){ cxt->active_sensor = cxt->active_sensor |(0x01 << handle); cxt->dev_list.data_dev[handle].delay = (int)maxBatchReportLatencyNs/1000/1000; delay = batch_update_polling_rate(); atomic_set(&cxt->delay, delay); mod_timer(&cxt->timer, jiffies + atomic_read(&cxt->delay)/(1000/HZ)); cxt->is_polling_run = true; } BATCH_ERR(" active_sensor param 0x%x\n", cxt->active_sensor); cxt->batch_result = 0; return count; }
static ssize_t batch_show_delay(struct device* dev, struct device_attribute *attr, char *buf) { int len = 0; BATCH_LOG(" batch_show_delay not support now\n"); return len; }
static ssize_t batch_show_batch(struct device* dev, struct device_attribute *attr, char *buf) { struct batch_context *cxt = NULL; int res = 0; cxt = batch_context_obj; res = cxt->batch_result; BATCH_LOG(" batch_show_delay batch result: %d\n", res); return snprintf(buf, PAGE_SIZE, "%d\n", res); }
/*----------------------------------------------------------------------------*/ static ssize_t batch_show_active(struct device* dev, struct device_attribute *attr, char *buf) { int len = 0; struct batch_context *cxt = NULL; cxt = batch_context_obj; //display now enabling sensors of batch mode BATCH_LOG("batch vender_div value: %d\n", len); return snprintf(buf, PAGE_SIZE, "%d\n", len); }
static void report_data_once(int handle) { struct batch_context *obj = batch_context_obj; //hwm_sensor_data *sensor_data = NULL; hwm_sensor_data *sensor_data = NULL; int err; if((obj->dev_list.ctl_dev[MAX_ANDROID_SENSOR_NUM].flush != NULL) && (obj->dev_list.data_dev[MAX_ANDROID_SENSOR_NUM].get_data != NULL)) { if((obj->active_sensor & (0x01<< handle))) { do{//need mutex against store active and report data once err = obj->dev_list.data_dev[MAX_ANDROID_SENSOR_NUM].get_data(handle, sensor_data); if(err == 0) report_batch_data(obj->idev, sensor_data); }while(err == 0); report_batch_finish(obj->idev, handle); obj->flush_result = obj->dev_list.ctl_dev[MAX_ANDROID_SENSOR_NUM].flush(handle); return; }else{ BATCH_LOG("batch mode is not enabled for this sensor!\n"); obj->flush_result= -1; return; } } if((obj->active_sensor & (0x01<< handle))){ if((obj->dev_list.ctl_dev[handle].flush != NULL) && (obj->dev_list.data_dev[handle].get_data != NULL)) { do{ err = obj->dev_list.data_dev[handle].get_data(handle, sensor_data); if(err == 0) report_batch_data(obj->idev, sensor_data); }while(err == 0); report_batch_finish(obj->idev, handle); obj->flush_result = obj->dev_list.ctl_dev[handle].flush(handle); return; }else{ BATCH_LOG("batch mode is not enabled for this sensor!\n"); obj->flush_result = -1; return; } } obj->flush_result = 0; }
static struct batch_context *batch_context_alloc_object(void) { struct batch_context *obj = kzalloc(sizeof(*obj), GFP_KERNEL); BATCH_LOG("batch_context_alloc_object++++\n"); if(!obj) { BATCH_ERR("Alloc batch object error!\n"); return NULL; } atomic_set(&obj->delay, 200); /*5Hz*/// set work queue delay time 200ms atomic_set(&obj->wake, 0); INIT_WORK(&obj->report, batch_work_func); init_timer(&obj->timer); obj->timer.expires = jiffies + atomic_read(&obj->delay)/(1000/HZ); obj->timer.function = batch_poll; obj->timer.data = (unsigned long)obj; obj->is_first_data_after_enable = false; obj->is_polling_run = false; obj->active_sensor = 0; mutex_init(&obj->batch_op_mutex); BATCH_LOG("batch_context_alloc_object----\n"); return obj; }
static void batch_work_func(struct work_struct *work) { struct batch_context *obj = batch_context_obj; hwm_sensor_data *sensor_data = NULL; int idx, err; if((obj->dev_list.ctl_dev[MAX_ANDROID_SENSOR_NUM].flush != NULL) && (obj->dev_list.data_dev[MAX_ANDROID_SENSOR_NUM].get_data != NULL)) { for(idx = 0; idx < MAX_ANDROID_SENSOR_NUM; idx++) { if((obj->active_sensor & (0x01<< idx))){ do{ err = obj->dev_list.data_dev[MAX_ANDROID_SENSOR_NUM].get_data(idx, sensor_data); if(err == 0) report_batch_data(obj->idev, sensor_data); }while(err == 0);//0:read one data success, not 0 data finsih } } } for(idx = 0; idx < MAX_ANDROID_SENSOR_NUM; idx++) { BATCH_LOG("get data from sensor (%d) !\n", idx); if((obj->dev_list.ctl_dev[idx].flush == NULL) || (obj->dev_list.data_dev[idx].get_data == NULL)) { continue; } if((obj->active_sensor & (0x01<< idx))) { do{ err = obj->dev_list.data_dev[idx].get_data(idx, sensor_data); //sensor_data.value_divide = obj->dev_list.data_dev[sensor_data.sensor-1].div; if(err == 0) report_batch_data(obj->idev, sensor_data); } while(err == 0); } } if(obj->is_polling_run){ mod_timer(&obj->timer, jiffies + atomic_read(&obj->delay)/(1000/HZ)); } }
static int batch_update_polling_rate(void) { struct batch_context *obj = batch_context_obj; int idx, mindelay; mindelay = obj->dev_list.data_dev[0].delay; for(idx = 0; idx < MAX_ANDROID_SENSOR_NUM; idx++)//choose first MAX_ANDROID_SENSOR_NUM sensors for different sensor type { if((obj->dev_list.data_dev[idx].delay < mindelay) && (obj->dev_list.data_dev[idx].delay!=0)) { mindelay = obj->dev_list.data_dev[idx].delay; } } BATCH_LOG("get polling rate min value (%d) !\n", mindelay); return mindelay; }
static ssize_t batch_store_flush(struct device* dev, struct device_attribute *attr, const char *buf, size_t count) { struct batch_context *cxt = NULL; int handle; cxt = batch_context_obj; if (1 != sscanf(buf, "%d", &handle)) { BATCH_ERR("invalid format!!\n"); return count; } report_data_once(handle);//handle need to use of this function BATCH_LOG(" batch_store_delay sucess\n"); return count; }
/*----------------------------------------------------------------------------*/ static void batch_late_resume(struct early_suspend *h) { atomic_set(&(batch_context_obj->early_suspend), 0); BATCH_LOG(" batch_late_resume ok------->hwm_obj->early_suspend=%d \n",atomic_read(&(batch_context_obj->early_suspend))); return ; }
static int batch_probe(struct platform_device *pdev) { int err; BATCH_LOG("+++++++++++++batch_probe!!\n"); batch_context_obj = batch_context_alloc_object(); if (!batch_context_obj) { err = -ENOMEM; BATCH_ERR("unable to allocate devobj!\n"); goto exit_alloc_data_failed; } //init input dev err = batch_input_init(batch_context_obj); if(err) { BATCH_ERR("unable to register batch input device!\n"); goto exit_alloc_input_dev_failed; } atomic_set(&(batch_context_obj->early_suspend), 0); batch_context_obj->early_drv.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING - 1, batch_context_obj->early_drv.suspend = batch_early_suspend, batch_context_obj->early_drv.resume = batch_late_resume, register_early_suspend(&batch_context_obj->early_drv); wake_lock_init(&(batch_context_obj->read_data_wake_lock),WAKE_LOCK_SUSPEND,"read_data_wake_lock"); //add misc dev for sensor hal control cmd err = batch_misc_init(batch_context_obj); if(err) { BATCH_ERR("unable to register batch misc device!!\n"); goto exit_err_sysfs; } err = sysfs_create_group(&batch_context_obj->mdev.this_device->kobj, &batch_attribute_group); if (err < 0) { BATCH_ERR("unable to create batch attribute file\n"); goto exit_misc_register_failed; } kobject_uevent(&batch_context_obj->mdev.this_device->kobj, KOBJ_ADD); BATCH_LOG("----batch_probe OK !!\n"); return 0; //exit_hwmsen_create_attr_failed: exit_misc_register_failed: if((err = misc_deregister(&batch_context_obj->mdev))) { BATCH_ERR("misc_deregister fail: %d\n", err); } exit_err_sysfs: if (err) { BATCH_ERR("sysfs node creation error \n"); batch_input_destroy(batch_context_obj); } exit_alloc_input_dev_failed: kfree(batch_context_obj); exit_alloc_data_failed: BATCH_LOG("----batch_probe fail !!!\n"); return err; }
static ssize_t batch_store_delay(struct device* dev, struct device_attribute *attr, const char *buf, size_t count) { BATCH_LOG(" batch_store_delay not support now\n"); return count; }