首页 / 操作系统 / Linux / OK6410矩阵键盘驱动问题(linux-2.6.36.2)
飞凌键盘驱动怎么老是出问题阿。。。涉及的文件:(内核版本linux-2.6.36.2)file1: driver/input/keyboard/samsung-keypad.cfile2: arch/arm/plat-samsung/include/plat/keypad.hfile3: arch/arm/mach-s3c64xx/mach-s3c64xx.cfile4: arch/arm/plat-samsung/Dev-keypad.c其中键盘的驱动代码主要为file1: samsung-keypad.c在内核根目录,make menuconfig查看了内核的配置,默认使用了gpio-keys驱动,也就是开发板上的6个一排的小红色按键的驱动。而在此我们使用的矩阵键盘驱动应该使用samsung-keypad。内核默认没有编译,因此我们可以单独编译该模块加载运行。照理说将file1拿出来单独编译成模块samsung-keypad.ko然后加载,就可以使用键盘了,但是世事难料,编译成功通过,但是加载后没有丝毫反应,于是在file1中的几个主要函数中添加了打印调试信息。再次加载发现,加载过程只进行到samsung_keypad_init()。也就是只是调用了 platform_driver_register(&samsung_keypad_driver);而probe函数没用运行,由此发出疑问:是不是矩阵键盘对应的设备数据没有在Platformbus 总线上安装?使用source insight 查看源代码 ,找到file3中定义的6410的设备列表:staticstruct platform_device *smdk6410_devices[] __initdata = {.。。。&s3c_device_fb,&s3c_device_ohci,&s3c_device_usb_hsotg,#if 0&s3c64xx_device_iisv4,&samsung_device_keypad,#endif
&s3c64xx_device_ac97,&s3c_device_adc,。。。};发现其中果然将&samsung_device_keypad,给屏蔽掉了。找到症结所在,去掉屏蔽,然后重新编译内核,编译驱动模块,加载运行,此时进入了probe函数,但是又出现了新的问题,内存错误,程序直接死掉。通过加入调试信息,将问题锁定在probe函数中调用的matrix_keypad_build_keymap()函数中,即:matrix_keypad_build_keymap(keymap_data,row_shift, input_dev->keycode, input_dev->keybit); 使用source insight 查看,该函数如下:staticinline voidmatrix_keypad_build_keymap(conststruct matrix_keymap_data *keymap_data,unsigned int row_shift,unsigned short *keymap, unsigned long *keybit){inti;for(i = 0; i < keymap_data->keymap_size; i++) {unsignedint key = keymap_data->keymap[i];unsignedint row = KEY_ROW(key);unsignedint col = KEY_COL(key);unsignedshort code = KEY_VAL(key);
keymap[MATRIX_SCAN_CODE(row,col, row_shift)] = code;__set_bit(code,keybit);}__clear_bit(KEY_RESERVED,keybit);}在调试时,我试图打印keymap_data->keymap_size发现结果很小的负数,打印keymap_data->keymap[i]的时候就会报内存出错,由此可见,keymap_data初始化出了问题。 继续查看源代码,在probe函数中,keymap_data= pdata->keymap_data; 而pdata= pdev->dev.platform_data;即:keymap_data=pdev->dev.platform_data->keymap_data其中,pdev也就是probe函数的参数:platform_device。.在这个模块中,应该就是file4:Dev-keypad.c文件中定义的:samsung_device_keypad,也即上面提到的6410设备列表中的samsung_device_keypadstructplatform_device samsung_device_keypad = {.name ="samsung-keypad",.id =-1,.num_resources =ARRAY_SIZE(samsung_keypad_resources),.resource =samsung_keypad_resources,};在系统开机时调用smdk6410_machine_init函数,在此函数中调用了samsung_keypad_set_platdata(&smdk6410_keypad_data);函数定义如下:void__init samsung_keypad_set_platdata(struct samsung_keypad_platdata*pd){structsamsung_keypad_platdata *npd;npd= s3c_set_platdata(pd, sizeof(struct samsung_keypad_platdata),&samsung_device_keypad);
if(!npd->cfg_gpio)npd->cfg_gpio= samsung_keypad_cfg_gpio;}其中调用:void__init *s3c_set_platdata(void *pd, size_t pdsize,struct platform_device *pdev){。。。pdev->dev.platform_data= npd; returnnpd;}所以pdev->dev.platform_data= &smdk6410_keypad_datasmdk6410_keypad_data及相关的数据结构定义如下:(在file3中) static uint32_t smdk6410_keymap[] __initdata = {/*KEY(row, col, keycode) */KEY(0,3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3),KEY(0,6, KEY_4), KEY(0, 7, KEY_5),KEY(1,3, KEY_A), KEY(1, 4, KEY_B), KEY(1, 5, KEY_C),KEY(1,6, KEY_D), KEY(1, 7, KEY_E)};
static struct matrix_keymap_data smdk6410_keymap_data __initdata = {
.keymap =smdk6410_keymap,.keymap_size =ARRAY_SIZE(smdk6410_keymap),};
static struct samsung_keypad_platdata smdk6410_keypad_data __initdata = {
.keymap_data =&smdk6410_keymap_data,.rows =2,.cols =8,};到这里,我们可以知道,上面说的初始化有问题的keymap_data应该就是这里的smdk6410_keymap_data 了,如果说初始化有问题,那就是smdk6410_keypad_data有问题了,也即probe函数中的pdata有问题。