zoukankan      html  css  js  c++  java
  • 基于input子系统的sensor驱动调试(二)

    继上一篇:http://www.cnblogs.com/linhaostudy/p/8303628.html#_label1_1

    一、驱动流程解析:

    1、模块加载:

     1 static struct of_device_id stk_match_table[] = {
     2     { .compatible = "stk,stk3x1x", },
     3     { },
     4 };
     5 
     6 static struct i2c_driver stk_ps_driver =
     7 {
     8     .driver = {
     9         .name = DEVICE_NAME,
    10         .owner = THIS_MODULE,
    11         .of_match_table = stk_match_table,
    12     },
    13     .probe = stk3x1x_probe,
    14     .remove = stk3x1x_remove,
    15     .id_table = stk_ps_id,
    16 };
    17 
    18 
    19 static int __init stk3x1x_init(void)
    20 {
    21     int ret;
    22     ret = i2c_add_driver(&stk_ps_driver);
    23     if (ret)
    24         return ret;
    25 
    26     return 0;
    27 }
    28 
    29 static void __exit stk3x1x_exit(void)
    30 {
    31     i2c_del_driver(&stk_ps_driver);
    32 }

    of_device_id与DTS中的匹配,这与内核2.6以前的i2c_board_info不一样;

    内核加载驱动模块的时候将调用到stk3x1x_init()方法:

    初始化了i2c_driver结构体给stk_ps_driver变量,将用于将设备注册到IIC。关键在于结构体中的probe()方法,注册完成的时候将调用;

    2、stk3x1x驱动初始化-probe函数:

      1 static int stk3x1x_probe(struct i2c_client *client,
      2                         const struct i2c_device_id *id)
      3 {
      4     int err = -ENODEV;
      5     struct stk3x1x_data *ps_data;
      6     struct stk3x1x_platform_data *plat_data;
      7     printk(KERN_INFO "%s: driver version = %s
    ", __func__, DRIVER_VERSION);
      8 
      9     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
     10     {
     11         printk(KERN_ERR "%s: No Support for I2C_FUNC_SMBUS_BYTE_DATA
    ", __func__);
     12         return -ENODEV;
     13     }
     14     if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
     15     {
     16         printk(KERN_ERR "%s: No Support for I2C_FUNC_SMBUS_WORD_DATA
    ", __func__);
     17         return -ENODEV;
     18     }
     19 
     20     ps_data = kzalloc(sizeof(struct stk3x1x_data),GFP_KERNEL);
     21     if(!ps_data)
     22     {
     23         printk(KERN_ERR "%s: failed to allocate stk3x1x_data
    ", __func__);
     24         return -ENOMEM;
     25     }
     26     ps_data->client = client;
     27     i2c_set_clientdata(client,ps_data);
     28     mutex_init(&ps_data->io_lock);
     29     wake_lock_init(&ps_data->ps_wakelock,WAKE_LOCK_SUSPEND, "stk_input_wakelock");
     30 
     31 #ifdef STK_POLL_PS
     32     wake_lock_init(&ps_data->ps_nosuspend_wl,WAKE_LOCK_SUSPEND, "stk_nosuspend_wakelock");
     33 #endif
     34     if (client->dev.of_node) {
     35         plat_data = devm_kzalloc(&client->dev,
     36             sizeof(struct stk3x1x_platform_data), GFP_KERNEL);
     37         if (!plat_data) {
     38             dev_err(&client->dev, "Failed to allocate memory
    ");
     39             return -ENOMEM;
     40         }
     41 
     42         err = stk3x1x_parse_dt(&client->dev, plat_data);
     43         dev_err(&client->dev,
     44             "%s: stk3x1x_parse_dt ret=%d
    ", __func__, err);
     45         if (err)
     46             return err;
     47     } else
     48         plat_data = client->dev.platform_data;
     49 
     50     if (!plat_data) {
     51         dev_err(&client->dev,
     52             "%s: no stk3x1x platform data!
    ", __func__);
     53         goto err_als_input_allocate;
     54     }
     55     ps_data->als_transmittance = plat_data->transmittance;
     56     ps_data->int_pin = plat_data->int_pin;
     57     ps_data->use_fir = plat_data->use_fir;
     58     ps_data->pdata = plat_data;
     59 
     60     if (ps_data->als_transmittance == 0) {
     61         dev_err(&client->dev,
     62             "%s: Please set als_transmittance
    ", __func__);
     63         goto err_als_input_allocate;
     64     }
     65 
     66     ps_data->als_input_dev = devm_input_allocate_device(&client->dev);
     67     if (ps_data->als_input_dev==NULL)
     68     {
     69         printk(KERN_ERR "%s: could not allocate als device
    ", __func__);
     70         err = -ENOMEM;
     71         goto err_als_input_allocate;
     72     }
     73     ps_data->ps_input_dev = devm_input_allocate_device(&client->dev);
     74     if (ps_data->ps_input_dev==NULL)
     75     {
     76         printk(KERN_ERR "%s: could not allocate ps device
    ", __func__);
     77         err = -ENOMEM;
     78         goto err_als_input_allocate;
     79     }
     80     ps_data->als_input_dev->name = ALS_NAME;
     81     ps_data->ps_input_dev->name = PS_NAME;
     82     set_bit(EV_ABS, ps_data->als_input_dev->evbit);
     83     set_bit(EV_ABS, ps_data->ps_input_dev->evbit);
     84     input_set_abs_params(ps_data->als_input_dev, ABS_MISC, 0, stk_alscode2lux(ps_data, (1<<16)-1), 0, 0);
     85     input_set_abs_params(ps_data->ps_input_dev, ABS_DISTANCE, 0,1, 0, 0);
     86     err = input_register_device(ps_data->als_input_dev);
     87     if (err<0)
     88     {
     89         printk(KERN_ERR "%s: can not register als input device
    ", __func__);
     90         goto err_als_input_allocate;
     91     }
     92     err = input_register_device(ps_data->ps_input_dev);
     93     if (err<0)
     94     {
     95         printk(KERN_ERR "%s: can not register ps input device
    ", __func__);
     96         goto err_als_input_allocate;
     97     }
     98 
     99     err = sysfs_create_group(&ps_data->als_input_dev->dev.kobj, &stk_als_attribute_group);
    100     if (err < 0)
    101     {
    102         printk(KERN_ERR "%s:could not create sysfs group for als
    ", __func__);
    103         goto err_als_input_allocate;
    104     }
    105     err = sysfs_create_group(&ps_data->ps_input_dev->dev.kobj, &stk_ps_attribute_group);
    106     if (err < 0)
    107     {
    108         printk(KERN_ERR "%s:could not create sysfs group for ps
    ", __func__);
    109         goto err_ps_sysfs_create_group;
    110     }
    111     input_set_drvdata(ps_data->als_input_dev, ps_data);
    112     input_set_drvdata(ps_data->ps_input_dev, ps_data);
    113 
    114 #ifdef STK_POLL_ALS
    115     ps_data->stk_als_wq = create_singlethread_workqueue("stk_als_wq");
    116     INIT_WORK(&ps_data->stk_als_work, stk_als_work_func);
    117     hrtimer_init(&ps_data->als_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    118     ps_data->als_poll_delay = ns_to_ktime(110 * NSEC_PER_MSEC);
    119     ps_data->als_timer.function = stk_als_timer_func;
    120 #endif
    121 
    122     ps_data->stk_ps_wq = create_singlethread_workqueue("stk_ps_wq");
    123     INIT_WORK(&ps_data->stk_ps_work, stk_ps_work_func);
    124     hrtimer_init(&ps_data->ps_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
    125     ps_data->ps_poll_delay = ns_to_ktime(110 * NSEC_PER_MSEC);
    126     ps_data->ps_timer.function = stk_ps_timer_func;
    127 #if (!defined(STK_POLL_ALS) || !defined(STK_POLL_PS))
    128     ps_data->stk_wq = create_singlethread_workqueue("stk_wq");
    129     INIT_WORK(&ps_data->stk_work, stk_work_func);
    130     err = stk3x1x_setup_irq(client);
    131     if(err < 0)
    132         goto err_stk3x1x_setup_irq;
    133 #endif
    134 
    135     err = stk3x1x_power_init(ps_data, true);
    136     if (err)
    137         goto err_power_init;
    138 
    139     err = stk3x1x_power_ctl(ps_data, true);
    140     if (err)
    141         goto err_power_on;
    142 
    143     ps_data->als_enabled = false;
    144     ps_data->ps_enabled = false;
    145 #ifdef CONFIG_HAS_EARLYSUSPEND
    146     ps_data->stk_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
    147     ps_data->stk_early_suspend.suspend = stk3x1x_early_suspend;
    148     ps_data->stk_early_suspend.resume = stk3x1x_late_resume;
    149     register_early_suspend(&ps_data->stk_early_suspend);
    150 #endif
    151     /* make sure everything is ok before registering the class device */
    152     ps_data->als_cdev = sensors_light_cdev;
    153     ps_data->als_cdev.sensors_enable = stk_als_enable_set;
    154     ps_data->als_cdev.sensors_poll_delay = stk_als_poll_delay_set;
    155     err = sensors_classdev_register(&client->dev, &ps_data->als_cdev);
    156     if (err)
    157         goto err_power_on;
    158 
    159     ps_data->ps_cdev = sensors_proximity_cdev;
    160     ps_data->ps_cdev.sensors_enable = stk_ps_enable_set;
    161     err = sensors_classdev_register(&client->dev, &ps_data->ps_cdev);
    162     if (err)
    163         goto err_class_sysfs;
    164 
    165     /* enable device power only when it is enabled */
    166     err = stk3x1x_power_ctl(ps_data, false);
    167     if (err)
    168         goto err_init_all_setting;
    169 
    170     dev_dbg(&client->dev, "%s: probe successfully", __func__);
    171 
    172     return 0;
    173 
    174 err_init_all_setting:
    175     stk3x1x_power_ctl(ps_data, false);
    176     sensors_classdev_unregister(&ps_data->ps_cdev);
    177 err_class_sysfs:
    178     sensors_classdev_unregister(&ps_data->als_cdev);
    179 err_power_on:
    180     stk3x1x_power_init(ps_data, false);
    181 err_power_init:
    182 #ifndef STK_POLL_PS
    183     free_irq(ps_data->irq, ps_data);
    184     gpio_free(plat_data->int_pin);
    185 #endif
    186 #if (!defined(STK_POLL_ALS) || !defined(STK_POLL_PS))
    187 err_stk3x1x_setup_irq:
    188 #endif
    189 #ifdef STK_POLL_ALS
    190     hrtimer_try_to_cancel(&ps_data->als_timer);
    191     destroy_workqueue(ps_data->stk_als_wq);
    192 #endif
    193     destroy_workqueue(ps_data->stk_ps_wq);
    194 #if (!defined(STK_POLL_ALS) || !defined(STK_POLL_PS))
    195     destroy_workqueue(ps_data->stk_wq);
    196 #endif
    197     sysfs_remove_group(&ps_data->ps_input_dev->dev.kobj, &stk_ps_attribute_group);
    198 err_ps_sysfs_create_group:
    199     sysfs_remove_group(&ps_data->als_input_dev->dev.kobj, &stk_als_attribute_group);
    200 err_als_input_allocate:
    201 #ifdef STK_POLL_PS
    202     wake_lock_destroy(&ps_data->ps_nosuspend_wl);
    203 #endif
    204     wake_lock_destroy(&ps_data->ps_wakelock);
    205     mutex_destroy(&ps_data->io_lock);
    206     kfree(ps_data);
    207     return err;
    208 }
    View Code

     在stk3x1x_probe函数中主要做了:

    1、为驱动私有数据结构体stk3x1x_data分配内存空间;

    2、 将设备驱动的私有数据(stk3x1x_data)连接到设备client(i2c_client)中;(bma255会增加一步:读取i2c的id);

    3、将stk3x1x驱动注册到linux input子系统;

    4、创建工作队列(主要是对sensor的数据采集);

    5、创建sysfs接口;

    2.1 创建input子系统:

    http://blog.csdn.net/ielife/article/details/7798952

    1、 在驱动加载模块中,设置你的input设备支持的事件类型;

    2、 注册中断处理函数,例如键盘设备需要编写按键的抬起、放下,触摸屏设备需要编写按下、抬起、绝对移动,鼠标设备需要编写单击、抬起、相对移动,并且需要在必要的时候提交硬件数据(键值/坐标/状态等等);

    3、将输入设备注册到输入子系统中;

     1   ps_data->als_input_dev = devm_input_allocate_device(&client->dev);    //分配内存空间
     2     if (ps_data->als_input_dev==NULL)
     3     {
     4         printk(KERN_ERR "%s: could not allocate als device
    ", __func__);
     5         err = -ENOMEM;
     6         goto err_als_input_allocate;
     7     }
     8     ps_data->ps_input_dev = devm_input_allocate_device(&client->dev);
     9     if (ps_data->ps_input_dev==NULL)
    10     {
    11         printk(KERN_ERR "%s: could not allocate ps device
    ", __func__);
    12         err = -ENOMEM;
    13         goto err_als_input_allocate;
    14     }
    15     ps_data->als_input_dev->name = ALS_NAME;     
    16     ps_data->ps_input_dev->name = PS_NAME;
    17     set_bit(EV_ABS, ps_data->als_input_dev->evbit);
    18     set_bit(EV_ABS, ps_data->ps_input_dev->evbit);
    19     input_set_abs_params(ps_data->als_input_dev, ABS_MISC, 0, stk_alscode2lux(ps_data, (1<<16)-1), 0, 0);    //设置input加载类型;
    20     input_set_abs_params(ps_data->ps_input_dev, ABS_DISTANCE, 0,1, 0, 0);
    21     err = input_register_device(ps_data->als_input_dev);
    22     if (err<0)
    23     {
    24         printk(KERN_ERR "%s: can not register als input device
    ", __func__);
    25         goto err_als_input_allocate;
    26     }
    27     err = input_register_device(ps_data->ps_input_dev);
    28     if (err<0)
    29     {
    30         printk(KERN_ERR "%s: can not register ps input device
    ", __func__);
    31         goto err_als_input_allocate;
    32     }
    1     err = stk3x1x_setup_irq(client);        //设置驱动中断函数
    2     if(err < 0)
    3         goto err_stk3x1x_setup_irq;

    2.2 创建工作队列:

    先提一个问题,为什么要创建工作队列?在前面的介绍中我们知道,sensor传感器获取数据后,将数据传给controller的寄存器中,供主控去查询读取数据。所以这里创建的工作队列,就是在一个工作者线程,通过IIC不断的去查询读取controller上的数据。

    工作队列的作用就是把工作推后,交由一个内核线程去执行,更直接的说就是如果写了一个函数,而现在不想马上执行它,想在将来某个时刻去执行它,那用工作队列准没错.大概会想到中断也是这样,提供一个中断服务函数,在发生中断的时候去执行,没错,和中断相比,工作队列最大的好处就是可以调度可以睡眠,灵活性更好。

    上面代码中我们看到INIT_WORK(&ps_data->stk_ps_work, stk_ps_work_func);,其实是一个宏的定义,在include/linux/workqueue.h中。stk_ps_work_func()就是我们定义的功能函数,用于查询读取Sensor的距离传感器数据的,并上报Input子系统,代码如下:

     1 static void stk_ps_work_func(struct work_struct *work)
     2 {
     3     struct stk3x1x_data *ps_data = container_of(work, struct stk3x1x_data, stk_ps_work);
     4     uint32_t reading;
     5     int32_t near_far_state;
     6     uint8_t org_flag_reg;
     7     int32_t ret;
     8     uint8_t disable_flag = 0;
     9     mutex_lock(&ps_data->io_lock);
    10 
    11     org_flag_reg = stk3x1x_get_flag(ps_data);
    12     if(org_flag_reg < 0)
    13     {
    14         printk(KERN_ERR "%s: get_status_reg fail, ret=%d", __func__, org_flag_reg);
    15         goto err_i2c_rw;
    16     }
    17     near_far_state = (org_flag_reg & STK_FLG_NF_MASK)?1:0;
    18     reading = stk3x1x_get_ps_reading(ps_data);
    19     if(ps_data->ps_distance_last != near_far_state)
    20     {
    21         ps_data->ps_distance_last = near_far_state;
    22         input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, near_far_state);    //input上报数据
    23         input_sync(ps_data->ps_input_dev);                    //input_sync()在这里不起关键作用。但如果是一个触摸屏,即有x坐标和y坐标,则需要通过input_sync()函数把x和y坐标完整地传递给输入子系统。
    24         wake_lock_timeout(&ps_data->ps_wakelock, 3*HZ);
    25 #ifdef STK_DEBUG_PRINTF
    26         printk(KERN_INFO "%s: ps input event %d cm, ps code = %d
    ",__func__, near_far_state, reading);
    27 #endif
    28     }
    29     ret = stk3x1x_set_flag(ps_data, org_flag_reg, disable_flag);
    30     if(ret < 0)
    31     {
    32         printk(KERN_ERR "%s:stk3x1x_set_flag fail, ret=%d
    ", __func__, ret);
    33         goto err_i2c_rw;
    34     }
    35 
    36     mutex_unlock(&ps_data->io_lock);
    37     return;
    38 
    39 err_i2c_rw:
    40     mutex_unlock(&ps_data->io_lock);
    41     msleep(30);
    42     return;
    43 }

     2.3 创建sysfs接口:

    为什么要创建sysfs接口?在驱动层创建了sysfs接口,HAL层通过这些sysfs接口,对Sensor进行操作,如使能、设置delay等。

    DEVICE_ATTR的使用:http://blog.csdn.net/njuitjf/article/details/16849333

     

    函数宏DEVICE_ATTR内封装的是__ATTR(_name,_mode,_show,_stroe)方法:

     _show:表示的是读方法,_stroe表示的是写方法。

    1、 调用宏DEVICE_ATTR完成对功能函数的注册:

     1 static struct device_attribute ps_enable_attribute = __ATTR(enable,0664,stk_ps_enable_show,stk_ps_enable_store);
     2 static struct device_attribute ps_enable_aso_attribute = __ATTR(enableaso,0664,stk_ps_enable_aso_show,stk_ps_enable_aso_store);
     3 static struct device_attribute ps_distance_attribute = __ATTR(distance,0664,stk_ps_distance_show, stk_ps_distance_store);
     4 static struct device_attribute ps_offset_attribute = __ATTR(offset,0664,stk_ps_offset_show, stk_ps_offset_store);
     5 static struct device_attribute ps_code_attribute = __ATTR(code, 0444, stk_ps_code_show, NULL);
     6 static struct device_attribute ps_code_thd_l_attribute = __ATTR(codethdl,0664,stk_ps_code_thd_l_show,stk_ps_code_thd_l_store);
     7 static struct device_attribute ps_code_thd_h_attribute = __ATTR(codethdh,0664,stk_ps_code_thd_h_show,stk_ps_code_thd_h_store);
     8 static struct device_attribute recv_attribute = __ATTR(recv,0664,stk_recv_show,stk_recv_store);
     9 static struct device_attribute send_attribute = __ATTR(send,0664,stk_send_show, stk_send_store);
    10 static struct device_attribute all_reg_attribute = __ATTR(allreg, 0444, stk_all_reg_show, NULL);
    11 
    12 static struct attribute *stk_ps_attrs [] =
    13 {
    14     &ps_enable_attribute.attr,
    15     &ps_enable_aso_attribute.attr,
    16     &ps_distance_attribute.attr,
    17     &ps_offset_attribute.attr,
    18     &ps_code_attribute.attr,
    19     &ps_code_thd_l_attribute.attr,
    20     &ps_code_thd_h_attribute.attr,
    21     &recv_attribute.attr,
    22     &send_attribute.attr,
    23     &all_reg_attribute.attr,
    24     NULL
    25 };
    26 
    27 static struct attribute_group stk_ps_attribute_group = {
    28     .attrs = stk_ps_attrs,
    29 };

    在probe函数中:

     1   err = sysfs_create_group(&ps_data->als_input_dev->dev.kobj, &stk_als_attribute_group);
     2     if (err < 0)
     3     {
     4         printk(KERN_ERR "%s:could not create sysfs group for als
    ", __func__);
     5         goto err_als_input_allocate;
     6     }
     7     err = sysfs_create_group(&ps_data->ps_input_dev->dev.kobj, &stk_ps_attribute_group);
     8     if (err < 0)
     9     {
    10         printk(KERN_ERR "%s:could not create sysfs group for ps
    ", __func__);
    11         goto err_ps_sysfs_create_group;
    12     }

    到此,完成了sysfs接口的创建,我们可以在根文件系统中看到/sys/class/input/input1/目录,在该目录下我们可以看到多个节点,其中就包含了enable和delay。我们以enable为例子,可以有两种方法完成对Gsensor的使能工作:

     

    3、读取上报数据:

    Android的HAL层,通过对/sys/class/input/input3/enable节点的写操作,使能sensor。调用到的方法是stk_ps_enable_store函数:

     1 static struct device_attribute ps_enable_attribute = __ATTR(enable,0664,stk_ps_enable_show,stk_ps_enable_store);
     2 static struct device_attribute ps_enable_aso_attribute = __ATTR(enableaso,0664,stk_ps_enable_aso_show,stk_ps_enable_aso_store);
     3 static struct device_attribute ps_distance_attribute = __ATTR(distance,0664,stk_ps_distance_show, stk_ps_distance_store);
     4 static struct device_attribute ps_offset_attribute = __ATTR(offset,0664,stk_ps_offset_show, stk_ps_offset_store);
     5 static struct device_attribute ps_code_attribute = __ATTR(code, 0444, stk_ps_code_show, NULL);
     6 static struct device_attribute ps_code_thd_l_attribute = __ATTR(codethdl,0664,stk_ps_code_thd_l_show,stk_ps_code_thd_l_store);
     7 static struct device_attribute ps_code_thd_h_attribute = __ATTR(codethdh,0664,stk_ps_code_thd_h_show,stk_ps_code_thd_h_store);
     8 static struct device_attribute recv_attribute = __ATTR(recv,0664,stk_recv_show,stk_recv_store);
     9 static struct device_attribute send_attribute = __ATTR(send,0664,stk_send_show, stk_send_store);
    10 static struct device_attribute all_reg_attribute = __ATTR(allreg, 0444, stk_all_reg_show, NULL);

     里面的show和store函数;

     1 static ssize_t stk_ps_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size)
     2 {
     3     struct stk3x1x_data *ps_data =  dev_get_drvdata(dev);
     4     uint8_t en;
     5     if (sysfs_streq(buf, "1"))
     6         en = 1;
     7     else if (sysfs_streq(buf, "0"))
     8         en = 0;
     9     else
    10     {
    11         printk(KERN_ERR "%s, invalid value %d
    ", __func__, *buf);
    12         return -EINVAL;
    13     }
    14     dev_dbg(dev, "%s: Enable PS : %d
    ", __func__, en);
    15     mutex_lock(&ps_data->io_lock);
    16     stk3x1x_enable_ps(ps_data, en);
    17     mutex_unlock(&ps_data->io_lock);
    18     return size;
    19 }
     1 static int32_t stk3x1x_enable_ps(struct stk3x1x_data *ps_data, uint8_t enable)
     2 {
     3     int32_t ret;
     4     uint8_t w_state_reg;
     5     uint8_t curr_ps_enable;
     6     curr_ps_enable = ps_data->ps_enabled?1:0;
     7     if(curr_ps_enable == enable)
     8         return 0;
     9 
    10     if (enable) {
    11         ret = stk3x1x_device_ctl(ps_data, enable);
    12         if (ret)
    13             return ret;
    14     }
    15 
    16     ret = i2c_smbus_read_byte_data(ps_data->client, STK_STATE_REG);
    17     if (ret < 0)
    18     {
    19             printk(KERN_ERR "%s: write i2c error, ret=%d
    ", __func__, ret);
    20         return ret;
    21     }
    22     w_state_reg = ret;
    23     w_state_reg &= ~(STK_STATE_EN_PS_MASK | STK_STATE_EN_WAIT_MASK | 0x60);
    24     if(enable)
    25     {
    26         w_state_reg |= STK_STATE_EN_PS_MASK;
    27         if(!(ps_data->als_enabled))
    28             w_state_reg |= STK_STATE_EN_WAIT_MASK;
    29     }
    30     ret = i2c_smbus_write_byte_data(ps_data->client, STK_STATE_REG, w_state_reg);
    31     if (ret < 0)
    32     {
    33         printk(KERN_ERR "%s: write i2c error, ret=%d
    ", __func__, ret);
    34         return ret;
    35     }
    36 
    37     if(enable)
    38     {
    39 #ifdef STK_POLL_PS
    40         hrtimer_start(&ps_data->ps_timer, ps_data->ps_poll_delay, HRTIMER_MODE_REL);    //定时一段时间后,开始开启工作队列
    41         ps_data->ps_distance_last = -1;
    42 #endif
    43         ps_data->ps_enabled = true;
    44 #ifndef STK_POLL_PS
    45 #ifndef STK_POLL_ALS
    46         if(!(ps_data->als_enabled))
    47 #endif    /* #ifndef STK_POLL_ALS    */
    48             enable_irq(ps_data->irq);
    49         msleep(1);
    50         ret = stk3x1x_get_flag(ps_data);
    51         if (ret < 0)
    52         {
    53             printk(KERN_ERR "%s: read i2c error, ret=%d
    ", __func__, ret);
    54             return ret;
    55         }
    56 
    57         near_far_state = ret & STK_FLG_NF_MASK;
    58         ps_data->ps_distance_last = near_far_state;
    59         input_report_abs(ps_data->ps_input_dev, ABS_DISTANCE, near_far_state);
    60         input_sync(ps_data->ps_input_dev);
    61         wake_lock_timeout(&ps_data->ps_wakelock, 3*HZ);
    62         reading = stk3x1x_get_ps_reading(ps_data);
    63         dev_dbg(&ps_data->client->dev,
    64             "%s: ps input event=%d, ps code = %d
    ",
    65             __func__, near_far_state, reading);
    66 #endif    /* #ifndef STK_POLL_PS */
    67     }
    68     else
    69     {
    70 #ifdef STK_POLL_PS
    71         hrtimer_cancel(&ps_data->ps_timer);
    72 #else
    73 #ifndef STK_POLL_ALS
    74         if(!(ps_data->als_enabled))
    75 #endif
    76             disable_irq(ps_data->irq);
    77 #endif
    78         ps_data->ps_enabled = false;
    79     }
    80     if (!enable) {
    81         ret = stk3x1x_device_ctl(ps_data, enable);
    82         if (ret)
    83             return ret;
    84     }
    85 
    86     return ret;
    87 }
    1 static enum hrtimer_restart stk_als_timer_func(struct hrtimer *timer)
    2 {
    3     struct stk3x1x_data *ps_data = container_of(timer, struct stk3x1x_data, als_timer);
    4     queue_work(ps_data->stk_als_wq, &ps_data->stk_als_work);        //开启工作队列
    5     hrtimer_forward_now(&ps_data->als_timer, ps_data->als_poll_delay);
    6     return HRTIMER_RESTART;
    7 }

    那么对于HAL层,将通过/dev/input/event1设备节点读取到sensor数据。到此,sensor驱动的工作流程完毕。应该很好理解吧!

  • 相关阅读:
    ISO/IEC 9899:2011 条款6.10.3——宏替换
    ISO/IEC 9899:2011 条款6.10.2——源文件包含
    关于Objective-C新增的__kindof关键字
    ISO/IEC 9899:2011 条款6.10.1——条件包含
    ISO/IEC 9899:2011 条款6.10——预处理指示符
    ISO/IEC 9899:2011 条款6.9.2——外部对象定义
    Objective-C中使用不定参数个数的方法调用
    php添加数据到xml文件的例子
    nginx rewrite重写与防盗链配置
    nginx url自动加斜杠的问题
  • 原文地址:https://www.cnblogs.com/linhaostudy/p/8304017.html
Copyright © 2011-2022 走看看