歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> OK6410矩陣鍵盤驅動問題(linux-2.6.36.2)

OK6410矩陣鍵盤驅動問題(linux-2.6.36.2)

日期:2017/3/1 10:10:47   编辑:Linux編程

飛凌鍵盤驅動怎麼老是出問題阿。。。

涉及的文件:(內核版本linux-2.6.36.2)

file1: driver/input/keyboard/samsung-keypad.c

file2: arch/arm/plat-samsung/include/plat/keypad.h

file3: arch/arm/mach-s3c64xx/mach-s3c64xx.c

file4: 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 void

matrix_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_keypad

structplatform_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_data

smdk6410_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有問題。

Copyright © Linux教程網 All Rights Reserved