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);
249 tio.c_cflag |= (CLOCAL | CREAD);
255 qCWarning(AndroidSerialPortLog) <<
"Unsupported baud rate:" << baudRate;
260 (void) ::cfsetispeed(&tio, speed);
261 (void) ::cfsetospeed(&tio, speed);
263 tio.c_cflag &= ~CSIZE;
282 tio.c_cflag &= ~PARENB;
285 tio.c_cflag |= PARENB;
286 tio.c_cflag &= ~PARODD;
289 tio.c_cflag |= (PARENB | PARODD);
292 qCWarning(AndroidSerialPortLog) <<
"Unsupported parity:" << parity_;
300 tio.c_cflag &= ~CSTOPB;
303 tio.c_cflag |= CSTOPB;
306 qCWarning(AndroidSerialPortLog) <<
"Unsupported stop bits:" << stopBits_;
312 switch (flowControl_) {
314 tio.c_cflag &= ~CRTSCTS;
315 tio.c_iflag &= ~(IXON | IXOFF);
318 tio.c_cflag |= CRTSCTS;
319 tio.c_iflag &= ~(IXON | IXOFF);
322 tio.c_cflag &= ~CRTSCTS;
323 tio.c_iflag |= (IXON | IXOFF);
326 qCWarning(AndroidSerialPortLog) <<
"Unsupported flow control:" << flowControl_;
328 QSerialPort::tr(
"Unsupported flow control")));
332 if (::tcsetattr(
descriptor, TCSANOW, &tio) == -1) {
333 qCWarning(AndroidSerialPortLog) <<
"tcsetattr failed on" <<
systemLocation <<
":" << strerror(errno);
341bool QSerialPortPrivate::_posixClear(QSerialPort::Directions directions)
355 qCWarning(AndroidSerialPortLog) <<
"tcflush failed on" <<
systemLocation <<
":" << strerror(errno);
363QSerialPort::PinoutSignals QSerialPortPrivate::_posixPinoutSignals()
366 if (::ioctl(
descriptor, TIOCMGET, &arg) == -1) {
367 qCWarning(AndroidSerialPortLog) <<
"TIOCMGET failed on" <<
systemLocation <<
":" << strerror(errno);
373 if (arg & TIOCM_DTR) {
376 if (arg & TIOCM_RTS) {
379 if (arg & TIOCM_CTS) {
382 if (arg & TIOCM_DSR) {
385 if (arg & TIOCM_CAR) {
388 if (arg & TIOCM_RNG) {
391 if (arg & TIOCM_ST) {
394 if (arg & TIOCM_SR) {
403 return (::ioctl(descriptor, set ? TIOCMBIS : TIOCMBIC, &line) != -1);
406bool QSerialPortPrivate::_posixSetDataTerminalReady(
bool set)
409 qCWarning(AndroidSerialPortLog) <<
"Failed to set DTR on" <<
systemLocation <<
":" << strerror(errno);
417bool QSerialPortPrivate::_posixSetRequestToSend(
bool set)
420 qCWarning(AndroidSerialPortLog) <<
"Failed to set RTS on" <<
systemLocation <<
":" << strerror(errno);
428bool QSerialPortPrivate::_posixSetBreakEnabled(
bool set)
430 if (::ioctl(
descriptor, set ? TIOCSBRK : TIOCCBRK) == -1) {
431 qCWarning(AndroidSerialPortLog) <<
"Failed to set break on" <<
systemLocation <<
":" << strerror(errno);
439bool QSerialPortPrivate::_posixWaitForReadyRead(
int msecs)
442 QMutexLocker locker(&_readMutex);
443 if (!buffer.isEmpty()) {
446 if (_pendingSizeLocked() > 0) {
447 (void) _drainPendingDataLocked();
452 QDeadlineTimer deadline(msecs);
455 const int pollTimeout = deadline.isForever() ? -1 :
static_cast<int>(qMax<qint64>(0, deadline.remainingTime()));
456 const int ret = ::poll(&pfd, 1, pollTimeout);
458 if (errno == EINTR) {
461 qCWarning(AndroidSerialPortLog) <<
"Poll error on" <<
systemLocation <<
":" << strerror(errno);
469 _posixReadActivated();
472 QMutexLocker locker(&_readMutex);
473 if (_pendingSizeLocked() > 0) {
474 (void) _drainPendingDataLocked();
476 if (!buffer.isEmpty()) {
489 if (pfd.revents & (POLLERR | POLLHUP | POLLNVAL)) {
497 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)