示例#1
0
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));
    }
}
示例#2
0
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");
        }
    }
}
示例#3
0
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;
}
示例#4
0
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;
}
示例#5
0
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;
}
示例#6
0
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));
}