android input子系统分析---驱动层
来源:互联网 发布:美拍用的抽奖软件 编辑:程序博客网 时间:2024/05/16 10:24
前言:
Input子系统包括标准Linux,Android核心驱动,Android相关设备驱动,G-sensor的设备驱动程序。传感器作为
一种输入设备,也是通过input系统把其数据上报给系统,或者通过input系统得到用户的配置信息。这里以传感器
为例学习input driver层。
Sensor驱动从通过I2C从寄存器中读取sensor值,然后写入/dev/input/目录下对应的文件。HAL层通过读取该文件的
值进一步传递给Framework层。每个厂商使用的具体的输入驱动硬件不同,因此软件也不尽相同,但是具体的原理都
是一样的。
代码路径: kernel\drivers\input。
1,概论
Sensor模块的module_i2c_driver方法会向i2c总线挂载该驱动。
module_i2c_driver(mpu6880_i2c_driver);
mpu6880_i2c_driver结构体如下,
static struct i2c_driver mpu6880_i2c_driver = {.driver= {.name= "mpu6880",.owner= THIS_MODULE,.pm= &mpu6880_pm,.of_match_table = mpu6880_of_match,},.probe= mpu6880_probe,.remove= mpu6880_remove,.id_table= mpu6880_ids,};module_i2c_driver(mpu6880_i2c_driver);
该驱动加载时的probe方法是mpu6880_probe。
mpu6880_probe方法有2个参数,
static int mpu6880_probe(struct i2c_client *client, const struct i2c_device_id *id){
第一个参数client是I2C寄存器在sensor驱动中的客户端,
第二个参数id是I2C寄存器在sensor驱动中的id,
通过这2个参数,sensor就可以从寄存器中读出sensor数据。
mpu6880_probe方法主要如下,
1,sensor模块初始化,
sensor = devm_kzalloc(&client->dev, sizeof(struct mpu6880_sensor), GFP_KERNEL);//申请内存•••sensor->client = client;//为mpu6880_sensor结构体赋值sensor->dev = &client->dev;•••sensor->accel_dev->name = MPU6880_DEV_NAME_ACCEL;sensor->gyro_dev->name = MPU6880_DEV_NAME_GYRO;sensor->accel_dev->id.bustype = BUS_I2C;sensor->gyro_dev->id.bustype = BUS_I2C;sensor->gyro_poll_ms = pdata->gyro_poll_ms;sensor->accel_poll_ms = pdata->accel_poll_ms;
mpu6880_sensor定义如下,
struct mpu6880_sensor {struct i2c_client *client;//i2c客户端struct device *dev; //设备struct input_dev *accel_dev;//加速度sensorstruct input_dev *gyro_dev;struct sensors_classdev accel_cdev;struct sensors_classdev gyro_cdev;struct mpu6880_platform_data *pdata;•••
2,注册2个sensor,
ret = input_register_device(sensor->accel_dev);if (ret) {dev_err(&client->dev, "Failed to register input device\n");goto err_free_irq;}ret = input_register_device(sensor->gyro_dev);if (ret) {dev_err(&client->dev, "Failed to register input device\n");goto err_unregister_accel;}
3,利用定时中断读取sensor数据,
INIT_DELAYED_WORK(&sensor->gyro_poll_work, mpu6880_gyro_work_fn);INIT_DELAYED_WORK(&sensor->accel_poll_work, mpu6880_accel_work_fn);
新建一个内核线程,入口方法为mpu6880_accel_work_fn,重力感应器在此以后就不啰嗦了,整个和加速度完全一样。
Sensor事件在驱动中的主要分为3个部分,
1,驱动层,从I2C寄存器中读取sensor数据。
2,核心层,统一发送给input子系统处理。
3,事件层,将处理后的event写入缓存,供HAL调用。
2,驱动层
2.1 sensor
调用流程如下,
mpu6880_accel_work_fn方法主要分为2个步骤,
1,首先调用mpu6880_read_accel_data方法读取寄存器中的sensor数据
mpu6880_read_accel_data(sensor, &sensor->axis);
2,然后调用mpu6880_accel_report方法进行处理。
mpu6880_accel_report(sensor);
2.1 数据读取
mpu6880_read_accel_data方法如下,
static void mpu6880_read_accel_data(struct mpu6880_sensor *sensor, struct axis_data *data){u16 buffer[3]; //缓存mpu6880_read_reg(sensor->client, sensor->reg.raw_accel,(u8 *)buffer, MPU6880_RAW_ACCEL_DATA_LEN); //读取sensor数据data->x = be16_to_cpu(buffer[0]);data->y = be16_to_cpu(buffer[1]);data->z = be16_to_cpu(buffer[2]);}
首先调用mpu6880_read_reg方法从寄存器中读取数据,然后将数据写入data结构体中。
mpu6880_read_reg方法如下,
static int mpu6880_read_reg(struct i2c_client *client, u8 start_addr, u8 *buffer, int length){struct i2c_msg msg[] = {{.addr = client->addr,.flags = 0,.len = 1,.buf = &start_addr,},{.addr = client->addr,.flags = I2C_M_RD,.len = length,.buf = buffer,},};return i2c_transfer(client->adapter, msg, 2);}
首先构造一个i2c_msg结构体,然后直接调用i2c_transfer方法读取数据, i2c_transfer是系统方法。
这样,寄存器的数据终于写入mpu6880_sensor结构体的axis_data结构体。
2.2 sensor处理
mpu6880_accel_report方法的主要逻辑如下,
input_report_abs(sensor->accel_dev, ABS_X, (sensor->axis.x )); //发送x轴加速度input_report_abs(sensor->accel_dev, ABS_Y, (sensor->axis.y )); //发送y轴加速度input_report_abs(sensor->accel_dev, ABS_Z, (sensor->axis.z )); //发送z轴加速度input_event(sensor->accel_dev, EV_SYN, SYN_TIME_SEC, ktime_to_timespec(ts).tv_sec);input_event(sensor->accel_dev, EV_SYN, SYN_TIME_NSEC, ktime_to_timespec(ts).tv_nsec);input_sync(sensor->accel_dev);
首先发送三个方向上的加速度,然后发送系统的当前时间,获取系统当前时间如下,
ktime_t ts;ts = ktime_get_boottime();
注意ktime_t结构体, tv_sec变量单位是s, tv_nsec单位是ns。这2个值同一单位相加就是1970年1月1日
到当前系统sensor数据上报的时间。
input.h的input_report_abs方法也是调用input.c的input_event方法进行处理。
static inline void input_report_abs(struct input_dev *dev, unsigned int code, int value){input_event(dev, EV_ABS, code, value);}
接下来的事就交由input.c 来做了。
- android input子系统分析---驱动层
- android input子系统分析---事件层
- android Input子系统分析
- input输入子系统驱动分析
- ads7846驱动及android系统input输入子系统分析
- Android Input子系统驱动部分
- input子系统事件处理层evdev分析
- input子系统二 驱动层input设备注册
- input子系统二 驱动层input设备注册
- input子系统二 驱动层input设备注册
- Android Input输入子系统分析
- input子系统框架、核心层、输入事件驱动层详解
- 基于input子系统的驱动分析
- Linux内核驱动之Input子系统设备驱动层
- android input子系统之二:核心层
- android input子系统之三:事件层
- android input子系统之一:驱动部分
- Linux input子系统分析---4、事件处理层分析
- 使用poi导出excel表格
- 决策树(decision tree)
- java笔记(一)
- 【网络实验】IP checksum的变化规律
- c++字面值常量
- android input子系统分析---驱动层
- B
- 字符串排列
- google账号注册手机号验证不通过
- ctags简单使用
- linux常用操作-3.快速切换用户
- Activiti之路
- get提交和post提交的区别
- activiti 任务中指派人优先级大于候选人