Source

Target

Commits (13)
Showing with 269 additions and 273 deletions
......@@ -36,6 +36,7 @@
#include <QWidget>
#include <QVBoxLayout>
#include <QLabel>
#include <QScrollArea>
#include <QtSerialPort/QSerialPortInfo>
QT_USE_NAMESPACE
......@@ -44,8 +45,6 @@ int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.setWindowTitle(QObject::tr("Info about all available serial ports."));
QVBoxLayout *layout = new QVBoxLayout;
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
......@@ -62,8 +61,13 @@ int main(int argc, char *argv[])
layout->addWidget(label);
}
w.setLayout(layout);
w.show();
QWidget *workPage = new QWidget;
workPage->setLayout(layout);
QScrollArea area;
area.setWindowTitle(QObject::tr("Info about all available serial ports."));
area.setWidget(workPage);
area.show();
return a.exec();
}
......@@ -41,6 +41,8 @@
QT_USE_NAMESPACE
static const char blankString[] = QT_TRANSLATE_NOOP("SettingsDialog", "N/A");
SettingsDialog::SettingsDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SettingsDialog)
......@@ -57,6 +59,8 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
this, SLOT(showPortInfo(int)));
connect(ui->baudRateBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(checkCustomBaudRatePolicy(int)));
connect(ui->serialPortInfoListBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(checkCustomDevicePathPolicy(int)));
fillPortsParameters();
fillPortsInfo();
......@@ -76,15 +80,16 @@ SettingsDialog::Settings SettingsDialog::settings() const
void SettingsDialog::showPortInfo(int idx)
{
if (idx != -1) {
QStringList list = ui->serialPortInfoListBox->itemData(idx).toStringList();
ui->descriptionLabel->setText(tr("Description: %1").arg(list.at(1)));
ui->manufacturerLabel->setText(tr("Manufacturer: %1").arg(list.at(2)));
ui->serialNumberLabel->setText(tr("Serial number: %1").arg(list.at(3)));
ui->locationLabel->setText(tr("Location: %1").arg(list.at(4)));
ui->vidLabel->setText(tr("Vendor Identifier: %1").arg(list.at(5)));
ui->pidLabel->setText(tr("Product Identifier: %1").arg(list.at(6)));
}
if (idx == -1)
return;
QStringList list = ui->serialPortInfoListBox->itemData(idx).toStringList();
ui->descriptionLabel->setText(tr("Description: %1").arg(list.count() > 1 ? list.at(1) : tr(blankString)));
ui->manufacturerLabel->setText(tr("Manufacturer: %1").arg(list.count() > 2 ? list.at(2) : tr(blankString)));
ui->serialNumberLabel->setText(tr("Serial number: %1").arg(list.count() > 3 ? list.at(3) : tr(blankString)));
ui->locationLabel->setText(tr("Location: %1").arg(list.count() > 4 ? list.at(4) : tr(blankString)));
ui->vidLabel->setText(tr("Vendor Identifier: %1").arg(list.count() > 5 ? list.at(5) : tr(blankString)));
ui->pidLabel->setText(tr("Product Identifier: %1").arg(list.count() > 6 ? list.at(6) : tr(blankString)));
}
void SettingsDialog::apply()
......@@ -104,13 +109,21 @@ void SettingsDialog::checkCustomBaudRatePolicy(int idx)
}
}
void SettingsDialog::checkCustomDevicePathPolicy(int idx)
{
bool isCustomPath = !ui->serialPortInfoListBox->itemData(idx).isValid();
ui->serialPortInfoListBox->setEditable(isCustomPath);
if (isCustomPath)
ui->serialPortInfoListBox->clearEditText();
}
void SettingsDialog::fillPortsParameters()
{
ui->baudRateBox->addItem(QStringLiteral("9600"), QSerialPort::Baud9600);
ui->baudRateBox->addItem(QStringLiteral("19200"), QSerialPort::Baud19200);
ui->baudRateBox->addItem(QStringLiteral("38400"), QSerialPort::Baud38400);
ui->baudRateBox->addItem(QStringLiteral("115200"), QSerialPort::Baud115200);
ui->baudRateBox->addItem(QStringLiteral("Custom"));
ui->baudRateBox->addItem(tr("Custom"));
ui->dataBitsBox->addItem(QStringLiteral("5"), QSerialPort::Data5);
ui->dataBitsBox->addItem(QStringLiteral("6"), QSerialPort::Data6);
......@@ -118,27 +131,26 @@ void SettingsDialog::fillPortsParameters()
ui->dataBitsBox->addItem(QStringLiteral("8"), QSerialPort::Data8);
ui->dataBitsBox->setCurrentIndex(3);
ui->parityBox->addItem(QStringLiteral("None"), QSerialPort::NoParity);
ui->parityBox->addItem(QStringLiteral("Even"), QSerialPort::EvenParity);
ui->parityBox->addItem(QStringLiteral("Odd"), QSerialPort::OddParity);
ui->parityBox->addItem(QStringLiteral("Mark"), QSerialPort::MarkParity);
ui->parityBox->addItem(QStringLiteral("Space"), QSerialPort::SpaceParity);
ui->parityBox->addItem(tr("None"), QSerialPort::NoParity);
ui->parityBox->addItem(tr("Even"), QSerialPort::EvenParity);
ui->parityBox->addItem(tr("Odd"), QSerialPort::OddParity);
ui->parityBox->addItem(tr("Mark"), QSerialPort::MarkParity);
ui->parityBox->addItem(tr("Space"), QSerialPort::SpaceParity);
ui->stopBitsBox->addItem(QStringLiteral("1"), QSerialPort::OneStop);
#ifdef Q_OS_WIN
ui->stopBitsBox->addItem(QStringLiteral("1.5"), QSerialPort::OneAndHalfStop);
ui->stopBitsBox->addItem(tr("1.5"), QSerialPort::OneAndHalfStop);
#endif
ui->stopBitsBox->addItem(QStringLiteral("2"), QSerialPort::TwoStop);
ui->flowControlBox->addItem(QStringLiteral("None"), QSerialPort::NoFlowControl);
ui->flowControlBox->addItem(QStringLiteral("RTS/CTS"), QSerialPort::HardwareControl);
ui->flowControlBox->addItem(QStringLiteral("XON/XOFF"), QSerialPort::SoftwareControl);
ui->flowControlBox->addItem(tr("None"), QSerialPort::NoFlowControl);
ui->flowControlBox->addItem(tr("RTS/CTS"), QSerialPort::HardwareControl);
ui->flowControlBox->addItem(tr("XON/XOFF"), QSerialPort::SoftwareControl);
}
void SettingsDialog::fillPortsInfo()
{
ui->serialPortInfoListBox->clear();
static const QString blankString = QObject::tr("N/A");
QString description;
QString manufacturer;
QString serialNumber;
......@@ -157,6 +169,8 @@ void SettingsDialog::fillPortsInfo()
ui->serialPortInfoListBox->addItem(list.first(), list);
}
ui->serialPortInfoListBox->addItem(tr("Custom"));
}
void SettingsDialog::updateSettings()
......
......@@ -79,6 +79,7 @@ private slots:
void showPortInfo(int idx);
void apply();
void checkCustomBaudRatePolicy(int idx);
void checkCustomDevicePathPolicy(int idx);
private:
void fillPortsParameters();
......
......@@ -36,6 +36,7 @@
#include "qserialport.h"
#include "qserialportinfo.h"
#include "qserialportinfo_p.h"
#ifdef Q_OS_WINCE
#include "qserialport_wince_p.h"
......@@ -435,7 +436,7 @@ QSerialPort::~QSerialPort()
void QSerialPort::setPortName(const QString &name)
{
Q_D(QSerialPort);
d->systemLocation = QSerialPortPrivate::portNameToSystemLocation(name);
d->systemLocation = QSerialPortInfoPrivate::portNameToSystemLocation(name);
}
/*!
......@@ -446,7 +447,7 @@ void QSerialPort::setPortName(const QString &name)
void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo)
{
Q_D(QSerialPort);
d->systemLocation = QSerialPortPrivate::portNameToSystemLocation(serialPortInfo.systemLocation());
d->systemLocation = serialPortInfo.systemLocation();
}
/*!
......@@ -460,7 +461,7 @@ void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo)
\li Brief Description
\row
\li Windows
\li Removes the prefix "\\\\.\\" from the system location
\li Removes the prefix "\\\\.\\" or "//./" from the system location
and returns the remainder of the string.
\row
\li Windows CE
......@@ -471,16 +472,9 @@ void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo)
\li Returns the system location as it is,
as it is equivalent to the port name.
\row
\li GNU/Linux
\li Unix, BSD
\li Removes the prefix "/dev/" from the system location
and returns the remainder of the string.
\row
\li Mac OSX
\li Removes the prefix "/dev/cu." and "/dev/tty." from the
system location and returns the remainder of the string.
\row
\li Other *nix
\li The same as for GNU/Linux.
\endtable
\sa setPort(), QSerialPortInfo::portName()
......@@ -488,7 +482,7 @@ void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo)
QString QSerialPort::portName() const
{
Q_D(const QSerialPort);
return QSerialPortPrivate::portNameFromSystemLocation(d->systemLocation);
return QSerialPortInfoPrivate::portNameFromSystemLocation(d->systemLocation);
}
/*!
......
......@@ -273,7 +273,7 @@ private:
Q_DISABLE_COPY(QSerialPort)
#if defined (Q_OS_WIN32) || defined(Q_OS_WIN64)
#if defined (Q_OS_WIN32)
Q_PRIVATE_SLOT(d_func(), bool _q_completeAsyncCommunication())
Q_PRIVATE_SLOT(d_func(), bool _q_completeAsyncRead())
Q_PRIVATE_SLOT(d_func(), bool _q_completeAsyncWrite())
......
......@@ -34,6 +34,7 @@
****************************************************************************/
#include "qserialport_unix_p.h"
#include "qserialportinfo_p.h"
#include <errno.h>
#include <sys/time.h>
......@@ -163,7 +164,7 @@ bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{
Q_Q(QSerialPort);
QString lockFilePath = serialPortLockFilePath(portNameFromSystemLocation(systemLocation));
QString lockFilePath = serialPortLockFilePath(QSerialPortInfoPrivate::portNameFromSystemLocation(systemLocation));
bool isLockFileEmpty = lockFilePath.isEmpty();
if (isLockFileEmpty) {
qWarning("Failed to create a lock file for opening the device");
......@@ -379,20 +380,14 @@ qint64 QSerialPortPrivate::readData(char *data, qint64 maxSize)
bool QSerialPortPrivate::waitForReadyRead(int msecs)
{
Q_Q(QSerialPort);
QElapsedTimer stopWatch;
stopWatch.start();
do {
bool readyToRead = false;
bool readyToWrite = false;
bool timedOut = false;
if (!waitForReadOrWrite(&readyToRead, &readyToWrite, true, !writeBuffer.isEmpty(),
timeoutValue(msecs, stopWatch.elapsed()), &timedOut)) {
if (!timedOut)
q->setError(decodeSystemError());
timeoutValue(msecs, stopWatch.elapsed()))) {
return false;
}
......@@ -407,23 +402,17 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs)
bool QSerialPortPrivate::waitForBytesWritten(int msecs)
{
Q_Q(QSerialPort);
if (writeBuffer.isEmpty() && pendingBytesWritten <= 0)
return false;
QElapsedTimer stopWatch;
stopWatch.start();
forever {
bool readyToRead = false;
bool readyToWrite = false;
bool timedOut = false;
if (!waitForReadOrWrite(&readyToRead, &readyToWrite, true, !writeBuffer.isEmpty(),
timeoutValue(msecs, stopWatch.elapsed()), &timedOut)) {
if (!timedOut)
q->setError(decodeSystemError());
timeoutValue(msecs, stopWatch.elapsed()))) {
return false;
}
......@@ -929,6 +918,26 @@ QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
case ENXIO:
error = QSerialPort::ResourceError;
break;
#endif
#ifdef EINVAL
case EINVAL:
error = QSerialPort::UnsupportedOperationError;
break;
#endif
#ifdef ENOIOCTLCMD
case ENOIOCTLCMD:
error = QSerialPort::UnsupportedOperationError;
break;
#endif
#ifdef ENOTTY
case ENOTTY:
error = QSerialPort::ResourceError;
break;
#endif
#ifdef EPERM
case EPERM:
error = QSerialPort::PermissionError;
break;
#endif
default:
error = QSerialPort::UnknownError;
......@@ -973,13 +982,12 @@ void QSerialPortPrivate::setWriteNotificationEnabled(bool enable)
bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectForWrite,
bool checkRead, bool checkWrite,
int msecs, bool *timedOut)
int msecs)
{
Q_Q(QSerialPort);
Q_ASSERT(selectForRead);
Q_ASSERT(selectForWrite);
Q_ASSERT(timedOut);
fd_set fdread;
FD_ZERO(&fdread);
......@@ -995,19 +1003,19 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor
tv.tv_sec = msecs / 1000;
tv.tv_usec = (msecs % 1000) * 1000;
int ret = ::select(descriptor + 1, &fdread, &fdwrite, 0, msecs < 0 ? 0 : &tv);
if (ret < 0)
const int ret = ::select(descriptor + 1, &fdread, &fdwrite, 0, msecs < 0 ? 0 : &tv);
if (ret < 0) {
q->setError(decodeSystemError());
return false;
}
if (ret == 0) {
*timedOut = true;
q->setError(QSerialPort::TimeoutError);
return false;
}
*selectForRead = FD_ISSET(descriptor, &fdread);
*selectForWrite = FD_ISSET(descriptor, &fdwrite);
return ret;
return true;
}
qint64 QSerialPortPrivate::readFromPort(char *data, qint64 maxSize)
......@@ -1158,38 +1166,6 @@ qint64 QSerialPortPrivate::readPerChar(char *data, qint64 maxSize)
return ret;
}
#ifdef Q_OS_MAC
static const QString defaultFilePathPrefix = QStringLiteral("/dev/cu.");
static const QString unusedFilePathPrefix = QStringLiteral("/dev/tty.");
#else
static const QString defaultFilePathPrefix = QStringLiteral("/dev/");
#endif
QString QSerialPortPrivate::portNameToSystemLocation(const QString &port)
{
QString ret = port;
#ifdef Q_OS_MAC
ret.remove(unusedFilePathPrefix);
#endif
if (!ret.contains(defaultFilePathPrefix))
ret.prepend(defaultFilePathPrefix);
return ret;
}
QString QSerialPortPrivate::portNameFromSystemLocation(const QString &location)
{
QString ret = location;
#ifdef Q_OS_MAC
ret.remove(unusedFilePathPrefix);
#endif
ret.remove(defaultFilePathPrefix);
return ret;
}
typedef QMap<qint32, qint32> BaudRateMap;
// The OS specific defines can be found in termios.h
......
......@@ -131,9 +131,6 @@ public:
qint64 bytesToWrite() const;
qint64 writeData(const char *data, qint64 maxSize);
static QString portNameToSystemLocation(const QString &port);
static QString portNameFromSystemLocation(const QString &location);
static qint32 baudRateFromSetting(qint32 setting);
static qint32 settingFromBaudRate(qint32 baudRate);
......@@ -177,7 +174,7 @@ private:
bool waitForReadOrWrite(bool *selectForRead, bool *selectForWrite,
bool checkRead, bool checkWrite,
int msecs, bool *timedOut);
int msecs);
qint64 readFromPort(char *data, qint64 maxSize);
qint64 writeToPort(const char *data, qint64 maxSize);
......
......@@ -127,6 +127,16 @@ QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q)
}
}
QSerialPortPrivate::~QSerialPortPrivate()
{
if (communicationOverlapped.hEvent)
CloseHandle(communicationOverlapped.hEvent);
if (readCompletionOverlapped.hEvent)
CloseHandle(readCompletionOverlapped.hEvent);
if (writeCompletionOverlapped.hEvent)
CloseHandle(writeCompletionOverlapped.hEvent);
}
bool QSerialPortPrivate::open(QIODevice::OpenMode mode)
{
Q_Q(QSerialPort);
......@@ -328,27 +338,19 @@ qint64 QSerialPortPrivate::readData(char *data, qint64 maxSize)
bool QSerialPortPrivate::waitForReadyRead(int msecs)
{
Q_Q(QSerialPort);
QElapsedTimer stopWatch;
stopWatch.start();
if (!writeStarted && !_q_startAsyncWrite())
return false;
const qint64 initialReadBufferSize = readBuffer.size();
qint64 currentReadBufferSize = initialReadBufferSize;
QElapsedTimer stopWatch;
stopWatch.start();
do {
bool timedOut = false;
HANDLE triggeredEvent = 0;
if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &timedOut, &triggeredEvent) || !triggeredEvent) {
// This is occur timeout or another error
if (!timedOut)
q->setError(decodeSystemError());
if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &triggeredEvent) || !triggeredEvent)
return false;
}
if (triggeredEvent == communicationOverlapped.hEvent) {
if (!_q_completeAsyncCommunication())
......@@ -379,26 +381,19 @@ bool QSerialPortPrivate::waitForReadyRead(int msecs)
bool QSerialPortPrivate::waitForBytesWritten(int msecs)
{
Q_Q(QSerialPort);
if (writeBuffer.isEmpty())
return false;
QElapsedTimer stopWatch;
stopWatch.start();
if (!writeStarted && !_q_startAsyncWrite())
return false;
QElapsedTimer stopWatch;
stopWatch.start();
forever {
bool timedOut = false;
HANDLE triggeredEvent = 0;
if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &timedOut, &triggeredEvent) || !triggeredEvent) {
if (!timedOut)
q->setError(decodeSystemError());
if (!waitAnyEvent(timeoutValue(msecs, stopWatch.elapsed()), &triggeredEvent) || !triggeredEvent)
return false;
}
if (triggeredEvent == communicationOverlapped.hEvent) {
if (!_q_completeAsyncCommunication())
......@@ -518,7 +513,7 @@ bool QSerialPortPrivate::setDataErrorPolicy(QSerialPort::DataErrorPolicy policy)
bool QSerialPortPrivate::_q_completeAsyncCommunication()
{
if (handleOverlappedResult(0, communicationOverlapped) == qint64(-1))
if (overlappedResult(communicationOverlapped) == qint64(-1))
return false;
if (EV_ERR & triggeredEventMask)
handleLineStatusErrors();
......@@ -528,7 +523,7 @@ bool QSerialPortPrivate::_q_completeAsyncCommunication()
bool QSerialPortPrivate::_q_completeAsyncRead()
{
const qint64 bytesTransferred = handleOverlappedResult(QSerialPort::Input, readCompletionOverlapped);
const qint64 bytesTransferred = overlappedResult(readCompletionOverlapped);
if (bytesTransferred == qint64(-1)) {
readStarted = false;
return false;
......@@ -553,7 +548,7 @@ bool QSerialPortPrivate::_q_completeAsyncWrite()
Q_Q(QSerialPort);
if (writeStarted) {
const qint64 bytesTransferred = handleOverlappedResult(QSerialPort::Output, writeCompletionOverlapped);
const qint64 bytesTransferred = overlappedResult(writeCompletionOverlapped);
if (bytesTransferred == qint64(-1)) {
writeStarted = false;
return false;
......@@ -809,7 +804,7 @@ bool QSerialPortPrivate::updateCommTimeouts()
return true;
}
qint64 QSerialPortPrivate::handleOverlappedResult(int direction, OVERLAPPED &overlapped)
qint64 QSerialPortPrivate::overlappedResult(OVERLAPPED &overlapped)
{
Q_Q(QSerialPort);
......@@ -819,9 +814,9 @@ qint64 QSerialPortPrivate::handleOverlappedResult(int direction, OVERLAPPED &ove
if (error == QSerialPort::NoError)
return qint64(0);
if (error != QSerialPort::ResourceError) {
if (direction == QSerialPort::Input)
if (&overlapped == &readCompletionOverlapped)
q->setError(QSerialPort::ReadError);
else if (direction == QSerialPort::Output)
else if (&overlapped == &writeCompletionOverlapped)
q->setError(QSerialPort::WriteError);
else
q->setError(error);
......@@ -872,12 +867,10 @@ QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
return error;
}
bool QSerialPortPrivate::waitAnyEvent(int msecs, bool *timedOut, HANDLE *triggeredEvent)
bool QSerialPortPrivate::waitAnyEvent(int msecs, HANDLE *triggeredEvent)
{
Q_Q(QSerialPort);
Q_ASSERT(timedOut);
QVector<HANDLE> handles = QVector<HANDLE>()
<< communicationOverlapped.hEvent
<< readCompletionOverlapped.hEvent
......@@ -888,36 +881,18 @@ bool QSerialPortPrivate::waitAnyEvent(int msecs, bool *timedOut, HANDLE *trigger
FALSE, // wait any event
msecs == -1 ? INFINITE : msecs);
if (waitResult == WAIT_TIMEOUT) {
*timedOut = true;
q->setError(QSerialPort::TimeoutError, qt_error_string(WAIT_TIMEOUT));
return false;
}
if (waitResult >= DWORD(WAIT_OBJECT_0 + handles.count()))
if (waitResult >= DWORD(WAIT_OBJECT_0 + handles.count())) {
q->setError(decodeSystemError());
return false;
}
*triggeredEvent = handles.at(waitResult - WAIT_OBJECT_0);
return true;
}
static const QString defaultPathPrefix = QStringLiteral("\\\\.\\");
QString QSerialPortPrivate::portNameToSystemLocation(const QString &port)
{
QString ret = port;
if (!ret.contains(defaultPathPrefix))
ret.prepend(defaultPathPrefix);
return ret;
}
QString QSerialPortPrivate::portNameFromSystemLocation(const QString &location)
{
QString ret = location;
if (ret.contains(defaultPathPrefix))
ret.remove(defaultPathPrefix);
return ret;
}
// This table contains standard values of baud rates that
// are defined in MSDN and/or in Win SDK file winbase.h
......
......@@ -63,6 +63,7 @@ class QSerialPortPrivate : public QSerialPortPrivateData
public:
QSerialPortPrivate(QSerialPort *q);
~QSerialPortPrivate();
bool open(QIODevice::OpenMode mode);
void close();
......@@ -108,9 +109,6 @@ public:
qint64 bytesToWrite() const;
qint64 writeData(const char *data, qint64 maxSize);
static QString portNameToSystemLocation(const QString &port);
static QString portNameFromSystemLocation(const QString &location);
static qint32 baudRateFromSetting(qint32 setting);
static qint32 settingFromBaudRate(qint32 baudRate);
......@@ -141,9 +139,9 @@ private:
bool initialize(QIODevice::OpenMode mode);
bool updateDcb();
bool updateCommTimeouts();
qint64 handleOverlappedResult(int direction, OVERLAPPED &overlapped);
qint64 overlappedResult(OVERLAPPED &overlapped);
bool waitAnyEvent(int msecs, bool *timedOut, HANDLE *triggeredEvent);
bool waitAnyEvent(int msecs, HANDLE *triggeredEvent);
};
......
......@@ -348,17 +348,14 @@ bool QSerialPortPrivate::waitForReadyRead(int msec)
return true;
QElapsedTimer stopWatch;
stopWatch.start();
forever {
bool readyToRead = false;
bool readyToWrite = false;
bool timedOut = false;
if (!waitForReadOrWrite(&readyToRead, &readyToWrite,
true, !writeBuffer.isEmpty(),
timeoutValue(msec, stopWatch.elapsed()),
&timedOut)) {
timeoutValue(msec, stopWatch.elapsed()))) {
return false;
}
if (readyToRead) {
......@@ -377,17 +374,14 @@ bool QSerialPortPrivate::waitForBytesWritten(int msec)
return false;
QElapsedTimer stopWatch;
stopWatch.start();
forever {
bool readyToRead = false;
bool readyToWrite = false;
bool timedOut = false;
if (!waitForReadOrWrite(&readyToRead, &readyToWrite,
true, !writeBuffer.isEmpty(),
timeoutValue(msec, stopWatch.elapsed()),
&timedOut)) {
timeoutValue(msec, stopWatch.elapsed()))) {
return false;
}
if (readyToRead) {
......@@ -735,7 +729,7 @@ QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const
bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectForWrite,
bool checkRead, bool checkWrite,
int msecs, bool *timedOut)
int msecs)
{
Q_Q(QSerialPort);
......@@ -748,11 +742,8 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor
breaker.stop();
if (breaker.isWorked()) {
*timedOut = true;
q->setError(QSerialPort::TimeoutError);
}
if (!breaker.isWorked()) {
} else {
if (checkRead) {
Q_ASSERT(selectForRead);
*selectForRead = eventMask & EV_RXCHAR;
......@@ -768,22 +759,6 @@ bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectFor
return false;
}
QString QSerialPortPrivate::portNameToSystemLocation(const QString &port)
{
QString ret = port;
if (!ret.contains(QLatin1Char(':')))
ret.append(QLatin1Char(':'));
return ret;
}
QString QSerialPortPrivate::portNameFromSystemLocation(const QString &location)
{
QString ret = location;
if (ret.contains(QLatin1Char(':')))
ret.remove(QLatin1Char(':'));
return ret;
}
static const QList<qint32> standardBaudRatePairList()
{
......
......@@ -99,9 +99,6 @@ public:
qint64 bytesToWrite() const;
qint64 writeData(const char *data, qint64 maxSize);
static QString portNameToSystemLocation(const QString &port);
static QString portNameFromSystemLocation(const QString &location);
static qint32 baudRateFromSetting(qint32 setting);
static qint32 settingFromBaudRate(qint32 baudRate);
......@@ -124,7 +121,7 @@ private:
bool waitForReadOrWrite(bool *selectForRead, bool *selectForWrite,
bool checkRead, bool checkWrite,
int msecs, bool *timedOut);
int msecs);
};
......
......@@ -65,7 +65,6 @@ QT_BEGIN_NAMESPACE
\sa isNull()
*/
QSerialPortInfo::QSerialPortInfo()
: d_ptr(new QSerialPortInfoPrivate)
{
}
......@@ -81,7 +80,6 @@ QSerialPortInfo::QSerialPortInfo(const QSerialPortInfo &other)
Constructs a QSerialPortInfo object from serial \a port.
*/
QSerialPortInfo::QSerialPortInfo(const QSerialPort &port)
: d_ptr(new QSerialPortInfoPrivate)
{
foreach (const QSerialPortInfo &serialPortInfo, availablePorts()) {
if (port.portName() == serialPortInfo.portName()) {
......@@ -99,7 +97,6 @@ QSerialPortInfo::QSerialPortInfo(const QSerialPort &port)
instance for that port.
*/
QSerialPortInfo::QSerialPortInfo(const QString &name)
: d_ptr(new QSerialPortInfoPrivate)
{
foreach (const QSerialPortInfo &serialPortInfo, availablePorts()) {
if (name == serialPortInfo.portName()) {
......@@ -109,6 +106,11 @@ QSerialPortInfo::QSerialPortInfo(const QString &name)
}
}
QSerialPortInfo::QSerialPortInfo(const QSerialPortInfoPrivate &dd)
: d_ptr(new QSerialPortInfoPrivate(dd))
{
}
/*!
Destroys the QSerialPortInfo object. References to the values in the
object become invalid.
......
......@@ -81,6 +81,7 @@ public:
static QList<QSerialPortInfo> availablePorts();
private:
QSerialPortInfo(const QSerialPortInfoPrivate &dd);
friend QList<QSerialPortInfo> availablePortsByUdev();
friend QList<QSerialPortInfo> availablePortsBySysfs();
friend QList<QSerialPortInfo> availablePortsByFiltersOfDevices();
......
......@@ -78,15 +78,15 @@ static quint16 searchShortIntProperty(io_registry_entry_t ioRegistryEntry,
return value;
}
static bool isCompleteInfo(const QSerialPortInfo &portInfo)
static bool isCompleteInfo(const QSerialPortInfoPrivate &priv)
{
return !portInfo.portName().isEmpty()
&& !portInfo.systemLocation().isEmpty()
&& !portInfo.manufacturer().isEmpty()
&& !portInfo.description().isEmpty()
&& !portInfo.serialNumber().isEmpty()
&& portInfo.hasProductIdentifier()
&& portInfo.hasVendorIdentifier();
return !priv.portName.isEmpty()
&& !priv.device.isEmpty()
&& !priv.manufacturer.isEmpty()
&& !priv.description.isEmpty()
&& !priv.serialNumber.isEmpty()
&& priv.hasProductIdentifier
&& priv.hasVendorIdentifier;
}
static QString devicePortName(io_registry_entry_t ioRegistryEntry)
......@@ -160,37 +160,37 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
if (!serialPortService)
break;
QSerialPortInfo serialPortInfo;
QSerialPortInfoPrivate priv;
forever {
if (serialPortInfo.portName().isEmpty())
serialPortInfo.d_ptr->portName = devicePortName(serialPortService);
if (priv.portName.isEmpty())
priv.portName = devicePortName(serialPortService);
if (serialPortInfo.systemLocation().isEmpty())
serialPortInfo.d_ptr->device = deviceSystemLocation(serialPortService);
if (priv.device.isEmpty())
priv.device = deviceSystemLocation(serialPortService);
if (serialPortInfo.description().isEmpty())
serialPortInfo.d_ptr->description = deviceDescription(serialPortService);
if (priv.description.isEmpty())
priv.description = deviceDescription(serialPortService);
if (serialPortInfo.manufacturer().isEmpty())
serialPortInfo.d_ptr->manufacturer = deviceManufacturer(serialPortService);
if (priv.manufacturer.isEmpty())
priv.manufacturer = deviceManufacturer(serialPortService);
if (serialPortInfo.serialNumber().isEmpty())
serialPortInfo.d_ptr->serialNumber = deviceSerialNumber(serialPortService);
if (priv.serialNumber.isEmpty())
priv.serialNumber = deviceSerialNumber(serialPortService);
if (!serialPortInfo.hasVendorIdentifier()) {
serialPortInfo.d_ptr->vendorIdentifier =
if (!priv.hasVendorIdentifier) {
priv.vendorIdentifier =
deviceVendorIdentifier(serialPortService,
serialPortInfo.d_ptr->hasVendorIdentifier);
priv.hasVendorIdentifier);
}
if (!serialPortInfo.hasProductIdentifier()) {
serialPortInfo.d_ptr->productIdentifier =
if (!priv.hasProductIdentifier) {
priv.productIdentifier =
deviceProductIdentifier(serialPortService,
serialPortInfo.d_ptr->hasProductIdentifier);
priv.hasProductIdentifier);
}
if (isCompleteInfo(serialPortInfo)) {
if (isCompleteInfo(priv)) {
::IOObjectRelease(serialPortService);
break;
}
......@@ -200,7 +200,7 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
break;
}
serialPortInfoList.append(serialPortInfo);
serialPortInfoList.append(priv);
}
::IOObjectRelease(serialPortIterator);
......@@ -242,4 +242,18 @@ bool QSerialPortInfo::isValid() const
return f.exists();
}
QString QSerialPortInfoPrivate::portNameToSystemLocation(const QString &source)
{
return (source.startsWith(QLatin1Char('/'))
|| source.startsWith(QStringLiteral("./"))
|| source.startsWith(QStringLiteral("../")))
? source : (QStringLiteral("/dev/") + source);
}
QString QSerialPortInfoPrivate::portNameFromSystemLocation(const QString &source)
{
return source.startsWith(QStringLiteral("/dev/"))
? source.mid(5) : source;
}
QT_END_NAMESPACE
......@@ -51,7 +51,7 @@
QT_BEGIN_NAMESPACE
class QSerialPortInfoPrivate
class Q_AUTOTEST_EXPORT QSerialPortInfoPrivate
{
public:
QSerialPortInfoPrivate()
......@@ -59,9 +59,15 @@ public:
, productIdentifier(0)
, hasVendorIdentifier(false)
, hasProductIdentifier(false)
{}
{
}
~QSerialPortInfoPrivate()
{
}
~QSerialPortInfoPrivate() {}
static QString portNameToSystemLocation(const QString &source);
static QString portNameFromSystemLocation(const QString &source);
QString portName;
QString device;
......
......@@ -98,10 +98,10 @@ QList<QSerialPortInfo> availablePortsByFiltersOfDevices()
QList<QSerialPortInfo> serialPortInfoList;
foreach (const QString &deviceFilePath, filteredDeviceFilePaths()) {
QSerialPortInfo serialPortInfo;
serialPortInfo.d_ptr->device = deviceFilePath;
serialPortInfo.d_ptr->portName = QSerialPortPrivate::portNameFromSystemLocation(deviceFilePath);
serialPortInfoList.append(serialPortInfo);
QSerialPortInfoPrivate priv;
priv.device = deviceFilePath;
priv.portName = QSerialPortInfoPrivate::portNameFromSystemLocation(deviceFilePath);
serialPortInfoList.append(priv);
}
return serialPortInfoList;
......@@ -125,7 +125,7 @@ QList<QSerialPortInfo> availablePortsBySysfs()
if (lastIndexOfSlash == -1)
continue;
QSerialPortInfo serialPortInfo;
QSerialPortInfoPrivate priv;
if (targetPath.contains(QStringLiteral("pnp"))) {
// TODO: Obtain more information
#ifndef Q_OS_ANDROID
......@@ -155,26 +155,26 @@ QList<QSerialPortInfo> availablePortsBySysfs()
QFile description(QFileInfo(targetDir, QStringLiteral("product")).absoluteFilePath());
if (description.open(QIODevice::ReadOnly | QIODevice::Text))
serialPortInfo.d_ptr->description = QString::fromLatin1(description.readAll()).simplified();
priv.description = QString::fromLatin1(description.readAll()).simplified();
QFile manufacturer(QFileInfo(targetDir, QStringLiteral("manufacturer")).absoluteFilePath());
if (manufacturer.open(QIODevice::ReadOnly | QIODevice::Text))
serialPortInfo.d_ptr->manufacturer = QString::fromLatin1(manufacturer.readAll()).simplified();
priv.manufacturer = QString::fromLatin1(manufacturer.readAll()).simplified();
QFile serialNumber(QFileInfo(targetDir, QStringLiteral("serial")).absoluteFilePath());
if (serialNumber.open(QIODevice::ReadOnly | QIODevice::Text))
serialPortInfo.d_ptr->serialNumber = QString::fromLatin1(serialNumber.readAll()).simplified();
priv.serialNumber = QString::fromLatin1(serialNumber.readAll()).simplified();
QFile vendorIdentifier(QFileInfo(targetDir, QStringLiteral("idVendor")).absoluteFilePath());
if (vendorIdentifier.open(QIODevice::ReadOnly | QIODevice::Text)) {
serialPortInfo.d_ptr->vendorIdentifier = QString::fromLatin1(vendorIdentifier.readAll())
.toInt(&serialPortInfo.d_ptr->hasVendorIdentifier, 16);
priv.vendorIdentifier = QString::fromLatin1(vendorIdentifier.readAll())
.toInt(&priv.hasVendorIdentifier, 16);
}
QFile productIdentifier(QFileInfo(targetDir, QStringLiteral("idProduct")).absoluteFilePath());
if (productIdentifier.open(QIODevice::ReadOnly | QIODevice::Text)) {
serialPortInfo.d_ptr->productIdentifier = QString::fromLatin1(productIdentifier.readAll())
.toInt(&serialPortInfo.d_ptr->hasProductIdentifier, 16);
priv.productIdentifier = QString::fromLatin1(productIdentifier.readAll())
.toInt(&priv.hasProductIdentifier, 16);
}
break;
......@@ -185,13 +185,13 @@ QList<QSerialPortInfo> availablePortsBySysfs()
QDir targetDir(targetPath + QStringLiteral("/device"));
QFile vendorIdentifier(QFileInfo(targetDir, QStringLiteral("vendor")).absoluteFilePath());
if (vendorIdentifier.open(QIODevice::ReadOnly | QIODevice::Text)) {
serialPortInfo.d_ptr->vendorIdentifier = QString::fromLatin1(vendorIdentifier.readAll())
.toInt(&serialPortInfo.d_ptr->hasVendorIdentifier, 16);
priv.vendorIdentifier = QString::fromLatin1(vendorIdentifier.readAll())
.toInt(&priv.hasVendorIdentifier, 16);
}
QFile productIdentifier(QFileInfo(targetDir, QStringLiteral("device")).absoluteFilePath());
if (productIdentifier.open(QIODevice::ReadOnly | QIODevice::Text)) {
serialPortInfo.d_ptr->productIdentifier = QString::fromLatin1(productIdentifier.readAll())
.toInt(&serialPortInfo.d_ptr->hasProductIdentifier, 16);
priv.productIdentifier = QString::fromLatin1(productIdentifier.readAll())
.toInt(&priv.hasProductIdentifier, 16);
}
// TODO: Obtain more information about the device
} else if (targetPath.contains(QStringLiteral(".serial/tty/tty"))) {
......@@ -201,9 +201,9 @@ QList<QSerialPortInfo> availablePortsBySysfs()
continue;
}
serialPortInfo.d_ptr->portName = targetPath.mid(lastIndexOfSlash + 1);
serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(serialPortInfo.d_ptr->portName);
serialPortInfoList.append(serialPortInfo);
priv.portName = targetPath.mid(lastIndexOfSlash + 1);
priv.device = QSerialPortInfoPrivate::portNameToSystemLocation(priv.portName);
serialPortInfoList.append(priv);
}
return serialPortInfoList;
......@@ -318,25 +318,25 @@ QList<QSerialPortInfo> availablePortsByUdev()
if (!dev)
return serialPortInfoList;
QSerialPortInfo serialPortInfo;
QSerialPortInfoPrivate priv;
serialPortInfo.d_ptr->device = QString::fromLatin1(::udev_device_get_devnode(dev.data()));
serialPortInfo.d_ptr->portName = QString::fromLatin1(::udev_device_get_sysname(dev.data()));
priv.device = QString::fromLatin1(::udev_device_get_devnode(dev.data()));
priv.portName = QString::fromLatin1(::udev_device_get_sysname(dev.data()));
udev_device *parentdev = ::udev_device_get_parent(dev.data());
if (parentdev) {
if (checkUdevForSerial8250Driver(parentdev))
continue;
serialPortInfo.d_ptr->description = getUdevModelName(dev.data());
serialPortInfo.d_ptr->manufacturer = getUdevVendorName(dev.data());
serialPortInfo.d_ptr->serialNumber = getUdevSerialNumber(dev.data());
serialPortInfo.d_ptr->vendorIdentifier = getUdevVendorIdentifier(dev.data(), serialPortInfo.d_ptr->hasVendorIdentifier);
serialPortInfo.d_ptr->productIdentifier = getUdevModelIdentifier(dev.data(), serialPortInfo.d_ptr->hasProductIdentifier);
priv.description = getUdevModelName(dev.data());
priv.manufacturer = getUdevVendorName(dev.data());
priv.serialNumber = getUdevSerialNumber(dev.data());
priv.vendorIdentifier = getUdevVendorIdentifier(dev.data(), priv.hasVendorIdentifier);
priv.productIdentifier = getUdevModelIdentifier(dev.data(), priv.hasProductIdentifier);
} else {
if (serialPortInfo.d_ptr->portName.startsWith(rfcommDeviceName)) {
if (priv.portName.startsWith(rfcommDeviceName)) {
bool ok;
int portNumber = serialPortInfo.d_ptr->portName.mid(rfcommDeviceName.length()).toInt(&ok);
int portNumber = priv.portName.mid(rfcommDeviceName.length()).toInt(&ok);
if (!ok || (portNumber < 0) || (portNumber > 255))
continue;
} else {
......@@ -344,7 +344,7 @@ QList<QSerialPortInfo> availablePortsByUdev()
}
}
serialPortInfoList.append(serialPortInfo);
serialPortInfoList.append(priv);
}
return serialPortInfoList;
......@@ -401,4 +401,18 @@ bool QSerialPortInfo::isValid() const
return f.exists();
}
QString QSerialPortInfoPrivate::portNameToSystemLocation(const QString &source)
{
return (source.startsWith(QLatin1Char('/'))
|| source.startsWith(QStringLiteral("./"))
|| source.startsWith(QStringLiteral("../")))
? source : (QStringLiteral("/dev/") + source);
}
QString QSerialPortInfoPrivate::portNameFromSystemLocation(const QString &source)
{
return source.startsWith(QStringLiteral("/dev/"))
? source.mid(5) : source;
}
QT_END_NAMESPACE
......@@ -312,23 +312,23 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
continue;
}
QSerialPortInfo serialPortInfo;
QSerialPortInfoPrivate priv;
serialPortInfo.d_ptr->portName = portName;
serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(portName);
serialPortInfo.d_ptr->description = deviceDescription(deviceInfoSet, &deviceInfoData);
serialPortInfo.d_ptr->manufacturer = deviceManufacturer(deviceInfoSet, &deviceInfoData);
priv.portName = portName;
priv.device = QSerialPortInfoPrivate::portNameToSystemLocation(portName);
priv.description = deviceDescription(deviceInfoSet, &deviceInfoData);
priv.manufacturer = deviceManufacturer(deviceInfoSet, &deviceInfoData);
const QString instanceIdentifier = deviceInstanceIdentifier(deviceInfoData.DevInst);
serialPortInfo.d_ptr->serialNumber =
priv.serialNumber =
deviceSerialNumber(instanceIdentifier, deviceInfoData.DevInst);
serialPortInfo.d_ptr->vendorIdentifier =
deviceVendorIdentifier(instanceIdentifier, serialPortInfo.d_ptr->hasVendorIdentifier);
serialPortInfo.d_ptr->productIdentifier =
deviceProductIdentifier(instanceIdentifier, serialPortInfo.d_ptr->hasProductIdentifier);
priv.vendorIdentifier =
deviceVendorIdentifier(instanceIdentifier, priv.hasVendorIdentifier);
priv.productIdentifier =
deviceProductIdentifier(instanceIdentifier, priv.hasProductIdentifier);
serialPortInfoList.append(serialPortInfo);
serialPortInfoList.append(priv);
}
::SetupDiDestroyDeviceInfoList(deviceInfoSet);
}
......@@ -336,10 +336,10 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
foreach (const QString &portName, portNamesFromHardwareDeviceMap()) {
if (std::find_if(serialPortInfoList.begin(), serialPortInfoList.end(),
SerialPortNameEqualFunctor(portName)) == serialPortInfoList.end()) {
QSerialPortInfo serialPortInfo;
serialPortInfo.d_ptr->portName = portName;
serialPortInfo.d_ptr->device = QSerialPortPrivate::portNameToSystemLocation(portName);
serialPortInfoList.append(serialPortInfo);
QSerialPortInfoPrivate priv;
priv.portName = portName;
priv.device = QSerialPortInfoPrivate::portNameToSystemLocation(portName);
serialPortInfoList.append(priv);
}
}
......@@ -379,4 +379,17 @@ bool QSerialPortInfo::isValid() const
return true;
}
QString QSerialPortInfoPrivate::portNameToSystemLocation(const QString &source)
{
return source.startsWith(QStringLiteral("COM"))
? (QStringLiteral("\\\\.\\") + source) : source;
}
QString QSerialPortInfoPrivate::portNameFromSystemLocation(const QString &source)
{
return (source.startsWith(QStringLiteral("\\\\.\\"))
|| source.startsWith(QStringLiteral("//./")))
? source.mid(4) : source;
}
QT_END_NAMESPACE
......@@ -105,13 +105,13 @@ QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
&di);
if (hSearch != INVALID_HANDLE_VALUE) {
do {
QSerialPortInfo serialPortInfo;
serialPortInfo.d_ptr->device = QString::fromWCharArray(di.szLegacyName);
serialPortInfo.d_ptr->portName = QSerialPortPrivate::portNameFromSystemLocation(serialPortInfo.d_ptr->device);
serialPortInfo.d_ptr->description = findDescription(HKEY_LOCAL_MACHINE,
QString::fromWCharArray(di.szDeviceKey));
QSerialPortInfoPrivate priv;
priv.device = QString::fromWCharArray(di.szLegacyName);
priv.portName = QSerialPortInfoPrivate::portNameFromSystemLocation(priv.device);
priv.description = findDescription(HKEY_LOCAL_MACHINE,
QString::fromWCharArray(di.szDeviceKey));
serialPortInfoList.append(serialPortInfo);
serialPortInfoList.append(priv);
} while (::FindNextDevice(hSearch, &di));
::FindClose(hSearch);
......@@ -153,4 +153,16 @@ bool QSerialPortInfo::isValid() const
return true;
}
QString QSerialPortInfoPrivate::portNameToSystemLocation(const QString &source)
{
return source.endsWith(QLatin1Char(':'))
? source : (source + QLatin1Char(':'));
}
QString QSerialPortInfoPrivate::portNameFromSystemLocation(const QString &source)
{
return source.endsWith(QLatin1Char(':'))
? source.mid(0, source.size() - 1) : source;
}
QT_END_NAMESPACE
......@@ -72,7 +72,7 @@ static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 07
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
register int fd;
int fd;
EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode));
// unknown flags are ignored, so we have no way of verifying if
......@@ -104,7 +104,7 @@ static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
static inline int qt_safe_close(int fd)
{
register int ret;
int ret;
EINTR_LOOP(ret, QT_CLOSE(fd));
return ret;
}
......
TEMPLATE = subdirs
SUBDIRS += qserialport cmake
SUBDIRS += qserialport qserialportinfo qserialportinfoprivate cmake
!contains(QT_CONFIG, private_tests): SUBDIRS -= \
qserialportinfoprivate