在上一篇《OK6410矩阵键盘驱动 linux2.6.36》http://blog.csdn.net/sun_rise2011/article/details/7626818 中已经详细给出了自定义矩阵键盘的驱动,主要是从内核中分离开来,作为单独的驱动模块,再用insmod samsung_keypad.ko加载驱动就可以了。按下时,就会出现调试语句,说明驱动能够正常运行。
但是,我要矩阵键盘驱动的目的是在Qt界面上可以输入文字,用18个按键实现拼音输入法。我之前的想法是,按下某个按键,从而在内核驱动中返回我自已义的编号:
unsigned int keypad_keycode[] = {'1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G'};
然而,在Qt应用程序中,我应该怎样读取这个编号呢?我之前的想法是:
也就是不停的读,从而得到ev_key.code。
之前没有认识到input结构体的能力,其实USB键盘也是用input结构体的,难道应用程序也要不停的读取吗?显然这是不可能的事啊!后来,在实际用的时候,发现只要按下按键,在文本框中马上会出现某些字符。也就是说,我自己定义的某些编号正好对应了电脑识别的编号。也就是不用一直read都可以实现输入。
经过研究,发现,只能在自己定义的编号中,只要符合电脑按键的标准键值,也可以了。
见下文,《嵌入式linux上Qt标准键盘输入的实现》http://blog.csdn.net/hongtao_liu/article/details/5463648
作者:刘洪涛,华清远见嵌入式学院讲师。
在嵌入式平台上运行QTE时,使用的键盘通常不是标准键盘,而是嵌入式设备外扩的普通按键。那么实现QTE键盘输入的方法大体上可以分为两类:
(1)编写一个普通按键驱动,然后开辟一个QT线程读取按键值,在通过信号把按键值发送出去。需要接收键盘输入的目标,声明槽函数,接收键盘信号。
(2)将按键驱动编写成标准键盘驱动,让QTE感觉和标准键盘在打交道。
上述两种方法给有特点。我在一些项目中多数都是使用第1种方式,感觉比较直观容易控制。但也有些情况要选用第2种方法。
第1种方法的实现比较容易,这里就不多说了。下面主要把第2种方法的实现过程描述一下。
具体实现标准键盘输入的过程可以分为两步:
(1) 找一个标准usb键盘,测试QTE能否正确设别标准键盘
(2) 编写按键驱动,模拟标准键盘输入
一、第1步的实现过程:
● 配置QTE支持标准USB键盘
配置qte库时,增加键盘支持的参数,如下:
./configure …… -qt-kbd-usb ……
● 配置内核支持USB键盘输入
● 插入USB键盘后,产生event设备节点,如/dev/event2
● 设置QTE关联的键盘设备的环境变量
export QWS_KEYBOARD=USB:/dev/event2
● 编写一个接收键盘事件的QT测试代码。
class MyDialog : public QDialog
{
……
protected:
virtual void keyPressEvent(QKeyEvent *k);
};
void MyDialog::keyPressEvent(QKeyEvent *k)
{
qDebug("in press event %x",k->key());
}
● 测试键盘输入
当按下F1~F12时,打印出:
in press event 1000030
in press event 1000031
in press event 1000032
in press event 1000033
in press event 1000034
in press event 1000035
in press event 1000036
in press event 1000037
in press event 1000038
in press event 1000039
in press event 100003a
查QT帮助 Key_F1=0x1000030
说明QDialog 的keyPressEvent可以接收到它能获取的键盘信号,即QTE和USB键盘连接正确。
二、第2步的实现过程:
主要参考/driver/usb/input/usbkbd.c程序,完成键盘模拟。程序主要思想是编写一个支持EV_KEY的input设备驱动。下面摘取关键代码。
● 完成input设备的注册、注销
struct input_dev *input_dev;
static unsigned char usb_kbd_keycode[256] = {
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0,
122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
150,158,159,128,136,177,178,176,142,152,173,140
};
/*初始化*/
static int button_init(void)
{
……
input_dev = input_allocate_device();//分配input设备
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
// EV_KEY为要支持的键盘事件
for (i = 0; i < 255; i++)
set_bit(usb_kbd_keycode[i], input_dev->keybit);
//设置支持的键盘码,可根据实际情况注册
input_register_device(input_dev);//注册input设备
}
/*注销*/
static void __exit button_cleanup(void)
{
……
input_unregister_device(input_dev);//注销input设备
}
● 中断处理过程中完成键盘值的获取及input事件的递交
static irqreturn_t button_irq(int irq, void *dev_id, struct pt_regs *regs)
{
……
input_report_key(input_dev, 59, 1); //模拟键盘码F1按下过程
input_report_key(input_dev, 59, 0);
input_sync(input_dev);
}
/*在内核include/linux/input.h中
#define KEY_F1 59
*/
上面给出了简要的过程,大家在具体实现过程中多参考/driver/usb/input/usbkbd.c文件,及注意按键去抖等问题。