Commit a0349893 authored by Tom Sutcliffe's avatar Tom Sutcliffe Committed by Pawel Polanski
Browse files

Sharing TcfTrkDevice connections between multiple clients

parent 31b352d2
......@@ -37,7 +37,7 @@
#include "codadevice.h"
#include "trkutils.h"
#include "gdbmi.h"
#include "virtualserialdevice.h"
#include "symbiandevicemanager.h"
#include "registerhandler.h"
#include "threadshandler.h"
......@@ -123,7 +123,6 @@ CodaGdbAdapter::CodaGdbAdapter(GdbEngine *engine) :
AbstractGdbAdapter(engine),
m_running(false),
m_stopReason(0),
m_trkDevice(new CodaDevice(this)),
m_gdbAckMode(true),
m_uid(0),
m_verbose(0),
......@@ -148,11 +147,15 @@ CodaGdbAdapter::CodaGdbAdapter(GdbEngine *engine) :
connect(debuggerCore()->action(VerboseLog), SIGNAL(valueChanged(QVariant)),
this, SLOT(setVerbose(QVariant)));
connect(m_trkDevice, SIGNAL(error(QString)),
}
void CodaGdbAdapter::setupTrkDeviceSignals()
{
connect(m_codaDevice.data(), SIGNAL(error(QString)),
this, SLOT(codaDeviceError(QString)));
connect(m_trkDevice, SIGNAL(logMessage(QString)),
connect(m_codaDevice.data(), SIGNAL(logMessage(QString)),
this, SLOT(trkLogMessage(QString)));
connect(m_trkDevice, SIGNAL(tcfEvent(Coda::CodaEvent)),
connect(m_codaDevice.data(), SIGNAL(tcfEvent(Coda::CodaEvent)),
this, SLOT(codaEvent(Coda::CodaEvent)));
}
......@@ -172,7 +175,8 @@ void CodaGdbAdapter::setVerbose(int verbose)
if (debug)
qDebug("CodaGdbAdapter::setVerbose %d", verbose);
m_verbose = verbose;
m_trkDevice->setVerbose(m_verbose);
if (m_codaDevice)
m_codaDevice->setVerbose(m_verbose);
}
void CodaGdbAdapter::trkLogMessage(const QString &msg)
......@@ -278,7 +282,7 @@ void CodaGdbAdapter::handleCodaRunControlModuleLoadContextSuspendedEvent(const C
qDebug() << "Initial module load suspended: " << m_session.toString();
} else {
// Consecutive module load suspended: (not observed yet): Just continue
m_trkDevice->sendRunControlResumeCommand(CodaCallback(), se.id());
m_codaDevice->sendRunControlResumeCommand(CodaCallback(), se.id());
}
}
}
......@@ -305,7 +309,7 @@ void CodaGdbAdapter::codaEvent(const CodaEvent &e)
switch (e.type()) {
case CodaEvent::LocatorHello:
m_trkDevice->sendLoggingAddListenerCommand(CodaCallback());
m_codaDevice->sendLoggingAddListenerCommand(CodaCallback());
startGdb(); // Commands are only accepted after hello
break;
case CodaEvent::RunControlModuleLoadSuspended: // A module was loaded
......@@ -349,7 +353,7 @@ void CodaGdbAdapter::codaEvent(const CodaEvent &e)
m_stopReason = reason.contains(QLatin1String("exception"), Qt::CaseInsensitive)
|| reason.contains(QLatin1String("panic"), Qt::CaseInsensitive) ?
gdbServerSignalSegfault : gdbServerSignalTrap;
m_trkDevice->sendRegistersGetMRangeCommand(
m_codaDevice->sendRegistersGetMRangeCommand(
CodaCallback(this, &CodaGdbAdapter::handleAndReportReadRegistersAfterStop),
currentThreadContextId(), 0,
Symbian::RegisterCount);
......@@ -604,7 +608,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
reportRegisters();
} else {
sendGdbServerAck();
if (m_trkDevice->registerNames().isEmpty()) {
if (m_codaDevice->registerNames().isEmpty()) {
m_registerRequestPending = true;
} else {
sendRegistersGetMCommand();
......@@ -688,7 +692,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
logMessage(_("Writing %1 bytes from 0x%2: %3").
arg(addrLength.second).arg(addrLength.first, 0, 16).
arg(QString::fromAscii(data.toHex())));
m_trkDevice->sendMemorySetCommand(
m_codaDevice->sendMemorySetCommand(
CodaCallback(this, &CodaGdbAdapter::handleWriteMemory),
m_tcfProcessId, addrLength.first, data);
}
......@@ -707,7 +711,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
sendGdbServerMessage(thread.gdbReportSingleRegister(registerNumber), thread.gdbSingleRegisterLogMessage(registerNumber));
} else {
//qDebug() << "Fetching single register";
m_trkDevice->sendRegistersGetMRangeCommand(
m_codaDevice->sendRegistersGetMRangeCommand(
CodaCallback(this, &CodaGdbAdapter::handleAndReportReadRegister),
currentThreadContextId(), registerNumber, 1);
}
......@@ -723,7 +727,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
logMessage(_("Setting register #%1 to 0x%2").arg(regnumValue.first).arg(regnumValue.second, 0, 16));
QByteArray registerValue;
trk::appendInt(&registerValue, trk::BigEndian); // Registers are big endian
m_trkDevice->sendRegistersSetCommand(
m_codaDevice->sendRegistersSetCommand(
CodaCallback(this, &CodaGdbAdapter::handleWriteRegister),
currentThreadContextId(), regnumValue.first, registerValue,
QVariant(regnumValue.first));
......@@ -899,7 +903,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
bp.setContextId(m_session.pid);
// We use the automatic ids calculated from the location
// address instead of the map in snapshot.
m_trkDevice->sendBreakpointsAddCommand(
m_codaDevice->sendBreakpointsAddCommand(
CodaCallback(this, &CodaGdbAdapter::handleAndReportSetBreakpoint),
bp);
} else {
......@@ -914,7 +918,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
// $z0,786a4ccc,4#99
const int pos = cmd.lastIndexOf(',');
const uint addr = cmd.mid(3, pos - 3).toUInt(0, 16);
m_trkDevice->sendBreakpointsRemoveCommand(
m_codaDevice->sendBreakpointsRemoveCommand(
CodaCallback(this, &CodaGdbAdapter::handleClearBreakpoint),
Coda::Breakpoint::idFromLocation(addr));
}
......@@ -960,7 +964,7 @@ void CodaGdbAdapter::sendRunControlTerminateCommand()
// Requires id of main thread to terminate.
// Note that calling 'Settings|set|removeExecutable' crashes TCF TRK,
// so, it is apparently not required.
m_trkDevice->sendRunControlTerminateCommand(CodaCallback(this, &CodaGdbAdapter::handleRunControlTerminate),
m_codaDevice->sendRunControlTerminateCommand(CodaCallback(this, &CodaGdbAdapter::handleRunControlTerminate),
mainThreadContextId());
}
......@@ -993,7 +997,7 @@ void CodaGdbAdapter::gdbSetCurrentThread(const QByteArray &cmd, const char *why)
void CodaGdbAdapter::interruptInferior()
{
m_trkDevice->sendRunControlSuspendCommand(CodaCallback(), m_tcfProcessId);
m_codaDevice->sendRunControlSuspendCommand(CodaCallback(), m_tcfProcessId);
}
void CodaGdbAdapter::startAdapter()
......@@ -1015,22 +1019,25 @@ void CodaGdbAdapter::startAdapter()
QSharedPointer<QTcpSocket> codaSocket;
if (parameters.communicationChannel == DebuggerStartParameters::CommunicationChannelTcpIp) {
m_codaDevice = QSharedPointer<Coda::CodaDevice>(new Coda::CodaDevice);
setupTrkDeviceSignals();
codaSocket = QSharedPointer<QTcpSocket>(new QTcpSocket);
m_trkDevice->setDevice(codaSocket);
m_codaDevice->setDevice(codaSocket);
m_trkIODevice = codaSocket;
} else {
QSharedPointer<SymbianUtils::VirtualSerialDevice> serialDevice(new SymbianUtils::VirtualSerialDevice(parameters.remoteChannel));
m_trkDevice->setSerialFrame(true);
m_trkDevice->setDevice(serialDevice);
bool ok = serialDevice->open(QIODevice::ReadWrite);
m_codaDevice = SymbianUtils::SymbianDeviceManager::instance()->getTcfPort(parameters.remoteChannel);
bool ok = m_codaDevice && m_codaDevice->device()->isOpen();
if (!ok) {
QString msg = QString("Couldn't open serial device: %1.")
.arg(serialDevice->errorString());
QString msg = QString("Couldn't open serial device %1").arg(parameters.remoteChannel);
if (m_codaDevice)
msg.append(QString(": %1").arg(m_codaDevice->device()->errorString()));
logMessage(msg, LogError);
m_engine->handleAdapterStartFailed(msg, QString());
return;
}
m_trkIODevice = serialDevice;
setupTrkDeviceSignals();
m_codaDevice->setVerbose(m_verbose);
}
if (debug)
......@@ -1071,7 +1078,7 @@ void CodaGdbAdapter::startAdapter()
.arg(codaAddress.first).arg(codaAddress.second));
codaSocket->connectToHost(codaAddress.first, codaAddress.second);
} else {
m_trkDevice->sendSerialPing(false);
m_codaDevice->sendSerialPing(false);
}
}
......@@ -1085,7 +1092,7 @@ void CodaGdbAdapter::setupInferior()
for (unsigned i = 0; i < libraryCount; i++)
libraries.push_back(QString::fromAscii(librariesC[i]));
m_trkDevice->sendProcessStartCommand(
m_codaDevice->sendProcessStartCommand(
CodaCallback(this, &CodaGdbAdapter::handleCreateProcess),
m_remoteExecutable, m_uid, m_remoteArguments,
QString(), true, libraries);
......@@ -1105,7 +1112,7 @@ void CodaGdbAdapter::addThread(unsigned id)
// We cannot retrieve register values unless the registers of that
// thread have been retrieved (TCF TRK oddity).
const QByteArray contextId = Coda::RunControlContext::tcfId(m_session.pid, id);
m_trkDevice->sendRegistersGetChildrenCommand(CodaCallback(this, &CodaGdbAdapter::handleRegisterChildren),
m_codaDevice->sendRegistersGetChildrenCommand(CodaCallback(this, &CodaGdbAdapter::handleRegisterChildren),
contextId, QVariant(contextId));
}
}
......@@ -1197,6 +1204,10 @@ void CodaGdbAdapter::cleanup()
}
}
} //!m_trkIODevice.isNull()
if (m_codaDevice) {
disconnect(m_codaDevice.data(), 0, this, 0);
SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_codaDevice);
}
}
void CodaGdbAdapter::shutdownInferior()
......@@ -1211,7 +1222,7 @@ void CodaGdbAdapter::shutdownAdapter()
m_engine->notifyAdapterShutdownOk();
} else {
// Something is wrong, gdb crashed. Kill debuggee (see handleDeleteProcess2)
if (m_trkDevice->device()->isOpen()) {
if (m_codaDevice->device()->isOpen()) {
logMessage("Emergency shutdown of CODA", LogError);
sendRunControlTerminateCommand();
}
......@@ -1244,9 +1255,9 @@ void CodaGdbAdapter::handleWriteRegister(const CodaCommandResult &result)
void CodaGdbAdapter::sendRegistersGetMCommand()
{
// Send off a register command, which requires the names to be present.
QTC_ASSERT(!m_trkDevice->registerNames().isEmpty(), return )
QTC_ASSERT(!m_codaDevice->registerNames().isEmpty(), return )
m_trkDevice->sendRegistersGetMRangeCommand(
m_codaDevice->sendRegistersGetMRangeCommand(
CodaCallback(this, &CodaGdbAdapter::handleAndReportReadRegisters),
currentThreadContextId(), 0,
Symbian::RegisterCount);
......@@ -1273,12 +1284,12 @@ void CodaGdbAdapter::handleRegisterChildren(const Coda::CodaCommandResult &resul
// able to access the register contents.
QVector<QByteArray> registerNames = Coda::CodaDevice::parseRegisterGetChildren(result);
if (registerNames.size() == 1) {
m_trkDevice->sendRegistersGetChildrenCommand(CodaCallback(this, &CodaGdbAdapter::handleRegisterChildren),
m_codaDevice->sendRegistersGetChildrenCommand(CodaCallback(this, &CodaGdbAdapter::handleRegisterChildren),
registerNames.front(), result.cookie);
return;
}
// First thread: Set base names in device.
if (!m_trkDevice->registerNames().isEmpty())
if (!m_codaDevice->registerNames().isEmpty())
return;
// Make sure we get all registers
const int registerCount = registerNames.size();
......@@ -1297,7 +1308,7 @@ void CodaGdbAdapter::handleRegisterChildren(const Coda::CodaCommandResult &resul
msg += QString::fromAscii(registerNames[i]);
}
logMessage(msg);
m_trkDevice->setRegisterNames(registerNames);
m_codaDevice->setRegisterNames(registerNames);
if (m_registerRequestPending) { // Request already pending?
logMessage(_("Resuming registers request after receiving register names..."));
sendRegistersGetMCommand();
......@@ -1425,7 +1436,7 @@ void CodaGdbAdapter::sendMemoryGetCommand(const MemoryRange &range, bool buffere
const CodaCallback cb = buffered ?
CodaCallback(this, &CodaGdbAdapter::handleReadMemoryBuffered) :
CodaCallback(this, &CodaGdbAdapter::handleReadMemoryUnbuffered);
m_trkDevice->sendMemoryGetCommand(cb, currentThreadContextId(), range.from, range.size(), cookie);
m_codaDevice->sendMemoryGetCommand(cb, currentThreadContextId(), range.from, range.size(), cookie);
}
void CodaGdbAdapter::handleReadMemoryBuffered(const CodaCommandResult &result)
......@@ -1563,7 +1574,7 @@ void CodaGdbAdapter::sendTrkContinue()
// at the next stop.
if (m_snapshot.threadInfo.size() > 1)
m_snapshot.threadInfo.remove(1, m_snapshot.threadInfo.size() - 1);
m_trkDevice->sendRunControlResumeCommand(CodaCallback(), m_tcfProcessId);
m_codaDevice->sendRunControlResumeCommand(CodaCallback(), m_tcfProcessId);
}
void CodaGdbAdapter::sendTrkStepRange()
......@@ -1586,7 +1597,7 @@ void CodaGdbAdapter::sendTrkStepRange()
logMessage(_("Stepping from 0x%1 to 0x%2 (current PC=0x%3), mode %4").
arg(from, 0, 16).arg(to, 0, 16).arg(pc).arg(int(mode)));
m_trkDevice->sendRunControlResumeCommand(
m_codaDevice->sendRunControlResumeCommand(
CodaCallback(this, &CodaGdbAdapter::handleStep),
currentThreadContextId(),
mode, 1, from, to);
......
......@@ -106,6 +106,7 @@ public:
virtual DumperHandling dumperHandling() const { return DumperNotAvailable; }
private:
void setupTrkDeviceSignals();
void startAdapter();
void setupInferior();
void runEngine();
......@@ -144,7 +145,8 @@ private:
QString m_gdbServerName; // 127.0.0.1:(2222+uid)
bool m_running;
int m_stopReason;
Coda::CodaDevice *m_trkDevice;
QSharedPointer<Coda::CodaDevice> m_codaDevice;
QSharedPointer<QIODevice> m_trkIODevice;
//
......
......@@ -65,7 +65,7 @@ using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
using namespace Coda;
enum { debug = 1 };
enum { debug = 0 };
CodaRunControl::CodaRunControl(RunConfiguration *runConfiguration, const QString &mode) :
S60RunControlBase(runConfiguration, mode),
......@@ -115,35 +115,37 @@ bool CodaRunControl::setupLauncher()
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();
bool ok = m_codaDevice && m_codaDevice->device()->isOpen();
if (!ok) {
appendMessage(tr("Couldn't open serial device: %1").arg(m_tcfTrkDevice->device()->errorString()), ErrorMessageFormat);
appendMessage(tr("Couldn't open serial device: %1").arg(m_codaDevice->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)));
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(Coda::CodaEvent)), this, SLOT(slotCodaEvent(Coda::CodaEvent)));
connect(m_codaDevice.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)));
connect(m_codaDevice.data(), SIGNAL(tcfEvent(Coda::CodaEvent)), this, SLOT(slotCodaEvent(Coda::CodaEvent)));
const QSharedPointer<QTcpSocket> codaSocket(new QTcpSocket);
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), NormalMessageFormat);
QTimer::singleShot(4000, this, SLOT(checkForTimeout()));
}
if (debug) m_tcfTrkDevice->setVerbose(1);
QTimer::singleShot(4000, this, SLOT(checkForTimeout()));
if (debug)
m_codaDevice->setVerbose(debug);
return true;
}
......
......@@ -314,9 +314,9 @@ void S60DeployStep::stop()
if (m_launcher)
m_launcher->terminate();
} else {
if (m_trkDevice) {
disconnect(m_trkDevice.data(), 0, this, 0);
SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_trkDevice);
if (m_codaDevice) {
disconnect(m_codaDevice.data(), 0, this, 0);
SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_codaDevice);
}
}
emit finished(false);
......@@ -342,7 +342,7 @@ void S60DeployStep::setupConnections()
} else {
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(tcfEvent(Coda::CodaEvent)), this, SLOT(slotCodaEvent(Coda::CodaEvent)), Qt::DirectConnection);
connect(m_codaDevice.data(), SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString)));
connect(this, SIGNAL(manualInstallation()), this, SLOT(showManualInstallationInfo()));
}
......@@ -353,7 +353,7 @@ void S60DeployStep::startDeployment()
if (m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection) {
QTC_ASSERT(m_launcher, return);
}
QTC_ASSERT(!m_trkDevice.data(), return);
QTC_ASSERT(!m_codaDevice.data(), return);
// We need to defer setupConnections() in the case of CommunicationCodaSerialConnection
//setupConnections();
......@@ -383,18 +383,19 @@ void S60DeployStep::startDeployment()
}
} else if (m_channel == S60DeployConfiguration::CommunicationCodaSerialConnection) {
appendMessage(tr("Deploying application to '%1'...").arg(m_serialPortFriendlyName), false);
m_trkDevice = SymbianUtils::SymbianDeviceManager::instance()->getTcfPort(m_serialPortName);
bool ok = m_trkDevice && m_trkDevice->device()->isOpen();
m_codaDevice = SymbianUtils::SymbianDeviceManager::instance()->getTcfPort(m_serialPortName);
bool ok = m_codaDevice && m_codaDevice->device()->isOpen();
if (!ok) {
QString deviceError = tr("No such port");
if (m_trkDevice) deviceError = m_trkDevice->device()->errorString();
if (m_codaDevice)
deviceError = m_codaDevice->device()->errorString();
reportError(tr("Couldn't open serial device: %1").arg(deviceError));
stop();
return;
}
setupConnections();
m_state = StateConnecting;
m_trkDevice->sendSerialPing(false);
m_codaDevice->sendSerialPing(false);
QTimer::singleShot(4000, this, SLOT(checkForTimeout()));
} else {
m_codaDevice = QSharedPointer<Coda::CodaDevice>(new Coda::CodaDevice);
......@@ -439,9 +440,9 @@ void S60DeployStep::run(QFutureInterface<bool> &fi)
delete m_timer;
m_timer = 0;
if (m_trkDevice) {
disconnect(m_trkDevice.data(), 0, this, 0);
SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_trkDevice);
if (m_codaDevice) {
disconnect(m_codaDevice.data(), 0, this, 0);
SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_codaDevice);
}
delete m_eventLoop;
......@@ -499,7 +500,7 @@ void S60DeployStep::initFileSending()
QString packageName(QFileInfo(m_signedPackages.at(m_currentFileIndex)).fileName());
QString remoteFileLocation = QString::fromLatin1("%1:\\Data\\%2").arg(m_installationDrive).arg(packageName);
m_trkDevice->sendFileSystemOpenCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemOpen),
m_codaDevice->sendFileSystemOpenCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemOpen),
remoteFileLocation.toAscii(), flags);
appendMessage(tr("Copying \"%1\"...").arg(packageName), false);
}
......@@ -512,11 +513,11 @@ void S60DeployStep::initFileInstallation()
QString packageName(QFileInfo(m_signedPackages.at(m_currentFileIndex)).fileName());
QString remoteFileLocation = QString::fromLatin1("%1:\\Data\\%2").arg(m_installationDrive).arg(packageName);
if (m_silentInstall) {
m_trkDevice->sendSymbianInstallSilentInstallCommand(Coda::CodaCallback(this, &S60DeployStep::handleSymbianInstall),
m_codaDevice->sendSymbianInstallSilentInstallCommand(Coda::CodaCallback(this, &S60DeployStep::handleSymbianInstall),
remoteFileLocation.toAscii(), QString::fromLatin1("%1:").arg(m_installationDrive).toAscii());
appendMessage(tr("Installing package \"%1\" on drive %2:...").arg(packageName).arg(m_installationDrive), false);
} else {
m_trkDevice->sendSymbianInstallUIInstallCommand(Coda::CodaCallback(this, &S60DeployStep::handleSymbianInstall),
m_codaDevice->sendSymbianInstallUIInstallCommand(Coda::CodaCallback(this, &S60DeployStep::handleSymbianInstall),
remoteFileLocation.toAscii());
appendMessage(tr("Please continue the installation on your device."), false);
emit manualInstallation();
......@@ -588,7 +589,7 @@ void S60DeployStep::putSendNextChunk()
qDebug("Writing %llu bytes to remote file '%s' at %llu\n",
m_putLastChunkSize,
m_remoteFileHandle.constData(), pos);
m_trkDevice->sendFileSystemWriteCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemWrite),
m_codaDevice->sendFileSystemWriteCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemWrite),
m_remoteFileHandle, data, unsigned(pos));
setCopyProgress((100*(m_putLastChunkSize+pos))/size);
}
......@@ -596,7 +597,7 @@ void S60DeployStep::putSendNextChunk()
void S60DeployStep::closeRemoteFile()
{
m_trkDevice->sendFileSystemCloseCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemClose),
m_codaDevice->sendFileSystemCloseCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemClose),
m_remoteFileHandle);
}
......
......@@ -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()
{