Commit 8175e4e4 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

S60: Introduce a communications device type.

- Introduce a communications device type flag, add stubs for
  Bluetooth to serialdevicelister and pass the device type
  in new struct CommunicationDevice along to run configuration
  and debugger start parameters (overriding the debugger settings).
- Give the s60devices::Device a tooltip in the settings page
parent c31795cb
......@@ -216,6 +216,7 @@ static const char *stateName(int s)
DebuggerStartParameters::DebuggerStartParameters()
: attachPID(-1),
useTerminal(false),
remoteChannelType(-1),
toolChainType(ProjectExplorer::ToolChain::UNKNOWN),
startMode(NoStartMode)
{}
......
......@@ -113,6 +113,7 @@ public:
QString crashParameter; // for AttachCrashedExternal
// for remote debugging
QString remoteChannel;
int remoteChannelType;
QString remoteArchitecture;
QString symbolFileName;
QString serverStartScript;
......
......@@ -191,6 +191,7 @@ void Snapshot::insertMemory(const MemoryRange &range, const QByteArray &ba)
TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
AbstractGdbAdapter(engine),
m_options(options),
m_overrideTrkDeviceType(-1),
m_running(false),
m_gdbAckMode(true),
m_verbose(2),
......@@ -225,7 +226,7 @@ TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
this, SLOT(handleTrkError(QString)));
m_trkDevice.setVerbose(m_verbose);
m_trkDevice.setSerialFrame(m_options->mode != TrkOptions::BlueTooth);
m_trkDevice.setSerialFrame(effectiveTrkDeviceType() != TrkOptions::BlueTooth);
connect(&m_trkDevice, SIGNAL(logMessage(QString)),
this, SLOT(trkLogMessage(QString)));
......@@ -237,16 +238,6 @@ TrkGdbAdapter::~TrkGdbAdapter()
logMessage("Shutting down.\n");
}
QString TrkGdbAdapter::overrideTrkDevice() const
{
return m_overrideTrkDevice;
}
void TrkGdbAdapter::setOverrideTrkDevice(const QString &d)
{
m_overrideTrkDevice = d;
}
QString TrkGdbAdapter::effectiveTrkDevice() const
{
if (!m_overrideTrkDevice.isEmpty())
......@@ -256,6 +247,13 @@ QString TrkGdbAdapter::effectiveTrkDevice() const
return m_options->serialPort;
}
int TrkGdbAdapter::effectiveTrkDeviceType() const
{
if (m_overrideTrkDeviceType >= 0)
return m_overrideTrkDeviceType;
return m_options->mode;
}
void TrkGdbAdapter::trkLogMessage(const QString &msg)
{
logMessage("TRK " + msg);
......@@ -403,7 +401,7 @@ void TrkGdbAdapter::waitForTrkConnect()
.arg(QChar("/-\\|"[direction])));
}
// Do not loop forever
if (m_waitCount++ < (m_options->mode == TrkOptions::BlueTooth ? 60 : 5)) {
if (m_waitCount++ < (effectiveTrkDeviceType() == TrkOptions::BlueTooth ? 60 : 5)) {
QTimer::singleShot(1000, this, SLOT(waitForTrkConnect()));
} else {
QString msg = _("Failed to connect to %1 after "
......@@ -1519,7 +1517,8 @@ void TrkGdbAdapter::startAdapter()
{
// Retrieve parameters
const DebuggerStartParameters &parameters = startParameters();
setOverrideTrkDevice(parameters.remoteChannel);
m_overrideTrkDevice = parameters.remoteChannel;
m_overrideTrkDeviceType = parameters.remoteChannelType;
m_remoteExecutable = parameters.executable;
m_symbolFile = parameters.symbolFileName;
// FIXME: testing hack, remove!
......@@ -1534,7 +1533,8 @@ void TrkGdbAdapter::startAdapter()
setState(AdapterStarting);
debugMessage(_("TRYING TO START ADAPTER"));
logMessage(QLatin1String("### Starting TrkGdbAdapter"));
if (m_options->mode == TrkOptions::BlueTooth) {
m_trkDevice.setSerialFrame(effectiveTrkDeviceType() != TrkOptions::BlueTooth);
if (effectiveTrkDeviceType() == TrkOptions::BlueTooth) {
const QString device = effectiveTrkDevice();
const QString blueToothListener = QLatin1String("rfcomm");
QStringList blueToothListenerArguments;
......
......@@ -142,16 +142,13 @@ public:
void setBufferedMemoryRead(bool b) { m_bufferedMemoryRead = b; }
trk::Session &session() { return m_session; }
// Set a device (from the project) to override the settings.
QString overrideTrkDevice() const;
void setOverrideTrkDevice(const QString &);
signals:
void output(const QString &msg);
private:
const TrkOptionsPtr m_options;
QString m_overrideTrkDevice;
int m_overrideTrkDeviceType;
QString m_gdbServerName; // 127.0.0.1:(2222+uid)
......@@ -302,6 +299,7 @@ private:
Q_SLOT void handleRfcommStateChanged(QProcess::ProcessState newState);
QString effectiveTrkDevice() const;
int effectiveTrkDeviceType() const;
// Debuggee state
trk::Session m_session; // global-ish data (process id, target information)
......
......@@ -34,6 +34,7 @@
#include "profilereader.h"
#include "s60manager.h"
#include "s60devices.h"
#include "serialdevicelister.h"
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
......@@ -59,12 +60,19 @@ static QString lsFile(const QString &f)
str << fi.size() << ' ' << fi.lastModified().toString(Qt::ISODate) << ' ' << QDir::toNativeSeparators(fi.absoluteFilePath());
return rc;
}
// ======== S60DeviceRunConfiguration
S60DeviceRunConfiguration::S60DeviceRunConfiguration(Project *project, const QString &proFilePath)
: RunConfiguration(project),
m_proFilePath(proFilePath),
m_cachedTargetInformationValid(false),
m_serialPortName("COM5"),
#ifdef Q_OS_WIN
m_serialPortName(QLatin1String("COM5")),
m_communicationType(SerialPortCommunication),
#else
m_serialPortName(QLatin1String(SerialDeviceLister::linuxBlueToothDeviceRootC) + QLatin1Char('0')),
m_communicationType(BlueToothCommunication),
#endif
m_signingMode(SignSelf)
{
if (!m_proFilePath.isEmpty())
......@@ -114,6 +122,7 @@ void S60DeviceRunConfiguration::save(PersistentSettingsWriter &writer) const
writer.saveValue("CustomSignaturePath", m_customSignaturePath);
writer.saveValue("CustomKeyPath", m_customKeyPath);
writer.saveValue("SerialPortName", m_serialPortName);
writer.saveValue("CommunicationType", m_communicationType);
RunConfiguration::save(writer);
}
......@@ -126,6 +135,7 @@ void S60DeviceRunConfiguration::restore(const PersistentSettingsReader &reader)
m_customSignaturePath = reader.restoreValue("CustomSignaturePath").toString();
m_customKeyPath = reader.restoreValue("CustomKeyPath").toString();
m_serialPortName = reader.restoreValue("SerialPortName").toString().trimmed();
m_communicationType = reader.restoreValue("CommunicationType").toInt();
}
QString S60DeviceRunConfiguration::serialPortName() const
......@@ -138,6 +148,16 @@ void S60DeviceRunConfiguration::setSerialPortName(const QString &name)
m_serialPortName = name.trimmed();
}
int S60DeviceRunConfiguration::communicationType() const
{
return m_communicationType;
}
void S60DeviceRunConfiguration::setCommunicationType(int t)
{
m_communicationType = t;
}
QString S60DeviceRunConfiguration::targetName() const
{
const_cast<S60DeviceRunConfiguration *>(this)->updateTarget();
......@@ -393,6 +413,7 @@ S60DeviceRunControlBase::S60DeviceRunControlBase(const QSharedPointer<RunConfigu
m_serialPortName = s60runConfig->serialPortName();
m_serialPortFriendlyName = S60Manager::instance()->serialDeviceLister()->friendlyNameForPort(m_serialPortName);
m_communicationType = s60runConfig->communicationType();
m_targetName = s60runConfig->targetName();
m_baseFileName = s60runConfig->basePackageFilePath();
m_symbianPlatform = s60runConfig->symbianPlatform();
......@@ -542,6 +563,7 @@ void S60DeviceRunControlBase::signsisProcessFinished()
//TODO sisx destination and file path user definable
m_launcher->setTrkServerName(m_serialPortName);
m_launcher->setSerialFrame(m_communicationType == SerialPortCommunication);
const QString copySrc(m_baseFileName + ".sisx");
const QString copyDst = QString("C:\\Data\\%1.sisx").arg(QFileInfo(m_baseFileName).fileName());
const QString runFileName = QString("C:\\sys\\bin\\%1.exe").arg(m_targetName);
......@@ -689,6 +711,7 @@ S60DeviceDebugRunControl::S60DeviceDebugRunControl(const QSharedPointer<ProjectE
Qt::QueuedConnection);
m_startParams->remoteChannel = rc->serialPortName();
m_startParams->remoteChannelType = rc->communicationType();
m_startParams->startMode = Debugger::StartInternal;
m_startParams->toolChainType = rc->toolChainType();
}
......
......@@ -64,6 +64,10 @@ public:
QString serialPortName() const;
void setSerialPortName(const QString &name);
// See SerialDeviceListener
int communicationType() const;
void setCommunicationType(int t);
QString targetName() const;
QString basePackageFilePath() const;
QString symbianPlatform() const;
......@@ -98,7 +102,8 @@ private:
QString m_packageTemplateFileName;
bool m_cachedTargetInformationValid;
QString m_serialPortName;
SigningMode m_signingMode;
int m_communicationType;
SigningMode m_signingMode;
QString m_customSignaturePath;
QString m_customKeyPath;
};
......@@ -163,6 +168,7 @@ private:
QString m_serialPortName;
QString m_serialPortFriendlyName;
int m_communicationType;
QString m_targetName;
QString m_baseFileName;
QString m_symbianPlatform;
......
......@@ -50,6 +50,8 @@
#include <QtGui/QApplication>
#include <QtGui/QSpacerItem>
Q_DECLARE_METATYPE(Qt4ProjectManager::Internal::CommunicationDevice)
namespace Qt4ProjectManager {
namespace Internal {
......@@ -167,16 +169,16 @@ void S60DeviceRunConfigurationWidget::updateSerialDevices()
m_serialPortsCombo->clear();
clearDeviceInfo();
const QString previousRunConfigurationPortName = m_runConfiguration->serialPortName();
const QList<SerialDeviceLister::SerialDevice> serialDevices = S60Manager::instance()->serialDeviceLister()->serialDevices();
const QList<CommunicationDevice> devices = S60Manager::instance()->serialDeviceLister()->communicationDevices();
int newIndex = -1;
for (int i = 0; i < serialDevices.size(); ++i) {
const SerialDeviceLister::SerialDevice &device = serialDevices.at(i);
m_serialPortsCombo->addItem(device.friendlyName, device.portName);
for (int i = 0; i < devices.size(); ++i) {
const CommunicationDevice &device = devices.at(i);
m_serialPortsCombo->addItem(device.friendlyName, qVariantFromValue(device));
if (device.portName == previousRunConfigurationPortName)
newIndex = i;
}
// Set new index: prefer to keep old or set to 0, if available.
if (newIndex == -1 && !serialDevices.empty())
if (newIndex == -1 && !devices.empty())
newIndex = 0;
m_serialPortsCombo->setCurrentIndex(newIndex);
if (newIndex == -1) {
......@@ -184,20 +186,25 @@ void S60DeviceRunConfigurationWidget::updateSerialDevices()
m_runConfiguration->setSerialPortName(QString());
} else {
m_deviceInfoButton->setEnabled(true);
const QString newPortName = portName(newIndex);
const QString newPortName = device(newIndex).portName;
if (newPortName != previousRunConfigurationPortName)
m_runConfiguration->setSerialPortName(newPortName);
}
}
QString S60DeviceRunConfigurationWidget::portName(int index) const
CommunicationDevice S60DeviceRunConfigurationWidget::device(int i) const
{
return index >= 0 ? m_serialPortsCombo->itemData(index).toString() : QString();
if (i >= 0) {
const QVariant data = m_serialPortsCombo->itemData(i);
if (qVariantCanConvert<Qt4ProjectManager::Internal::CommunicationDevice>(data))
return qVariantValue<Qt4ProjectManager::Internal::CommunicationDevice>(data);
}
return CommunicationDevice(SerialPortCommunication);
}
QString S60DeviceRunConfigurationWidget::currentPortName() const
CommunicationDevice S60DeviceRunConfigurationWidget::currentDevice() const
{
return portName(m_serialPortsCombo->currentIndex());
return device(m_serialPortsCombo->currentIndex());
}
void S60DeviceRunConfigurationWidget::nameEdited(const QString &text)
......@@ -212,7 +219,9 @@ void S60DeviceRunConfigurationWidget::updateTargetInformation()
void S60DeviceRunConfigurationWidget::setSerialPort(int index)
{
m_runConfiguration->setSerialPortName(portName(index));
const CommunicationDevice d = device(index);
m_runConfiguration->setSerialPortName(d.portName);
m_runConfiguration->setCommunicationType(d.type);
m_deviceInfoButton->setEnabled(index >= 0);
clearDeviceInfo();
updateSummary();
......@@ -252,7 +261,7 @@ void S60DeviceRunConfigurationWidget::updateSummary()
tr("<No Device>");
const QString signature = m_runConfiguration->signingMode() == S60DeviceRunConfiguration::SignCustom ?
tr("(custom certificate)") :
tr("(self-signed certificate)");
tr("(self-signed certificate)");
m_detailsWidget->setSummaryText(tr("Summary: Run on '%1' %2").arg(device, signature));
}
......@@ -284,7 +293,9 @@ bool S60DeviceRunConfigurationWidget::getDeviceInfo(QString *message)
// Do a launcher run with the ping protocol. Instantiate launcher on heap
// as not to introduce delays when destructing a device with timeout
trk::Launcher *launcher = new trk::Launcher(trk::Launcher::ActionPingOnly, this);
launcher->setTrkServerName(currentPortName());
const CommunicationDevice commDev = currentDevice();
launcher->setSerialFrame(commDev.type == SerialPortCommunication);
launcher->setTrkServerName(commDev.portName);
if (!launcher->startServer(message)) {
launcher->deleteLater();
return false;
......
......@@ -47,6 +47,7 @@ namespace Utils {
namespace Qt4ProjectManager {
namespace Internal {
struct CommunicationDevice;
class S60DeviceRunConfiguration;
/* Configuration widget for S60 devices on serial ports that are
......@@ -73,8 +74,9 @@ private slots:
void clearDeviceInfo();
private:
inline QString currentPortName() const;
inline QString portName(int index) const;
inline CommunicationDevice device(int i) const;
inline CommunicationDevice currentDevice() const;
bool getDeviceInfo(QString *message);
void setDeviceInfoLabel(const QString &message, bool isError = false);
......
......@@ -31,8 +31,11 @@
#include <QtCore/QSettings>
#include <QtCore/QXmlStreamReader>
#include <QtCore/QTextStream>
#include <QtCore/QFile>
#include <QtCore/QDir>
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
namespace {
const char * const SYMBIAN_SDKS_KEY = "HKEY_LOCAL_MACHINE\\Software\\Symbian\\EPOC SDKs";
......@@ -47,17 +50,58 @@ namespace {
const char * const DEVICE_TOOLSROOT = "toolsroot";
}
using namespace Qt4ProjectManager::Internal;
namespace Qt4ProjectManager {
namespace Internal {
S60Devices::Device::Device() :
isDefault(false)
{
}
QString S60Devices::Device::toHtml() const
{
QString rc;
QTextStream str(&rc);
str << "<html><body><table>"
<< "<tr><td><b>" << QCoreApplication::translate("Qt4ProjectManager::Internal::S60Devices::Device", "Id:")
<< "</b></td><td>" << id << "</td></tr>"
<< "<tr><td><b>" << QCoreApplication::translate("Qt4ProjectManager::Internal::S60Devices::Device", "Name:")
<< "</b></td><td>" << name << "</td></tr>"
<< "<tr><td><b>" << QCoreApplication::translate("Qt4ProjectManager::Internal::S60Devices::Device", "EPOC:")
<< "</b></td><td>" << epocRoot << "</td></tr>"
<< "<tr><td><b>" << QCoreApplication::translate("Qt4ProjectManager::Internal::S60Devices::Device", "Tools:")
<< "</b></td><td>" << toolsRoot << "</td></tr>"
<< "<tr><td><b>" << QCoreApplication::translate("Qt4ProjectManager::Internal::S60Devices::Device", "Qt:")
<< "</b></td><td>" << qt << "</td></tr>";
return rc;
}
S60Devices::S60Devices(QObject *parent)
: QObject(parent)
{
}
bool S60Devices::readLinux()
{
m_errorString = QLatin1String("not implemented.");
return false;
}
bool S60Devices::read()
{
m_devices.clear();
m_errorString = QString();
m_errorString.clear();
#ifdef Q_OS_WIN
return readWin();
#else
return readLinux();
#endif
}
// Windows EPOC
bool S60Devices::readWin()
{
// Check the windows registry via QSettings for devices.xml path
QSettings settings(SYMBIAN_SDKS_KEY, QSettings::NativeFormat);
QString devicesXmlPath = settings.value(SYMBIAN_PATH_KEY).toString();
......@@ -180,3 +224,22 @@ QString S60Devices::cleanedRootPath(const QString &deviceRoot)
}
return path;
}
QDebug operator<<(QDebug db, const S60Devices::Device &d)
{
QDebug nospace = db.nospace();
nospace << "id='" << d.id << "' name='" << d.name << "' default="
<< d.isDefault << " Epoc='" << d.epocRoot << "' tools='"
<< d.toolsRoot << "' Qt='" << d.qt << '\'';
return db;
}
QDebug operator<<(QDebug dbg, const S60Devices &d)
{
foreach(const S60Devices::Device &device, d.devices())
dbg << device;
return dbg;
}
} // namespace Internal
} // namespace Qt4ProjectManager
......@@ -34,6 +34,10 @@
#include <QtCore/QString>
#include <QtCore/QList>
QT_BEGIN_NAMESPACE
class QDebug;
QT_END_NAMESPACE
namespace Qt4ProjectManager {
namespace Internal {
......@@ -42,6 +46,9 @@ class S60Devices : public QObject
Q_OBJECT
public:
struct Device {
Device();
QString toHtml() const;
QString id;
QString name;
bool isDefault;
......@@ -62,10 +69,15 @@ signals:
void qtVersionsChanged();
private:
bool readLinux();
bool readWin();
QString m_errorString;
QList<Device> m_devices;
};
QDebug operator<<(QDebug dbg, const S60Devices::Device &d);
QDebug operator<<(QDebug dbg, const S60Devices &d);
} // namespace Internal
} // namespace Qt4ProjectManager
......
......@@ -64,8 +64,13 @@ void S60DevicesWidget::updateDevicesList()
QList<S60Devices::Device> devices = m_devices->devices();
m_ui->list->clear();
foreach (const S60Devices::Device &device, devices) {
m_ui->list->addTopLevelItem(new QTreeWidgetItem(QStringList() << device.epocRoot
<< (device.qt.isEmpty()?tr("No Qt installed"):device.qt)));
QStringList columns;
columns << device.epocRoot << (device.qt.isEmpty()?tr("No Qt installed"):device.qt);
QTreeWidgetItem *item = new QTreeWidgetItem(columns);
const QString tooltip = device.toHtml();
item->setToolTip(0, tooltip);
item->setToolTip(1, tooltip);
m_ui->list->addTopLevelItem(item);
}
}
......
......@@ -31,6 +31,7 @@
#include <QtCore/QSettings>
#include <QtCore/QStringList>
#include <QtCore/QFileInfo>
#include <QtGui/QApplication>
#include <QtGui/QWidget>
#include <QtDebug>
......@@ -42,6 +43,17 @@ namespace {
const char * const USBSER = "Services/usbser/Enum";
}
const char *SerialDeviceLister::linuxBlueToothDeviceRootC = "/dev/rfcomm";
CommunicationDevice::CommunicationDevice(DeviceCommunicationType t,
const QString &p,
const QString &f) :
portName(p),
friendlyName(f),
type(t)
{
}
SerialDeviceLister::SerialDeviceLister(QObject *parent)
: QObject(parent),
m_initialized(false)
......@@ -53,18 +65,18 @@ SerialDeviceLister::~SerialDeviceLister()
{
}
QList<SerialDeviceLister::SerialDevice> SerialDeviceLister::serialDevices() const
QList<CommunicationDevice> SerialDeviceLister::communicationDevices() const
{
if (!m_initialized) {
updateSilently();
m_initialized = true;
}
return m_devices;
return m_devices2;
}
QString SerialDeviceLister::friendlyNameForPort(const QString &port) const
{
foreach (const SerialDevice &device, m_devices) {
foreach (const CommunicationDevice &device, m_devices2) {
if (device.portName == port)
return device.friendlyName;
}
......@@ -79,19 +91,44 @@ void SerialDeviceLister::update()
void SerialDeviceLister::updateSilently() const
{
m_devices.clear();
m_devices2 = serialPorts() + blueToothDevices();
}
QList<CommunicationDevice> SerialDeviceLister::serialPorts() const
{
QList<CommunicationDevice> rc;
#ifdef Q_OS_WIN32
QSettings registry(REGKEY_CURRENT_CONTROL_SET, QSettings::NativeFormat);
int count = registry.value(QString::fromLatin1("%1/Count").arg(USBSER)).toInt();
const int count = registry.value(QString::fromLatin1("%1/Count").arg(USBSER)).toInt();
for (int i = 0; i < count; ++i) {
QString driver = registry.value(QString::fromLatin1("%1/%2").arg(USBSER).arg(i)).toString();
if (driver.contains("JAVACOMM")) {
driver.replace('\\', '/');
SerialDeviceLister::SerialDevice device;
CommunicationDevice device(SerialPortCommunication);
device.friendlyName = registry.value(QString::fromLatin1("Enum/%1/FriendlyName").arg(driver)).toString();
device.portName = registry.value(QString::fromLatin1("Enum/%1/Device Parameters/PortName").arg(driver)).toString();
m_devices.append(device);
rc.append(device);
}
}
#endif
return rc;
}
QList<CommunicationDevice> SerialDeviceLister::blueToothDevices() const
{
QList<CommunicationDevice> rc;
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
// Bluetooth devices are created on connection. List the existing ones
// or at least the first one.
const QString prefix = QLatin1String(linuxBlueToothDeviceRootC);
const QString friendlyFormat = QLatin1String("Bluetooth device (%1)");
for (int d = 0; d < 4; d++) {
CommunicationDevice device(BlueToothCommunication, prefix + QString::number(d));
if (d == 0 || QFileInfo(device.portName).exists()) {
device.friendlyName = friendlyFormat.arg(device.portName);
rc.push_back(device);
}
}
#endif
return rc;
}
......@@ -30,32 +30,36 @@
#ifndef SERIALDEVICELISTER_H
#define SERIALDEVICELISTER_H
#include <QtCore/QAbstractEventDispatcher>