注:此驱动对应英文handler和内核的驱动(driver)不是一回事
如果认真看过shiroki写的QtEmbedded键盘驱动分析(上篇,下篇),那么自己再来看鼠标驱动的流程基本上也是大同小异,软件的实现框架是一模一样的。只不过搜索引擎可能不知道这个事情,那么我就把键盘两字改为鼠标再写一篇。
写作本文的目的是为了梳理QtEmbedded中鼠标的加载流程,在你的鼠标不工作的时候,可以一步一步的去排查问题所在,真正做到以不变应万变。如果想只是通过修改某个变量或者文件而把问题解决的想法是不可靠的,也是本人不推荐的。
下面我们就来看看QtEmbedded是怎么从main函数到加载鼠标驱动的。
1. 从QApplication开始,因为每个带GUI的main函数都会创建一个QApplication的实例
2. 构造函数中调用QApplicationPrivate::construct(…)
src/gui/kernel/qapplication.cpp
665 QApplication::QApplication(int &argc, char **argv)
666 : QCoreApplication(*new QApplicationPrivate(argc, argv, GuiClient))
667 { Q_D(QApplication); d->construct(); }
3. construct(…)则会调用qt_init(…)函数
4. qt_init(…) 则会解析命令行参数,从而调用QWSServer::startup(flags);
src/gui/kernel/qapplication_qws.cpp
2279 if (type == QApplication::GuiServer) {
2280 qt_appType = QApplication::Type(type);
2281 qws_single_process = true;
2282 QWSServer::startup(flags);
2283 setenv(”QWS_DISPLAY”, qws_display_spec.constData(), 0);
2284 }
我们知道如果应用命令行加”-qws”选项,就会以server(GuiSever)方式运行。上面代码中的startup的参数flags也是通过对命令行参数做运算得到的.
5. QWSServer::startup(flags) 会创建QWSServer的一个实例
src/gui/embedded/qwindowsystem_qws.cpp
4054 void QWSServer::startup(int flags)
4055 {
4056 if (qwsServer)
4057 return;
4058 unlink(qws_qtePipeFilename().toLatin1().constData());
4059 (void)new QWSServer(flags);
4060 }
6. QWSServer的构造函数则会调用QWSServerPrivate::initServer(…)
src/gui/embedded/qwindowsystem_qws.cpp
1303 QWSServer::QWSServer(int flags, QObject *parent) :
1304 QObject(*new QWSServerPrivate, parent)
1305 {
1306 Q_D(QWSServer);
1307 d->initServer(flags);
1308 }
7. initServer则会在这里调用openMouse()
src/gui/embedded/qwindowsystem_qws.cpp
1440 if (!(flags&QWSServer::DisableMouse)) {
1441 q->openMouse();
1442 }
1443 #ifndef QT_NO_QWS_KEYBOARD
1444 if (!(flags&QWSServer::DisableKeyboard)) {
1445 q->openKeyboard();
1446 }
1447 #endif
鼠标相关的东西从这里进入我们视野,1440行的判断来自于命令行参数,如果运行server程序的时候带了”-nomouse”选项,那么这里就1441行就不会被调用了。
我们还可以看到openKeyboard()也是在这个函数里被调用的,可见他们还真是哥俩。
8.a openMouse()函数则根据Linux中的环境变量QWS_MOUSE_PROTO来判断加载什么样的鼠标驱动(handler)
从上面代码我们可以得出3个结论
A) 控制使用什么鼠标的环境变量是QWS_MOUSE_PROTO
B) 如果QWS_MOUSE_PROTO没有设置,系统会加载默认的鼠标驱动
C) 可以加载多个鼠标hanlder,也就是可以接多个鼠标设备.在QWS_MOUSE_PROTO变量中以空格分开
newMouseHandler(…)是被调用去创建鼠标驱动的函数
8.b newMouseHandler(QString spec)处理具体的某一个驱动规格
spec的形式可能是这样的”Vr41xx:press=500:/dev/misc/ts”,该函数会对spec进行分离出不同的部分,然后调用QMouseDriverFactory::create(mouseProto, mouseDev)去创建真正的驱动。
src/gui/embedded/qwindowsystem_qws.cpp
3695 QWSMouseHandler *handler = 0;
3696 handler = QMouseDriverFactory::create(mouseProto, mouseDev);
如果返回值 handler为0就有问题了:(
8.c QMouseDriverFactory::create 是真正创建QWSMouseHandler实例的具体地方,不同的鼠标类型处理都是QWSMouseHandler的子类,这些QWSMouseHandler子类有可能编译成库文件,也有可能以插件的形式存在,如果以插件形式存在那么加载方法是
src/gui/embedded/qmousedriverfactory_qws.cpp
144 if (QWSMouseHandlerFactoryInterface *factory = qobject_cast(loader()->instance(driver)))
145 return factory->create(driver, device);
你的鼠标驱动是否加载成功,这第八步的3个函数很关键,前面的七步基本上不会出问题,作为系统运行的一个了解就可以。
关于一个具体鼠标Handler里的设计,将放在本文的下篇里去讲解。