static void Po188_resume(struct early_suspend *h) { int ret = 0; if( po188_driver.status_on ) { ret = regulator_enable(gPo188Regulator); if (ret < 0) { PO188_ERRMSG("enable po188 vcc drive error"); return; } ret = k3_adc_open_channel(PO188_ADC_CHANNEL); if (ret < 0) { PO188_ERRMSG("k3_adc_open_channel error\n"); regulator_disable(gPo188Regulator); return; } mod_timer(&po188_driver.timer, jiffies + msecs_to_jiffies(po188_driver.delay_time)); } }
static void Po188_suspend(struct early_suspend *h) { int ret = 0; if( po188_driver.status_on ) { cancel_work_sync(&po188_cb_work); flush_workqueue(po188_driver.po188_wq); del_timer(&po188_driver.timer); ret = k3_adc_close_channal(PO188_ADC_CHANNEL); if (ret < 0) { PO188_ERRMSG("k3_adc_close_channal error\n"); } ret = regulator_disable(gPo188Regulator); if (ret < 0) { PO188_ERRMSG("disable po188 vcc drive error"); } } }
static int __init po188_init(void) { int err; int ret; struct kobject *kobj = NULL; po188_driver.dev.name = PO188_DEV_NAME; po188_driver.dev.minor = MISC_DYNAMIC_MINOR; po188_driver.fops.open = po188_open; po188_driver.fops.release = po188_release; /* Begin: leyihua modified for Linux Kernel 3.0, begin 2011/11/26 */ po188_driver.fops.unlocked_ioctl = po188_ioctl; /* End: leyihua modified for Linux Kernel 3.0, end 2011/11/26 */ po188_driver.dev.fops = &po188_driver.fops; po188_driver.last_voltage = 0; po188_driver.current_voltage = 0; po188_driver.vol_flag = false; if ((err = misc_register(&po188_driver.dev))) { PO188_ERRMSG("misc_register() failed"); goto EXIT_ERROR; } /* Begin: leyihua modified for Linux Kernel 3.0, begin 2011/11/26 */ sema_init(&(po188_driver.run_sem), 1); /* End: leyihua modified for Linux Kernel 3.0, begin 2011/11/26 */ po188_driver.po188_wq = create_singlethread_workqueue("po188_wq"); if (!po188_driver.po188_wq) { printk(KERN_ERR "***********************%s: create workque failed \n", __func__); return -ENOMEM; } init_timer(&po188_driver.timer); po188_driver.timer.expires = jiffies + SENSOR_POLLING_JIFFIES; po188_driver.timer.data = 0; po188_driver.timer.function = po188_start_cb_thread; add_timer(&po188_driver.timer); /* G-sensor & Light share input dev. suchangyu. 20100513. begin. */ if (sensor_dev == NULL) { po188_driver.input_dev = input_allocate_device(); if (po188_driver.input_dev == NULL) { printk(KERN_ERR "po188_init : Failed to allocate input device\n"); return -1; } /* Modified by suchangyu. 20100513. begin. */ po188_driver.input_dev->name = "sensors"; // "light_sensor" /* Modified by suchangyu. 20100513. end. */ input_set_drvdata(po188_driver.input_dev, &po188_driver); ret = input_register_device(po188_driver.input_dev); if (ret) { printk(KERN_ERR "[%s]Unable to register %s input device\n", __func__,po188_driver.input_dev->name); return -1; } sensor_dev = po188_driver.input_dev; } else { po188_driver.input_dev = sensor_dev; } /* G-sensor & Light share input dev. suchangyu. 20100513. end. */ /* Modified by suchangyu. 20100513. begin. */ set_bit(EV_ABS,po188_driver.input_dev->evbit); set_bit(ABS_MISC, po188_driver.input_dev->absbit); set_bit(EV_SYN,po188_driver.input_dev->evbit); po188_driver.early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; po188_driver.early_suspend.suspend = Po188_suspend; po188_driver.early_suspend.resume = Po188_resume; register_early_suspend(&po188_driver.early_suspend); kobj = kobject_create_and_add("po188", NULL); if (kobj == NULL) { return -1; } if (sysfs_create_group(kobj, &po188_defattr_group)) { kobject_put(kobj); return -1; } return 0; EXIT_ERROR: /* Modified by suchangyu. 20100514. begin */ kobject_put(kobj); sysfs_remove_group(kobj, &po188_defattr_group); /* Modified by suchangyu. 20100514. end */ return err; }
static int __init po188_init(void) { int err = -1; int ret = -1; struct kobject *kobj = NULL; struct regulator* ldo15_3v3; po188_driver.dev.name = PO188_DEV_NAME; po188_driver.dev.minor = MISC_DYNAMIC_MINOR; po188_driver.fops.unlocked_ioctl = po188_ioctl; po188_driver.dev.fops = &po188_driver.fops; po188_driver.last_voltage = 0; //set the initial delay value: 1s po188_driver.delay_time = SENSOR_POLLING_JIFFIES; // mutex_init(&po188_driver.lock); if ((err = misc_register(&po188_driver.dev))) { PO188_ERRMSG("misc_register failed"); goto misc_register_failed; } //regulater config ldo15_3v3 = regulator_get(po188_driver.dev.this_device, "light-vcc"); if (IS_ERR(ldo15_3v3)) { PO188_ERRMSG("cannot get po188 vcc drive"); goto regulator_get_failed; } gPo188Regulator = ldo15_3v3; ret = regulator_set_voltage(ldo15_3v3, PO188_VCC_VOLTAGE, PO188_VCC_VOLTAGE); if (ret < 0) { PO188_ERRMSG("set po188 vcc drive error"); goto regulator_set_voltage_failed; } /* ret = regulator_enable(ldo15_3v3); if (ret < 0) { PO188_ERRMSG("enable po188 vcc drive error"); goto regulator_enable_failed; }*/ po188_driver.po188_wq = create_singlethread_workqueue("po188_wq"); if (!po188_driver.po188_wq) { PO188_ERRMSG("create workque failed \n"); goto create_singlethread_workqueue_failed; } //set time, and time overrun function init_timer(&po188_driver.timer); po188_driver.timer.expires = jiffies + msecs_to_jiffies( po188_driver.delay_time); po188_driver.timer.data = 0; po188_driver.timer.function = po188_start_cb_thread; //add_timer(&po188_driver.timer); po188_driver.input_dev = input_allocate_device(); if (po188_driver.input_dev == NULL) { PO188_ERRMSG("po188_init : Failed to allocate input device\n"); goto input_allocate_device_failed; } po188_driver.input_dev->name = PO188_DEV_NAME; input_set_drvdata(po188_driver.input_dev, &po188_driver); ret = input_register_device(po188_driver.input_dev); if (ret) { PO188_ERRMSG("Unable to register %s input device\n", po188_driver.input_dev->name); goto input_register_device_failed; } err = set_sensor_input(PO188, po188_driver.input_dev->dev.kobj.name); if (err) { PO188_ERRMSG("set_sensor_input error\n"); goto set_sensor_input_failed; } set_bit(EV_ABS,po188_driver.input_dev->evbit); set_bit(EV_SYN,po188_driver.input_dev->evbit); input_set_abs_params(po188_driver.input_dev, ABS_MISC, 0, 10000, 0, 0); /*no need early_suspend, the system can call enable/disable when suspend and resume*/ /* po188_driver.early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; po188_driver.early_suspend.suspend = Po188_suspend; po188_driver.early_suspend.resume = Po188_resume; register_early_suspend(&po188_driver.early_suspend);*/ kobj = kobject_create_and_add(PO188_NAME, NULL); if (kobj == NULL) { goto kobject_create_and_add_failed; } if (sysfs_create_group(kobj, &po188_defattr_group)) { goto sysfs_create_group_failed; } spin_lock_init(&po188_driver.s_lock); po188_driver.status_on = false; //status_on must have init value /* //open adc channel ret = k3_adc_open_channel(PO188_ADC_CHANNEL); if (ret < 0) { PO188_ERRMSG("k3_adc_open_channel error\n"); goto k3_adc_open_channel_failed; }*/ return 0; //k3_adc_open_channel_failed: // sysfs_remove_group(&po188_driver.dev.parent->kobj, &po188_defattr_group); sysfs_create_group_failed: kobject_put(kobj); kobject_create_and_add_failed: set_sensor_input_failed: input_unregister_device(po188_driver.input_dev); input_register_device_failed: input_free_device(po188_driver.input_dev); input_allocate_device_failed: destroy_workqueue(po188_driver.po188_wq); create_singlethread_workqueue_failed: // regulator_disable(ldo15_3v3); //regulator_enable_failed: regulator_set_voltage_failed: regulator_put(ldo15_3v3); regulator_get_failed: misc_deregister(&po188_driver.dev); misc_register_failed: return err; }
static long po188_ioctl(struct file* file, unsigned int cmd, unsigned long param) { int ret = 0; int flags = 0; void __user *argp = (void __user *)param; int iDelayTime = 0; switch (cmd) { case LIGHTSENSOR_IOCTL_ENABLE: if (copy_from_user(&flags, argp, sizeof(flags))) { ret = -EFAULT; } else { if ( 0==flags ) { PO188_DMSG("active disable pol88\n"); spin_lock(&po188_driver.s_lock); po188_driver.status_on = false; spin_unlock(&po188_driver.s_lock); cancel_work_sync(&po188_cb_work); flush_workqueue(po188_driver.po188_wq); del_timer(&po188_driver.timer); ret = k3_adc_close_channal(PO188_ADC_CHANNEL); if (ret < 0) { PO188_ERRMSG("k3_adc_close_channal error\n"); } ret = regulator_disable(gPo188Regulator); if (ret < 0) { PO188_ERRMSG("disable po188 vcc drive error"); } } else if (1 == flags) { PO188_DMSG("active enable pol88\n"); ret = regulator_enable(gPo188Regulator); if (ret < 0) { PO188_ERRMSG("enable po188 vcc drive error"); return ret;//regulator_enable error, return. } ret = k3_adc_open_channel(PO188_ADC_CHANNEL); if (ret < 0) { PO188_ERRMSG("k3_adc_open_channel error\n"); regulator_disable(gPo188Regulator); return ret; } mod_timer(&po188_driver.timer, jiffies + msecs_to_jiffies(po188_driver.delay_time)); spin_lock(&po188_driver.s_lock); po188_driver.status_on = true; spin_unlock(&po188_driver.s_lock); } } break; case LIGHTSENSOR_IOCTL_GET_ENABLED: spin_lock(&po188_driver.s_lock); flags = po188_driver.status_on; spin_unlock(&po188_driver.s_lock); if (copy_to_user(argp, &flags, sizeof(flags))) { ret = -EFAULT; } break; case LIGHTSENSOR_IOCTL_GET_DELAY: spin_lock(&po188_driver.s_lock); iDelayTime = po188_driver.delay_time; spin_unlock(&po188_driver.s_lock); if (copy_to_user(argp, &iDelayTime, sizeof(iDelayTime))) { ret = -EFAULT; } break; case LIGHTSENSOR_IOCTL_SET_DELAY: if (copy_from_user(&iDelayTime, argp, sizeof(iDelayTime))) { ret = -EFAULT; } else { spin_lock(&po188_driver.s_lock); po188_driver.delay_time = iDelayTime; spin_unlock(&po188_driver.s_lock); } break; default: PO188_ERRMSG("CMD INVALID.\n"); ret = -EINVAL; break; } return ret; }
static void po188_work_func(struct work_struct *work) { /*static int voltage[TIMES];//remember the last 3 value static int iVolIndex=0; static int iSumCount=0; int i = 0; int iSum = 0; int iAveVol = 0;*/ int iVoltage_new = 0; int iVoltage_last = 0; int ret = 0; ret = po188_read_adc(PO188_ADC_CHANNEL); if (ret < 0) //read value failed. invalid value, don't report. { PO188_ERRMSG("po188 have not read adc value"); msleep(5000); //sleep 5s //delay 1s to read. mod_timer(&po188_driver.timer, jiffies + msecs_to_jiffies(po188_driver.delay_time)); return; } //iVoltage_new = po188_get_converted_level(ret); iVoltage_new = ret; /* voltage[iVolIndex]=po188_driver.voltage_now; iVolIndex = (iVolIndex+1)%TIMES; if (iSumCount<TIMES) { iSumCount++; } for(i=0; i<iSumCount; i++)// count the current average value { iSum += voltage[i]; } //remember the last 3 average voltage value iAveVol = iSum / iSumCount; */ spin_lock(&po188_driver.s_lock); po188_driver.voltage_now = iVoltage_new; iVoltage_last = po188_driver.last_voltage; spin_unlock(&po188_driver.s_lock); //check if it's reach the threshold data and report to hal level /* if ( (po188_driver.last_voltage - iAveVol >= PO188_REPORT_THRESHOLD) || (iAveVol - po188_driver.last_voltage >= PO188_REPORT_THRESHOLD) ) { po188_report_data(); } */ // if ( (iVoltage_last - iVoltage_new >= PO188_REPORT_THRESHOLD) || // (iVoltage_new - iVoltage_last >= PO188_REPORT_THRESHOLD) ) { po188_report_data(iVoltage_new); spin_lock(&po188_driver.s_lock); po188_driver.last_voltage = iVoltage_new; spin_unlock(&po188_driver.s_lock); } mod_timer(&po188_driver.timer, jiffies + msecs_to_jiffies(po188_driver.delay_time)); }