在嵌入式开发中,qt的键盘往往都是特制的,如何让特制的键盘被qt用起来,需要对linux的input子系统有一定了解,并且特别要追一下qt对外界输入时间的处理方式。应用层和驱动层相互关联,在此仅先粗略分析下qt这部分:
在qt的源码中grep下/dev/input/event之类的,就可以顺藤摸瓜了
对于qt的embedded版本,第一个运行的QApp当作server,后起来的QApps当作client。在QApplication的构造函数中:
Q_D(QApplication);d->construct();
在construct()中调用
qt_init(this, qt_appType
#ifdef Q_WS_X11
, dpy, visual, cmap
#endif
);
在qt_init函数中有QWSServer::startup(flags);
在startup中有(void)new QWSServer(flags);
在QWSServer的构造函数中有
Q_D(QWSServer);
d->initServer(flags)
在initServer中有
#ifndef QT_NO_QWS_KEYBOARD
if(!(flags&QWSServer::DisableKeyboard)){
q->openKeyboard();
}
#endif
在openKeyboard中创立一个handler。
QWSKeyboardHandler *handler = QkbdDriverFactory::create(type, device);
在create中,有
QWSKeyboardHandler *QKbdDriverFactory::create(const QString& key, const QString& device)
{
QString driver = key.toLower();
#ifndef QT_NO_QWS_KBD_SL5000
if (driver == QLatin1String("sl5000") || driver.isEmpty())
return new QWSSL5000KeyboardHandler(device);
#endif
#ifndef QT_NO_QWS_KBD_YOPY
if (driver == QLatin1String("yopy") || driver.isEmpty())
return new QWSYopyKeyboardHandler(device);
#endif
#ifndef QT_NO_QWS_KBD_VR41XX
if (driver == QLatin1String("vr41xx") || driver.isEmpty())
return new QWSVr41xxKeyboardHandler(device);
#endif
#ifndef QT_NO_QWS_KEYBOARD
# ifndef QT_NO_QWS_KBD_TTY
if (driver == QLatin1String("tty") || driver.isEmpty())
return new QWSTtyKeyboardHandler(device);
# endif
# ifndef QT_NO_QWS_KBD_USB
if (driver == QLatin1String("usb"))
return new QWSUsbKeyboardHandler(device);
# endif
# ifndef QT_NO_QWS_KBD_UM
if (driver == QLatin1String("um") || driver == QLatin1String("qvfbkeyboard"))
return new QWSUmKeyboardHandler(device);
# endif
# ifndef QT_NO_QWS_KBD_QVFB
if (driver == QLatin1String("qvfbkbd")
|| driver == QLatin1String("qvfbkeyboard")
|| driver == QLatin1String("qvfb"))
return new QVFbKeyboardHandler(device);
# endif
#endif
#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL)
#ifndef QT_NO_LIBRARY
if (QWSKeyboardHandlerFactoryInterface *factory = qobject_cast
return factory->create(driver, device);
#endif
#endif
return 0;
}
根据不同的keyboard类型进行创建,这里挑usb类型的看一下
# ifndef QT_NO_QWS_KBD_USB
if (driver == QLatin1String("usb"))
return new QWSUsbKeyboardHandler(device);
# endif
QWSUsbKeyboardHandler::QWSUsbKeyboardHandler(const QString &device)
: QWSPC101KeyboardHandler(device)
{
d = new QWSUsbKbPrivate(this, device);
}
QWSUsbKbPrivate::QWSUsbKbPrivate(QWSPC101KeyboardHandler *h, const QString &device) : handler(h)
{
#ifdef QT_QWS_ZYLONITE
shift = FALSE;
#endif
fd = ::open(device.isEmpty()?"/dev/input/event1":device.toLocal8Bit(),O_RDONLY, 0);
if (fd >= 0) {
QSocketNotifier *notifier;
notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
connect(notifier, SIGNAL(activated(int)),this,
SLOT(readKeyboardData()));
}
}
这里就用的linux设备中的input子设备,监听该fd,如果有数据了,就 readKeyboardData.
这里监听的方法是Qt自己的类 QsocketNotifier,但效果和select、poll等是一样的。
readKeyboardData函数首先从fd中读取标准的input_event结构体。根据这个结构体的内容转换为内部的标识。最后调用 handler->processKeyEvent(unicode, key_code, (Qt::KeyboardModifiers)modifiers, event.value!=0, false);进行处理。
按照这个流程下来,我们可以很清楚的知晓如何在Qt下添加键盘。
在qkbddriverfactory_qws.cpp中的create函数中新建自己的handler。仿照qkbdusb_qws.cpp建立自己的处理方式就可以了.
Qt里边的修改的大概过程就是如此,那么对于特定的嵌入式系统,如何将设备融入到input子系统呢。如果按照这种方式,需要对input子系统比较熟悉才能将硬件抽象为input设备。
其实,还有一个比较简单的方式,使用pipe。比如按键的面板是一个51单片机控制的,单片机和arm通过串口通信,那么可以将串口的数据转换为标准的input_event结构体,然后将其写入到pipe中。而qt中就监听类似于/dev/input/keybdpipe之类的文件就行了.