diff --git a/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp b/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp index ca55a627c09..c7518236268 100644 --- a/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp @@ -43,7 +43,7 @@ #include "qt4symbiantarget.h" #include "qt4target.h" #include "qtoutputformatter.h" -#include "virtualserialdevice.h" +#include "symbiandevicemanager.h" #include #include @@ -65,11 +65,10 @@ using namespace Qt4ProjectManager; using namespace Qt4ProjectManager::Internal; using namespace Coda; -enum { debug = 0 }; +enum { debug = 1 }; CodaRunControl::CodaRunControl(RunConfiguration *runConfiguration, const QString &mode) : S60RunControlBase(runConfiguration, mode), - m_codaDevice(0), m_port(0), m_state(StateUninit) { @@ -89,12 +88,6 @@ CodaRunControl::CodaRunControl(RunConfiguration *runConfiguration, const QString } } -CodaRunControl::~CodaRunControl() -{ - if (m_codaDevice) - m_codaDevice->deleteLater(); -} - bool CodaRunControl::doStart() { if (m_address.isEmpty() && m_serialPort.isEmpty()) { @@ -117,31 +110,32 @@ bool CodaRunControl::setupLauncher() { QTC_ASSERT(!m_codaDevice, return false); - m_codaDevice = new CodaDevice; - if (debug) - m_codaDevice->setVerbose(debug); - - connect(m_codaDevice, SIGNAL(error(QString)), this, SLOT(slotError(QString))); - connect(m_codaDevice, SIGNAL(logMessage(QString)), this, SLOT(slotTrkLogMessage(QString))); - connect(m_codaDevice, SIGNAL(tcfEvent(Coda::CodaEvent)), this, SLOT(slotCodaEvent(Coda::CodaEvent))); - connect(m_codaDevice, SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString))); - if (m_serialPort.length()) { - const QSharedPointer serialDevice(new SymbianUtils::VirtualSerialDevice(m_serialPort)); - appendMessage(tr("Conecting to '%2'...").arg(m_serialPort), NormalMessageFormat); - m_codaDevice->setSerialFrame(true); - m_codaDevice->setDevice(serialDevice); - bool ok = serialDevice->open(QIODevice::ReadWrite); + // We get the port from SymbianDeviceManager + appendMessage(tr("Connecting to '%2'...").arg(m_serialPort), NormalMessageFormat); + m_codaDevice = SymbianUtils::SymbianDeviceManager::instance()->getTcfPort(m_serialPort); + + bool ok = m_codaDevice && m_tcfTrkDevice->device()->isOpen(); if (!ok) { - appendMessage(tr("Couldn't open serial device: %1").arg(serialDevice->errorString()), ErrorMessageFormat); + appendMessage(tr("Couldn't open serial device: %1").arg(m_tcfTrkDevice->device()->errorString()), ErrorMessageFormat); return false; } connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(deviceRemoved(const SymbianUtils::SymbianDevice)), this, SLOT(deviceRemoved(SymbianUtils::SymbianDevice))); + connect(m_tcfTrkDevice.data(), SIGNAL(error(QString)), this, SLOT(slotError(QString))); + connect(m_tcfTrkDevice.data(), SIGNAL(logMessage(QString)), this, SLOT(slotTrkLogMessage(QString))); + connect(m_tcfTrkDevice.data(), SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)), this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent))); + connect(m_tcfTrkDevice.data(), SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString))); m_state = StateConnecting; m_codaDevice->sendSerialPing(false); QTimer::singleShot(4000, this, SLOT(checkForTimeout())); } else { + // For TCP we don't use device manager, we just set it up directly + m_codaDevice = QSharedPointer(new Coda::CodaDevice); + connect(m_codaDevice.data(), SIGNAL(error(QString)), this, SLOT(slotError(QString))); + connect(m_codaDevice.data(), SIGNAL(logMessage(QString)), this, SLOT(slotTrkLogMessage(QString))); + connect(m_codaDevice.data(), SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)), this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent))); + const QSharedPointer codaSocket(new QTcpSocket); m_codaDevice->setDevice(codaSocket); codaSocket->connectToHost(m_address, m_port); @@ -149,6 +143,7 @@ bool CodaRunControl::setupLauncher() appendMessage(tr("Connecting to %1:%2...").arg(m_address).arg(m_port), NormalMessageFormat); QTimer::singleShot(4000, this, SLOT(checkForTimeout())); } + if (debug) m_tcfTrkDevice->setVerbose(1); return true; } @@ -325,9 +320,10 @@ void CodaRunControl::handleCreateProcess(const CodaCommandResult &result) void CodaRunControl::finishRunControl() { m_runningProcessId.clear(); - if (m_codaDevice) - m_codaDevice->deleteLater(); - m_codaDevice = 0; + if (m_codaDevice) { + disconnect(m_codaDevice.data(), 0, this, 0); + SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_codaDevice); + } m_state = StateUninit; emit finished(); } diff --git a/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h b/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h index 2dfbb745d2c..2adfffaf62e 100644 --- a/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h +++ b/src/plugins/qt4projectmanager/qt-s60/codaruncontrol.h @@ -60,7 +60,6 @@ class CodaRunControl : public S60RunControlBase Q_OBJECT public: CodaRunControl(ProjectExplorer::RunConfiguration *runConfiguration, const QString &mode); - ~CodaRunControl(); virtual bool isRunning() const; static QMessageBox *createCodaWaitingMessageBox(QWidget *parent = 0); @@ -104,7 +103,7 @@ private: StateProcessRunning }; - Coda::CodaDevice *m_codaDevice; + QSharedPointer m_codaDevice; QString m_address; unsigned short m_port; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp index 327d2b1bf32..15f4acb8465 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp @@ -48,7 +48,6 @@ #include #include -#include #include #include @@ -108,7 +107,6 @@ S60DeployStep::S60DeployStep(ProjectExplorer::BuildStepList *bc, m_releaseDeviceAfterLauncherFinish(bs->m_releaseDeviceAfterLauncherFinish), m_handleDeviceRemoval(bs->m_handleDeviceRemoval), m_launcher(0), - m_trkDevice(0), m_eventLoop(0), m_state(StateUninit), m_putWriteOk(false), @@ -127,7 +125,6 @@ S60DeployStep::S60DeployStep(ProjectExplorer::BuildStepList *bc): m_releaseDeviceAfterLauncherFinish(true), m_handleDeviceRemoval(true), m_launcher(0), - m_trkDevice(0), m_eventLoop(0), m_state(StateUninit), m_putWriteOk(false), @@ -151,7 +148,6 @@ S60DeployStep::~S60DeployStep() { delete m_timer; delete m_launcher; - delete m_trkDevice; delete m_eventLoop; } @@ -294,8 +290,7 @@ void S60DeployStep::start() return; } if (!trkClient) { - QTC_ASSERT(!m_trkDevice, return); - m_trkDevice = new Coda::CodaDevice; + QTC_ASSERT(!m_codaDevice.data(), return); if (m_address.isEmpty() && !serialConnection) { errorMessage = tr("No address for a device has been defined. Please define an address and try again."); reportError(errorMessage); @@ -320,8 +315,8 @@ void S60DeployStep::stop() m_launcher->terminate(); } else { if (m_trkDevice) { - delete m_trkDevice; - m_trkDevice = 0; + disconnect(m_trkDevice.data(), 0, this, 0); + SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_trkDevice); } } emit finished(false); @@ -345,10 +340,10 @@ void S60DeployStep::setupConnections() connect(m_launcher, SIGNAL(stateChanged(int)), this, SLOT(slotLauncherStateChanged(int))); connect(m_launcher, SIGNAL(copyProgress(int)), this, SLOT(setCopyProgress(int))); } else { - connect(m_trkDevice, SIGNAL(error(QString)), this, SLOT(slotError(QString))); - connect(m_trkDevice, SIGNAL(logMessage(QString)), this, SLOT(slotTrkLogMessage(QString))); - connect(m_trkDevice, SIGNAL(tcfEvent(Coda::CodaEvent)), this, SLOT(slotCodaEvent(Coda::CodaEvent)), Qt::DirectConnection); - connect(m_trkDevice, SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString))); + connect(m_codaDevice.data(), SIGNAL(error(QString)), this, SLOT(slotError(QString))); + connect(m_codaDevice.data(), SIGNAL(logMessage(QString)), this, SLOT(slotTrkLogMessage(QString))); + connect(m_codaDevice.data(), SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)), this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent)), Qt::DirectConnection); + connect(m_codaDevice.data(), SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString))); connect(this, SIGNAL(manualInstallation()), this, SLOT(showManualInstallationInfo())); } } @@ -357,13 +352,14 @@ void S60DeployStep::startDeployment() { if (m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection) { QTC_ASSERT(m_launcher, return); - } else { - QTC_ASSERT(m_trkDevice, return); } + QTC_ASSERT(!m_trkDevice.data(), return); - setupConnections(); + // We need to defer setupConnections() in the case of CommunicationCodaSerialConnection + //setupConnections(); if (m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection) { + setupConnections(); QStringList copyDst; foreach (const QString &signedPackage, m_signedPackages) copyDst << QString::fromLatin1("%1:\\Data\\%2").arg(m_installationDrive).arg(QFileInfo(signedPackage).fileName()); @@ -386,22 +382,25 @@ void S60DeployStep::startDeployment() 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); + m_trkDevice = SymbianUtils::SymbianDeviceManager::instance()->getTcfPort(m_serialPortName); + bool ok = m_trkDevice && m_trkDevice->device()->isOpen(); if (!ok) { - reportError(tr("Couldn't open serial device: %1").arg(serialDevice->errorString())); + QString deviceError = tr("No such port"); + if (m_trkDevice) deviceError = m_trkDevice->device()->errorString(); + reportError(tr("Couldn't open serial device: %1").arg(deviceError)); stop(); return; } + setupConnections(); m_state = StateConnecting; m_trkDevice->sendSerialPing(false); QTimer::singleShot(4000, this, SLOT(checkForTimeout())); } else { + m_codaDevice = QSharedPointer(new Coda::CodaDevice); + setupConnections(); const QSharedPointer codaSocket(new QTcpSocket); - m_trkDevice->setDevice(codaSocket); + m_codaDevice->setDevice(codaSocket); codaSocket->connectToHost(m_address, m_port); m_state = StateConnecting; appendMessage(tr("Connecting to %1:%2...").arg(m_address).arg(m_port), false); @@ -440,8 +439,10 @@ void S60DeployStep::run(QFutureInterface &fi) delete m_timer; m_timer = 0; - delete m_trkDevice; - m_trkDevice = 0; + if (m_trkDevice) { + disconnect(m_trkDevice.data(), 0, this, 0); + SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_trkDevice); + } delete m_eventLoop; m_eventLoop = 0; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h index 5357d3360a5..1c3e85176db 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60deploystep.h @@ -201,7 +201,8 @@ private: QFutureInterface *m_futureInterface; //not owned trk::Launcher *m_launcher; - Coda::CodaDevice *m_trkDevice; + + QSharedPointer m_codaDevice; QEventLoop *m_eventLoop; bool m_deployResult; diff --git a/src/shared/symbianutils/codadevice.cpp b/src/shared/symbianutils/codadevice.cpp index 28bd6b7f219..c01a798293b 100644 --- a/src/shared/symbianutils/codadevice.cpp +++ b/src/shared/symbianutils/codadevice.cpp @@ -43,7 +43,7 @@ #include #include -enum { debug = 0 }; +enum { debug = 1 }; static const char tcpMessageTerminatorC[] = "\003\001"; @@ -347,6 +347,7 @@ CodaDevicePrivate::CodaDevicePrivate() : CodaDevice::CodaDevice(QObject *parent) : QObject(parent), d(new CodaDevicePrivate) { + if (debug) setVerbose(true); } CodaDevice::~CodaDevice() @@ -470,26 +471,45 @@ void CodaDevice::slotDeviceReadyRead() // Find a serial header in input stream '0x1', '0x92', 'lenH', 'lenL' // and return message position and size. -static inline QPair findSerialHeader(const QByteArray &in) +QPair TcfTrkDevice::findSerialHeader(QByteArray &in) { - const int size = in.size(); const char header1 = 0x1; const char header2 = char(0x92); + const char header2tracecore = char(0x91); // Header should in theory always be at beginning of - // buffer. Warn if there are bogus data in-between. - for (int pos = 0; pos < size; ) { - if (pos + 4 < size && in.at(pos) == header1 && in.at(pos + 1) == header2) { + // buffer. Warn if there are bogus data in-between. + + while (in.size() >= 4) { + if (in.at(0) == header1 && in.at(1) == header2) { + // Good packet const int length = trk::extractShort(in.constData() + 2); - return QPair(pos + 4, length); + return QPair(4, length); + } else if (in.at(0) == header1 && in.at(1) == header2tracecore) { + // We recognise it but it's not a TCF message - emit it for any interested party to handle + const int length = trk::extractShort(in.constData() + 2); + if (4 + length <= in.size()) { + // We have all the data + QByteArray data(in.mid(4, length)); + emit traceCoreEvent(data); + in.remove(0, 4+length); + // and continue + } else { + // If we don't have all this packet, there can't be any data following it, so return now + // and wait for more data + return QPair(-1, -1); + } + } else { + // Bad data - log it, remove it, and go round again + int nextHeader = in.indexOf(header1, 1); + QByteArray bad = in.mid(0, nextHeader); + qWarning("Bogus data received on serial line: %s\n" + "Frame Header at: %d", qPrintable(trk::stringFromArray(bad)), nextHeader); + d->m_device->write(bad); // Backatcha - TOMSCI TESTING + in.remove(0, bad.length()); + // and continue } - // Find next - pos = in.indexOf(header1, pos + 1); - qWarning("Bogus data received on serial line: %s\n" - "Frame Header at: %d", qPrintable(trk::stringFromArray(in)), pos); - if (pos < 0) - break; } - return QPair(-1, -1); + return QPair(-1, -1); // No more data, or not enough for a complete header } void CodaDevice::deviceReadyReadSerial() @@ -767,6 +787,9 @@ void CodaDevice::sendSerialPing(bool pingOnly) if (!checkOpen()) return; + dumpObjectInfo(); + d->m_device->dumpObjectInfo(); + d->m_serialPingOnly = pingOnly; setSerialFrame(true); writeMessage(QByteArray(serialPingC, qstrlen(serialPingC)), false); @@ -839,7 +862,9 @@ void CodaDevice::writeMessage(QByteArray data, bool ensureTerminating0) if (debug > 1) qDebug("Writing:\n%s", qPrintable(formatData(data))); - d->m_device->write(data); + int result = d->m_device->write(data); + if (result < data.length()) + qWarning("Failed to write all data! result=%d", result); if (QAbstractSocket *as = qobject_cast(d->m_device.data())) as->flush(); } diff --git a/src/shared/symbianutils/codadevice.h b/src/shared/symbianutils/codadevice.h index 22be8d1dc9d..a52c8d86149 100644 --- a/src/shared/symbianutils/codadevice.h +++ b/src/shared/symbianutils/codadevice.h @@ -367,6 +367,7 @@ public: signals: void genericTcfEvent(int service, const QByteArray &name, const QVector &value); void tcfEvent(const Coda::CodaEvent &knownEvent); + void traceCoreEvent(const QByteArray& data); void serialPong(const QString &codaVersion); void logMessage(const QString &); @@ -393,6 +394,9 @@ private: inline void processSerialMessage(const QByteArray &message); int parseTcfCommandReply(char type, const QVector &tokens); int parseTcfEvent(const QVector &tokens); + +private: + QPair findSerialHeader(QByteArray &in); CodaDevicePrivate *d; }; diff --git a/src/shared/symbianutils/symbiandevicemanager.cpp b/src/shared/symbianutils/symbiandevicemanager.cpp index a2032aba119..61c976126f1 100644 --- a/src/shared/symbianutils/symbiandevicemanager.cpp +++ b/src/shared/symbianutils/symbiandevicemanager.cpp @@ -33,6 +33,8 @@ #include "symbiandevicemanager.h" #include "trkdevice.h" +#include "tcftrkdevice.h" +#include "virtualserialdevice.h" #include #include @@ -42,6 +44,8 @@ #include #include #include +#include +#include namespace SymbianUtils { @@ -58,7 +62,7 @@ public: SymbianDeviceData(); ~SymbianDeviceData(); - inline bool isOpen() const { return !device.isNull() && device->isOpen(); } + bool isOpen() const; void forcedClose(); QString portName; @@ -69,6 +73,7 @@ public: DeviceCommunicationType type; QSharedPointer device; + QSharedPointer tcfdevice; bool deviceAcquired; }; @@ -78,6 +83,18 @@ SymbianDeviceData::SymbianDeviceData() : { } +bool SymbianDeviceData::isOpen() const +{ + if (device) { + // TRK device + return device->isOpen(); + } else if (tcfdevice) { + return tcfdevice->device()->isOpen(); + } else { + return false; + } +} + SymbianDeviceData::~SymbianDeviceData() { forcedClose(); @@ -93,7 +110,8 @@ void SymbianDeviceData::forcedClose() if (deviceAcquired) qWarning("Device on '%s' unplugged while an operation is in progress.", qPrintable(portName)); - device->close(); + if (device) device->close(); + else tcfdevice->device()->close(); } } @@ -247,17 +265,34 @@ SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDevice &cd) // ------------- SymbianDeviceManagerPrivate struct SymbianDeviceManagerPrivate { - SymbianDeviceManagerPrivate() : m_initialized(false), m_destroyReleaseMapper(0) {} + SymbianDeviceManagerPrivate() : m_initialized(false) /*, m_destroyReleaseMapper(0),*/ {} bool m_initialized; SymbianDeviceManager::SymbianDeviceList m_devices; - QSignalMapper *m_destroyReleaseMapper; + //QSignalMapper *m_destroyReleaseMapper; + // The following 2 variables are needed to manage requests for a TCF port not coming from the main thread + int m_constructTcfPortEventType; + QMutex m_tcfPortWaitMutex; }; +class QConstructTcfPortEvent : public QEvent +{ +public: + QConstructTcfPortEvent(QEvent::Type eventId, const QString &portName, TcfTrkDevicePtr *device, QWaitCondition *waiter) : + QEvent(eventId), m_portName(portName), m_device(device), m_waiter(waiter) + {} + + QString m_portName; + TcfTrkDevicePtr* m_device; + QWaitCondition *m_waiter; +}; + + SymbianDeviceManager::SymbianDeviceManager(QObject *parent) : QObject(parent), d(new SymbianDeviceManagerPrivate) { + d->m_constructTcfPortEventType = QEvent::registerEventType(); } SymbianDeviceManager::~SymbianDeviceManager() @@ -318,6 +353,85 @@ SymbianDeviceManager::TrkDevicePtr return rc; } +TcfTrkDevicePtr SymbianDeviceManager::getTcfPort(const QString &port) +{ + ensureInitialized(); + const int idx = findByPortName(port); + if (idx == -1) { + qWarning("Attempt to acquire device '%s' that does not exist.", qPrintable(port)); + if (debug) + qDebug() << *this; + return TcfTrkDevicePtr(); + } + SymbianDevice& device = d->m_devices[idx]; + if (device.m_data->device) { + qWarning("Attempting to open a port '%s' that is configured for TRK!", qPrintable(port)); + return TcfTrkDevicePtr(); + } + TcfTrkDevicePtr& devicePtr = device.m_data->tcfdevice; + if (devicePtr.isNull()) { + // Check we instanciate in the correct thread - we can't afford to create the TcfTrkDevice (and more specifically, open the VirtualSerialDevice) in a thread that isn't guaranteed to be long-lived. + // Therefore, if we're not in SymbianDeviceManager's thread, rejig things so it's opened in the main thread + if (QThread::currentThread() != thread()) { + // SymbianDeviceManager is owned by the current thread + d->m_tcfPortWaitMutex.lock(); + QWaitCondition waiter; + QCoreApplication::postEvent(this, new QConstructTcfPortEvent((QEvent::Type)d->m_constructTcfPortEventType, port, &devicePtr, &waiter)); + waiter.wait(&d->m_tcfPortWaitMutex); + // When the wait returns (due to the wakeAll in SymbianDeviceManager::customEvent), the TcfTrkDevice will be fully set up + d->m_tcfPortWaitMutex.unlock(); + } else { + // We're in the main thread, just set it up directly + constructTcfPort(devicePtr, port); + } + } + if (!devicePtr->device()->isOpen()) { + bool ok = devicePtr->device().staticCast()->open(QIODevice::ReadWrite); + if (!ok && debug) { + qDebug("SymbianDeviceManager: Failed to open port %s", qPrintable(port)); + } + // We still carry on in the case we failed to open so the client can access the IODevice's errorString() + } + //Q_ASSERT(QThread::currentThread() == devicePtr->thread()); + return devicePtr; +} + +void SymbianDeviceManager::constructTcfPort(TcfTrkDevicePtr& device, const QString& portName) +{ + QMutexLocker locker(&d->m_tcfPortWaitMutex); + device = QSharedPointer(new tcftrk::TcfTrkDevice); + const QSharedPointer serialDevice(new SymbianUtils::VirtualSerialDevice(portName)); + device->setSerialFrame(true); + device->setDevice(serialDevice); +} + +void SymbianDeviceManager::customEvent(QEvent *event) +{ + if (event->type() == d->m_constructTcfPortEventType) + { + QConstructTcfPortEvent* constructEvent = static_cast(event); + constructTcfPort(*constructEvent->m_device, constructEvent->m_portName); + constructEvent->m_waiter->wakeAll(); // Should only ever be one thing waiting on this + } +} + +/* +TcfTrkDevicePtr SymbianDeviceManager::getTcfPort(const QString &host, quint16 port) +{ + // No attempt to check the device list. The main purpose in doing that is to cooperatively share the port with other services, and there's no need to do that with TCP/IP as you can just use separate port numbers. + // Ok it might make it slightly quicker but I'm not going to worry about it just now + +} +*/ + +void SymbianDeviceManager::releaseTcfPort(TcfTrkDevicePtr &aPort) +{ + if (aPort) { + aPort.clear(); + } + //TODO close the port after a timeer if last reference? +} + void SymbianDeviceManager::update() { update(true); diff --git a/src/shared/symbianutils/symbiandevicemanager.h b/src/shared/symbianutils/symbiandevicemanager.h index af5fbd201f5..1ff885c59a6 100644 --- a/src/shared/symbianutils/symbiandevicemanager.h +++ b/src/shared/symbianutils/symbiandevicemanager.h @@ -48,6 +48,9 @@ QT_END_NAMESPACE namespace trk { class TrkDevice; } +namespace tcftrk { + class TcfTrkDevice; +} namespace SymbianUtils { @@ -59,6 +62,8 @@ enum DeviceCommunicationType { BlueToothCommunication = 1 }; +typedef QSharedPointer TcfTrkDevicePtr; + // SymbianDevice: Explicitly shared device data and a TrkDevice // instance that can be acquired (exclusively) for use. // A device removal from the manager will result in the @@ -82,13 +87,6 @@ public: QString additionalInformation() const; void setAdditionalInformation(const QString &); - // Acquire: Mark the device as 'out' and return a shared pointer - // unless it is already in use by another owner. The result should not - // be passed on further. - TrkDevicePtr acquireDevice(); - // Give back a device and mark it as 'free'. - void releaseDevice(TrkDevicePtr *ptr = 0); - bool isOpen() const; // Windows only. @@ -99,6 +97,14 @@ public: QString toString() const; private: + // Acquire: Mark the device as 'out' and return a shared pointer + // unless it is already in use by another owner. The result should not + // be passed on further. + // TRK only + TrkDevicePtr acquireDevice(); + // Give back a device and mark it as 'free'. TRK only. + void releaseDevice(TrkDevicePtr *ptr = 0); + void forcedClose(); QExplicitlySharedDataPointer m_data; @@ -137,15 +143,27 @@ public: SymbianDeviceList devices() const; QString toString() const; - // Acquire a device for use. See releaseDevice(). + // Acquire a TRK device for use. Assuming the port is found, equivalent to devices()[findByPortName(port)].acquireDevice(). See also releaseDevice(). TrkDevicePtr acquireDevice(const QString &port); + //// The TCF code prefers to set up the TcfTrkDevice object itself, so we let it and just handle opening the underlying QIODevice and keeping track of the TcfTrkDevice + //// Returns true if port was opened successfully. + + // Gets the TcfTrkDevice, which may or may not be open depending on what other clients have already acquired it. + // Therefore once clients have set up any signals and slots they required, they should check TcfTrkDevice::device()->isOpen() + // and if false, the open failed and they should check device()->errorString() if required. + // Caller should call releaseTcfPort if they want the port to auto-close itself + TcfTrkDevicePtr getTcfPort(const QString &port); + + // Caller is responsible for disconnecting any signals from aPort - do not assume the TcfTrkDevice will be deleted as a result of this call. On return aPort will be clear()ed. + void releaseTcfPort(TcfTrkDevicePtr &aPort); + int findByPortName(const QString &p) const; QString friendlyNameForPort(const QString &port) const; public slots: void update(); - // Relase a device, make it available for further use. + // Release a device, make it available for further use. Only for use with a TRK device void releaseDevice(const QString &port); void setAdditionalInformation(const QString &port, const QString &ai); @@ -159,6 +177,8 @@ private: void update(bool emitSignals); SymbianDeviceList serialPorts() const; SymbianDeviceList blueToothDevices() const; + void customEvent(QEvent *event); + void constructTcfPort(TcfTrkDevicePtr& device, const QString& portName); SymbianDeviceManagerPrivate *d; }; diff --git a/src/shared/symbianutils/symbianutils.pri b/src/shared/symbianutils/symbianutils.pri index 2da4a64c72e..2d32680defa 100644 --- a/src/shared/symbianutils/symbianutils.pri +++ b/src/shared/symbianutils/symbianutils.pri @@ -15,7 +15,7 @@ HEADERS += $$PWD/symbianutils_global.h \ $$PWD/codadevice.h \ $$PWD/codamessage.h \ $$PWD/json.h \ - $$PWD/virtualserialdevice.h + $$PWD/virtualserialdevice.h SOURCES += $$PWD/trkutils.cpp \ $$PWD/trkdevice.cpp \ diff --git a/src/shared/symbianutils/virtualserialdevice.cpp b/src/shared/symbianutils/virtualserialdevice.cpp index 4d35b31abba..2d950a69acd 100644 --- a/src/shared/symbianutils/virtualserialdevice.cpp +++ b/src/shared/symbianutils/virtualserialdevice.cpp @@ -23,10 +23,9 @@ const QString& VirtualSerialDevice::getPortName() const void VirtualSerialDevice::close() { if (isOpen()) { - Q_ASSERT(thread() == QThread::currentThread()); // My brain will explode otherwise + QMutexLocker locker(&lock); delete waiterForBytesWritten; waiterForBytesWritten = NULL; - QMutexLocker locker(&lock); QIODevice::close(); platClose(); }