MID驱动之二G-sensor

         G-sensor驱动和TP驱动基本是一样的,因为他们都是通过i2c来传输命令和数据,另外都将数据解析后,上报到输入子系统中。整个驱动的流程和TP驱动是一样的,我还是讲整个驱动流程分析一下。

         驱动入口函数:late_initcall(BMA250_init);

进入BMA250_init()函数,开头非常明显定义了三个重要变量

struct i2c_board_info info;

struct i2c_adapter *adapter;

struct i2c_client *client;

紧接着就是info和adapter收集资源,注册i2c_clint,函数为client = i2c_new_device(adapter, &info);接下来是注册i2c_driver,函数为i2c_add_driver(&bma250_driver);根据匹配过程,probe函数被调用,进入到bma250_probe()函数。

         bma250_probe()函数开头定义了一个重要的指针,struct bma250_data *data;看到这个,我们会觉得和TP的驱动如此相似,有一点不一样的话,bma250_data结构体中有一个regulator指针,应该可以通过编程控制电源供应。有关regulator的详细资料,可以参考:

http://lhsblog01.blog.163.com/blog/static/1020045192010221104120218/

regulator =regulator_get(&client->dev, buf);

err = regulator_set_voltage(regulator,2800000, 2800000);

err = regulator_enable(regulator);

设置电源管理

         接着会检查adapter,分配structbma250_data的空间:

i2c_check_functionality(client->adapter, I2C_FUNC_I2C)

data = kzalloc(sizeof(struct bma250_data), GFP_KERNEL);

         然后读取芯片id同时检查i2c能否正常通信

                   tempvalue= i2c_smbus_read_byte_data(client, BMA250_CHIP_ID_REG);

         对structbma250_data结构体进行设置和初始化工作

                   i2c_set_clientdata(client,data);

                  data->bma250_client = client;

                  mutex_init(&data->value_mutex);

                  mutex_init(&data->mode_mutex);

                  mutex_init(&data->enable_mutex);

                  bma250_set_bandwidth(client,BMA250_BW_SET);

                  bma250_set_range(client,BMA250_RANGE_SET);

                   INIT_WORK(&data->irq_work,bma250_irq_work_func);

                  data->IRQ = client->irq;

         然后会去注册中断

                   err= request_irq(data->IRQ, bma250_irq_handler, IRQF_TRIGGER_RISING,

                            "bma250",data);

         接下来我们会发现一个很有趣的代码:

                   INIT_DELAYED_WORK(&data->work,bma250_work_func);

                  atomic_set(&data->delay,BMA250_MAX_DELAY);

                  atomic_set(&data->enable, 0);

         这里会去初始化一个延时任务,设置延时时间。

         原来在structbma250_data结构体中,有一个work_struct,就是中断处理下半部的任务,同时有一个delayed_work是用来定时上报G-sensor的xyz坐标的,我去查看了bma150中的代码,发现bma150中并没有采用中断的方式,而是直接采用延时任务,应该是bma250添加了中断处理。

         还剩下的事情就是输入子系统的申请,绑定和注册了

                   dev= input_allocate_device();

                   input_set_drvdata(dev,data);

                   data->input= dev;

                   err= input_register_device(dev);

         除了在内核中注册中断子系统以外,还要将它映射到用户空间,供用户空间使用,下面这个函数会实现:

                            err =sysfs_create_group(&data->input->dev.kobj,&bma250_attribute_group);

         有关sysfs的更多知识可以参考:

                   http://blog.csdn.net/suwenqiang2011/article/details/8613818

关于G-sensor的处理流程,我们到中断处理函数bma250_irq_handler()以及延时任务函数bma250_work_func()中去看看就知道了

         bma250_irq_handler()的内容仅仅有一个函数

                   schedule_work(&data->irq_work);

         为什么这里和TP驱动中的中断处理函数内容:queue_work(ts->elan_wq,&ts->work);有所不一样呢,原来在TP驱动中,申请了一个工作队列,而G-sensor驱动使用的是默认工作队列,在每个cpu核上,都有一个默认的工作队列。

         进入中断下半部,bma250_irq_work_func()主要就是接受数据,解析,然后上报,和TP的流程是一样的。

         另外延时任务函数bma250_work_func()的内容也很简单,时间到了就读取G-sensor的当前值,然后上报:

                   bma250_read_accel_xyz(bma250->bma250_client,&acc);

                   input_report_abs(bma250->input,ABS_X, acc.x);

                  input_report_abs(bma250->input,ABS_Y, acc.y);

                  input_report_abs(bma250->input,ABS_Z, acc.z);

                  input_sync(bma250->input);

         重新调度延时任务:

                   schedule_delayed_work(&bma250->work,delay);

整个G-sensor驱动的分析就完成了,主要使用到了i2c设备驱动,中断下半部-工作队列,延时任务,中断,输入子系统等知识。

        

 

你可能感兴趣的:(MID驱动之二G-sensor)