diff options
author | Tom Sutcliffe <ext-thomas.1.sutcliffe@nokia.com> | 2011-02-07 14:14:57 +0100 |
---|---|---|
committer | Pawel Polanski <pawel.3.polanski@nokia.com> | 2011-02-08 09:18:45 +0100 |
commit | a0349893500530f5769fae7b4bbc9a1edea22260 (patch) | |
tree | b914293b405821af10b4f632c4da5dcbb87d0b0a /src/shared | |
parent | 31b352d2199ebbbcc7d86d9d0040c5ec8756617d (diff) | |
download | qt-creator-a0349893500530f5769fae7b4bbc9a1edea22260.tar.gz |
Sharing TcfTrkDevice connections between multiple clients
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/symbianutils/codadevice.cpp | 51 | ||||
-rw-r--r-- | src/shared/symbianutils/codadevice.h | 4 | ||||
-rw-r--r-- | src/shared/symbianutils/symbiandevicemanager.cpp | 88 | ||||
-rw-r--r-- | src/shared/symbianutils/symbiandevicemanager.h | 20 | ||||
-rw-r--r-- | src/shared/symbianutils/virtualserialdevice_posix.cpp | 13 |
5 files changed, 89 insertions, 87 deletions
diff --git a/src/shared/symbianutils/codadevice.cpp b/src/shared/symbianutils/codadevice.cpp index c01a798293..a8a77d06d3 100644 --- a/src/shared/symbianutils/codadevice.cpp +++ b/src/shared/symbianutils/codadevice.cpp @@ -43,7 +43,7 @@ #include <QtCore/QDateTime> #include <QtCore/QFileInfo> -enum { debug = 1 }; +enum { debug = 0 }; static const char tcpMessageTerminatorC[] = "\003\001"; @@ -60,15 +60,18 @@ static const char locatorAnswerC[] = "E\0Locator\0Hello\0[\"Locator\"]"; static const unsigned serialChunkLength = 0x400; // 1K max USB router static const int maxSerialMessageLength = 0x10000; // given chunking scheme +static const char validProtocolIdStart = (char)0x90; +static const char validProtocolIdEnd = (char)0x95; +static const char codaProtocolId = (char)0x92; static const unsigned char serialChunkingStart = 0xfe; static const unsigned char serialChunkingContinuation = 0x0; enum { SerialChunkHeaderSize = 2 }; // Create USB router frame -static inline void encodeSerialFrame(const QByteArray &data, QByteArray *target) +static inline void encodeSerialFrame(const QByteArray &data, QByteArray *target, char protocolId) { target->append(char(0x01)); - target->append(char(0x92)); // CODA serial message ID + target->append(protocolId); appendShort(target, ushort(data.size()), trk::BigEndian); target->append(data); } @@ -76,14 +79,14 @@ static inline void encodeSerialFrame(const QByteArray &data, QByteArray *target) // Split in chunks of 1K according to CODA protocol chunking static inline QByteArray encodeUsbSerialMessage(const QByteArray &dataIn) { - // Reserve 2 header bytes + // Reserve 2 header bytes static const int chunkSize = serialChunkLength - SerialChunkHeaderSize; const int size = dataIn.size(); QByteArray frame; // Do we need to split? if (size < chunkSize) { // Nope, all happy. frame.reserve(size + 4); - encodeSerialFrame(dataIn, &frame); + encodeSerialFrame(dataIn, &frame, codaProtocolId); return frame; } // Split. @@ -102,7 +105,7 @@ static inline QByteArray encodeUsbSerialMessage(const QByteArray &dataIn) chunk.append(char(static_cast<unsigned char>(c))); // Avoid any signedness issues. const int chunkEnd = qMin(pos + chunkSize, size); chunk.append(dataIn.mid(pos, chunkEnd - pos)); - encodeSerialFrame(chunk, &frame); + encodeSerialFrame(chunk, &frame, codaProtocolId); pos = chunkEnd; } if (debug > 1) @@ -471,26 +474,24 @@ void CodaDevice::slotDeviceReadyRead() // Find a serial header in input stream '0x1', '0x92', 'lenH', 'lenL' // and return message position and size. -QPair<int, int> TcfTrkDevice::findSerialHeader(QByteArray &in) +QPair<int, int> CodaDevice::findSerialHeader(QByteArray &in) { - const char header1 = 0x1; - const char header2 = char(0x92); - const char header2tracecore = char(0x91); - // Header should in theory always be at beginning of + static const char header1 = 0x1; + // Header should in theory always be at beginning of // buffer. Warn if there are bogus data in-between. while (in.size() >= 4) { - if (in.at(0) == header1 && in.at(1) == header2) { + if (in.at(0) == header1 && in.at(1) == codaProtocolId) { // Good packet const int length = trk::extractShort(in.constData() + 2); return QPair<int, int>(4, length); - } else if (in.at(0) == header1 && in.at(1) == header2tracecore) { + } else if (in.at(0) == header1 && in.at(1) >= validProtocolIdStart && in.at(1) <= validProtocolIdEnd) { // 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); + emit unknownEvent(in.at(1), data); in.remove(0, 4+length); // and continue } else { @@ -504,7 +505,6 @@ QPair<int, int> TcfTrkDevice::findSerialHeader(QByteArray &in) 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 } @@ -787,9 +787,6 @@ 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); @@ -869,6 +866,24 @@ void CodaDevice::writeMessage(QByteArray data, bool ensureTerminating0) as->flush(); } +void CodaDevice::writeCustomData(char protocolId, const QByteArray &data) +{ + if (!checkOpen()) + return; + + if (!d->m_serialFrame) { + qWarning("Ignoring request to send data to non-serial CodaDevice"); + return; + } + if (data.length() > 0xFFFF) { + qWarning("Ignoring request to send too large packet, of size %d", data.length()); + return; + } + QByteArray framedData; + encodeSerialFrame(data, &framedData, protocolId); + device()->write(framedData); +} + void CodaDevice::checkSendQueue() { // Fire off messages or invoke noops until a message with reply is found diff --git a/src/shared/symbianutils/codadevice.h b/src/shared/symbianutils/codadevice.h index a52c8d8614..f2e029be91 100644 --- a/src/shared/symbianutils/codadevice.h +++ b/src/shared/symbianutils/codadevice.h @@ -360,6 +360,8 @@ public: // Settings void sendSettingsEnableLogCommand(); + void writeCustomData(char protocolId, const QByteArray &aData); + static QByteArray parseMemoryGet(const CodaCommandResult &r); static QVector<QByteArray> parseRegisterGetChildren(const CodaCommandResult &r); static CodaStatResponse parseStat(const CodaCommandResult &r); @@ -367,7 +369,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 unknownEvent(uchar protocolId, const QByteArray& data); void serialPong(const QString &codaVersion); void logMessage(const QString &); diff --git a/src/shared/symbianutils/symbiandevicemanager.cpp b/src/shared/symbianutils/symbiandevicemanager.cpp index 61c976126f..c36bab9995 100644 --- a/src/shared/symbianutils/symbiandevicemanager.cpp +++ b/src/shared/symbianutils/symbiandevicemanager.cpp @@ -33,7 +33,7 @@ #include "symbiandevicemanager.h" #include "trkdevice.h" -#include "tcftrkdevice.h" +#include "codadevice.h" #include "virtualserialdevice.h" #include <QtCore/QSettings> @@ -73,7 +73,7 @@ public: DeviceCommunicationType type; QSharedPointer<trk::TrkDevice> device; - QSharedPointer<tcftrk::TcfTrkDevice> tcfdevice; + QSharedPointer<Coda::CodaDevice> codaDevice; bool deviceAcquired; }; @@ -85,14 +85,11 @@ SymbianDeviceData::SymbianDeviceData() : bool SymbianDeviceData::isOpen() const { - if (device) { - // TRK device + if (device) return device->isOpen(); - } else if (tcfdevice) { - return tcfdevice->device()->isOpen(); - } else { - return false; - } + if (codaDevice) + return codaDevice->device()->isOpen(); + return false; } SymbianDeviceData::~SymbianDeviceData() @@ -110,8 +107,10 @@ void SymbianDeviceData::forcedClose() if (deviceAcquired) qWarning("Device on '%s' unplugged while an operation is in progress.", qPrintable(portName)); - if (device) device->close(); - else tcfdevice->device()->close(); + if (device) + device->close(); + else + codaDevice->device()->close(); } } @@ -278,12 +277,12 @@ struct SymbianDeviceManagerPrivate { class QConstructTcfPortEvent : public QEvent { public: - QConstructTcfPortEvent(QEvent::Type eventId, const QString &portName, TcfTrkDevicePtr *device, QWaitCondition *waiter) : + QConstructTcfPortEvent(QEvent::Type eventId, const QString &portName, CodaDevicePtr *device, QWaitCondition *waiter) : QEvent(eventId), m_portName(portName), m_device(device), m_waiter(waiter) {} QString m_portName; - TcfTrkDevicePtr* m_device; + CodaDevicePtr* m_device; QWaitCondition *m_waiter; }; @@ -353,7 +352,7 @@ SymbianDeviceManager::TrkDevicePtr return rc; } -TcfTrkDevicePtr SymbianDeviceManager::getTcfPort(const QString &port) +CodaDevicePtr SymbianDeviceManager::getTcfPort(const QString &port) { ensureInitialized(); const int idx = findByPortName(port); @@ -361,16 +360,16 @@ TcfTrkDevicePtr SymbianDeviceManager::getTcfPort(const QString &port) qWarning("Attempt to acquire device '%s' that does not exist.", qPrintable(port)); if (debug) qDebug() << *this; - return TcfTrkDevicePtr(); + return CodaDevicePtr(); } 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(); + return CodaDevicePtr(); } - 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. + CodaDevicePtr& devicePtr = device.m_data->codaDevice; + if (devicePtr.isNull() || !devicePtr->device()->isOpen()) { + // Check we instanciate in the correct thread - we can't afford to create the CodaDevice (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 @@ -378,57 +377,47 @@ TcfTrkDevicePtr SymbianDeviceManager::getTcfPort(const QString &port) 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 + // When the wait returns (due to the wakeAll in SymbianDeviceManager::customEvent), the CodaDevice will be fully set up d->m_tcfPortWaitMutex.unlock(); } else { // We're in the main thread, just set it up directly constructTcfPort(devicePtr, port); } + // We still carry on in the case we failed to open so the client can access the IODevice's errorString() } - 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) +void SymbianDeviceManager::constructTcfPort(CodaDevicePtr& 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); + if (device.isNull()) { + device = QSharedPointer<Coda::CodaDevice>(new Coda::CodaDevice); + const QSharedPointer<SymbianUtils::VirtualSerialDevice> serialDevice(new SymbianUtils::VirtualSerialDevice(portName)); + device->setSerialFrame(true); + device->setDevice(serialDevice); + } + if (!device->device()->isOpen()) { + bool ok = device->device().staticCast<SymbianUtils::VirtualSerialDevice>()->open(QIODevice::ReadWrite); + if (!ok && debug) { + qDebug("SymbianDeviceManager: Failed to open port %s", qPrintable(portName)); + } + } } void SymbianDeviceManager::customEvent(QEvent *event) { - if (event->type() == d->m_constructTcfPortEventType) - { + 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) +void SymbianDeviceManager::releaseTcfPort(CodaDevicePtr &aPort) { - // 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) { + if (aPort) aPort.clear(); - } //TODO close the port after a timeer if last reference? } @@ -442,11 +431,10 @@ void SymbianDeviceManager::releaseDevice(const QString &port) const int idx = findByPortName(port); if (debug) qDebug() << "SymbianDeviceManager::releaseDevice" << port << idx << sender(); - if (idx != -1) { + if (idx != -1) d->m_devices[idx].releaseDevice(); - } else { + else qWarning("Attempt to release non-existing device %s.", qPrintable(port)); - } } void SymbianDeviceManager::setAdditionalInformation(const QString &port, const QString &ai) diff --git a/src/shared/symbianutils/symbiandevicemanager.h b/src/shared/symbianutils/symbiandevicemanager.h index 1ff885c59a..3ebb8aeffb 100644 --- a/src/shared/symbianutils/symbiandevicemanager.h +++ b/src/shared/symbianutils/symbiandevicemanager.h @@ -48,8 +48,8 @@ QT_END_NAMESPACE namespace trk { class TrkDevice; } -namespace tcftrk { - class TcfTrkDevice; +namespace Coda { + class CodaDevice; } namespace SymbianUtils { @@ -62,7 +62,7 @@ enum DeviceCommunicationType { BlueToothCommunication = 1 }; -typedef QSharedPointer<tcftrk::TcfTrkDevice> TcfTrkDevicePtr; +typedef QSharedPointer<Coda::CodaDevice> CodaDevicePtr; // SymbianDevice: Explicitly shared device data and a TrkDevice // instance that can be acquired (exclusively) for use. @@ -146,17 +146,17 @@ public: // 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 + //// The TCF code prefers to set up the CodaDevice object itself, so we let it and just handle opening the underlying QIODevice and keeping track of the CodaDevice //// 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() + // Gets the CodaDevice, 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 CodaDevice::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); + CodaDevicePtr 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); + // Caller is responsible for disconnecting any signals from aPort - do not assume the CodaDevice will be deleted as a result of this call. On return aPort will be clear()ed. + void releaseTcfPort(CodaDevicePtr &aPort); int findByPortName(const QString &p) const; QString friendlyNameForPort(const QString &port) const; @@ -178,7 +178,7 @@ private: SymbianDeviceList serialPorts() const; SymbianDeviceList blueToothDevices() const; void customEvent(QEvent *event); - void constructTcfPort(TcfTrkDevicePtr& device, const QString& portName); + void constructTcfPort(CodaDevicePtr& device, const QString& portName); SymbianDeviceManagerPrivate *d; }; diff --git a/src/shared/symbianutils/virtualserialdevice_posix.cpp b/src/shared/symbianutils/virtualserialdevice_posix.cpp index 5fdfc2f5e2..c6598438a3 100644 --- a/src/shared/symbianutils/virtualserialdevice_posix.cpp +++ b/src/shared/symbianutils/virtualserialdevice_posix.cpp @@ -127,14 +127,11 @@ bool VirtualSerialDevice::tryWrite(const char *data, qint64 maxSize, qint64& byt while (maxSize > 0) { 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; - } + if (errno == EAGAIN) + return true; // Need to wait + setErrorString(QString("Posix error %1 from write to %2").arg(errno).arg(portName)); + bytesWritten = -1; + return false; } else { if (result == 0) qWarning("Zero bytes written to port!"); |