一、usb设备的热插拔
之前就做过Qt之支持usb触摸屏热插拔(Qt4.7)_朗朗上口就行啦的博客-CSDN博客的USB触摸屏热插拔,在Qt5的又碰到了被干扰之后恢复,一开始我根据百度的情况,我以为我是界面对触摸屏不支持热插拔,所以就无法操作了。来针对usb热插拔的进行了解决,根据网络大佬的解释,我在直接替换了Qt5.7的源码中的:
qtbase/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp
qtbase/src/platformsupport/devicediscovery/qdevicediscovery_static_p.h
这两个文件在末尾有,当时我这个改动后重新编译替换库文件之后,我是不起作用的,原因是我用的是触摸屏,设备节点是/dev/input/event1,但是我这个节点我是开机后就存在的,我断开后也不会消失,而上文的解决办法是会检测设备节点的,我的设备节点不会发生改变,所以这个办法很明显对于我来说是无效的
二、usb触摸屏的断开检测
我断开usb触摸屏设备之后,我提示的报错信息是
evdevtouch: Could not read from input device (No such device)
我在源码目录下搜索这个报错信息:
发现是在 qtbase/src/platformsupport/input/evdevtouch/目录下的qevdevtouchhandler.cpp,所以打开后一目了然,和我以前在Qt4.7解决usb触摸屏断开后恢复的方法一模一样
一样的打开设备节点后关联,然后通过槽函数readData读取触摸点信息
看一下readData函数
void QEvdevTouchScreenHandler::readData()
{
::input_event buffer[32];
int events = 0;
#if !defined(QT_NO_MTDEV)
forever {
do {
events = mtdev_get(m_mtdev, m_fd, buffer, sizeof(buffer) / sizeof(::input_event));
// keep trying mtdev_get if we get interrupted. note that we do not
// (and should not) handle EAGAIN; EAGAIN means that reading would
// block and we'll get back here later to try again anyway.
} while (events == -1 && errno == EINTR);
// 0 events is EOF, -1 means error, handle both in the same place
if (events <= 0)
goto err;
// process our shiny new events
for (int i = 0; i < events; ++i)
d->processInputEvent(&buffer[i]);
// and try to get more
}
#else
int n = 0;
for (; ;) {
events = QT_READ(m_fd, reinterpret_cast<char*>(buffer) + n, sizeof(buffer) - n);
if (events <= 0)
goto err;
n += events;
if (n % sizeof(::input_event) == 0)
break;
}
n /= sizeof(::input_event);
for (int i = 0; i < n; ++i)
d->processInputEvent(&buffer[i]);
#endif
return;
err:
if (!events) {
qWarning("evdevtouch: Got EOF from input device");
return;
} else if (events < 0) {
if (errno != EINTR && errno != EAGAIN) {
qErrnoWarning(errno, "evdevtouch: Could not read from input device");
if (errno == ENODEV) { // device got disconnected -> stop reading
delete m_notify;
m_notify = Q_NULLPTR;
QT_CLOSE(m_fd);
m_fd = -1;
unregisterTouchDevice();
}
return;
}
}
}
在前面的都不需要看,只需要看到触摸点读取出现异常的情况,可以看到当出现异常时,关闭文件描述符,删除设备,从设备树中取消注册,原因就出现在这里,他出现异常之后取消了注册,如果我的设备节点连接时能被监测到,那么此时问题也能解决,可是我的设备节点一直存在,他出现异常被发现的原因是因为被读取失败,所以他取消注册之后就不会再连接上,那么这个自然而然是要屏蔽掉的。
主要修改内容:
if (!events) {
qWarning("evdevtouch: Got EOF from input device");
return;
} else if (events < 0) {
if (errno != EINTR && errno != EAGAIN) {
qErrnoWarning(errno, "evdevtouch: Could not read from input device");
if (errno == ENODEV) { // device got disconnected -> stop reading
disconnect(m_notify, 0, 0, 0);
delete m_notify;
m_notify = Q_NULLPTR;
QT_CLOSE(m_fd);
m_fd = -1;
while(1){
m_fd = QT_OPEN(d->myDeviceName.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
if(m_fd >= 0){
m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
connect(m_notify, SIGNAL(activated(int)), this, SLOT(readData()));
return;
}
system("echo waiting for tp ...");
system("sleep 1");
}
//unregisterTouchDevice();
}
return;
}
}
myDeviceName就是传入的设备节点名称,在完整文件中会有,其他的没有东西,与Qt4.7的做法一模一样
三、修改后的资源文件
1、qdevicediscovery_static链接
链接: https://pan.baidu.com/s/18_fLDWjlyJb-tiz1fcnpuQ 提取码: z82g 复制这段内容后打开百度网盘手机App,操作更方便哦
2、qevdevtouchhandler.cpp链接
链接: https://pan.baidu.com/s/1fBToefEvho8Ao9BzzrWycA 提取码: 44t6 复制这段内容后打开百度网盘手机App,操作更方便哦