QWS LinuxInput and Hotplugging USB Keyboards
-
For QWS and Embedded Linux, what is the recommended way of supporting USB keyboards that can be added/removed at any time? (I realize that this may be a rather infrequent use case for most Qt Embedded devs.)
Providing a /dev/input/eventX node to the keyboard driver implemented by qkbdlinuxinput_qws.cpp does not suffice, as it simply spins on the bad file descriptor once the keyboard has been removed, printing "Could not read from input device:" I'm not sure if this should be reported as a bug, or if I should simply be doing things a different way.
I am considering modifying/extending the qkbdlinuxinput_qws driver to monitor (via inotify) and scan /proc/bus/input for added keyboards, and then switch over to a newly discovered device after the QT_READ() of the current keyboard device fails. This seems like it'd be a bit of a design overhaul (that I don't think would conform with the existing code) to add this recovery functionality, which makes me think there's probably a cleaner (or perhaps pre-existing) solution -- any comments on this?
Despite it being a referred to as a "hack" in various Linux documentation files, mousedev (mapping all mouse events to a persistent /dev/input/mice) certainly works well for hotplugging USB mice with QWS. If I remember correctly, there was a similar "keybdev" mechanism that fell out of the kernel a while back...not sure if that's worth investigating for new designs now that it's deprecated...
Obligatory version info: Currently using 4.7.4, but I see that qkbdlinuxinput_qws.cpp hasn't changed too much in 4.8.0.
-
We also ran into this problem and found an easy workaround.
Instead of providing the input device as a environment variable, the input device can be set at runtime. We use a QFileSystemWatcher to register that the node does not exists anymore and in that case, close the keyboard. It is also possible to register a new input device and then set it as the default keyboard.
In our case the only keyboard may be at node /dev/input/event1 so the following code snipped (incomplete) works out well for us:
//Initialization of QFileSystemWatcher somewhere after startup { pFileSystemWatcher = new QFileSystemWatcher(this); pFileSystemWatcher->addPath("/dev/input/"); connect(pFileSystemWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(on_fileSystemWatcher_directoryChanged(QString))); closeKeyboard(); on_fileSystemWatcher_directoryChanged(QString()); } // Slot to receive a removed or added input device void on_fileSystemWatcher_directoryChanged(const QString& path) { QFileInfo eventFile("/dev/input/event1"); if (!keyboardPresent && eventFile.exists()) { setKeyboard(); } else if (keyboardPresent && !eventFile.exists()) { closeKeyboard(); } } void setKeyboard() { QWSKeyboardHandler *pKeyboardHandler = QKbdDriverFactory::create("LinuxInput", "/dev/input/event1"); QWSServer* pQwsServer = QWSServer::instance(); pQwsServer->setKeyboardHandler(pKeyboardHandler); keyboardPresent = true; } void closeKeyboard() { QWSServer* pQwsServer = QWSServer::instance(); pQwsServer->closeKeyboard(); keyboardPresent = false; }