作者:刘洪涛,华清远见嵌入式学院讲师。
在嵌入式平台上运行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文件,及注意按键去抖等问题。