In progress: making TcfTrkDevice connections persistant

This commit is contained in:
Tom Sutcliffe
2011-02-04 12:08:19 +01:00
committed by Pawel Polanski
parent 813778ac23
commit ca622b32e9
10 changed files with 243 additions and 84 deletions

View File

@@ -43,7 +43,7 @@
#include "qt4symbiantarget.h"
#include "qt4target.h"
#include "qtoutputformatter.h"
#include "virtualserialdevice.h"
#include "symbiandevicemanager.h"
#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
@@ -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<SymbianUtils::VirtualSerialDevice> 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<Coda::CodaDevice>(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<QTcpSocket> 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();
}

View File

@@ -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<Coda::CodaDevice> m_codaDevice;
QString m_address;
unsigned short m_port;

View File

@@ -48,7 +48,6 @@
#include <symbianutils/launcher.h>
#include <symbianutils/symbiandevicemanager.h>
#include <symbianutils/virtualserialdevice.h>
#include <utils/qtcassert.h>
#include <QtGui/QMessageBox>
@@ -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<SymbianUtils::VirtualSerialDevice> 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<Coda::CodaDevice>(new Coda::CodaDevice);
setupConnections();
const QSharedPointer<QTcpSocket> 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<bool> &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;

View File

@@ -201,7 +201,8 @@ private:
QFutureInterface<bool> *m_futureInterface; //not owned
trk::Launcher *m_launcher;
Coda::CodaDevice *m_trkDevice;
QSharedPointer<Coda::CodaDevice> m_codaDevice;
QEventLoop *m_eventLoop;
bool m_deployResult;

View File

@@ -43,7 +43,7 @@
#include <QtCore/QDateTime>
#include <QtCore/QFileInfo>
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<int, int> findSerialHeader(const QByteArray &in)
QPair<int, int> 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) {
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<int, int>(pos + 4, length);
}
// 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<int, int>(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<int, int>(-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
}
}
return QPair<int, int>(-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<QAbstractSocket *>(d->m_device.data()))
as->flush();
}

View File

@@ -367,6 +367,7 @@ public:
signals:
void genericTcfEvent(int service, const QByteArray &name, const QVector<JsonValue> &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<QByteArray> &tokens);
int parseTcfEvent(const QVector<QByteArray> &tokens);
private:
QPair<int, int> findSerialHeader(QByteArray &in);
CodaDevicePrivate *d;
};

View File

@@ -33,6 +33,8 @@
#include "symbiandevicemanager.h"
#include "trkdevice.h"
#include "tcftrkdevice.h"
#include "virtualserialdevice.h"
#include <QtCore/QSettings>
#include <QtCore/QStringList>
@@ -42,6 +44,8 @@
#include <QtCore/QSharedData>
#include <QtCore/QScopedPointer>
#include <QtCore/QSignalMapper>
#include <QtCore/QThread>
#include <QtCore/QWaitCondition>
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<trk::TrkDevice> device;
QSharedPointer<tcftrk::TcfTrkDevice> 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<SymbianUtils::VirtualSerialDevice>()->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<tcftrk::TcfTrkDevice>(new tcftrk::TcfTrkDevice);
const QSharedPointer<SymbianUtils::VirtualSerialDevice> 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<QConstructTcfPortEvent*>(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);

View File

@@ -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<tcftrk::TcfTrkDevice> 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<SymbianDeviceData> 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;
};

View File

@@ -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();
}