分类: LINUX
2009-11-27 11:12:35
昨天终于做完了一个通路的驱动,底下用i2c驱动跟电容式触摸屏通信,再在内核里利用input子系统把坐标送到用户空间,上面用qt实现鼠标动作。下面就稍微详细分析i2c和input子系统。
一:i2c子系统
首先module_init(eeprom_init); 进入eeprom_init函数,函数里调用i2c_add_driver(&eeprom_driver);从而进入eeprom_attach_adapter(struct i2c_adapter *adapter) 这个函数,这个函数里再调用i2c_probe(adapter, &addr_data, eeprom_detect);
其实很多i2c驱动很多没有eeprom_attach_adapter(struct i2c_adapter *adapter) 这个函数,而直接调用xxx_probe(struct i2c_client *client)( .probe = xxx_probe,),其实这个eeprom_attach_adapter也可以不用,这个函数里也直接调用i2c_probe了,里面会进行地址的匹配(可以定义好几个地址,这个函数会自动匹配),这也就是这个函数的作用,如果直接不要这个函数就得直接给定从设备的地址,特别注意的是在地址匹配过程中地址不能小于0x03不能大于0x77,如果有用attach这个函数的话下面就进入detect这个函数进入从设备的初始化。具体i2c总线的架构可以看宋宝华的《linux设备驱动开发详解》,
二:input子系统
ts.dev = input_allocate_device(); 分配空间
ts.dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS); 所支持的事件
ts.dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT(BTN_TOUCH);
input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0);
input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0);
input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0);
设备的初始化
input_report_abs(ts.dev, ABS_X, ts.xp);
input_report_abs(ts.dev, ABS_Y, ts.yp);
input_report_key(ts.dev, BTN_TOUCH, 1);
input_report_abs(ts.dev, ABS_PRESSURE, 1);
input_sync(ts.dev);
report时要前一次和后一次的值不一样才会发送,如果一样的话在事件处理那是不会向上发的。
还有很多没写出来,有机会再补
最后在写驱动是不要用到太多的局部指针,特别是退出时,尽量不要用局部的指针,在定时器里也如果是因为指针的原因导致系统崩溃,可以用工作队列解决。
谢谢各位的阅读!