Commit 440bba25 authored by Pawel Polanski's avatar Pawel Polanski
Browse files

Symbian: Added a serial connection type to CODA

parent 7bfc798a
......@@ -56,6 +56,11 @@ public:
CommunicationChannelUsb
};
enum DebugClient {
DebugClientTrk,
DebugClientCoda
};
DebuggerStartParameters()
: isSnapshot(false),
attachPID(-1),
......@@ -68,8 +73,9 @@ public:
toolChainType(ProjectExplorer::ToolChain_UNKNOWN),
startMode(NoStartMode),
executableUid(0),
communicationChannel(CommunicationChannelTcpIp),
serverPort(0)
communicationChannel(CommunicationChannelUsb),
serverPort(0),
debugClient(DebugClientTrk)
{}
QString executable;
......@@ -122,6 +128,7 @@ public:
CommunicationChannel communicationChannel;
QString serverAddress;
quint16 serverPort;
DebugClient debugClient;
};
} // namespace Debugger
......
......@@ -1792,8 +1792,7 @@ AbstractGdbAdapter *GdbEngine::createAdapter()
case ProjectExplorer::ToolChain_RVCT2_ARMV6:
case ProjectExplorer::ToolChain_RVCT_ARMV5_GNUPOC:
case ProjectExplorer::ToolChain_GCCE_GNUPOC:
// FIXME: 1 of 3 testing hacks.
if (sp.communicationChannel == DebuggerStartParameters::CommunicationChannelTcpIp)
if (sp.debugClient == DebuggerStartParameters::DebugClientCoda)
return new TcfTrkGdbAdapter(this);
else
return new TrkGdbAdapter(this);
......
......@@ -37,6 +37,7 @@
#include "tcftrkdevice.h"
#include "trkutils.h"
#include "gdbmi.h"
#include "virtualserialdevice.h"
#include "registerhandler.h"
#include "threadshandler.h"
......@@ -1012,9 +1013,25 @@ void TcfTrkGdbAdapter::startAdapter()
QPair<QString, unsigned short> tcfTrkAddress;
QSharedPointer<QTcpSocket> tcfTrkSocket(new QTcpSocket);
m_trkDevice->setDevice(tcfTrkSocket);
m_trkIODevice = tcfTrkSocket;
QSharedPointer<QTcpSocket> tcfTrkSocket;
if (parameters.communicationChannel == DebuggerStartParameters::CommunicationChannelTcpIp) {
tcfTrkSocket = QSharedPointer<QTcpSocket>(new QTcpSocket);
m_trkDevice->setDevice(tcfTrkSocket);
m_trkIODevice = tcfTrkSocket;
} else {
QSharedPointer<SymbianUtils::VirtualSerialDevice> serialDevice(new SymbianUtils::VirtualSerialDevice(parameters.remoteChannel));
m_trkDevice->setSerialFrame(true);
m_trkDevice->setDevice(serialDevice);
bool ok = serialDevice->open(QIODevice::ReadWrite);
if (!ok) {
QString msg = QString("Couldn't open serial device: %1.")
.arg(serialDevice->errorString());
logMessage(msg, LogError);
m_engine->handleAdapterStartFailed(msg, QString());
return;
}
m_trkIODevice = serialDevice;
}
if (debug)
qDebug() << parameters.processArgs;
......@@ -1049,9 +1066,13 @@ void TcfTrkGdbAdapter::startAdapter()
connect(m_gdbServer, SIGNAL(newConnection()),
this, SLOT(handleGdbConnection()));
logMessage(_("Connecting to TCF TRK on %1:%2")
.arg(tcfTrkAddress.first).arg(tcfTrkAddress.second));
tcfTrkSocket->connectToHost(tcfTrkAddress.first, tcfTrkAddress.second);
if (parameters.communicationChannel == DebuggerStartParameters::CommunicationChannelTcpIp) {
logMessage(_("Connecting to TCF TRK on %1:%2")
.arg(tcfTrkAddress.first).arg(tcfTrkAddress.second));
tcfTrkSocket->connectToHost(tcfTrkAddress.first, tcfTrkAddress.second);
} else {
m_trkDevice->sendSerialPing(false);
}
}
void TcfTrkGdbAdapter::setupInferior()
......
......@@ -43,6 +43,7 @@
#include "qt4symbiantarget.h"
#include "qt4target.h"
#include "qtoutputformatter.h"
#include "virtualserialdevice.h"
#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
......@@ -75,8 +76,15 @@ CodaRunControl::CodaRunControl(RunConfiguration *runConfiguration, const QString
const S60DeployConfiguration *activeDeployConf = qobject_cast<S60DeployConfiguration *>(s60runConfig->qt4Target()->activeDeployConfiguration());
QTC_ASSERT(activeDeployConf, return);
m_address = activeDeployConf->deviceAddress();
m_port = activeDeployConf->devicePort().toInt();
S60DeployConfiguration::CommunicationChannel channel = activeDeployConf->communicationChannel();
if (channel == S60DeployConfiguration::CommunicationCodaTcpConnection) {
m_address = activeDeployConf->deviceAddress();
m_port = activeDeployConf->devicePort().toInt();
} else if (channel == S60DeployConfiguration::CommunicationCodaSerialConnection) {
m_serialPort = activeDeployConf->serialPortName();
} else {
QTC_ASSERT(false, return);
}
}
CodaRunControl::~CodaRunControl()
......@@ -87,7 +95,7 @@ CodaRunControl::~CodaRunControl()
bool CodaRunControl::doStart()
{
if (m_address.isEmpty()) {
if (m_address.isEmpty() && m_serialPort.isEmpty()) {
cancelProgress();
QString msg = tr("No device is connected. Please connect a device and try again.");
appendMessage(msg, NormalMessageFormat);
......@@ -116,12 +124,26 @@ bool CodaRunControl::setupLauncher()
connect(m_tcfTrkDevice, SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)), this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent)));
connect(m_tcfTrkDevice, SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString)));
const QSharedPointer<QTcpSocket> tcfTrkSocket(new QTcpSocket);
m_tcfTrkDevice->setDevice(tcfTrkSocket);
tcfTrkSocket->connectToHost(m_address, m_port);
m_state = StateConnecting;
appendMessage(tr("Connecting to %1:%2...").arg(m_address).arg(m_port), NormalMessageFormat);
QTimer::singleShot(4000, this, SLOT(checkForTimeout()));
if (m_serialPort.length()) {
const QSharedPointer<SymbianUtils::VirtualSerialDevice> serialDevice(new SymbianUtils::VirtualSerialDevice(m_serialPort));
appendMessage(tr("Conecting to '%2'...").arg(m_serialPort), NormalMessageFormat);
m_tcfTrkDevice->setSerialFrame(true);
m_tcfTrkDevice->setDevice(serialDevice);
bool ok = serialDevice->open(QIODevice::ReadWrite);
if (!ok) {
appendMessage(tr("Couldn't open serial device: %1").arg(serialDevice->errorString()), ErrorMessageFormat);
return false;
}
m_state = StateConnecting;
m_tcfTrkDevice->sendSerialPing(false);
} else {
const QSharedPointer<QTcpSocket> tcfTrkSocket(new QTcpSocket);
m_tcfTrkDevice->setDevice(tcfTrkSocket);
tcfTrkSocket->connectToHost(m_address, m_port);
m_state = StateConnecting;
appendMessage(tr("Connecting to %1:%2...").arg(m_address).arg(m_port), NormalMessageFormat);
QTimer::singleShot(4000, this, SLOT(checkForTimeout()));
}
return true;
}
......
......@@ -103,6 +103,7 @@ private:
QString m_address;
unsigned short m_port;
QString m_serialPort;
QString m_runningProcessId;
State m_state;
......
......@@ -180,7 +180,8 @@ bool Qt4SymbianTarget::isSymbianConnectionAvailable(QString &tooltipText)
if (!s60DeployConf)
return false;
switch (s60DeployConf->communicationChannel()) {
case S60DeployConfiguration::CommunicationTrkSerialConnection: {
case S60DeployConfiguration::CommunicationTrkSerialConnection:
case S60DeployConfiguration::CommunicationCodaSerialConnection: {
const SymbianUtils::SymbianDeviceManager *sdm = SymbianUtils::SymbianDeviceManager::instance();
const int deviceIndex = sdm->findByPortName(s60DeployConf->serialPortName());
if (deviceIndex == -1) {
......
......@@ -86,7 +86,9 @@ S60DeployConfigurationWidget::S60DeployConfigurationWidget(QWidget *parent)
m_silentInstallCheckBox(new QCheckBox(tr("Silent installation"))),
m_serialRadioButton(new QRadioButton(tr("Serial:"))),
m_wlanRadioButton(new QRadioButton(tr("Experimental WLAN:"))), //TODO: Remove ""Experimental" when CODA is stable and official
m_ipAddress(new Utils::IpAddressLineEdit)
m_ipAddress(new Utils::IpAddressLineEdit),
m_trkRadioButton(new QRadioButton(tr("TRK"))),
m_codaRadioButton(new QRadioButton(tr("CODA")))
{
}
......@@ -140,7 +142,37 @@ void S60DeployConfigurationWidget::init(ProjectExplorer::DeployConfiguration *dc
connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(updated()),
this, SLOT(updateSerialDevices()));
formLayout->addRow(createCommunicationChannel());
//Debug Client
QHBoxLayout *debugClientHBoxLayout = new QHBoxLayout;
QVBoxLayout *debugClientVBoxLayout = new QVBoxLayout;
debugClientVBoxLayout->addWidget(m_trkRadioButton);
debugClientVBoxLayout->addWidget(m_codaRadioButton);
debugClientVBoxLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Ignored, QSizePolicy::Expanding));
debugClientHBoxLayout->addLayout(debugClientVBoxLayout);
debugClientHBoxLayout->addWidget(createCommunicationChannel());
debugClientHBoxLayout->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Ignored));
QGroupBox *debugClientGroupBox = new QGroupBox(tr("Debug Client"));
debugClientGroupBox->setLayout(debugClientHBoxLayout);
bool usingTrk = m_deployConfiguration->communicationChannel() == S60DeployConfiguration::CommunicationTrkSerialConnection;
m_trkRadioButton->setChecked(usingTrk);
m_codaRadioButton->setChecked(!usingTrk);
bool usingTcp = m_deployConfiguration->communicationChannel() == S60DeployConfiguration::CommunicationCodaTcpConnection;
m_serialRadioButton->setChecked(!usingTcp);
m_wlanRadioButton->setChecked(usingTcp);
connect(m_trkRadioButton, SIGNAL(clicked()), this, SLOT(updateDebugClient()));
connect(m_codaRadioButton, SIGNAL(clicked()), this, SLOT(updateDebugClient()));
updateDebugClient();
formLayout->addRow(debugClientGroupBox);
// Device Info with button. Widgets are enabled in above call to updateSerialDevices()
QHBoxLayout *infoHBoxLayout = new QHBoxLayout;
......@@ -180,7 +212,7 @@ QWidget *S60DeployConfigurationWidget::createCommunicationChannel()
serialPortHBoxLayout->addWidget(updateSerialDevicesButton);
#endif
QGroupBox *communicationChannelGroupBox = new QGroupBox(tr("Communication channel"));
QGroupBox *communicationChannelGroupBox = new QGroupBox(tr("Communication Channel"));
QFormLayout *communicationChannelFormLayout = new QFormLayout();
communicationChannelFormLayout->setWidget(0, QFormLayout::LabelRole, m_serialRadioButton);
communicationChannelFormLayout->setWidget(1, QFormLayout::LabelRole, m_wlanRadioButton);
......@@ -201,21 +233,6 @@ QWidget *S60DeployConfigurationWidget::createCommunicationChannel()
communicationChannelFormLayout->setLayout(0, QFormLayout::FieldRole, serialPortHBoxLayout);
communicationChannelFormLayout->setLayout(1, QFormLayout::FieldRole, wlanChannelLayout);
switch (m_deployConfiguration->communicationChannel()) {
case S60DeployConfiguration::CommunicationTrkSerialConnection:
m_serialRadioButton->setChecked(true);
m_ipAddress->setDisabled(true);
m_serialPortsCombo->setDisabled(false);
break;
case S60DeployConfiguration::CommunicationCodaTcpConnection:
m_wlanRadioButton->setChecked(true);
m_ipAddress->setDisabled(false);
m_serialPortsCombo->setDisabled(true);
break;
default:
break;
}
communicationChannelGroupBox->setLayout(communicationChannelFormLayout);
return communicationChannelGroupBox;
}
......@@ -303,20 +320,40 @@ void S60DeployConfigurationWidget::setSerialPort(int index)
clearDeviceInfo();
}
void S60DeployConfigurationWidget::updateDebugClient()
{
if (!m_trkRadioButton->isChecked() && !m_codaRadioButton->isChecked())
m_trkRadioButton->setChecked(true);
if (m_trkRadioButton->isChecked()) {
m_serialRadioButton->setEnabled(true);
m_serialRadioButton->setChecked(true);
m_wlanRadioButton->setEnabled(false);
updateSerialDevices();
} else if(m_codaRadioButton->isChecked()) {
m_serialRadioButton->setEnabled(true);
m_wlanRadioButton->setEnabled(true);
}
updateCommunicationChannel();
}
void S60DeployConfigurationWidget::updateCommunicationChannel()
{
if (!m_serialRadioButton->isChecked() && !m_wlanRadioButton->isChecked())
m_serialRadioButton->setChecked(true);
if (m_serialRadioButton->isChecked()) {
m_ipAddress->setDisabled(true);
m_serialPortsCombo->setDisabled(false);
m_deployConfiguration->setCommunicationChannel(S60DeployConfiguration::CommunicationTrkSerialConnection);
if (m_trkRadioButton->isChecked())
m_deployConfiguration->setCommunicationChannel(S60DeployConfiguration::CommunicationTrkSerialConnection);
else
m_deployConfiguration->setCommunicationChannel(S60DeployConfiguration::CommunicationCodaSerialConnection);
updateSerialDevices();
} else if(m_wlanRadioButton->isChecked()) {
QMessageBox::information(this, tr("CODA required"),
tr("You need to have CODA v4.0.14 (or newer) installed on your device "
"in order to use the WLAN functionality.")); //TODO: Remove this when CODA is stable and official
m_ipAddress->setDisabled(false);
m_serialPortsCombo->setDisabled(true);
m_deviceInfoButton->setEnabled(false);
m_deployConfiguration->setCommunicationChannel(S60DeployConfiguration::CommunicationCodaTcpConnection);
}
}
......
......@@ -90,6 +90,7 @@ private slots:
void slotWaitingForTrkClosed();
void silentInstallChanged(int);
void updateCommunicationChannel();
void updateDebugClient();
void updateWlanAddress(const QString &address);
void cleanWlanAddress();
......@@ -114,6 +115,8 @@ private:
QRadioButton *m_serialRadioButton;
QRadioButton *m_wlanRadioButton;
Utils::IpAddressLineEdit *m_ipAddress;
QRadioButton *m_trkRadioButton;
QRadioButton *m_codaRadioButton;
};
} // namespace Internal
......
......@@ -48,7 +48,7 @@
#include <symbianutils/launcher.h>
#include <symbianutils/symbiandevicemanager.h>
#include <symbianutils/virtualserialdevice.h>
#include <utils/qtcassert.h>
#include <QtGui/QMessageBox>
......@@ -66,7 +66,7 @@
using namespace ProjectExplorer;
using namespace Qt4ProjectManager::Internal;
enum { debug = 0 };
enum {debug = 0};
static const quint64 DEFAULT_CHUNK_SIZE = 10240;
......@@ -277,16 +277,20 @@ void S60DeployStep::start()
{
QString errorMessage;
if (m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection) {
if (m_serialPortName.isEmpty() || !m_launcher) {
errorMessage = tr("No device is connected. Please connect a device and try again.");
reportError(errorMessage);
return;
}
} else {
bool serialConnection = (m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection
|| m_channel == S60DeployConfiguration::CommunicationCodaSerialConnection);
bool trkClient = m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection;
if (serialConnection && m_serialPortName.isEmpty()
|| (trkClient && !m_launcher)) {
errorMessage = tr("No device is connected. Please connect a device and try again.");
reportError(errorMessage);
return;
}
if (!trkClient) {
QTC_ASSERT(!m_trkDevice, return);
m_trkDevice = new tcftrk::TcfTrkDevice;
if (m_address.isEmpty() || !m_trkDevice) {
if (m_address.isEmpty() && !serialConnection) {
errorMessage = tr("No address for a device has been defined. Please define an address and try again.");
reportError(errorMessage);
return;
......@@ -374,6 +378,19 @@ void S60DeployStep::startDeployment()
reportError(errorMessage);
stop();
}
} else if (m_channel == S60DeployConfiguration::CommunicationCodaSerialConnection) {
const QSharedPointer<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);
if (!ok) {
reportError(tr("Couldn't open serial device: %1").arg(serialDevice->errorString()));
stop();
return;
}
m_state = StateConnecting;
m_trkDevice->sendSerialPing(false);
} else {
const QSharedPointer<QTcpSocket> tcfTrkSocket(new QTcpSocket);
m_trkDevice->setDevice(tcfTrkSocket);
......@@ -729,9 +746,6 @@ void S60DeployStep::launcherFinished(bool success)
void S60DeployStep::deploymentFinished(bool success)
{
m_deployResult = success;
if (m_trkDevice)
m_trkDevice->deleteLater();
m_trkDevice = 0;
if (m_eventLoop)
m_eventLoop->exit();
}
......
......@@ -522,10 +522,14 @@ static Debugger::DebuggerStartParameters s60DebuggerStartParams(const S60DeviceR
sp.serverAddress = activeDeployConf->deviceAddress();
sp.serverPort = activeDeployConf->devicePort().toInt();
//FIXME: there should be only one... trkAdapter
sp.communicationChannel = activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationTrkSerialConnection?
Debugger::DebuggerStartParameters::CommunicationChannelUsb:
Debugger::DebuggerStartParameters::CommunicationChannelTcpIp;
sp.communicationChannel = activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationCodaTcpConnection?
Debugger::DebuggerStartParameters::CommunicationChannelTcpIp:
Debugger::DebuggerStartParameters::CommunicationChannelUsb;
sp.debugClient = activeDeployConf->communicationChannel() == S60DeployConfiguration::CommunicationTrkSerialConnection?
Debugger::DebuggerStartParameters::DebugClientTrk:
Debugger::DebuggerStartParameters::DebugClientCoda;
QTC_ASSERT(sp.executableUid, return sp);
// Prefer the '*.sym' file over the '.exe', which should exist at the same
......
......@@ -14,7 +14,8 @@ HEADERS += $$PWD/symbianutils_global.h \
$$PWD/symbiandevicemanager.h \
$$PWD/tcftrkdevice.h \
$$PWD/tcftrkmessage.h \
$$PWD/json.h
$$PWD/json.h \
$$PWD/virtualserialdevice.h
SOURCES += $$PWD/trkutils.cpp \
$$PWD/trkdevice.cpp \
......@@ -24,7 +25,12 @@ SOURCES += $$PWD/trkutils.cpp \
$$PWD/symbiandevicemanager.cpp \
$$PWD/tcftrkdevice.cpp \
$$PWD/tcftrkmessage.cpp \
$$PWD/json.cpp
$$PWD/json.cpp \
$$PWD/virtualserialdevice.cpp
DEFINES += HAS_SERIALPORT
win32:SOURCES += $$PWD/virtualserialdevice_win.cpp
unix:SOURCES += $$PWD/virtualserialdevice_posix.cpp
# Tests/trklauncher is a console application
contains(QT, gui) {
......
......@@ -512,7 +512,7 @@ void TcfTrkDevice::deviceReadyReadSerial()
break;
processSerialMessage(d->m_readBuffer.mid(messagePos.first, messagePos.second));
d->m_readBuffer.remove(0, messageEnd);
} while (d->m_readBuffer.isEmpty());
} while (!d->m_readBuffer.isEmpty());
checkSendQueue(); // Send off further messages
}
......
#include "virtualserialdevice.h"
#include <QtCore/QThread>
namespace SymbianUtils {
bool VirtualSerialDevice::isSequential() const
{
return true;
}
VirtualSerialDevice::VirtualSerialDevice(const QString &aPortName, QObject *parent) :
QIODevice(parent), portName(aPortName), lock(QMutex::NonRecursive), emittingBytesWritten(false)
{
platInit();
}
const QString& VirtualSerialDevice::getPortName() const
{
return portName;
}
void VirtualSerialDevice::close()
{
if (isOpen()) {
Q_ASSERT(thread() == QThread::currentThread()); // My brain will explode otherwise
flush();
QMutexLocker locker(&lock);
QIODevice::close();
platClose();
}
}
void VirtualSerialDevice::emitBytesWrittenIfNeeded(QMutexLocker& locker, qint64 len)
{
if (!emittingBytesWritten) {
emittingBytesWritten = true;
locker.unlock();
emit bytesWritten(len);
locker.relock();
emittingBytesWritten = false;
}
}
} // namespace SymbianUtils
#ifndef VIRTUALSERIALPORT_H
#define VIRTUALSERIALPORT_H
#include <QtCore/QIODevice>
#include <QtCore/QString>
#include <QtCore/QMutex>
#include "symbianutils_global.h"
namespace SymbianUtils {
class VirtualSerialDevicePrivate;
class SYMBIANUTILS_EXPORT VirtualSerialDevice : public QIODevice
{
Q_OBJECT
public:
explicit VirtualSerialDevice(const QString &name, QObject *parent = 0);
~VirtualSerialDevice();
bool open(OpenMode mode);
void close();
const QString &getPortName() const;
void flush();
qint64 bytesAvailable() const;
bool isSequential() const;
bool waitForBytesWritten(int msecs);
bool waitForReadyRead(int msecs);
protected:
qint64 readData(char *data, qint64 maxSize);
qint64 writeData(const char *data, qint64 maxSize);
private:
Q_DISABLE_COPY(VirtualSerialDevice)
void platInit();
void platClose();
void emitBytesWrittenIfNeeded(QMutexLocker &locker, qint64 len);
private:
QString portName;
mutable QMutex lock;
QList<QByteArray> pendingWrites;
bool emittingBytesWritten;
VirtualSerialDevicePrivate *d;
// Platform-specific stuff
#ifdef Q_OS_WIN
private:
qint64 writeNextBuffer(QMutexLocker &locker);
private slots:
void writeCompleted();
void commEventOccurred();
#endif
#ifdef Q_OS_UNIX
private:
bool tryWrite(const char *data, qint64 maxSize, qint64 &bytesWritten);
enum FlushPendingOption {
NothingSpecial = 0,
StopAfterWritingOneBuffer = 1,
EmitBytesWrittenAsync = 2, // Needed so we don't emit bytesWritten signal directly from writeBytes
};
Q_DECLARE_FLAGS(FlushPendingOptions, FlushPendingOption)
bool tryFlushPendingBuffers(QMutexLocker& locker, FlushPendingOptions flags = NothingSpecial);
private slots:
void writeHasUnblocked(int fileHandle);
signals:
void AsyncCall_emitBytesWrittenIfNeeded(qint64 len);
#endif
};
} // namespace SymbianUtils
#endif // VIRTUALSERIALPORT_H
#include <stdio.h>
#include <fcntl.h>