diff -rN ./serialport/qserialport_android.cpp ./aserialport/qserialport_android.cpp 0a1,1523 > /**************************************************************************** > ** > ** Copyright (C) 2012 Denis Shienkov > ** Copyright (C) 2012 Laszlo Papp > ** Copyright (C) 2012 Andre Hartmann > ** Contact: http://www.qt-project.org/legal > ** > ** This file is part of the QtSerialPort module of the Qt Toolkit. > ** > ** $QT_BEGIN_LICENSE:LGPL$ > ** Commercial License Usage > ** Licensees holding valid commercial Qt licenses may use this file in > ** accordance with the commercial license agreement provided with the > ** Software or, alternatively, in accordance with the terms contained in > ** a written agreement between you and Digia. For licensing terms and > ** conditions see http://qt.digia.com/licensing. For further information > ** use the contact form at http://qt.digia.com/contact-us. > ** > ** GNU Lesser General Public License Usage > ** Alternatively, this file may be used under the terms of the GNU Lesser > ** General Public License version 2.1 as published by the Free Software > ** Foundation and appearing in the file LICENSE.LGPL included in the > ** packaging of this file. Please review the following information to > ** ensure the GNU Lesser General Public License version 2.1 requirements > ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. > ** > ** In addition, as a special exception, Digia gives you certain additional > ** rights. These rights are described in the Digia Qt LGPL Exception > ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. > ** > ** GNU General Public License Usage > ** Alternatively, this file may be used under the terms of the GNU > ** General Public License version 3.0 as published by the Free Software > ** Foundation and appearing in the file LICENSE.GPL included in the > ** packaging of this file. Please review the following information to > ** ensure the GNU General Public License version 3.0 requirements will be > ** met: http://www.gnu.org/copyleft/gpl.html. > ** > ** > ** $QT_END_LICENSE$ > ** > ****************************************************************************/ > > #include "qserialport_android_p.h" > #include "qttylocker_unix_p.h" > > #include > #include > #include > #include > #include > > # define FNDELAY O_NDELAY > > #include > #include > #include > > QT_BEGIN_NAMESPACE > > JavaVM *m_javaVM; > > JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* /*reserved*/) > { > m_javaVM = vm; > return JNI_VERSION_1_6; > } > > class ReadNotifier : public QSocketNotifier > { > public: > ReadNotifier(QSerialPortPrivate *d, QObject *parent) > : QSocketNotifier(d->descriptor, QSocketNotifier::Read, parent) > , dptr(d) > {} > > protected: > virtual bool event(QEvent *e) { > bool ret = QSocketNotifier::event(e); > if (ret) > dptr->readNotification(); > return ret; > } > > private: > QSerialPortPrivate *dptr; > }; > > class WriteNotifier : public QSocketNotifier > { > public: > WriteNotifier(QSerialPortPrivate *d, QObject *parent) > : QSocketNotifier(d->descriptor, QSocketNotifier::Write, parent) > , dptr(d) > {} > > protected: > virtual bool event(QEvent *e) { > bool ret = QSocketNotifier::event(e); > if (ret) > dptr->writeNotification(QSerialPortPrivateData::WriteChunkSize); > return ret; > } > > private: > QSerialPortPrivate *dptr; > }; > > class ExceptionNotifier : public QSocketNotifier > { > public: > ExceptionNotifier(QSerialPortPrivate *d, QObject *parent) > : QSocketNotifier(d->descriptor, QSocketNotifier::Exception, parent) > , dptr(d) > {} > > protected: > virtual bool event(QEvent *e) { > bool ret = QSocketNotifier::event(e); > if (ret) > dptr->exceptionNotification(); > return ret; > } > > private: > QSerialPortPrivate *dptr; > }; > > QSerialPortPrivate::QSerialPortPrivate(QSerialPort *q) > : QSerialPortPrivateData(q) > , descriptor(-1) > , isCustomBaudRateSupported(false) > , readNotifier(0) > , writeNotifier(0) > , exceptionNotifier(0) > , readPortNotifierCalled(false) > , readPortNotifierState(false) > , readPortNotifierStateSet(false) > , emittedReadyRead(false) > , emittedBytesWritten(false) > , m_socket(0) > , use_bluetooth_socket(false) > { > } > > bool QSerialPortPrivate::open(QIODevice::OpenMode mode) > { > use_bluetooth_socket = systemLocation.contains("bt://"); > if (use_bluetooth_socket) > { > bool ok = true; > // Get Java enveronment > jint res = m_javaVM->AttachCurrentThread(&m_JEnv, NULL); > if (res < 0) > { > ok = false; > qDebug("error get Java enveronment!"); > } > > JAVA_GET_CLASS(BAClass, "android/bluetooth/BluetoothAdapter") > JAVA_GET_CLASS(BDClass, "android/bluetooth/BluetoothDevice") > JAVA_GET_CLASS(UUIDClass, "java/util/UUID") > JAVA_GET_CLASS(BSClass, "android/bluetooth/BluetoothSocket") > JAVA_GET_CLASS(m_BOSClass, "java/io/OutputStream") > JAVA_GET_CLASS(m_BISClass, "java/io/InputStream") > > JAVA_GET_METHOD(BAClass, getDefaultAdapter, "()Landroid/bluetooth/BluetoothAdapter;", Static) > JAVA_GET_METHOD(BAClass, isEnabled, "()Z") > JAVA_GET_METHOD(BAClass, cancelDiscovery, "()Z") > JAVA_GET_METHOD(BAClass, getRemoteDevice, "(Ljava/lang/String;)Landroid/bluetooth/BluetoothDevice;") > JAVA_GET_METHOD(BDClass, createRfcommSocketToServiceRecord, "(Ljava/util/UUID;)Landroid/bluetooth/BluetoothSocket;") > JAVA_GET_METHOD(UUIDClass, fromString, "(Ljava/lang/String;)Ljava/util/UUID;", Static) > JAVA_GET_METHOD(BSClass, getInputStream, "()Ljava/io/InputStream;") > JAVA_GET_METHOD(BSClass, getOutputStream, "()Ljava/io/OutputStream;") > JAVA_GET_METHOD(BSClass, connect, "()V") > JAVA_GET_METHOD(BSClass, isConnected, "()Z") > > JAVA_GET_METHOD_GLOBAL(m_BOSClass, write, "([B)V") > JAVA_GET_METHOD_GLOBAL(m_BISClass, read, "([B)I") > JAVA_GET_METHOD_GLOBAL(m_BISClass, available, "()I") > > // Get Bluetooth adapter > jobject BAObject; > if (ok) > { > BAObject = m_JEnv->CallStaticObjectMethod(BAClass, BAClass_getDefaultAdapter); > if (BAObject == NULL) > { > ok = false; > } > } > > // Check Bluetooth on enabled > jboolean b = m_JEnv->CallBooleanMethod(BAObject, BAClass_isEnabled); > if (!b) > { > ok = false; > } > if (ok) > { > jstring mac = m_JEnv->NewStringUTF(portNameFromSystemLocation(systemLocation).mid(5).toLatin1().data()); > jobject device = m_JEnv->CallObjectMethod(BAObject, BAClass_getRemoteDevice, mac); > if (m_JEnv->ExceptionOccurred()) > { > ok = false; > } > else > { > jstring uuid = m_JEnv->NewStringUTF(RFCOMM_UUID); > jobject ouuid = m_JEnv->CallStaticObjectMethod(UUIDClass, UUIDClass_fromString, uuid); > m_socket = m_JEnv->CallObjectMethod(device, BDClass_createRfcommSocketToServiceRecord, ouuid); > if (m_JEnv->ExceptionOccurred()) > { > ok = false; > m_socket = 0; > } > if (ok) > { > m_JEnv->CallBooleanMethod(BAObject, BAClass_cancelDiscovery); > if (m_JEnv->ExceptionOccurred()) > { > ok = false; > } > m_JEnv->CallVoidMethod(m_socket, BSClass_connect); > if (m_JEnv->ExceptionOccurred()) > { > ok = false; > } > jboolean connected = m_JEnv->CallBooleanMethod(m_socket, BSClass_isConnected); > if (!connected) > { > ok = false; > } > else > { > m_jistream = m_JEnv->CallObjectMethod(m_socket, BSClass_getInputStream); > m_jostream = m_JEnv->CallObjectMethod(m_socket, BSClass_getOutputStream); > if (m_JEnv->ExceptionOccurred()) > { > ok = false; > } > } > > } > } > } > > if (!ok) > { > m_JEnv->ExceptionDescribe(); > m_JEnv->ExceptionClear(); > m_javaVM->DetachCurrentThread(); > use_bluetooth_socket = false; > } > return ok; > } > /*QByteArray portName = portNameFromSystemLocation(systemLocation).toLocal8Bit(); > const char *ptr = portName.constData(); > > bool byCurrPid = false; > if (QTtyLocker::isLocked(ptr, &byCurrPid)) { > q_ptr->setError(QSerialPort::PermissionError); > return false; > }*/ > > int flags = O_NOCTTY | O_NONBLOCK; > > switch (mode & QIODevice::ReadWrite) { > case QIODevice::WriteOnly: > flags |= O_WRONLY; > break; > case QIODevice::ReadWrite: > flags |= O_RDWR; > break; > default: > flags |= O_RDONLY; > break; > } > > descriptor = ::open(systemLocation.toLocal8Bit().constData(), flags); > > if (descriptor == -1) { > q_ptr->setError(decodeSystemError()); > return false; > } > > ::fcntl(descriptor, F_SETFL, FNDELAY); > > /*QTtyLocker::lock(ptr); > if (!QTtyLocker::isLocked(ptr, &byCurrPid)) { > q_ptr->setError(QSerialPort::PermissionError); > return false; > }*/ > > #ifdef TIOCEXCL > ::ioctl(descriptor, TIOCEXCL); > #endif > > if (::tcgetattr(descriptor, &restoredTermios) == -1) { > q_ptr->setError(decodeSystemError()); > return false; > } > > currentTermios = restoredTermios; > ::cfmakeraw(¤tTermios); > currentTermios.c_cflag |= CLOCAL; > currentTermios.c_cc[VTIME] = 0; > currentTermios.c_cc[VMIN] = 0; > > if (mode & QIODevice::ReadOnly) > currentTermios.c_cflag |= CREAD; > > if (!updateTermios()) > return false; > > setExceptionNotificationEnabled(true); > > if ((flags & O_WRONLY) == 0) > setReadNotificationEnabled(true); > > detectDefaultSettings(); > return true; > } > > void QSerialPortPrivate::close() > { > if (use_bluetooth_socket) > { > bool ok = true; > JAVA_GET_CLASS(BSClass, "android/bluetooth/BluetoothSocket") > JAVA_GET_METHOD(BSClass, close, "()V") > > m_JEnv->CallVoidMethod(m_socket, BSClass_close); > if (m_JEnv->ExceptionOccurred()) > { > m_JEnv->ExceptionDescribe(); > m_JEnv->ExceptionClear(); > } > m_javaVM->DetachCurrentThread(); > use_bluetooth_socket = false; > return; > } > > if (settingsRestoredOnClose) { > ::tcsetattr(descriptor, TCSANOW, &restoredTermios); > } > > #ifdef TIOCNXCL > ::ioctl(descriptor, TIOCNXCL); > #endif > > if (readNotifier) { > readNotifier->setEnabled(false); > readNotifier->deleteLater(); > readNotifier = 0; > } > > if (writeNotifier) { > writeNotifier->setEnabled(false); > writeNotifier->deleteLater(); > writeNotifier = 0; > } > > if (exceptionNotifier) { > exceptionNotifier->setEnabled(false); > exceptionNotifier->deleteLater(); > exceptionNotifier = 0; > } > > ::close(descriptor); > > /*QByteArray portName = portNameFromSystemLocation(systemLocation).toLocal8Bit(); > const char *ptr = portName.constData(); > > bool byCurrPid = false; > if (QTtyLocker::isLocked(ptr, &byCurrPid) && byCurrPid) > QTtyLocker::unlock(ptr);*/ > > descriptor = -1; > isCustomBaudRateSupported = false; > } > > QSerialPort::PinoutSignals QSerialPortPrivate::pinoutSignals() const > { > if (use_bluetooth_socket) > { > return 0; > } > > int arg = 0; > QSerialPort::PinoutSignals ret = QSerialPort::NoSignal; > > if (::ioctl(descriptor, TIOCMGET, &arg) == -1) { > q_ptr->setError(decodeSystemError()); > return ret; > } > > #ifdef TIOCM_LE > if (arg & TIOCM_LE) > ret |= QSerialPort::DataSetReadySignal; > #endif > #ifdef TIOCM_DTR > if (arg & TIOCM_DTR) > ret |= QSerialPort::DataTerminalReadySignal; > #endif > #ifdef TIOCM_RTS > if (arg & TIOCM_RTS) > ret |= QSerialPort::RequestToSendSignal; > #endif > #ifdef TIOCM_ST > if (arg & TIOCM_ST) > ret |= QSerialPort::SecondaryTransmittedDataSignal; > #endif > #ifdef TIOCM_SR > if (arg & TIOCM_SR) > ret |= QSerialPort::SecondaryReceivedDataSignal; > #endif > #ifdef TIOCM_CTS > if (arg & TIOCM_CTS) > ret |= QSerialPort::ClearToSendSignal; > #endif > #ifdef TIOCM_CAR > if (arg & TIOCM_CAR) > ret |= QSerialPort::DataCarrierDetectSignal; > #elif defined TIOCM_CD > if (arg & TIOCM_CD) > ret |= QSerialPort::DataCarrierDetectSignal; > #endif > #ifdef TIOCM_RNG > if (arg & TIOCM_RNG) > ret |= QSerialPort::RingIndicatorSignal; > #elif defined TIOCM_RI > if (arg & TIOCM_RI) > ret |= QSerialPort::RingIndicatorSignal; > #endif > #ifdef TIOCM_DSR > if (arg & TIOCM_DSR) > ret |= QSerialPort::DataSetReadySignal; > #endif > > return ret; > } > > bool QSerialPortPrivate::setDataTerminalReady(bool set) > { > int status = TIOCM_DTR; > return ::ioctl(descriptor, set ? TIOCMBIS : TIOCMBIC, &status) != -1; > } > > bool QSerialPortPrivate::setRequestToSend(bool set) > { > int status = TIOCM_RTS; > return ::ioctl(descriptor, set ? TIOCMBIS : TIOCMBIC, &status) != -1; > } > > bool QSerialPortPrivate::flush() > { > #ifdef Q_OS_ANDROID > return writeNotification() && (::ioctl(descriptor, TCSBRK, 1) != -1); > #else > return writeNotification() && (::tcdrain(descriptor) != -1); > #endif > } > > bool QSerialPortPrivate::clear(QSerialPort::Directions dir) > { > return ::tcflush(descriptor, (dir == QSerialPort::AllDirections) > ? TCIOFLUSH : (dir & QSerialPort::Input) ? TCIFLUSH : TCOFLUSH) != -1; > } > > bool QSerialPortPrivate::sendBreak(int duration) > { > return ::tcsendbreak(descriptor, duration) != -1; > } > > bool QSerialPortPrivate::setBreak(bool set) > { > return ::ioctl(descriptor, set ? TIOCSBRK : TIOCCBRK) != -1; > } > > qint64 QSerialPortPrivate::systemInputQueueSize () const > { > int nbytes = 0; > #ifdef TIOCINQ > if (::ioctl(descriptor, TIOCINQ, &nbytes) == -1) > return -1; > #endif > return nbytes; > } > > qint64 QSerialPortPrivate::systemOutputQueueSize () const > { > int nbytes = 0; > #ifdef TIOCOUTQ > if (::ioctl(descriptor, TIOCOUTQ, &nbytes) == -1) > return -1; > #endif > return nbytes; > } > > qint64 QSerialPortPrivate::bytesAvailable() const > { > if (use_bluetooth_socket) > { > int avail = m_JEnv->CallIntMethod(m_jistream, m_BISClass_available); > if (m_JEnv->ExceptionOccurred()) > { > m_JEnv->ExceptionDescribe(); > m_JEnv->ExceptionClear(); > return 0; > } > return avail; > } > return readBuffer.size(); > } > > qint64 QSerialPortPrivate::readFromBuffer(char *data, qint64 maxSize) > { > if (use_bluetooth_socket) > { > if (bytesAvailable() == 0) > { > data[0] = 0; > return 0; > } > if (bytesAvailable() < maxSize) > { > maxSize = bytesAvailable(); > } > qint64 readed = 0; > jbyteArray jbuf = m_JEnv->NewByteArray(maxSize); > readed = m_JEnv->CallIntMethod(m_jistream, m_BISClass_read, jbuf); > if (m_JEnv->ExceptionOccurred()) > { > m_JEnv->ExceptionDescribe(); > m_JEnv->ExceptionClear(); > readed = -1; > } > jboolean isCopy; > jbyte *jdata = m_JEnv->GetByteArrayElements(jbuf, &isCopy); > for (int i(0); i < maxSize; i++) > { > data[i] = jdata[i]; > } > data[maxSize] = 0; > m_JEnv->ReleaseByteArrayElements(jbuf, jdata, 0); > m_JEnv->DeleteLocalRef(jbuf); > return readed; > } > > if (readBuffer.isEmpty()) > return 0; > > if (maxSize == 1) { > *data = readBuffer.getChar(); > if (readBuffer.isEmpty()) > setReadNotificationEnabled(true); > return 1; > } > > const qint64 bytesToRead = qMin(qint64(readBuffer.size()), maxSize); > qint64 readSoFar = 0; > while (readSoFar < bytesToRead) { > const char *ptr = readBuffer.readPointer(); > const int bytesToReadFromThisBlock = qMin(int(bytesToRead - readSoFar), > readBuffer.nextDataBlockSize()); > ::memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock); > readSoFar += bytesToReadFromThisBlock; > readBuffer.free(bytesToReadFromThisBlock); > } > > if (!isReadNotificationEnabled()) > setReadNotificationEnabled(true); > > if (readSoFar > 0) { > if (readBuffer.isEmpty()) > setReadNotificationEnabled(true); > return readSoFar; > } > > return readSoFar; > } > > qint64 QSerialPortPrivate::writeToBuffer(const char *data, qint64 maxSize) > { > if (use_bluetooth_socket) > { > qint64 written = 0; > jbyteArray jdata = m_JEnv->NewByteArray(maxSize); > m_JEnv->SetByteArrayRegion(jdata, 0, maxSize, reinterpret_cast(const_cast(data))); > m_JEnv->CallVoidMethod(m_jostream, m_BOSClass_write, jdata); > if (m_JEnv->ExceptionOccurred()) > { > m_JEnv->ExceptionDescribe(); > m_JEnv->ExceptionClear(); > written = -1; > } > else > { > written = maxSize; > } > m_JEnv->DeleteLocalRef(jdata); > return written; > } > > char *ptr = writeBuffer.reserve(maxSize); > if (maxSize == 1) > *ptr = *data; > else > ::memcpy(ptr, data, maxSize); > > const qint64 written = maxSize; > > if (!writeBuffer.isEmpty() && !isWriteNotificationEnabled()) > setWriteNotificationEnabled(true); > > return written; > } > > bool QSerialPortPrivate::waitForReadyRead(int msecs) > { > QElapsedTimer stopWatch; > > stopWatch.start(); > > do { > if (use_bluetooth_socket) > { > if (bytesAvailable() > 0) > { > return true; > } > } > else > { > bool readyToRead = false; > bool readyToWrite = false; > bool timedOut = false; > if (!waitForReadOrWrite(&readyToRead, &readyToWrite, true, !writeBuffer.isEmpty(), > timeoutValue(msecs, stopWatch.elapsed()), &timedOut)) { > q_ptr->setError(decodeSystemError()); > return false; > } > > if (readyToRead) { > if (readNotification()) > return true; > } > > if (readyToWrite) > writeNotification(WriteChunkSize); > } > > } while (msecs == -1 || timeoutValue(msecs, stopWatch.elapsed()) > 0); > return false; > } > > bool QSerialPortPrivate::waitForBytesWritten(int msecs) > { > if (use_bluetooth_socket) > { > return true; > } > > if (writeBuffer.isEmpty()) > 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)) { > q_ptr->setError(decodeSystemError()); > return false; > } > > if (readyToRead && !readNotification()) > return false; > > if (readyToWrite) > return writeNotification(WriteChunkSize); > } > return false; > } > > bool QSerialPortPrivate::setBaudRate(qint32 baudRate, QSerialPort::Directions dir) > { > if (use_bluetooth_socket) > { > return true; > } > bool ret = baudRate > 0; > > // prepare section > > if (ret) { > const qint32 unixBaudRate = QSerialPortPrivate::settingFromBaudRate(baudRate); > if (unixBaudRate > 0) { > // try prepate to set standard baud rate > // prepare to set standard baud rate > ret = !(((dir & QSerialPort::Input) && ::cfsetispeed(¤tTermios, unixBaudRate) < 0) > || ((dir & QSerialPort::Output) && ::cfsetospeed(¤tTermios, unixBaudRate) < 0)); > } else { > // try prepate to set custom baud rate > ret = false; > } > } > > // finally section > if (ret) // finally, set baud rate > ret = updateTermios(); > else > q_ptr->setError(decodeSystemError()); > return ret; > } > > bool QSerialPortPrivate::setDataBits(QSerialPort::DataBits dataBits) > { > if (use_bluetooth_socket) > { > return true; > } > > currentTermios.c_cflag &= ~CSIZE; > switch (dataBits) { > case QSerialPort::Data5: > currentTermios.c_cflag |= CS5; > break; > case QSerialPort::Data6: > currentTermios.c_cflag |= CS6; > break; > case QSerialPort::Data7: > currentTermios.c_cflag |= CS7; > break; > case QSerialPort::Data8: > currentTermios.c_cflag |= CS8; > break; > default: > currentTermios.c_cflag |= CS8; > break; > } > return updateTermios(); > } > > bool QSerialPortPrivate::setParity(QSerialPort::Parity parity) > { > if (use_bluetooth_socket) > { > return true; > } > > currentTermios.c_iflag &= ~(PARMRK | INPCK); > currentTermios.c_iflag |= IGNPAR; > > switch (parity) { > > #ifdef CMSPAR > // Here Installation parity only for GNU/Linux where the macro CMSPAR. > case QSerialPort::SpaceParity: > currentTermios.c_cflag &= ~PARODD; > currentTermios.c_cflag |= PARENB | CMSPAR; > break; > case QSerialPort::MarkParity: > currentTermios.c_cflag |= PARENB | CMSPAR | PARODD; > break; > #endif > case QSerialPort::NoParity: > currentTermios.c_cflag &= ~PARENB; > break; > case QSerialPort::EvenParity: > currentTermios.c_cflag &= ~PARODD; > currentTermios.c_cflag |= PARENB; > break; > case QSerialPort::OddParity: > currentTermios.c_cflag |= PARENB | PARODD; > break; > default: > currentTermios.c_cflag |= PARENB; > currentTermios.c_iflag |= PARMRK | INPCK; > currentTermios.c_iflag &= ~IGNPAR; > break; > } > > return updateTermios(); > } > > bool QSerialPortPrivate::setStopBits(QSerialPort::StopBits stopBits) > { > if (use_bluetooth_socket) > { > return true; > } > > switch (stopBits) { > case QSerialPort::OneStop: > currentTermios.c_cflag &= ~CSTOPB; > break; > case QSerialPort::TwoStop: > currentTermios.c_cflag |= CSTOPB; > break; > default: > currentTermios.c_cflag &= ~CSTOPB; > break; > } > return updateTermios(); > } > > bool QSerialPortPrivate::setFlowControl(QSerialPort::FlowControl flow) > { > if (use_bluetooth_socket) > { > return true; > } > > switch (flow) { > case QSerialPort::NoFlowControl: > currentTermios.c_cflag &= ~CRTSCTS; > currentTermios.c_iflag &= ~(IXON | IXOFF | IXANY); > break; > case QSerialPort::HardwareControl: > currentTermios.c_cflag |= CRTSCTS; > currentTermios.c_iflag &= ~(IXON | IXOFF | IXANY); > break; > case QSerialPort::SoftwareControl: > currentTermios.c_cflag &= ~CRTSCTS; > currentTermios.c_iflag |= IXON | IXOFF | IXANY; > break; > default: > currentTermios.c_cflag &= ~CRTSCTS; > currentTermios.c_iflag &= ~(IXON | IXOFF | IXANY); > break; > } > return updateTermios(); > } > > bool QSerialPortPrivate::setDataErrorPolicy(QSerialPort::DataErrorPolicy policy) > { > if (use_bluetooth_socket) > { > return true; > } > > tcflag_t parmrkMask = PARMRK; > #ifndef CMSPAR > // in space/mark parity emulation also used PARMRK flag > if (parity == QSerialPort::SpaceParity > || parity == QSerialPort::MarkParity) { > parmrkMask = 0; > } > #endif //CMSPAR > switch (policy) { > case QSerialPort::SkipPolicy: > currentTermios.c_iflag &= ~parmrkMask; > currentTermios.c_iflag |= IGNPAR | INPCK; > break; > case QSerialPort::PassZeroPolicy: > currentTermios.c_iflag &= ~(IGNPAR | parmrkMask); > currentTermios.c_iflag |= INPCK; > break; > case QSerialPort::IgnorePolicy: > currentTermios.c_iflag &= ~INPCK; > break; > case QSerialPort::StopReceivingPolicy: > currentTermios.c_iflag &= ~IGNPAR; > currentTermios.c_iflag |= parmrkMask | INPCK; > break; > default: > currentTermios.c_iflag &= ~INPCK; > break; > } > return updateTermios(); > } > > bool QSerialPortPrivate::readNotification() > { > // Prevent recursive calls > if (readPortNotifierCalled) { > if (!readPortNotifierStateSet) { > readPortNotifierStateSet = true; > readPortNotifierState = isReadNotificationEnabled(); > setReadNotificationEnabled(false); > } > } > > readPortNotifierCalled = true; > > // Always buffered, read data from the port into the read buffer > qint64 newBytes = readBuffer.size(); > qint64 bytesToRead = policy == QSerialPort::IgnorePolicy ? ReadChunkSize : 1; > > if (readBufferMaxSize && bytesToRead > (readBufferMaxSize - readBuffer.size())) { > bytesToRead = readBufferMaxSize - readBuffer.size(); > if (bytesToRead == 0) { > // Buffer is full. User must read data from the buffer > // before we can read more from the port. > return false; > } > } > > char *ptr = readBuffer.reserve(bytesToRead); > const qint64 readBytes = readFromPort(ptr, bytesToRead); > > if (readBytes <= 0) { > readBuffer.chop(bytesToRead); > return false; > } > > readBuffer.chop(bytesToRead - qMax(readBytes, qint64(0))); > > newBytes = readBuffer.size() - newBytes; > > // If read buffer is full, disable the read port notifier. > if (readBufferMaxSize && readBuffer.size() == readBufferMaxSize) > setReadNotificationEnabled(false); > > // only emit readyRead() when not recursing, and only if there is data available > const bool hasData = newBytes > 0; > > if (!emittedReadyRead && hasData) { > emittedReadyRead = true; > emit q_ptr->readyRead(); > emittedReadyRead = false; > } > > if (!hasData) > setReadNotificationEnabled(true); > > // reset the read port notifier state if we reentered inside the > // readyRead() connected slot. > if (readPortNotifierStateSet > && readPortNotifierState != isReadNotificationEnabled()) { > setReadNotificationEnabled(readPortNotifierState); > readPortNotifierStateSet = false; > } > return true; > } > > bool QSerialPortPrivate::writeNotification(int maxSize) > { > const int tmp = writeBuffer.size(); > > if (writeBuffer.isEmpty()) { > setWriteNotificationEnabled(false); > return false; > } > > int nextSize = qMin(writeBuffer.nextDataBlockSize(), maxSize); > > const char *ptr = writeBuffer.readPointer(); > > // Attempt to write it chunk. > qint64 written = writeToPort(ptr, nextSize); > if (written < 0) > return false; > > // Remove what we wrote so far. > writeBuffer.free(written); > if (written > 0) { > // Don't emit bytesWritten() recursively. > if (!emittedBytesWritten) { > emittedBytesWritten = true; > emit q_ptr->bytesWritten(written); > emittedBytesWritten = false; > } > } > > if (writeBuffer.isEmpty()) > setWriteNotificationEnabled(false); > > return (writeBuffer.size() < tmp); > } > > bool QSerialPortPrivate::exceptionNotification() > { > QSerialPort::SerialPortError error = decodeSystemError(); > q_ptr->setError(error); > > return true; > } > > bool QSerialPortPrivate::updateTermios() > { > if (::tcsetattr(descriptor, TCSANOW, ¤tTermios) == -1) { > q_ptr->setError(decodeSystemError()); > return false; > } > return true; > } > > void QSerialPortPrivate::detectDefaultSettings() > { > // Detect baud rate. > const speed_t inputUnixBaudRate = ::cfgetispeed(¤tTermios); > const speed_t outputUnixBaudRate = ::cfgetospeed(¤tTermios); > bool isCustomBaudRateCurrentSet = false; > > if (!isCustomBaudRateSupported || !isCustomBaudRateCurrentSet) { > inputBaudRate = QSerialPortPrivate::baudRateFromSetting(inputUnixBaudRate); > outputBaudRate = QSerialPortPrivate::baudRateFromSetting(outputUnixBaudRate); > } > > // Detect databits. > switch (currentTermios.c_cflag & CSIZE) { > case CS5: > dataBits = QSerialPort::Data5; > break; > case CS6: > dataBits = QSerialPort::Data6; > break; > case CS7: > dataBits = QSerialPort::Data7; > break; > case CS8: > dataBits = QSerialPort::Data8; > break; > default: > dataBits = QSerialPort::UnknownDataBits; > break; > } > > // Detect parity. > #ifdef CMSPAR > if (currentTermios.c_cflag & CMSPAR) { > parity = currentTermios.c_cflag & PARODD ? > QSerialPort::MarkParity : QSerialPort::SpaceParity; > } else { > #endif > if (currentTermios.c_cflag & PARENB) { > parity = currentTermios.c_cflag & PARODD ? > QSerialPort::OddParity : QSerialPort::EvenParity; > } else { > parity = QSerialPort::NoParity; > } > #ifdef CMSPAR > } > #endif > > // Detect stopbits. > stopBits = currentTermios.c_cflag & CSTOPB ? > QSerialPort::TwoStop : QSerialPort::OneStop; > > // Detect flow control. > if ((!(currentTermios.c_cflag & CRTSCTS)) && (!(currentTermios.c_iflag & (IXON | IXOFF | IXANY)))) > flow = QSerialPort::NoFlowControl; > else if ((!(currentTermios.c_cflag & CRTSCTS)) && (currentTermios.c_iflag & (IXON | IXOFF | IXANY))) > flow = QSerialPort::SoftwareControl; > else if ((currentTermios.c_cflag & CRTSCTS) && (!(currentTermios.c_iflag & (IXON | IXOFF | IXANY)))) > flow = QSerialPort::HardwareControl; > else > flow = QSerialPort::UnknownFlowControl; > } > > QSerialPort::SerialPortError QSerialPortPrivate::decodeSystemError() const > { > QSerialPort::SerialPortError error; > switch (errno) { > case ENOTTY: > error = QSerialPort::NoError; > break; > case ENODEV: > error = QSerialPort::DeviceNotFoundError; > break; > case EACCES: > error = QSerialPort::PermissionError; > break; > case EBUSY: > error = QSerialPort::PermissionError; > break; > case EAGAIN: > error = QSerialPort::ResourceError; > break; > case EIO: > error = QSerialPort::ResourceError; > break; > case EBADF: > error = QSerialPort::ResourceError; > break; > #ifdef Q_OS_MAC > case ENXIO: > error = QSerialPort::ResourceError; > break; > #endif > default: > error = QSerialPort::UnknownError; > break; > } > return error; > } > > bool QSerialPortPrivate::isReadNotificationEnabled() const > { > return readNotifier && readNotifier->isEnabled(); > } > > void QSerialPortPrivate::setReadNotificationEnabled(bool enable) > { > if (readNotifier) { > readNotifier->setEnabled(enable); > } else if (enable) { > readNotifier = new ReadNotifier(this, q_ptr); > readNotifier->setEnabled(true); > } > } > > bool QSerialPortPrivate::isWriteNotificationEnabled() const > { > return writeNotifier && writeNotifier->isEnabled(); > } > > void QSerialPortPrivate::setWriteNotificationEnabled(bool enable) > { > if (writeNotifier) { > writeNotifier->setEnabled(enable); > } else if (enable) { > writeNotifier = new WriteNotifier(this, q_ptr); > writeNotifier->setEnabled(true); > } > } > > bool QSerialPortPrivate::isExceptionNotificationEnabled() const > { > return exceptionNotifier && exceptionNotifier->isEnabled(); > } > > void QSerialPortPrivate::setExceptionNotificationEnabled(bool enable) > { > if (exceptionNotifier) { > exceptionNotifier->setEnabled(enable); > } else if (enable) { > exceptionNotifier = new ExceptionNotifier(this, q_ptr); > exceptionNotifier->setEnabled(true); > } > } > > bool QSerialPortPrivate::waitForReadOrWrite(bool *selectForRead, bool *selectForWrite, > bool checkRead, bool checkWrite, > int msecs, bool *timedOut) > { > Q_ASSERT(selectForRead); > Q_ASSERT(selectForWrite); > Q_ASSERT(timedOut); > > fd_set fdread; > FD_ZERO(&fdread); > if (checkRead) > FD_SET(descriptor, &fdread); > > fd_set fdwrite; > FD_ZERO(&fdwrite); > if (checkWrite) > FD_SET(descriptor, &fdwrite); > > struct timeval tv; > 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) > return false; > if (ret == 0) { > *timedOut = true; > return false; > } > > *selectForRead = FD_ISSET(descriptor, &fdread); > *selectForWrite = FD_ISSET(descriptor, &fdwrite); > > return ret; > } > > qint64 QSerialPortPrivate::readFromPort(char *data, qint64 maxSize) > { > qint64 bytesRead = 0; > > > #if defined (CMSPAR) > if (parity == QSerialPort::NoParity > || policy != QSerialPort::StopReceivingPolicy) { > #else > if (parity != QSerialPort::MarkParity > && parity != QSerialPort::SpaceParity) { > #endif > bytesRead = ::read(descriptor, data, maxSize); > } else {// Perform parity emulation. > bytesRead = readPerChar(data, maxSize); > } > > if (bytesRead <= 0) { > QSerialPort::SerialPortError error = decodeSystemError(); > if (error != QSerialPort::ResourceError) > error = QSerialPort::ReadError; > q_ptr->setError(error); > } > > return bytesRead; > } > > qint64 QSerialPortPrivate::writeToPort(const char *data, qint64 maxSize) > { > qint64 bytesWritten = 0; > > #if defined (CMSPAR) > bytesWritten = ::write(descriptor, data, maxSize); > #else > if (parity != QSerialPort::MarkParity > && parity != QSerialPort::SpaceParity) { > bytesWritten = ::write(descriptor, data, maxSize); > } else {// Perform parity emulation. > bytesWritten = writePerChar(data, maxSize); > } > #endif > > if (bytesWritten < 0) { > QSerialPort::SerialPortError error = decodeSystemError(); > if (error != QSerialPort::ResourceError) > error = QSerialPort::WriteError; > q_ptr->setError(error); > } > > return bytesWritten; > } > > static inline bool evenParity(quint8 c) > { > c ^= c >> 4; //(c7 ^ c3)(c6 ^ c2)(c5 ^ c1)(c4 ^ c0) > c ^= c >> 2; //[(c7 ^ c3)(c5 ^ c1)][(c6 ^ c2)(c4 ^ c0)] > c ^= c >> 1; > return c & 1; //(c7 ^ c3)(c5 ^ c1)(c6 ^ c2)(c4 ^ c0) > } > > #ifndef CMSPAR > > qint64 QSerialPortPrivate::writePerChar(const char *data, qint64 maxSize) > { > qint64 ret = 0; > quint8 const charMask = (0xFF >> (8 - dataBits)); > > while (ret < maxSize) { > > bool par = evenParity(*data & charMask); > // False if need EVEN, true if need ODD. > par ^= parity == QSerialPort::MarkParity; > if (par ^ (currentTermios.c_cflag & PARODD)) { // Need switch parity mode? > currentTermios.c_cflag ^= PARODD; > flush(); //force sending already buffered data, because updateTermios() cleares buffers > //todo: add receiving buffered data!!! > if (!updateTermios()) > break; > } > > int r = ::write(descriptor, data, 1); > if (r < 0) > return -1; > if (r > 0) { > data += r; > ret += r; > } > } > return ret; > } > > #endif //CMSPAR > > qint64 QSerialPortPrivate::readPerChar(char *data, qint64 maxSize) > { > qint64 ret = 0; > quint8 const charMask = (0xFF >> (8 - dataBits)); > > // 0 - prefix not started, > // 1 - received 0xFF, > // 2 - received 0xFF and 0x00 > int prefix = 0; > while (ret < maxSize) { > > qint64 r = ::read(descriptor, data, 1); > if (r < 0) { > if (errno == EAGAIN) // It is ok for nonblocking mode. > break; > return -1; > } > if (r == 0) > break; > > bool par = true; > switch (prefix) { > case 2: // Previously received both 0377 and 0. > par = false; > prefix = 0; > break; > case 1: // Previously received 0377. > if (*data == '\0') { > ++prefix; > continue; > } > prefix = 0; > break; > default: > if (*data == '\377') { > prefix = 1; > continue; > } > break; > } > // Now: par contains parity ok or error, *data contains received character > par ^= evenParity(*data & charMask); //par contains parity bit value for EVEN mode > par ^= (currentTermios.c_cflag & PARODD); //par contains parity bit value for current mode > if (par ^ (parity == QSerialPort::SpaceParity)) { //if parity error > switch (policy) { > case QSerialPort::SkipPolicy: > continue; //ignore received character > case QSerialPort::StopReceivingPolicy: > if (parity != QSerialPort::NoParity) > q_ptr->setError(QSerialPort::ParityError); > else > q_ptr->setError(*data == '\0' ? > QSerialPort::BreakConditionError : QSerialPort::FramingError); > return ++ret; //abort receiving > break; > case QSerialPort::UnknownPolicy: > // Unknown error policy is used! Falling back to PassZeroPolicy > case QSerialPort::PassZeroPolicy: > *data = '\0'; //replace received character by zero > break; > case QSerialPort::IgnorePolicy: > break; //ignore error and pass received character > } > } > ++data; > ++ret; > } > return ret; > } > > #ifdef Q_OS_MAC > static const QLatin1String defaultFilePathPrefix("/dev/cu."); > static const QLatin1String unusedFilePathPrefix("/dev/tty."); > #else > static const QLatin1String defaultFilePathPrefix("/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 BaudRateMap; > > // The OS specific defines can be found in termios.h > > static const BaudRateMap createStandardBaudRateMap() > { > BaudRateMap baudRateMap; > > #ifdef B50 > baudRateMap.insert(50, B50); > #endif > > #ifdef B75 > baudRateMap.insert(75, B75); > #endif > > #ifdef B110 > baudRateMap.insert(110, B110); > #endif > > #ifdef B134 > baudRateMap.insert(134, B134); > #endif > > #ifdef B150 > baudRateMap.insert(150, B150); > #endif > > #ifdef B200 > baudRateMap.insert(200, B200); > #endif > > #ifdef B300 > baudRateMap.insert(300, B300); > #endif > > #ifdef B600 > baudRateMap.insert(600, B600); > #endif > > #ifdef B1200 > baudRateMap.insert(1200, B1200); > #endif > > #ifdef B1800 > baudRateMap.insert(1800, B1800); > #endif > > #ifdef B2400 > baudRateMap.insert(2400, B2400); > #endif > > #ifdef B4800 > baudRateMap.insert(4800, B4800); > #endif > > #ifdef B9600 > baudRateMap.insert(9600, B9600); > #endif > > #ifdef B19200 > baudRateMap.insert(19200, B19200); > #endif > > #ifdef B38400 > baudRateMap.insert(38400, B38400); > #endif > > #ifdef B57600 > baudRateMap.insert(57600, B57600); > #endif > > #ifdef B115200 > baudRateMap.insert(115200, B115200); > #endif > > #ifdef B230400 > baudRateMap.insert(230400, B230400); > #endif > > #ifdef B460800 > baudRateMap.insert(460800, B460800); > #endif > > #ifdef B500000 > baudRateMap.insert(500000, B500000); > #endif > > #ifdef B576000 > baudRateMap.insert(576000, B576000); > #endif > > #ifdef B921600 > baudRateMap.insert(921600, B921600); > #endif > > #ifdef B1000000 > baudRateMap.insert(1000000, B1000000); > #endif > > #ifdef B1152000 > baudRateMap.insert(1152000, B1152000); > #endif > > #ifdef B1500000 > baudRateMap.insert(1500000, B1500000); > #endif > > #ifdef B2000000 > baudRateMap.insert(2000000, B2000000); > #endif > > #ifdef B2500000 > baudRateMap.insert(2500000, B2500000); > #endif > > #ifdef B3000000 > baudRateMap.insert(3000000, B3000000); > #endif > > #ifdef B3500000 > baudRateMap.insert(3500000, B3500000); > #endif > > #ifdef B4000000 > baudRateMap.insert(4000000, B4000000); > #endif > > return baudRateMap; > } > > static const BaudRateMap& standardBaudRateMap() > { > static const BaudRateMap baudRateMap = createStandardBaudRateMap(); > return baudRateMap; > } > > qint32 QSerialPortPrivate::baudRateFromSetting(qint32 setting) > { > return standardBaudRateMap().key(setting); > } > > qint32 QSerialPortPrivate::settingFromBaudRate(qint32 baudRate) > { > return standardBaudRateMap().value(baudRate); > } > > QList QSerialPortPrivate::standardBaudRates() > { > return standardBaudRateMap().keys(); > } > > QT_END_NAMESPACE diff -rN ./serialport/qserialport_android_p.h ./aserialport/qserialport_android_p.h 0a1,209 > /**************************************************************************** > ** > ** Copyright (C) 2012 Denis Shienkov > ** Copyright (C) 2012 Laszlo Papp > ** Contact: http://www.qt-project.org/legal > ** > ** This file is part of the QtSerialPort module of the Qt Toolkit. > ** > ** $QT_BEGIN_LICENSE:LGPL$ > ** Commercial License Usage > ** Licensees holding valid commercial Qt licenses may use this file in > ** accordance with the commercial license agreement provided with the > ** Software or, alternatively, in accordance with the terms contained in > ** a written agreement between you and Digia. For licensing terms and > ** conditions see http://qt.digia.com/licensing. For further information > ** use the contact form at http://qt.digia.com/contact-us. > ** > ** GNU Lesser General Public License Usage > ** Alternatively, this file may be used under the terms of the GNU Lesser > ** General Public License version 2.1 as published by the Free Software > ** Foundation and appearing in the file LICENSE.LGPL included in the > ** packaging of this file. Please review the following information to > ** ensure the GNU Lesser General Public License version 2.1 requirements > ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. > ** > ** In addition, as a special exception, Digia gives you certain additional > ** rights. These rights are described in the Digia Qt LGPL Exception > ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. > ** > ** GNU General Public License Usage > ** Alternatively, this file may be used under the terms of the GNU > ** General Public License version 3.0 as published by the Free Software > ** Foundation and appearing in the file LICENSE.GPL included in the > ** packaging of this file. Please review the following information to > ** ensure the GNU General Public License version 3.0 requirements will be > ** met: http://www.gnu.org/copyleft/gpl.html. > ** > ** > ** $QT_END_LICENSE$ > ** > ****************************************************************************/ > > #ifndef QSERIALPORT_UNIX_P_H > #define QSERIALPORT_UNIX_P_H > > #include "qserialport_p.h" > > #include > #include > > > // Initializing JNI > #include > > #define JAVA_GET_CLASS_GLOBAL(class_name, class_path) \ > if (ok) \ > { \ > class_name = m_JEnv->FindClass(class_path); \ > if (m_JEnv->ExceptionOccurred()) \ > { \ > ok = false; \ > qDebug("error find Java class '%s'!", class_path); \ > } \ > if (class_name == NULL) \ > { \ > ok = false; \ > qDebug("error: Java class is NULL: '%s'!", class_path); \ > } \ > } > > #define JAVA_GET_CLASS(class_name, class_path) \ > jclass class_name; \ > JAVA_GET_CLASS_GLOBAL(class_name, class_path) > > #define JAVA_GET_METHOD_GLOBAL(class_name, method_name, signature, ...) \ > if (ok) \ > { \ > class_name##_##method_name = m_JEnv->Get##__VA_ARGS__##MethodID(class_name, #method_name, signature); \ > if (m_JEnv->ExceptionOccurred()) \ > { \ > ok = false; \ > qDebug("error get Java class method '%s'!", #method_name); \ > } \ > if (class_name##_##method_name == NULL) \ > { \ > ok = false; \ > qDebug("error: Java class method is NULL: '%s'!", #method_name); \ > } \ > } > > #define JAVA_GET_METHOD(class_name, method_name, signature, ...) \ > jmethodID class_name##_##method_name; \ > JAVA_GET_METHOD_GLOBAL(class_name, method_name, signature, __VA_ARGS__) > > //#define RFCOMM_UUID "00001101-0000-1000-8000-00805f9b34fb" > #define RFCOMM_UUID "00001101-0000-1000-8000-00805F9B34FB" > //"00001105-0000-1000-8000-00805F9B34FB" > > > > QT_BEGIN_NAMESPACE > > class QSocketNotifier; > > class QSerialPortPrivate : public QSerialPortPrivateData > { > public: > QSerialPortPrivate(QSerialPort *q); > > bool open(QIODevice::OpenMode mode); > void close(); > > QSerialPort::PinoutSignals pinoutSignals() const; > > bool setDataTerminalReady(bool set); > bool setRequestToSend(bool set); > > bool flush(); > bool clear(QSerialPort::Directions dir); > > bool sendBreak(int duration); > bool setBreak(bool set); > > qint64 systemInputQueueSize () const; > qint64 systemOutputQueueSize () const; > > qint64 bytesAvailable() const; > > qint64 readFromBuffer(char *data, qint64 maxSize); > qint64 writeToBuffer(const char *data, qint64 maxSize); > > bool waitForReadyRead(int msecs); > bool waitForBytesWritten(int msecs); > > bool setBaudRate(qint32 baudRate, QSerialPort::Directions dir); > bool setDataBits(QSerialPort::DataBits dataBits); > bool setParity(QSerialPort::Parity parity); > bool setStopBits(QSerialPort::StopBits stopBits); > bool setFlowControl(QSerialPort::FlowControl flow); > bool setDataErrorPolicy(QSerialPort::DataErrorPolicy policy); > > bool readNotification(); > bool writeNotification(int maxSize = INT_MAX); > bool exceptionNotification(); > > static QString portNameToSystemLocation(const QString &port); > static QString portNameFromSystemLocation(const QString &location); > > static qint32 baudRateFromSetting(qint32 setting); > static qint32 settingFromBaudRate(qint32 baudRate); > > static QList standardBaudRates(); > > struct termios currentTermios; > struct termios restoredTermios; > int descriptor; > bool isCustomBaudRateSupported; > > QSocketNotifier *readNotifier; > QSocketNotifier *writeNotifier; > QSocketNotifier *exceptionNotifier; > > bool readPortNotifierCalled; > bool readPortNotifierState; > bool readPortNotifierStateSet; > > bool emittedReadyRead; > bool emittedBytesWritten; > > private: > bool use_bluetooth_socket; > JNIEnv *m_JEnv; > jobject m_socket; > jobject m_jistream; > jobject m_jostream; > jmethodID m_BOSClass_write; > jmethodID m_BISClass_read; > jmethodID m_BISClass_available; > > bool updateTermios(); > > void detectDefaultSettings(); > QSerialPort::SerialPortError decodeSystemError() const; > > bool isReadNotificationEnabled() const; > void setReadNotificationEnabled(bool enable); > bool isWriteNotificationEnabled() const; > void setWriteNotificationEnabled(bool enable); > bool isExceptionNotificationEnabled() const; > void setExceptionNotificationEnabled(bool enable); > > bool waitForReadOrWrite(bool *selectForRead, bool *selectForWrite, > bool checkRead, bool checkWrite, > int msecs, bool *timedOut); > > qint64 readFromPort(char *data, qint64 maxSize); > qint64 writeToPort(const char *data, qint64 maxSize); > > #ifndef CMSPAR > qint64 writePerChar(const char *data, qint64 maxSize); > #endif > qint64 readPerChar(char *data, qint64 maxSize); > > }; > > > QT_END_NAMESPACE > > #endif // QSERIALPORT_UNIX_P_H diff -rN ./serialport/qserialport.cpp ./aserialport/qserialport.cpp 51a52,53 > #elif defined (Q_OS_ANDROID) > #include "qserialport_android_p.h" diff -rN ./serialport/qserialport.h ./aserialport/qserialport.h 47a48,50 > #ifdef Q_OS_ANDROID > #include > #else 48a52 > #endif diff -rN ./serialport/qserialportinfo_android.cpp ./aserialport/qserialportinfo_android.cpp 0a1,237 > /**************************************************************************** > ** > ** Copyright (C) 2011-2012 Denis Shienkov > ** Copyright (C) 2011 Sergey Belyashov > ** Copyright (C) 2012 Laszlo Papp > ** Contact: http://www.qt-project.org/legal > ** > ** This file is part of the QtSerialPort module of the Qt Toolkit. > ** > ** $QT_BEGIN_LICENSE:LGPL$ > ** Commercial License Usage > ** Licensees holding valid commercial Qt licenses may use this file in > ** accordance with the commercial license agreement provided with the > ** Software or, alternatively, in accordance with the terms contained in > ** a written agreement between you and Digia. For licensing terms and > ** conditions see http://qt.digia.com/licensing. For further information > ** use the contact form at http://qt.digia.com/contact-us. > ** > ** GNU Lesser General Public License Usage > ** Alternatively, this file may be used under the terms of the GNU Lesser > ** General Public License version 2.1 as published by the Free Software > ** Foundation and appearing in the file LICENSE.LGPL included in the > ** packaging of this file. Please review the following information to > ** ensure the GNU Lesser General Public License version 2.1 requirements > ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. > ** > ** In addition, as a special exception, Digia gives you certain additional > ** rights. These rights are described in the Digia Qt LGPL Exception > ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. > ** > ** GNU General Public License Usage > ** Alternatively, this file may be used under the terms of the GNU > ** General Public License version 3.0 as published by the Free Software > ** Foundation and appearing in the file LICENSE.GPL included in the > ** packaging of this file. Please review the following information to > ** ensure the GNU General Public License version 3.0 requirements will be > ** met: http://www.gnu.org/copyleft/gpl.html. > ** > ** > ** $QT_END_LICENSE$ > ** > ****************************************************************************/ > > #include "qserialportinfo.h" > #include "qserialportinfo_p.h" > #include "qserialport_android_p.h" > #include > > #include > #include > > //#include > > QT_BEGIN_NAMESPACE > > extern JavaVM *m_javaVM; > > static inline const QStringList &filtersOfDevices() > { > static const QStringList deviceFileNameFilterList = QStringList() > > << QLatin1String("ttyS*") // Standart UART 8250 and etc. > << QLatin1String("ttyUSB*") // Usb/serial converters PL2303 and etc. > << QLatin1String("ttyACM*") // CDC_ACM converters (i.e. Mobile Phones). > << QLatin1String("ttyGS*") // Gadget serial device (i.e. Mobile Phones with gadget serial driver). > << QLatin1String("ttyMI*") // MOXA pci/serial converters. > << QLatin1String("rfcomm*"); // Bluetooth serial device. > > return deviceFileNameFilterList; > } > > > QList QSerialPortInfo::availablePorts() > { > QList serialPortInfoList; > > QDir devDir(QLatin1String("/dev")); > if (devDir.exists()) { > > devDir.setFilter(QDir::Files | QDir::System | QDir::NoSymLinks); > devDir.setNameFilters(filtersOfDevices()); > > QStringList foundDevices; // Found devices list. > > foreach (const QFileInfo &deviceFileInfo, devDir.entryInfoList()) { > QString deviceFilePath = deviceFileInfo.absoluteFilePath(); > if (!foundDevices.contains(deviceFilePath)) { > foundDevices.append(deviceFilePath); > > QSerialPortInfo serialPortInfo; > > serialPortInfo.d_ptr->device = deviceFilePath; > serialPortInfo.d_ptr->portName = QSerialPortPrivate::portNameFromSystemLocation(deviceFilePath); > > // Get description, manufacturer, vendor identifier, product > // identifier are not supported. > > serialPortInfoList.append(serialPortInfo); > > } > } > } > > > // Work on ANDROID via JNI interface to Android Blutooth API > > bool ok = true; > // Get Java enveronment > JNIEnv *m_JEnv; > jint res = m_javaVM->AttachCurrentThread(&m_JEnv, NULL); > if (res < 0) > { > ok = false; > qDebug("error get Java enveronment!"); > } > > // Get classes and methods > JAVA_GET_CLASS(BAClass, "android/bluetooth/BluetoothAdapter") > JAVA_GET_CLASS(SetClass, "java/util/Set") > JAVA_GET_CLASS(BDClass, "android/bluetooth/BluetoothDevice") > JAVA_GET_CLASS(PUUIDClass, "android/os/ParcelUuid") > > JAVA_GET_METHOD(BAClass, getDefaultAdapter, "()Landroid/bluetooth/BluetoothAdapter;", Static) > JAVA_GET_METHOD(BAClass, isEnabled, "()Z") > JAVA_GET_METHOD(BAClass, getBondedDevices, "()Ljava/util/Set;") > JAVA_GET_METHOD(SetClass, toArray, "()[Ljava/lang/Object;") > JAVA_GET_METHOD(BDClass, getName, "()Ljava/lang/String;") > JAVA_GET_METHOD(BDClass, getAddress, "()Ljava/lang/String;") > JAVA_GET_METHOD(BDClass, getUuids, "()[Landroid/os/ParcelUuid;") > JAVA_GET_METHOD(PUUIDClass, toString, "()Ljava/lang/String;") > > > // Get Bluetooth adapter > jobject BAObject; > if (ok) > { > BAObject = m_JEnv->CallStaticObjectMethod(BAClass, BAClass_getDefaultAdapter); > if (BAObject == NULL) > { > ok = false; > qDebug("error: Java object method is NULL: 'BAObject'!"); > } > } > > // Check Bluetooth on enabled > jboolean b = m_JEnv->CallBooleanMethod(BAObject, BAClass_isEnabled); > if (!b) > { > ok = false; > } > > // Get paired devices list > if (ok) > { > jobject set = m_JEnv->CallObjectMethod(BAObject, BAClass_getBondedDevices); > jobjectArray devices = (jobjectArray)m_JEnv->CallObjectMethod(set, SetClass_toArray); > if (m_JEnv->ExceptionOccurred()) > { > qDebug("error get devices list!"); > m_JEnv->ExceptionClear(); > } > else > { > jsize count = m_JEnv->GetArrayLength(devices); > for (jsize i(0); i < count; i++) > { > jobject device = m_JEnv->GetObjectArrayElement(devices, i); > > jobjectArray puuids = (jobjectArray)m_JEnv->CallObjectMethod(device, BDClass_getUuids); > jsize puuids_count = m_JEnv->GetArrayLength(puuids); > bool have_rfcomm(false); > for (jsize j(0); j < puuids_count; j++) > { > jobject puuid = m_JEnv->GetObjectArrayElement(puuids, j); > jstring juuid = (jstring)m_JEnv->CallObjectMethod(puuid, PUUIDClass_toString); > const char *cuuid = m_JEnv->GetStringUTFChars(juuid, 0); > QString uuid(cuuid); > m_JEnv->ReleaseStringUTFChars(juuid, cuuid); > if (uuid.toUpper() == RFCOMM_UUID) > { > have_rfcomm = true; > break; > } > } > if (!have_rfcomm) continue; > > jstring jname = (jstring)m_JEnv->CallObjectMethod(device, BDClass_getName); > const char *cname = m_JEnv->GetStringUTFChars(jname, 0); > QString name(cname); > m_JEnv->ReleaseStringUTFChars(jname, cname); > jstring jaddress = (jstring)m_JEnv->CallObjectMethod(device, BDClass_getAddress); > const char *caddress = m_JEnv->GetStringUTFChars(jaddress, 0); > QString address(caddress); > m_JEnv->ReleaseStringUTFChars(jaddress, caddress); > > QSerialPortInfo serialPortInfo; > serialPortInfo.d_ptr->device = QString("bt://%1").arg(address); > serialPortInfo.d_ptr->description = name; > serialPortInfo.d_ptr->portName = serialPortInfo.d_ptr->device; > serialPortInfoList.append(serialPortInfo); > } > } > } > > if (!ok) > { > m_JEnv->ExceptionDescribe(); > m_JEnv->ExceptionClear(); > } > m_javaVM->DetachCurrentThread(); > > return serialPortInfoList; > } > > > // common part > > QList QSerialPortInfo::standardBaudRates() > { > return QSerialPortPrivate::standardBaudRates(); > } > > bool QSerialPortInfo::isBusy() const > { > //bool currentPid = false; > //return QTtyLocker::isLocked(portName().toLocal8Bit().constData(), ¤tPid); > return false; > } > > bool QSerialPortInfo::isValid() const > { > //QFile f(systemLocation()); > //return f.exists(); > return true; > } > > QT_END_NAMESPACE diff -rN ./serialport/qserialportinfo.h ./aserialport/qserialportinfo.h 48a49,51 > #ifdef Q_OS_ANDROID > #include > #else 49a53 > #endif diff -rN ./serialport/qserialportinfo_unix.cpp ./aserialport/qserialportinfo_unix.cpp 63a64,69 > #ifdef Q_OS_ANDROID > > #include > > #endif // Q_OS_ANDROID > 70c76 < static inline const QStringList& filtersOfDevices() --- > static inline const QStringList &filtersOfDevices() 230a237,258 > > // Work on ANDROID via RFCOMM socket > #ifdef Q_OS_ANDROID > > /*QBluetoothDeviceDiscoveryAgent discoveryAgent; > //QEventLoop loop; > //loop.connect(&discoveryAgent, SIGNAL(finished()), &loop, SLOT(quit())); > discoveryAgent.start(); > //loop.exec(); > foreach (QBluetoothDeviceInfo info, discoveryAgent.discoveredDevices()) > { > if (info.serviceUuids().contains(QBluetoothUuid::Rfcomm)) > { > QSerialPortInfo serialPortInfo; > serialPortInfo.d_ptr->device = info.name(); > serialPortInfo.d_ptr->portName = info.address().toString(); > serialPortInfo.d_ptr->manufacturer = info.manufacturerSpecificData(); > serialPortInfoList.append(serialPortInfo); > } > }*/ > > #endif // Q_OS_ANDROID diff -rN ./serialport/qserialport_p.h ./aserialport/qserialport_p.h 50c50,51 < #include --- > //#include > #include <5.1.0/QtCore/private/qringbuffer_p.h> diff -rN ./serialport/qserialport_unix.cpp ./aserialport/qserialport_unix.cpp 57a58,60 > #ifdef Q_OS_ANDROID > # define FNDELAY O_NDELAY > #endif 324a328,330 > #ifdef Q_OS_ANDROID > return writeNotification() && (::ioctl(descriptor, TCSBRK, 1) != -1); > #else 325a332 > #endif 508c515,517 < ret = (::cfsetspeed(¤tTermios, B38400) != -1); --- > //ret = (::cfsetspeed(¤tTermios, B38400) != -1); > ret = !(((dir & QSerialPort::Input) && ::cfsetispeed(¤tTermios, unixBaudRate) < 0) > || ((dir & QSerialPort::Output) && ::cfsetospeed(¤tTermios, unixBaudRate) < 0)); diff -rN ./serialport/qserialport_unix_p.h ./aserialport/qserialport_unix_p.h 50,52d49 < #ifdef Q_OS_LINUX < # include < #endif 109,112d105 < #ifdef Q_OS_LINUX < struct serial_struct currentSerialInfo; < struct serial_struct restoredSerialInfo; < #endif diff -rN ./serialport/serialport-lib.pri ./aserialport/serialport-lib.pri 3c3 < unix { --- > unix:!android { 66c66,81 < unix:!symbian { --- > android { > message("android build!") > HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS \ > $$PWD/qserialport_android_p.h > > SOURCES += \ > $$PWD/qserialportinfo_android.cpp \ > $$PWD/qserialport_android.cpp > > CONFIG += mobility > MOBILITY = connectivity > > } > > unix:!symbian:!android { > message("unix build!") 86,87d100 < < HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS