diff --git a/src/plugins/debugger/debuggerstartparameters.h b/src/plugins/debugger/debuggerstartparameters.h index d2dc6c83b9d..fb9ec1e5944 100644 --- a/src/plugins/debugger/debuggerstartparameters.h +++ b/src/plugins/debugger/debuggerstartparameters.h @@ -56,6 +56,11 @@ public: CommunicationChannelUsb }; + enum DebugClient { + DebugClientTrk, + DebugClientCoda + }; + DebuggerStartParameters() : isSnapshot(false), attachPID(-1), @@ -68,8 +73,9 @@ public: toolChainType(ProjectExplorer::ToolChain_UNKNOWN), startMode(NoStartMode), executableUid(0), - communicationChannel(CommunicationChannelTcpIp), - serverPort(0) + communicationChannel(CommunicationChannelUsb), + serverPort(0), + debugClient(DebugClientTrk) {} QString executable; @@ -122,6 +128,7 @@ public: CommunicationChannel communicationChannel; QString serverAddress; quint16 serverPort; + DebugClient debugClient; }; } // namespace Debugger diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 1db2d8a5f30..c2ee199c372 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1792,8 +1792,7 @@ AbstractGdbAdapter *GdbEngine::createAdapter() case ProjectExplorer::ToolChain_RVCT2_ARMV6: case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC: case ProjectExplorer::ToolChain_GCCE_GNUPOC: - // FIXME: 1 of 3 testing hacks. - if (sp.communicationChannel == DebuggerStartParameters::CommunicationChannelTcpIp) + if (sp.debugClient == DebuggerStartParameters::DebugClientCoda) return new TcfTrkGdbAdapter(this); else return new TrkGdbAdapter(this); diff --git a/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp b/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp index a9f629aee24..1092c8bc254 100644 --- a/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp +++ b/src/plugins/debugger/gdb/tcftrkgdbadapter.cpp @@ -37,6 +37,7 @@ #include "tcftrkdevice.h" #include "trkutils.h" #include "gdbmi.h" +#include "virtualserialdevice.h" #include "registerhandler.h" #include "threadshandler.h" @@ -1012,9 +1013,25 @@ void TcfTrkGdbAdapter::startAdapter() QPair tcfTrkAddress; - QSharedPointer tcfTrkSocket(new QTcpSocket); - m_trkDevice->setDevice(tcfTrkSocket); - m_trkIODevice = tcfTrkSocket; + QSharedPointer tcfTrkSocket; + if (parameters.communicationChannel == DebuggerStartParameters::CommunicationChannelTcpIp) { + tcfTrkSocket = QSharedPointer(new QTcpSocket); + m_trkDevice->setDevice(tcfTrkSocket); + m_trkIODevice = tcfTrkSocket; + } else { + QSharedPointer serialDevice(new SymbianUtils::VirtualSerialDevice(parameters.remoteChannel)); + m_trkDevice->setSerialFrame(true); + m_trkDevice->setDevice(serialDevice); + bool ok = serialDevice->open(QIODevice::ReadWrite); + if (!ok) { + QString msg = QString("Couldn't open serial device: %1.") + .arg(serialDevice->errorString()); + logMessage(msg, LogError); + m_engine->handleAdapterStartFailed(msg, QString()); + return; + } + m_trkIODevice = serialDevice; + } if (debug) qDebug() << parameters.processArgs; @@ -1049,9 +1066,13 @@ void TcfTrkGdbAdapter::startAdapter() connect(m_gdbServer, SIGNAL(newConnection()), this, SLOT(handleGdbConnection())); - logMessage(_("Connecting to TCF TRK on %1:%2") - .arg(tcfTrkAddress.first).arg(tcfTrkAddress.second)); - tcfTrkSocket->connectToHost(tcfTrkAddress.first, tcfTrkAddress.second); + if (parameters.communicationChannel == DebuggerStartParameters::CommunicationChannelTcpIp) { + logMessage(_("Connecting to TCF TRK on %1:%2") + .arg(tcfTrkAddress.first).arg(tcfTrkAddress.second)); + tcfTrkSocket->connectToHost(tcfTrkAddress.first, tcfTrkAddress.second); + } else { + m_trkDevice->sendSerialPing(false); + } } void TcfTrkGdbAdapter::setupInferior() diff --git a/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp b/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp index 279b847e197..1fd21d04859 100644 --- a/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp @@ -43,6 +43,7 @@ #include "qt4symbiantarget.h" #include "qt4target.h" #include "qtoutputformatter.h" +#include "virtualserialdevice.h" #include #include @@ -75,8 +76,15 @@ CodaRunControl::CodaRunControl(RunConfiguration *runConfiguration, const QString const S60DeployConfiguration *activeDeployConf = qobject_cast(s60runConfig->qt4Target()->activeDeployConfiguration()); QTC_ASSERT(activeDeployConf, return); - m_address = activeDeployConf->deviceAddress(); - m_port = activeDeployConf->devicePort().toInt(); + S60DeployConfiguration::CommunicationChannel channel = activeDeployConf->communicationChannel(); + if (channel == S60DeployConfiguration::CommunicationCodaTcpConnection) { + m_address = activeDeployConf->deviceAddress(); + m_port = activeDeployConf->devicePort().toInt(); + } else if (channel == S60DeployConfiguration::CommunicationCodaSerialConnection) { + m_serialPort = activeDeployConf->serialPortName(); + } else { + QTC_ASSERT(false, return); + } } CodaRunControl::~CodaRunControl() @@ -87,7 +95,7 @@ CodaRunControl::~CodaRunControl() bool CodaRunControl::doStart() { - if (m_address.isEmpty()) { + if (m_address.isEmpty() && m_serialPort.isEmpty()) { cancelProgress(); QString msg = tr("No device is connected. Please connect a device and try again."); appendMessage(msg, NormalMessageFormat); @@ -116,12 +124,26 @@ bool CodaRunControl::setupLauncher() connect(m_tcfTrkDevice, SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)), this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent))); connect(m_tcfTrkDevice, SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString))); - const QSharedPointer tcfTrkSocket(new QTcpSocket); - m_tcfTrkDevice->setDevice(tcfTrkSocket); - tcfTrkSocket->connectToHost(m_address, m_port); - m_state = StateConnecting; - appendMessage(tr("Connecting to %1:%2...").arg(m_address).arg(m_port), NormalMessageFormat); - QTimer::singleShot(4000, this, SLOT(checkForTimeout())); + if (m_serialPort.length()) { + const QSharedPointer serialDevice(new SymbianUtils::VirtualSerialDevice(m_serialPort)); + appendMessage(tr("Conecting to '%2'...").arg(m_serialPort), NormalMessageFormat); + m_tcfTrkDevice->setSerialFrame(true); + m_tcfTrkDevice->setDevice(serialDevice); + bool ok = serialDevice->open(QIODevice::ReadWrite); + if (!ok) { + appendMessage(tr("Couldn't open serial device: %1").arg(serialDevice->errorString()), ErrorMessageFormat); + return false; + } + m_state = StateConnecting; + m_tcfTrkDevice->sendSerialPing(false); + } else { + const QSharedPointer tcfTrkSocket(new QTcpSocket); + m_tcfTrkDevice->setDevice(tcfTrkSocket); + tcfTrkSocket->connectToHost(m_address, m_port); + m_state = StateConnecting; + appendMessage(tr("Connecting to %1:%2...").arg(m_address).arg(m_port), NormalMessageFormat); + QTimer::singleShot(4000, this, SLOT(checkForTimeout())); + } return true; } diff --git a/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h b/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h index 7c364cf83f1..087fcb0e034 100644 --- a/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h +++ b/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h @@ -103,6 +103,7 @@ private: QString m_address; unsigned short m_port; + QString m_serialPort; QString m_runningProcessId; State m_state; diff --git a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp index a66d07f5b51..19b8f97dd3b 100644 --- a/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/qt4symbiantarget.cpp @@ -180,7 +180,8 @@ bool Qt4SymbianTarget::isSymbianConnectionAvailable(QString &tooltipText) if (!s60DeployConf) return false; switch (s60DeployConf->communicationChannel()) { - case S60DeployConfiguration::CommunicationTrkSerialConnection: { + case S60DeployConfiguration::CommunicationTrkSerialConnection: + case S60DeployConfiguration::CommunicationCodaSerialConnection: { const SymbianUtils::SymbianDeviceManager *sdm = SymbianUtils::SymbianDeviceManager::instance(); const int deviceIndex = sdm->findByPortName(s60DeployConf->serialPortName()); if (deviceIndex == -1) { diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp index ab932d425fa..6b15b0c2c58 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.cpp @@ -86,7 +86,9 @@ S60DeployConfigurationWidget::S60DeployConfigurationWidget(QWidget *parent) m_silentInstallCheckBox(new QCheckBox(tr("Silent installation"))), m_serialRadioButton(new QRadioButton(tr("Serial:"))), m_wlanRadioButton(new QRadioButton(tr("Experimental WLAN:"))), //TODO: Remove ""Experimental" when CODA is stable and official - m_ipAddress(new Utils::IpAddressLineEdit) + m_ipAddress(new Utils::IpAddressLineEdit), + m_trkRadioButton(new QRadioButton(tr("TRK"))), + m_codaRadioButton(new QRadioButton(tr("CODA"))) { } @@ -140,7 +142,37 @@ void S60DeployConfigurationWidget::init(ProjectExplorer::DeployConfiguration *dc connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(updated()), this, SLOT(updateSerialDevices())); - formLayout->addRow(createCommunicationChannel()); + //Debug Client + QHBoxLayout *debugClientHBoxLayout = new QHBoxLayout; + + QVBoxLayout *debugClientVBoxLayout = new QVBoxLayout; + debugClientVBoxLayout->addWidget(m_trkRadioButton); + debugClientVBoxLayout->addWidget(m_codaRadioButton); + + debugClientVBoxLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::Expanding)); + + debugClientHBoxLayout->addLayout(debugClientVBoxLayout); + + debugClientHBoxLayout->addWidget(createCommunicationChannel()); + debugClientHBoxLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored)); + + QGroupBox *debugClientGroupBox = new QGroupBox(tr("Debug Client")); + debugClientGroupBox->setLayout(debugClientHBoxLayout); + + bool usingTrk = m_deployConfiguration->communicationChannel() == S60DeployConfiguration::CommunicationTrkSerialConnection; + m_trkRadioButton->setChecked(usingTrk); + m_codaRadioButton->setChecked(!usingTrk); + + bool usingTcp = m_deployConfiguration->communicationChannel() == S60DeployConfiguration::CommunicationCodaTcpConnection; + m_serialRadioButton->setChecked(!usingTcp); + m_wlanRadioButton->setChecked(usingTcp); + + connect(m_trkRadioButton, SIGNAL(clicked()), this, SLOT(updateDebugClient())); + connect(m_codaRadioButton, SIGNAL(clicked()), this, SLOT(updateDebugClient())); + + updateDebugClient(); + + formLayout->addRow(debugClientGroupBox); // Device Info with button. Widgets are enabled in above call to updateSerialDevices() QHBoxLayout *infoHBoxLayout = new QHBoxLayout; @@ -180,7 +212,7 @@ QWidget *S60DeployConfigurationWidget::createCommunicationChannel() serialPortHBoxLayout->addWidget(updateSerialDevicesButton); #endif - QGroupBox *communicationChannelGroupBox = new QGroupBox(tr("Communication channel")); + QGroupBox *communicationChannelGroupBox = new QGroupBox(tr("Communication Channel")); QFormLayout *communicationChannelFormLayout = new QFormLayout(); communicationChannelFormLayout->setWidget(0, QFormLayout::LabelRole, m_serialRadioButton); communicationChannelFormLayout->setWidget(1, QFormLayout::LabelRole, m_wlanRadioButton); @@ -201,21 +233,6 @@ QWidget *S60DeployConfigurationWidget::createCommunicationChannel() communicationChannelFormLayout->setLayout(0, QFormLayout::FieldRole, serialPortHBoxLayout); communicationChannelFormLayout->setLayout(1, QFormLayout::FieldRole, wlanChannelLayout); - switch (m_deployConfiguration->communicationChannel()) { - case S60DeployConfiguration::CommunicationTrkSerialConnection: - m_serialRadioButton->setChecked(true); - m_ipAddress->setDisabled(true); - m_serialPortsCombo->setDisabled(false); - break; - case S60DeployConfiguration::CommunicationCodaTcpConnection: - m_wlanRadioButton->setChecked(true); - m_ipAddress->setDisabled(false); - m_serialPortsCombo->setDisabled(true); - break; - default: - break; - } - communicationChannelGroupBox->setLayout(communicationChannelFormLayout); return communicationChannelGroupBox; } @@ -303,20 +320,40 @@ void S60DeployConfigurationWidget::setSerialPort(int index) clearDeviceInfo(); } +void S60DeployConfigurationWidget::updateDebugClient() +{ + if (!m_trkRadioButton->isChecked() && !m_codaRadioButton->isChecked()) + m_trkRadioButton->setChecked(true); + + if (m_trkRadioButton->isChecked()) { + m_serialRadioButton->setEnabled(true); + m_serialRadioButton->setChecked(true); + m_wlanRadioButton->setEnabled(false); + updateSerialDevices(); + } else if(m_codaRadioButton->isChecked()) { + m_serialRadioButton->setEnabled(true); + m_wlanRadioButton->setEnabled(true); + } + + updateCommunicationChannel(); +} + void S60DeployConfigurationWidget::updateCommunicationChannel() { + if (!m_serialRadioButton->isChecked() && !m_wlanRadioButton->isChecked()) + m_serialRadioButton->setChecked(true); + if (m_serialRadioButton->isChecked()) { m_ipAddress->setDisabled(true); m_serialPortsCombo->setDisabled(false); - m_deployConfiguration->setCommunicationChannel(S60DeployConfiguration::CommunicationTrkSerialConnection); + if (m_trkRadioButton->isChecked()) + m_deployConfiguration->setCommunicationChannel(S60DeployConfiguration::CommunicationTrkSerialConnection); + else + m_deployConfiguration->setCommunicationChannel(S60DeployConfiguration::CommunicationCodaSerialConnection); updateSerialDevices(); } else if(m_wlanRadioButton->isChecked()) { - QMessageBox::information(this, tr("CODA required"), - tr("You need to have CODA v4.0.14 (or newer) installed on your device " - "in order to use the WLAN functionality.")); //TODO: Remove this when CODA is stable and official m_ipAddress->setDisabled(false); m_serialPortsCombo->setDisabled(true); - m_deviceInfoButton->setEnabled(false); m_deployConfiguration->setCommunicationChannel(S60DeployConfiguration::CommunicationCodaTcpConnection); } } diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h b/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h index 287a4a9d6c7..2feb862f21b 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60deployconfigurationwidget.h @@ -90,6 +90,7 @@ private slots: void slotWaitingForTrkClosed(); void silentInstallChanged(int); void updateCommunicationChannel(); + void updateDebugClient(); void updateWlanAddress(const QString &address); void cleanWlanAddress(); @@ -114,6 +115,8 @@ private: QRadioButton *m_serialRadioButton; QRadioButton *m_wlanRadioButton; Utils::IpAddressLineEdit *m_ipAddress; + QRadioButton *m_trkRadioButton; + QRadioButton *m_codaRadioButton; }; } // namespace Internal diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp index bfeef6c45ee..b0941613867 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp @@ -48,7 +48,7 @@ #include #include - +#include #include #include @@ -66,7 +66,7 @@ using namespace ProjectExplorer; using namespace Qt4ProjectManager::Internal; -enum { debug = 0 }; +enum {debug = 0}; static const quint64 DEFAULT_CHUNK_SIZE = 10240; @@ -277,16 +277,20 @@ void S60DeployStep::start() { QString errorMessage; - if (m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection) { - if (m_serialPortName.isEmpty() || !m_launcher) { - errorMessage = tr("No device is connected. Please connect a device and try again."); - reportError(errorMessage); - return; - } - } else { + bool serialConnection = (m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection + || m_channel == S60DeployConfiguration::CommunicationCodaSerialConnection); + bool trkClient = m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection; + + if (serialConnection && m_serialPortName.isEmpty() + || (trkClient && !m_launcher)) { + errorMessage = tr("No device is connected. Please connect a device and try again."); + reportError(errorMessage); + return; + } + if (!trkClient) { QTC_ASSERT(!m_trkDevice, return); m_trkDevice = new tcftrk::TcfTrkDevice; - if (m_address.isEmpty() || !m_trkDevice) { + if (m_address.isEmpty() && !serialConnection) { errorMessage = tr("No address for a device has been defined. Please define an address and try again."); reportError(errorMessage); return; @@ -374,6 +378,19 @@ void S60DeployStep::startDeployment() reportError(errorMessage); stop(); } + } else if (m_channel == S60DeployConfiguration::CommunicationCodaSerialConnection) { + const QSharedPointer serialDevice(new SymbianUtils::VirtualSerialDevice(m_serialPortName)); + appendMessage(tr("Deploying application to '%1'...").arg(m_serialPortFriendlyName), false); + m_trkDevice->setSerialFrame(true); + m_trkDevice->setDevice(serialDevice); + bool ok = serialDevice->open(QIODevice::ReadWrite); + if (!ok) { + reportError(tr("Couldn't open serial device: %1").arg(serialDevice->errorString())); + stop(); + return; + } + m_state = StateConnecting; + m_trkDevice->sendSerialPing(false); } else { const QSharedPointer tcfTrkSocket(new QTcpSocket); m_trkDevice->setDevice(tcfTrkSocket); @@ -729,9 +746,6 @@ void S60DeployStep::launcherFinished(bool success) void S60DeployStep::deploymentFinished(bool success) { m_deployResult = success; - if (m_trkDevice) - m_trkDevice->deleteLater(); - m_trkDevice = 0; if (m_eventLoop) m_eventLoop->exit(); } diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 1eb5647d4d1..ae9a6614ccc 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -522,10 +522,14 @@ static Debugger::DebuggerStartParameters s60DebuggerStartParams(const S60DeviceR sp.serverAddress = activeDeployConf->deviceAddress(); sp.serverPort = activeDeployConf->devicePort().toInt(); - //FIXME: there should be only one... trkAdapter - sp.communicationChannel = activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationTrkSerialConnection? - Debugger::DebuggerStartParameters::CommunicationChannelUsb: - Debugger::DebuggerStartParameters::CommunicationChannelTcpIp; + sp.communicationChannel = activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationCodaTcpConnection? + Debugger::DebuggerStartParameters::CommunicationChannelTcpIp: + Debugger::DebuggerStartParameters::CommunicationChannelUsb; + + sp.debugClient = activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationTrkSerialConnection? + Debugger::DebuggerStartParameters::DebugClientTrk: + Debugger::DebuggerStartParameters::DebugClientCoda; + QTC_ASSERT(sp.executableUid, return sp); // Prefer the '*.sym' file over the '.exe', which should exist at the same diff --git a/src/shared/symbianutils/symbianutils.pri b/src/shared/symbianutils/symbianutils.pri index f07e494ed17..d33881f3839 100644 --- a/src/shared/symbianutils/symbianutils.pri +++ b/src/shared/symbianutils/symbianutils.pri @@ -14,7 +14,8 @@ HEADERS += $$PWD/symbianutils_global.h \ $$PWD/symbiandevicemanager.h \ $$PWD/tcftrkdevice.h \ $$PWD/tcftrkmessage.h \ - $$PWD/json.h + $$PWD/json.h \ + $$PWD/virtualserialdevice.h SOURCES += $$PWD/trkutils.cpp \ $$PWD/trkdevice.cpp \ @@ -24,7 +25,12 @@ SOURCES += $$PWD/trkutils.cpp \ $$PWD/symbiandevicemanager.cpp \ $$PWD/tcftrkdevice.cpp \ $$PWD/tcftrkmessage.cpp \ - $$PWD/json.cpp + $$PWD/json.cpp \ + $$PWD/virtualserialdevice.cpp + +DEFINES += HAS_SERIALPORT +win32:SOURCES += $$PWD/virtualserialdevice_win.cpp +unix:SOURCES += $$PWD/virtualserialdevice_posix.cpp # Tests/trklauncher is a console application contains(QT, gui) { diff --git a/src/shared/symbianutils/tcftrkdevice.cpp b/src/shared/symbianutils/tcftrkdevice.cpp index 850fc5632ab..ae4ed4a472b 100644 --- a/src/shared/symbianutils/tcftrkdevice.cpp +++ b/src/shared/symbianutils/tcftrkdevice.cpp @@ -512,7 +512,7 @@ void TcfTrkDevice::deviceReadyReadSerial() break; processSerialMessage(d->m_readBuffer.mid(messagePos.first, messagePos.second)); d->m_readBuffer.remove(0, messageEnd); - } while (d->m_readBuffer.isEmpty()); + } while (!d->m_readBuffer.isEmpty()); checkSendQueue(); // Send off further messages } diff --git a/src/shared/symbianutils/virtualserialdevice.cpp b/src/shared/symbianutils/virtualserialdevice.cpp new file mode 100644 index 00000000000..9795fbf33ef --- /dev/null +++ b/src/shared/symbianutils/virtualserialdevice.cpp @@ -0,0 +1,44 @@ +#include "virtualserialdevice.h" +#include + +namespace SymbianUtils { + +bool VirtualSerialDevice::isSequential() const +{ + return true; +} + +VirtualSerialDevice::VirtualSerialDevice(const QString &aPortName, QObject *parent) : + QIODevice(parent), portName(aPortName), lock(QMutex::NonRecursive), emittingBytesWritten(false) +{ + platInit(); +} + +const QString& VirtualSerialDevice::getPortName() const +{ + return portName; +} + +void VirtualSerialDevice::close() +{ + if (isOpen()) { + Q_ASSERT(thread() == QThread::currentThread()); // My brain will explode otherwise + flush(); + QMutexLocker locker(&lock); + QIODevice::close(); + platClose(); + } +} + +void VirtualSerialDevice::emitBytesWrittenIfNeeded(QMutexLocker& locker, qint64 len) +{ + if (!emittingBytesWritten) { + emittingBytesWritten = true; + locker.unlock(); + emit bytesWritten(len); + locker.relock(); + emittingBytesWritten = false; + } +} + +} // namespace SymbianUtils diff --git a/src/shared/symbianutils/virtualserialdevice.h b/src/shared/symbianutils/virtualserialdevice.h new file mode 100644 index 00000000000..a5bac72eb85 --- /dev/null +++ b/src/shared/symbianutils/virtualserialdevice.h @@ -0,0 +1,80 @@ +#ifndef VIRTUALSERIALPORT_H +#define VIRTUALSERIALPORT_H + +#include +#include +#include + +#include "symbianutils_global.h" + +namespace SymbianUtils { + +class VirtualSerialDevicePrivate; + +class SYMBIANUTILS_EXPORT VirtualSerialDevice : public QIODevice +{ + Q_OBJECT +public: + explicit VirtualSerialDevice(const QString &name, QObject *parent = 0); + ~VirtualSerialDevice(); + + bool open(OpenMode mode); + void close(); + const QString &getPortName() const; + void flush(); + + qint64 bytesAvailable() const; + bool isSequential() const; + bool waitForBytesWritten(int msecs); + bool waitForReadyRead(int msecs); + +protected: + qint64 readData(char *data, qint64 maxSize); + qint64 writeData(const char *data, qint64 maxSize); + +private: + Q_DISABLE_COPY(VirtualSerialDevice) + void platInit(); + void platClose(); + void emitBytesWrittenIfNeeded(QMutexLocker &locker, qint64 len); + +private: + QString portName; + mutable QMutex lock; + QList pendingWrites; + bool emittingBytesWritten; + VirtualSerialDevicePrivate *d; + +// Platform-specific stuff +#ifdef Q_OS_WIN +private: + qint64 writeNextBuffer(QMutexLocker &locker); +private slots: + void writeCompleted(); + void commEventOccurred(); +#endif + +#ifdef Q_OS_UNIX +private: + bool tryWrite(const char *data, qint64 maxSize, qint64 &bytesWritten); + enum FlushPendingOption { + NothingSpecial = 0, + StopAfterWritingOneBuffer = 1, + EmitBytesWrittenAsync = 2, // Needed so we don't emit bytesWritten signal directly from writeBytes + }; + Q_DECLARE_FLAGS(FlushPendingOptions, FlushPendingOption) + bool tryFlushPendingBuffers(QMutexLocker& locker, FlushPendingOptions flags = NothingSpecial); + +private slots: + void writeHasUnblocked(int fileHandle); + +signals: + void AsyncCall_emitBytesWrittenIfNeeded(qint64 len); + +#endif + +}; + +} // namespace SymbianUtils + +#endif // VIRTUALSERIALPORT_H diff --git a/src/shared/symbianutils/virtualserialdevice_posix.cpp b/src/shared/symbianutils/virtualserialdevice_posix.cpp new file mode 100644 index 00000000000..cfc802398ee --- /dev/null +++ b/src/shared/symbianutils/virtualserialdevice_posix.cpp @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include +#include +#include +#include // For qt_safe_select +#include "virtualserialdevice.h" + +namespace SymbianUtils { + +class VirtualSerialDevicePrivate +{ +public: + int portHandle; + QSocketNotifier* readNotifier; + QSocketNotifier* writeUnblockedNotifier; +}; + +void VirtualSerialDevice::platInit() +{ + d = new VirtualSerialDevicePrivate; + d->portHandle = -1; + d->readNotifier = NULL; + d->writeUnblockedNotifier = NULL; + connect(this, SIGNAL(AsyncCall_emitBytesWrittenIfNeeded(qint64)), this, SIGNAL(bytesWritten(qint64)), Qt::QueuedConnection); +} + +bool VirtualSerialDevice::open(OpenMode mode) +{ + if (isOpen()) return true; + + d->portHandle = ::open(portName.toAscii().constData(), O_RDWR | O_NONBLOCK | O_NOCTTY); + if (d->portHandle == -1) { + setErrorString(QString("Posix error %1 opening %2").arg(errno).arg(portName)); + return false; + } + + // Not totally sure this stuff is needed -tomsci + /* + struct termios termInfo; + if (tcgetattr(d->portHandle, &termInfo) < 0) { + setErrorString(QString::fromLatin1("Unable to retrieve terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno)))); + close(); + return false; + } + cfmakeraw(&termInfo); //TOMSCI TESTING + // Turn off terminal echo as not get messages back, among other things + termInfo.c_cflag |= CREAD|CLOCAL; + + // BEGIN TESTING + //termInfo.c_cflag&=(~CBAUD); + //termInfo.c_cflag|=B115200; + //termInfo.c_cc[VTIME] = 5; + //END TESTING + + termInfo.c_lflag &= (~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG)); + termInfo.c_iflag &= (~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY)); + termInfo.c_oflag &= (~OPOST); + termInfo.c_cc[VMIN] = 0; + termInfo.c_cc[VINTR] = _POSIX_VDISABLE; + termInfo.c_cc[VQUIT] = _POSIX_VDISABLE; + termInfo.c_cc[VSTART] = _POSIX_VDISABLE; + termInfo.c_cc[VSTOP] = _POSIX_VDISABLE; + termInfo.c_cc[VSUSP] = _POSIX_VDISABLE; + if (tcsetattr(d->portHandle, TCSAFLUSH, &termInfo) < 0) { + setErrorString(QString::fromLatin1("Unable to apply terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno)))); + close(); + return false; + } + //fcntl(d->portHandle, F_SETFL, O_SYNC); // TOMSCI TESTING + */ + + d->readNotifier = new QSocketNotifier(d->portHandle, QSocketNotifier::Read); + connect(d->readNotifier, SIGNAL(activated(int)), this, SIGNAL(readyRead())); + + d->writeUnblockedNotifier = new QSocketNotifier(d->portHandle, QSocketNotifier::Write); + d->writeUnblockedNotifier->setEnabled(false); + connect(d->writeUnblockedNotifier, SIGNAL(activated(int)), this, SLOT(writeHasUnblocked(int))); + + bool ok = QIODevice::open(mode); + if (!ok) close(); + return ok; +} + +void VirtualSerialDevice::platClose() +{ + delete d->readNotifier; + d->readNotifier = NULL; + + delete d->writeUnblockedNotifier; + d->writeUnblockedNotifier = NULL; + + ::close(d->portHandle); + d->portHandle = -1; +} + +VirtualSerialDevice::~VirtualSerialDevice() +{ + close(); + delete d; +} + +qint64 VirtualSerialDevice::bytesAvailable() const +{ + QMutexLocker locker(&lock); + if (!isOpen()) return 0; + + int avail = 0; + if (ioctl(d->portHandle, FIONREAD, &avail) == -1) { + return 0; + } + return (qint64)avail + QIODevice::bytesAvailable(); +} + +qint64 VirtualSerialDevice::readData(char *data, qint64 maxSize) +{ + QMutexLocker locker(&lock); + int result = ::read(d->portHandle, data, maxSize); + if (result == -1 && errno == EAGAIN) result = 0; // To Qt, 0 here means nothing ready right now, and -1 is reserved for permanent errors + return result; +} + +qint64 VirtualSerialDevice::writeData(const char *data, qint64 maxSize) +{ + QMutexLocker locker(&lock); + qint64 bytesWritten; + bool needToWait = tryFlushPendingBuffers(locker, EmitBytesWrittenAsync); + if (!needToWait) { + needToWait = tryWrite(data, maxSize, bytesWritten); + } + + if (needToWait) { + pendingWrites.append(QByteArray(data, maxSize)); + d->writeUnblockedNotifier->setEnabled(true); + // Now wait for the writeUnblocked signal or for a call to waitForBytesWritten + return maxSize; + } else { + //emitBytesWrittenIfNeeded(locker, bytesWritten); + // Can't emit bytesWritten directly from writeData - means clients end up recursing + emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten); + return bytesWritten; + } +} + +/* Returns true if EAGAIN encountered. + * if error occurred (other than EAGAIN) returns -1 in bytesWritten + * lock must be held. Doesn't emit signals or set notifiers. + */ +bool VirtualSerialDevice::tryWrite(const char *data, qint64 maxSize, qint64& bytesWritten) +{ + // Must be locked + int result = ::write(d->portHandle, data, maxSize); + if (result == -1) { + if (errno == EAGAIN) { + // Need to wait + return true; + } else { + setErrorString(QString("Posix error %1 from write to %2").arg(errno).arg(portName)); + bytesWritten = -1; + return false; + } + } else { + Q_ASSERT(result == maxSize); // Otherwise I cry + bytesWritten = maxSize; + return false; + } +} + +/* Returns true if EAGAIN encountered. Emits (or queues) bytesWritten for any buffers written. + * If stopAfterWritingOneBuffer is true, return immediately if a single buffer is written, rather than + * attempting to drain the whole queue. + * Doesn't modify notifier. + */ +bool VirtualSerialDevice::tryFlushPendingBuffers(QMutexLocker& locker, FlushPendingOptions flags) //bool stopAfterWritingOneBuffer) +{ + while (pendingWrites.count() > 0) { + // Try writing everything we've got, until we hit EAGAIN + const QByteArray& data = pendingWrites[0]; + qint64 bytesWritten; + bool needToWait = tryWrite(data.constData(), data.size(), bytesWritten); + if (needToWait) { + return needToWait; + } else { + pendingWrites.removeFirst(); + if (flags & EmitBytesWrittenAsync) { + emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten); + } else { + emitBytesWrittenIfNeeded(locker, bytesWritten); + } + if (flags & StopAfterWritingOneBuffer) return false; + // Otherwise go round loop again + } + } + return false; // no EAGAIN encountered +} + +void VirtualSerialDevice::writeHasUnblocked(int fileHandle) +{ + Q_ASSERT(fileHandle == d->portHandle); + (void)fileHandle; // Compiler shutter-upper + d->writeUnblockedNotifier->setEnabled(false); + + QMutexLocker locker(&lock); + bool needToWait = tryFlushPendingBuffers(locker); + if (needToWait) d->writeUnblockedNotifier->setEnabled(true); +} + +bool VirtualSerialDevice::waitForBytesWritten(int msecs) +{ + //TODO this won't handle multithreading... need to disable writeCompleteNotifier in main thread context (or use bytesWrittenSignalsAlreadyEmitted) + + QMutexLocker locker(&lock); + if (pendingWrites.count() == 0) return false; + + d->writeUnblockedNotifier->setEnabled(false); + forever { + fd_set writeSet; + FD_ZERO(&writeSet); + FD_SET(d->portHandle, &writeSet); + + struct timeval timeout; + if (msecs != -1) { + timeout.tv_sec = msecs / 1000; + timeout.tv_usec = (msecs % 1000) * 1000; + } + int ret = qt_safe_select(d->portHandle+1, NULL, &writeSet, NULL, msecs == -1 ? NULL : &timeout); + + if (ret == 0) { + // Timeout + return false; + } else if (ret < 0) { + setErrorString(QString("Posix error %1 returned from select in waitForBytesWritten").arg(errno)); + return false; + } else { + bool needToWait = tryFlushPendingBuffers(locker, StopAfterWritingOneBuffer); + if (needToWait) { + // go round the select again + } else { + return true; + } + } + } +} + +void VirtualSerialDevice::flush() +{ + while (waitForBytesWritten(-1)) { /* loop */ } + tcflush(d->portHandle, TCIOFLUSH); +} + +bool VirtualSerialDevice::waitForReadyRead(int msecs) +{ + return QIODevice::waitForReadyRead(msecs); //TODO +} + +} // namespace SymbianUtils diff --git a/src/shared/symbianutils/virtualserialdevice_win.cpp b/src/shared/symbianutils/virtualserialdevice_win.cpp new file mode 100644 index 00000000000..71ed7599adf --- /dev/null +++ b/src/shared/symbianutils/virtualserialdevice_win.cpp @@ -0,0 +1,281 @@ +#include "virtualserialdevice.h" +#include +#include +#include + +namespace SymbianUtils { + +class VirtualSerialDevicePrivate +{ +public: + HANDLE portHandle; + OVERLAPPED writeOverlapped; + OVERLAPPED commEventOverlapped; + DWORD commEventMask; + QWinEventNotifier *writeCompleteNotifier; + QWinEventNotifier *commEventNotifier; + int bytesWrittenSignalsAlreadyEmitted; +}; + +void VirtualSerialDevice::platInit() +{ + d = new VirtualSerialDevicePrivate; + d->portHandle = INVALID_HANDLE_VALUE; + d->writeCompleteNotifier = NULL; + memset(&d->writeOverlapped, 0, sizeof(OVERLAPPED)); + d->commEventNotifier = NULL; + memset(&d->commEventOverlapped, 0, sizeof(OVERLAPPED)); + d->bytesWrittenSignalsAlreadyEmitted = 0; +} + +bool VirtualSerialDevice::open(OpenMode mode) +{ + Q_ASSERT(QThread::currentThread() == thread()); + if (isOpen()) return true; + + d->portHandle = CreateFileA(portName.toAscii(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); + if (d->portHandle == INVALID_HANDLE_VALUE) { + setErrorString(QString("Windows error %1 opening %2").arg(GetLastError()).arg(portName)); + return false; + } + + DCB commState; + memset(&commState, 0, sizeof(DCB)); + commState.DCBlength = sizeof(DCB); + bool ok = GetCommState(d->portHandle, &commState); + if (ok) { + commState.BaudRate = CBR_115200; + commState.fBinary = TRUE; + commState.fParity = FALSE; + commState.fOutxCtsFlow = FALSE; + commState.fOutxDsrFlow = FALSE; + commState.fInX = FALSE; + commState.fOutX = FALSE; + commState.fNull = FALSE; + commState.fAbortOnError = FALSE; + commState.fDsrSensitivity = FALSE; + commState.fDtrControl = DTR_CONTROL_DISABLE; + commState.ByteSize = 8; + commState.Parity = NOPARITY; + commState.StopBits = ONESTOPBIT; + ok = SetCommState(d->portHandle, &commState); + } + if (!ok) { + qWarning("Windows error %d setting comm state", (int)GetLastError()); + } + + // http://msdn.microsoft.com/en-us/library/aa363190(v=vs.85).aspx says this means + // "the read operation is to return immediately with the bytes that have already been received, even if no bytes have been received" + COMMTIMEOUTS timeouts; + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 0; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + SetCommTimeouts(d->portHandle, &timeouts); + + d->writeOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + d->writeCompleteNotifier = new QWinEventNotifier(d->writeOverlapped.hEvent, this); + connect(d->writeCompleteNotifier, SIGNAL(activated(HANDLE)), this, SLOT(writeCompleted())); + + // This is how we implement readyRead notifications + d->commEventOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + d->commEventNotifier = new QWinEventNotifier(d->commEventOverlapped.hEvent, this); + connect(d->commEventNotifier, SIGNAL(activated(HANDLE)), this, SLOT(commEventOccurred())); + + if (!SetCommMask(d->portHandle, EV_RXCHAR)) { + // What to do? + qWarning("Couldn't set comm mask, err=%d", (int)GetLastError()); + } + bool result = WaitCommEvent(d->portHandle, &d->commEventMask, &d->commEventOverlapped); + Q_ASSERT(result == false); // Can't see how it would make sense to be anything else... + (void)result; // For release build + if (GetLastError() != ERROR_IO_PENDING) { + setErrorString(QString("Windows error %1 waiting for read notifications from %2").arg(GetLastError()).arg(portName)); + close(); + return false; + } + + ok = QIODevice::open(mode); + if (!ok) close(); + return ok; +} + +void VirtualSerialDevice::platClose() +{ + delete d->writeCompleteNotifier; + d->writeCompleteNotifier = NULL; + CloseHandle(d->writeOverlapped.hEvent); + d->writeOverlapped.hEvent = INVALID_HANDLE_VALUE; + + delete d->commEventNotifier; + d->commEventNotifier = NULL; + d->commEventOverlapped.hEvent = INVALID_HANDLE_VALUE; + + CloseHandle(d->portHandle); + d->portHandle = INVALID_HANDLE_VALUE; +} + +VirtualSerialDevice::~VirtualSerialDevice() +{ + close(); + delete d; +} + +qint64 VirtualSerialDevice::bytesAvailable() const +{ + QMutexLocker locker(&lock); + if (!isOpen()) return 0; + + qint64 avail = 0; + COMSTAT Status; + if (ClearCommError(d->portHandle, NULL, &Status)) { + avail = Status.cbInQue; + } + return avail + QIODevice::bytesAvailable(); +} + +void VirtualSerialDevice::commEventOccurred() +{ + DWORD event = d->commEventMask; + if (event & EV_RXCHAR) { + emit readyRead(); + } + ResetEvent(d->commEventOverlapped.hEvent); + WaitCommEvent(d->portHandle, &d->commEventMask, &d->commEventOverlapped); +} + +qint64 VirtualSerialDevice::readData(char *data, qint64 maxSize) +{ + QMutexLocker locker(&lock); + // We do our reads synchronously + OVERLAPPED readOverlapped; + memset(&readOverlapped, 0, sizeof(OVERLAPPED)); + DWORD bytesRead; + BOOL done = ReadFile(d->portHandle, data, maxSize, &bytesRead, &readOverlapped); + if (done) return (qint64)bytesRead; + + if (GetLastError() == ERROR_IO_PENDING) { + // Note the TRUE to wait for the read to complete + done = GetOverlappedResult(d->portHandle, &readOverlapped, &bytesRead, TRUE); + if (done) return (qint64)bytesRead; + } + + // If we reach here an error has occurred + setErrorString(QString("Windows error %1 reading from %2").arg(GetLastError()).arg(portName)); + return -1; +} + + +qint64 VirtualSerialDevice::writeData(const char *data, qint64 maxSize) +{ + QMutexLocker locker(&lock); + + pendingWrites.append(QByteArray(data, maxSize)); // Can't see a way of doing async io safely without having to copy here... + if (pendingWrites.count() == 1) { + return writeNextBuffer(locker); + } else { + return maxSize; + } +} + +qint64 VirtualSerialDevice::writeNextBuffer(QMutexLocker& locker) +{ + Q_UNUSED(locker) + // Must be locked on entry + qint64 bufLen = pendingWrites[0].length(); + BOOL ok = WriteFile(d->portHandle, pendingWrites[0].constData(), bufLen, NULL, &d->writeOverlapped); + if (ok || GetLastError() == ERROR_IO_PENDING) { + // Apparently it can return true for a small asynchronous write... + // Hopefully it still gets signalled in the same way! + + // Wait for signal via writeCompleted + return bufLen; + } + else { + setErrorString(QString("Windows error %1 writing to %2").arg(GetLastError()).arg(portName)); + pendingWrites.removeFirst(); + return -1; + } +} + +void VirtualSerialDevice::writeCompleted() +{ + ResetEvent(d->writeOverlapped.hEvent); + + QMutexLocker locker(&lock); + + if (d->bytesWrittenSignalsAlreadyEmitted > 0) { + // The signal has already been emitted due to waitForBytesWritten being called, so don't do it here + d->bytesWrittenSignalsAlreadyEmitted--; + return; + } + + if (pendingWrites.count() == 0) { + qWarning("writeCompleted called when there are no pending writes!"); + return; + } + //Q_ASSERT(pendingWrites.count()); + qint64 len = pendingWrites.first().length(); + pendingWrites.removeFirst(); + + if (pendingWrites.count() > 0) { + // Get the next write started before notifying in case client calls waitForBytesWritten in their slot + writeNextBuffer(locker); + } + + emitBytesWrittenIfNeeded(locker, len); +} + +bool VirtualSerialDevice::waitForBytesWritten(int msecs) +{ + QMutexLocker locker(&lock); + if (pendingWrites.count() == 0) return false; + + DWORD waitTime = msecs; + if (msecs == -1) waitTime = INFINITE; // Ok these are probably bitwise the same, but just to prove I've thought about it... + DWORD result = WaitForSingleObject(d->writeOverlapped.hEvent, waitTime); // Do I need WaitForSingleObjectEx and worry about alertable states? + if (result == WAIT_TIMEOUT) { + return false; + } + else if (result == WAIT_OBJECT_0) { + DWORD bytesWritten; + BOOL ok = GetOverlappedResult(d->portHandle, &d->writeOverlapped, &bytesWritten, TRUE); + if (!ok) { + setErrorString(QString("Windows error %1 syncing on waitForBytesWritten for %2").arg(GetLastError()).arg(portName)); + return false; + } + Q_ASSERT(bytesWritten == (DWORD)pendingWrites.first().length()); + + //TODO should we call writeNextBuffer() here? (Probably) + + /*if (thread() == QThread::currentThread()) { + ResetEvent(writeHandle); // Make sure we don't cause a writeCompleted via the writeCompleteNotifier + + } + else*/ { + // We're waiting in another thread - make sure the main thread doesn't also emit bytesWritten + d->bytesWrittenSignalsAlreadyEmitted++; + qint64 len = pendingWrites.first().length(); + pendingWrites.removeFirst(); + emitBytesWrittenIfNeeded(locker, len); + return true; + } + } + else { + setErrorString(QString("Windows error %1 in waitForBytesWritten for %2").arg(GetLastError()).arg(portName)); + return false; + } +} + +void VirtualSerialDevice::flush() +{ + while (waitForBytesWritten(-1)) { /* loop */ } +} + +bool VirtualSerialDevice::waitForReadyRead(int msecs) +{ + return QIODevice::waitForReadyRead(msecs); //TODO +} + +} // namespace SymbianUtils diff --git a/tests/tools/codaclient/codaclient.pro b/tests/tools/codaclient/codaclient.pro index 3c579b4342d..0682df39a2b 100644 --- a/tests/tools/codaclient/codaclient.pro +++ b/tests/tools/codaclient/codaclient.pro @@ -2,7 +2,6 @@ DEFINES += SYMBIANUTILS_INCLUDE_PRI include(../../../qtcreator.pri) include(../../../src/shared/symbianutils/symbianutils.pri) -# include(../../../src/libs/3rdparty/qextserialport/qextserialport.pri) QT += core gui network TARGET = codaclient diff --git a/tests/tools/codaclient/codaclientapplication.cpp b/tests/tools/codaclient/codaclientapplication.cpp index 4a3272f4bdf..382fd1ce926 100644 --- a/tests/tools/codaclient/codaclientapplication.cpp +++ b/tests/tools/codaclient/codaclientapplication.cpp @@ -34,7 +34,7 @@ #include "codaclientapplication.h" #ifdef HAS_SERIALPORT -# include +#include "virtualserialdevice.h" #endif #include "tcftrkdevice.h" @@ -322,32 +322,16 @@ bool CodaClientApplication::start() if (isSerialPort(m_address)) { #ifdef HAS_SERIALPORT // Serial -#ifdef Q_OS_WIN - const QString fullPort = QextSerialPort::fullPortNameWin(m_address); -#else - const QString fullPort = m_address; -#endif - const QSharedPointer - serialPort(new QextSerialPort(fullPort, QextSerialPort::EventDriven)); - std::printf("Opening port %s...\n", qPrintable(fullPort)); - - // Magic USB serial parameters - serialPort->setTimeout(2000); - serialPort->setBaudRate(BAUD115200); - serialPort->setFlowControl(FLOW_OFF); - serialPort->setParity(PAR_NONE); - serialPort->setDataBits(DATA_8); - serialPort->setStopBits(STOP_1); - + const QSharedPointer serialPort(new SymbianUtils::VirtualSerialDevice(m_address)); + std::printf("Opening port %s...\n", qPrintable(m_address)); m_trkDevice->setSerialFrame(true); m_trkDevice->setDevice(serialPort); // Grab all data from start - if (!serialPort->open(QIODevice::ReadWrite|QIODevice::Unbuffered)) { + if (!serialPort->open(QIODevice::ReadWrite)) { std::fprintf(stderr, "Cannot open port: %s", qPrintable(serialPort->errorString())); return false; } // Initiate communication m_trkDevice->sendSerialPing(m_mode == Ping); - serialPort->flush(); #else std::fprintf(stderr, "Not implemented\n"); return false;