##背景
嵌入式设备常常使用tslib 处理单点触屏; [ref https://doc.qt.io/qt-5/inputs-linux-device.html ), 但因为电磁干扰或者别的原因,USB"插拔"后,触摸没有反应. 默认QT源码里tslib-plugin并没有相应的处理.本文提供一种简单解决方案. [#qt 版本 5.9.5]
##分析
插拔触摸屏usb后, cat /dev/input/touchscreen |hexdump , 发现有输出,说明问题处在QT或tslib里. 通过dmesg查询日志,很容易得知对应的event文件经历销毁和重建. 所以猜测,tslib 绑定的文件句柄发生变更,需要重新建立绑定关系.
##解决问题
搜索TSLIB_TSDEVICE, 快速找到qt-tslib-plugin的代码; [很容易理解qtslib.cpp],从下面代码可以看出 tslib利用QSocketNotifier来关联read触摸消息(event).
思路是,能够监视触摸屏(usb)插拔消息,然后构造函数重新建立绑定关系.
所以关键是能够watch插拔消息.
QTsLibMouseHandler::QTsLibMouseHandler(const QString &key,
.....
qCDebug(qLcTsLib) << "Initializing tslib plugin" << key << specification;
setObjectName(QLatin1String("TSLib Mouse Handler"));
device = qgetenv("TSLIB_TSDEVICE");
if (specification.startsWith(QLatin1String("/dev/")))
device = specification.toLocal8Bit();
if (device.isEmpty())
device = QByteArrayLiteral("/dev/input/event1");
m_dev = ts_open(device.constData(), 1);
if (!m_dev) {
qErrnoWarning(errno, "ts_open() failed");
return;
}
if (ts_config(m_dev))
qErrnoWarning(errno, "ts_config() failed");
m_rawMode = !key.compare(QLatin1String("TslibRaw"), Qt::CaseInsensitive);
int fd = ts_fd(m_dev);
if (fd >= 0) {
qCDebug(qLcTsLib) << "tslib device is" << device;
m_notify = new QSocketNotifier(fd, QSocketNotifier::Read, this);
**connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData()));**
} else {
qErrnoWarning(errno, "tslib: Cannot open input device %s", device.constData());
}
查询,QSocketNotifier , 有 Exception信号,试图添加该消息,来监控触摸屏插拔消息. 测试失败,未能正常工作, 查询QT网页给出 如下提示:
插拔,底层驱动,会导致/dev/input/event0 (TSLIB_TSDEVICE)的变化,创建和销毁;所以可以使用 QFileSystemWatcher *m_fileWatcher; 来监视插拔消息.
###构造函数修改
m_fileWatcher = new QFileSystemWatcher(this);
// QString dev_=device;
m_fileWatcher->addPath(QLatin1String("/dev/input/")); // "dev/input/"
connect(m_fileWatcher, SIGNAL(directoryChanged(QString)), this, SLOT(handleHotPlugWatch(QString)));
###重连处理
void QTsLibMouseHandler::handleHotPlugWatch(const QString &path)
{
QFile file(QLatin1String("/dev/input/event0")); // shoud be TSLIB_TSDEVICE
qCDebug(qLcTsLib) << path << "is changing";
if(file.exists())
{
qCDebug(qLcTsLib) << "tslib device disconnected .., try connecting ...";
disconnect(m_notify, 0, 0, 0);
delete m_notify;
QByteArray device = qgetenv("TSLIB_TSDEVICE");
m_dev = ts_open(device.constData(), 1);
if (!m_dev)
{
qCDebug(qLcTsLib) << " touchscreen doesn't exist";
qErrnoWarning(errno, "ts_open() failed");
}
else {
if (ts_config(m_dev))
qErrnoWarning(errno, "ts_config() failed");
m_notify = new QSocketNotifier(ts_fd(m_dev), QSocketNotifier::Read, this);
connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData()));
return;
}
qCDebug(qLcTsLib) << path << "is added";
} else{
qCDebug(qLcTsLib) << path << "is removed";
}
}