5#include <QtCore/QDeadlineTimer>
6#include <QtCore/QSocketNotifier>
91bool QSerialPortPrivate::_posixOpen(QIODevice::OpenMode mode)
95 qCDebug(AndroidSerialPortLog) <<
"Opening (POSIX)" <<
systemLocation;
97 int flags = O_NOCTTY | O_NONBLOCK;
98 if ((mode & QIODevice::ReadWrite) == QIODevice::ReadWrite) {
100 }
else if (mode & QIODevice::WriteOnly) {
108 qCWarning(AndroidSerialPortLog) <<
"Error opening" <<
systemLocation <<
":" << strerror(errno);
117 qCWarning(AndroidSerialPortLog) <<
systemLocation <<
"is not a tty device";
125 qCDebug(AndroidSerialPortLog) <<
"Failed to set exclusive access on" <<
systemLocation <<
":"
129 if (!_posixApplyPortSettings(
inputBaudRate, dataBits, stopBits, parity, flowControl)) {
130 qCWarning(AndroidSerialPortLog) <<
"Failed to set serial port parameters for" <<
systemLocation;
137 if (mode & QIODevice::ReadOnly) {
138 _posixReadNotifier =
new QSocketNotifier(
descriptor, QSocketNotifier::Read, q);
139 QObject::connect(_posixReadNotifier, &QSocketNotifier::activated, q, [
this]() { _posixReadActivated(); });
145void QSerialPortPrivate::_posixClose()
147 qCDebug(AndroidSerialPortLog) <<
"Closing (POSIX)" <<
systemLocation;
149 delete _posixReadNotifier;
150 _posixReadNotifier =
nullptr;
154 qCWarning(AndroidSerialPortLog) <<
"Failed to close" <<
systemLocation <<
":" << strerror(errno);
160bool QSerialPortPrivate::_posixStartAsyncRead()
162 if (_posixReadNotifier) {
163 _posixReadNotifier->setEnabled(
true);
167 _scheduleReadyRead();
172bool QSerialPortPrivate::_posixStopAsyncRead()
174 if (_posixReadNotifier) {
175 _posixReadNotifier->setEnabled(
false);
181void QSerialPortPrivate::_posixReadActivated()
186 const ssize_t bytesRead = ::read(
descriptor, readBuf,
sizeof(readBuf));
189 if (bytesRead <
static_cast<ssize_t
>(
sizeof(readBuf))) {
195 if ((bytesRead < 0) && (errno == EINTR)) {
199 if ((bytesRead < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK)) {
200 qCWarning(AndroidSerialPortLog) <<
"Read error on" <<
systemLocation <<
":" << strerror(errno);
208qint64 QSerialPortPrivate::_posixWrite(
const char* data, qint64 maxSize,
int timeoutMs)
210 qint64 totalWritten = 0;
211 QDeadlineTimer deadline(timeoutMs);
213 while (totalWritten < maxSize) {
214 const ssize_t written = ::write(
descriptor, data + totalWritten,
static_cast<size_t>(maxSize - totalWritten));
216 totalWritten += written;
220 if ((written < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR)) {
221 qCWarning(AndroidSerialPortLog) <<
"Write error on" <<
systemLocation <<
":" << strerror(errno);
225 if (deadline.hasExpired()) {
226 qCWarning(AndroidSerialPortLog) <<
"Write timeout on" <<
systemLocation;
231 const int pollTimeout = deadline.isForever() ? -1 :
static_cast<int>(qMax<qint64>(0, deadline.remainingTime()));
232 (void) ::poll(&pfd, 1, pollTimeout);
238qint64 QSerialPortPrivate::_posixWriteWithProgress(
const char* data, qint64 maxSize,
int timeoutMs)
240 qint64 totalWritten = 0;
242 const QDeadlineTimer deadline =
243 timeoutMs == 0 ? QDeadlineTimer(QDeadlineTimer::Forever) : QDeadlineTimer(timeoutMs);
245 while (totalWritten < maxSize) {
246 const ssize_t written = ::write(
descriptor, data + totalWritten,
static_cast<size_t>(maxSize - totalWritten));
248 totalWritten += written;
252 if ((written < 0) && (errno != EAGAIN) && (errno != EWOULDBLOCK) && (errno != EINTR)) {
253 qCWarning(AndroidSerialPortLog) <<
"Write error on" <<
systemLocation <<
":" << strerror(errno);
255 return totalWritten > 0 ? totalWritten : -1;
258 if (deadline.hasExpired()) {
260 qCDebug(AndroidSerialPortLog) <<
"Write timeout on" <<
systemLocation <<
"after" << totalWritten <<
"bytes";
265 const int pollTimeout = deadline.isForever() ? -1 :
static_cast<int>(qMax<qint64>(0, deadline.remainingTime()));
266 (void) ::poll(&pfd, 1, pollTimeout);
283 tio.c_cflag |= (CLOCAL | CREAD);
289 qCWarning(AndroidSerialPortLog) <<
"Unsupported baud rate:" << baudRate;
294 (void) ::cfsetispeed(&tio, speed);
295 (void) ::cfsetospeed(&tio, speed);
297 tio.c_cflag &= ~CSIZE;
316 tio.c_cflag &= ~PARENB;
319 tio.c_cflag |= PARENB;
320 tio.c_cflag &= ~PARODD;
323 tio.c_cflag |= (PARENB | PARODD);
326 qCWarning(AndroidSerialPortLog) <<
"Unsupported parity:" << parity_;
334 tio.c_cflag &= ~CSTOPB;
337 tio.c_cflag |= CSTOPB;
340 qCWarning(AndroidSerialPortLog) <<
"Unsupported stop bits:" << stopBits_;
346 switch (flowControl_) {
348 tio.c_cflag &= ~CRTSCTS;
349 tio.c_iflag &= ~(IXON | IXOFF);
352 tio.c_cflag |= CRTSCTS;
353 tio.c_iflag &= ~(IXON | IXOFF);
356 tio.c_cflag &= ~CRTSCTS;
357 tio.c_iflag |= (IXON | IXOFF);
360 qCWarning(AndroidSerialPortLog) <<
"Unsupported flow control:" << flowControl_;
362 QSerialPort::tr(
"Unsupported flow control")));
366 if (::tcsetattr(
descriptor, TCSANOW, &tio) == -1) {
367 qCWarning(AndroidSerialPortLog) <<
"tcsetattr failed on" <<
systemLocation <<
":" << strerror(errno);
375bool QSerialPortPrivate::_posixClear(QSerialPort::Directions directions)
389 qCWarning(AndroidSerialPortLog) <<
"tcflush failed on" <<
systemLocation <<
":" << strerror(errno);
397QSerialPort::PinoutSignals QSerialPortPrivate::_posixPinoutSignals()
400 if (::ioctl(
descriptor, TIOCMGET, &arg) == -1) {
401 qCWarning(AndroidSerialPortLog) <<
"TIOCMGET failed on" <<
systemLocation <<
":" << strerror(errno);
407 if (arg & TIOCM_DTR) {
410 if (arg & TIOCM_RTS) {
413 if (arg & TIOCM_CTS) {
416 if (arg & TIOCM_DSR) {
419 if (arg & TIOCM_CAR) {
422 if (arg & TIOCM_RNG) {
425 if (arg & TIOCM_ST) {
428 if (arg & TIOCM_SR) {
437 return (::ioctl(descriptor, set ? TIOCMBIS : TIOCMBIC, &line) != -1);
440bool QSerialPortPrivate::_posixSetDataTerminalReady(
bool set)
443 const int dtrError = errno;
446 qCDebug(AndroidSerialPortLog) <<
"Failed to set DTR on" <<
systemLocation <<
":" << strerror(dtrError);
454bool QSerialPortPrivate::_posixSetRequestToSend(
bool set)
457 const int rtsError = errno;
460 qCDebug(AndroidSerialPortLog) <<
"Failed to set RTS on" <<
systemLocation <<
":" << strerror(rtsError);
468bool QSerialPortPrivate::_posixSetBreakEnabled(
bool set)
470 if (::ioctl(
descriptor, set ? TIOCSBRK : TIOCCBRK) == -1) {
471 qCWarning(AndroidSerialPortLog) <<
"Failed to set break on" <<
systemLocation <<
":" << strerror(errno);
479bool QSerialPortPrivate::_posixWaitForReadyRead(
int msecs)
482 QMutexLocker locker(&_readMutex);
483 if (!buffer.isEmpty()) {
486 if (_pendingSizeLocked() > 0) {
487 (void) _drainPendingDataLocked();
492 QDeadlineTimer deadline(msecs);
495 const int pollTimeout = deadline.isForever() ? -1 :
static_cast<int>(qMax<qint64>(0, deadline.remainingTime()));
496 const int ret = ::poll(&pfd, 1, pollTimeout);
498 if (errno == EINTR) {
501 qCWarning(AndroidSerialPortLog) <<
"Poll error on" <<
systemLocation <<
":" << strerror(errno);
509 _posixReadActivated();
512 QMutexLocker locker(&_readMutex);
513 if (_pendingSizeLocked() > 0) {
514 (void) _drainPendingDataLocked();
516 if (!buffer.isEmpty()) {
529 if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
537 if (deadline.hasExpired()) {
void setError(const QSerialPortErrorInfo &errorInfo)
bool open(QIODevice::OpenMode mode)
void newDataArrived(const char *bytes, int length)
Provides functions to access serial ports.
DataBits
This enum describes the number of data bits used.
Parity
This enum describes the parity scheme used.
SerialPortError
This enum describes the errors that may be contained by the QSerialPort::error property.
@ UnsupportedOperationError
@ DataTerminalReadySignal
@ DataCarrierDetectSignal
@ SecondaryTransmittedDataSignal
@ SecondaryReceivedDataSignal
StopBits
This enum describes the number of stop bits used.
FlowControl
This enum describes the flow control used.
speed_t baudRateToSpeed(qint32 baudRate)
static bool setControlLine(int descriptor, int line, bool set)