QSerialPort::availablePorts reports portName available after unplugging
-
Re: [QSerialPort issues - error signals](plugging/unplugging quickly)
-
You are probably right.
If I put a sleep(1) after availablePorts(), I get accurate info and can even reconnect.
#include "jtagclient.h" #include <unistd.h> #include <QSerialPortInfo> #include <QTimer> QString JtagClient::m_usbDevice = "ttyUSB0"; JtagClient::JtagClient(QObject *parent) : QObject(parent) { m_serialPort = new QSerialPort(m_usbDevice); } void JtagClient::run() { if (!m_serialPort->open(QIODevice::ReadWrite)) { emit usbDeviceStatus("Could not open serial port"); return; } QTimer *tm = new QTimer; QTimer *retmr = new QTimer; tm->setInterval(500); tm->setSingleShot(false); retmr->setInterval(500); retmr->setSingleShot(false); QObject::connect(this, &JtagClient::stopDisconnectTimer, tm, &QTimer::stop); QObject::connect(this, &JtagClient::stopReconnectTimer, retmr, &QTimer::stop); QObject::connect(this, SIGNAL(startReconnectTimer()), retmr, SLOT(start())); QObject::connect(this, &JtagClient::finished, tm, &QTimer::deleteLater); QObject::connect(this, &JtagClient::finished, retmr, &QTimer::deleteLater); QObject::connect(tm, &QTimer::timeout, [&]() { bool found = false; foreach (QSerialPortInfo inf, QSerialPortInfo::availablePorts()) { if (m_usbDevice == inf.portName()) { emit usbDeviceStatus("Waiting for usb serial disconnect"); found = true; break; } } if (!found) { m_serialPort->close(); m_serialPort->deleteLater(); emit usbDeviceStatus("Cable removed"); emit stopDisconnectTimer(); emit startReconnectTimer(); } }); QObject::connect(retmr, &QTimer::timeout, [&]() { bool found = false; foreach (QSerialPortInfo inf, QSerialPortInfo::availablePorts()) { if (m_usbDevice == inf.portName()) { found = true; //500000 causes a Permission denied error, presumably the kernel hasn't finished the inode //750000 causes a Permission denied error for ReadWrite, but works for ReadOnly //usleep(750000); sleep(1); m_serialPort = new QSerialPort(m_usbDevice); if (!m_serialPort->open(QIODevice::ReadWrite)) { emit usbDeviceStatus(QString("Could not re-open device: %1").arg(m_serialPort->errorString())); } else { emit usbDeviceStatus("Connection re-established"); } break; } } if (found) { emit stopReconnectTimer(); emit finished(); } else emit usbDeviceStatus("Waiting for re-connect"); }); tm->start(); }
-
Re: [QSerialPort issues - error signals](plugging/unplugging quickly)
Given the following code, the if (!found) block is never executed after a serial port was open, then unplugged. I need to either unplug (or preferably power down) the serial device.
QTimer *tm = new QTimer; tm->setInterval(250); tm->setSingleShot(false); QObject::connect(tm, &QTimer::timeout, [&]() { bool found = false; foreach (QSerialPortInfo inf, QSerialPortInfo::availablePorts()) { if (m_usbDevice == inf.portName()) { if (tmct++ %4 == 0) { //I see this message even after unplugging the device. emit usbDeviceStatus("Waiting for device power down"); } found = true; break; } } if (!found) { qDebug() << "serial port closed"; //never see it m_serialPort->deleteLater(); qDebug() << "deleting serial port"; //device powered off emit usbDeviceStatus("Device powered down"); tm->stop(); tm->deleteLater(); retmr->start(); qDebug() << "started retmr"; } });
-
Given the following code, the if (!found) block is never executed after a serial port was open, then unplugged. I need to either unplug (or preferably power down) the serial device.
QTimer *tm = new QTimer; tm->setInterval(250); tm->setSingleShot(false); QObject::connect(tm, &QTimer::timeout, [&]() { bool found = false; foreach (QSerialPortInfo inf, QSerialPortInfo::availablePorts()) { if (m_usbDevice == inf.portName()) { if (tmct++ %4 == 0) { //I see this message even after unplugging the device. emit usbDeviceStatus("Waiting for device power down"); } found = true; break; } } if (!found) { qDebug() << "serial port closed"; //never see it m_serialPort->deleteLater(); qDebug() << "deleting serial port"; //device powered off emit usbDeviceStatus("Device powered down"); tm->stop(); tm->deleteLater(); retmr->start(); qDebug() << "started retmr"; } });
Hi @Jeff-Barnes,
- which platform is that?
- and which Qt version?
-
Hi @Jeff-Barnes,
- which platform is that?
- and which Qt version?
@aha_1980 Platform Ubuntu 16.04 Qt 5.11
-
@aha_1980 Platform Ubuntu 16.04 Qt 5.11
@Jeff-Barnes
Hi
Have you checked that ubuntu does in fact remove
the dev name when you unplug the sub->serial device ? -
Before unplugging serial cable:
ls /dev/ttyUSB0
/dev/ttyUSB0After:
ls /dev/ttyUSB0
ls: cannot access '/dev/ttyUSB0': No such file or directory -
Before unplugging serial cable:
ls /dev/ttyUSB0
/dev/ttyUSB0After:
ls /dev/ttyUSB0
ls: cannot access '/dev/ttyUSB0': No such file or directory@Jeff-Barnes IMO, this is a bug in QSerialPort/QSerialPortInfo implementation, because the serial port is de-registered with the computer when the serial cable is unplugged, yet QSerialPortInfo::availablePorts() still lists it.
However, in my particular use case, I worked around it by leaving the QSerialPort open, the serial cable plugged in and power cycling the board. The USB is providing power to the serial port, so it is still active.
-
@Jeff-Barnes IMO, this is a bug in QSerialPort/QSerialPortInfo implementation, because the serial port is de-registered with the computer when the serial cable is unplugged, yet QSerialPortInfo::availablePorts() still lists it.
However, in my particular use case, I worked around it by leaving the QSerialPort open, the serial cable plugged in and power cycling the board. The USB is providing power to the serial port, so it is still active.
Hi @Jeff-Barnes, it could be a bug indeed.
Which type of USB adapter is this? Can you post the
dmesg
lines after plugging the adapter in and out? @kuzulis, any more information for investigation needed? -
jbarnes@jbarnes-All-Series:~/rail/desktop-tools$ sudo dmesg -C
jbarnes@jbarnes-All-Series:~/rail/desktop-tools$ dmesg
[1370519.563632] usb 3-4: USB disconnect, device number 78
[1370519.563719] ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
[1370519.563731] ftdi_sio 3-4:1.0: device disconnected
[1370527.159840] usb 3-4: new full-speed USB device number 81 using xhci_hcd
[1370527.293315] usb 3-4: New USB device found, idVendor=0403, idProduct=6001
[1370527.293317] usb 3-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[1370527.293318] usb 3-4: Product: FT232R USB UART
[1370527.293319] usb 3-4: Manufacturer: FTDI
[1370527.293321] usb 3-4: SerialNumber: A50285BI
[1370527.295768] ftdi_sio 3-4:1.0: FTDI USB Serial Device converter detected
[1370527.295805] usb 3-4: Detected FT232RL
[1370527.295939] usb 3-4: FTDI USB Serial Device converter now attached to ttyUSB0 -
QSerialPortInfo takes info from the udev... Usually if you keep a serial port open, and then unplug an USB cable, then it can show that a device still is present in system.
From your code it is unclear what do you do. You should try to check it in two variants:
- Try to keep QSerialPort as open.
- Try do not touch the QSeralPort at all.
PS: It is not a QSPI issue, most likelly, you should address it to systemd bug-tracker or the kernel dev-list.
-
You are probably right.
If I put a sleep(1) after availablePorts(), I get accurate info and can even reconnect.
-
This post is deleted!
-
You are probably right.
If I put a sleep(1) after availablePorts(), I get accurate info and can even reconnect.
This post is deleted! -
You are probably right.
If I put a sleep(1) after availablePorts(), I get accurate info and can even reconnect.
#include "jtagclient.h" #include <unistd.h> #include <QSerialPortInfo> #include <QTimer> QString JtagClient::m_usbDevice = "ttyUSB0"; JtagClient::JtagClient(QObject *parent) : QObject(parent) { m_serialPort = new QSerialPort(m_usbDevice); } void JtagClient::run() { if (!m_serialPort->open(QIODevice::ReadWrite)) { emit usbDeviceStatus("Could not open serial port"); return; } QTimer *tm = new QTimer; QTimer *retmr = new QTimer; tm->setInterval(500); tm->setSingleShot(false); retmr->setInterval(500); retmr->setSingleShot(false); QObject::connect(this, &JtagClient::stopDisconnectTimer, tm, &QTimer::stop); QObject::connect(this, &JtagClient::stopReconnectTimer, retmr, &QTimer::stop); QObject::connect(this, SIGNAL(startReconnectTimer()), retmr, SLOT(start())); QObject::connect(this, &JtagClient::finished, tm, &QTimer::deleteLater); QObject::connect(this, &JtagClient::finished, retmr, &QTimer::deleteLater); QObject::connect(tm, &QTimer::timeout, [&]() { bool found = false; foreach (QSerialPortInfo inf, QSerialPortInfo::availablePorts()) { if (m_usbDevice == inf.portName()) { emit usbDeviceStatus("Waiting for usb serial disconnect"); found = true; break; } } if (!found) { m_serialPort->close(); m_serialPort->deleteLater(); emit usbDeviceStatus("Cable removed"); emit stopDisconnectTimer(); emit startReconnectTimer(); } }); QObject::connect(retmr, &QTimer::timeout, [&]() { bool found = false; foreach (QSerialPortInfo inf, QSerialPortInfo::availablePorts()) { if (m_usbDevice == inf.portName()) { found = true; //500000 causes a Permission denied error, presumably the kernel hasn't finished the inode //750000 causes a Permission denied error for ReadWrite, but works for ReadOnly //usleep(750000); sleep(1); m_serialPort = new QSerialPort(m_usbDevice); if (!m_serialPort->open(QIODevice::ReadWrite)) { emit usbDeviceStatus(QString("Could not re-open device: %1").arg(m_serialPort->errorString())); } else { emit usbDeviceStatus("Connection re-established"); } break; } } if (found) { emit stopReconnectTimer(); emit finished(); } else emit usbDeviceStatus("Waiting for re-connect"); }); tm->start(); }