Commit 3d23d269 authored by Pawel Polanski's avatar Pawel Polanski
Browse files

CODA: Added support for device info button in project settings (for CODA serial connections)

parent 130a55af
......@@ -1043,7 +1043,7 @@ void CodaGdbAdapter::startAdapter()
m_codaSocketIODevice = codaSocket;
} else {
m_codaDevice = SymbianUtils::SymbianDeviceManager::instance()
->getTcfPort(parameters.remoteChannel);
->getCodaDevice(parameters.remoteChannel);
bool ok = m_codaDevice && m_codaDevice->device()->isOpen();
if (!ok) {
......@@ -1233,7 +1233,7 @@ void CodaGdbAdapter::cleanup()
// Ensure process is stopped after being suspended.
sendRunControlTerminateCommand();
disconnect(m_codaDevice.data(), 0, this, 0);
SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_codaDevice);
SymbianUtils::SymbianDeviceManager::instance()->releaseCodaDevice(m_codaDevice);
}
}
......
......@@ -117,7 +117,7 @@ bool CodaRunControl::setupLauncher()
if (m_serialPort.length()) {
// We get the port from SymbianDeviceManager
appendMessage(tr("Connecting to '%1'...").arg(m_serialPort), NormalMessageFormat);
m_codaDevice = SymbianUtils::SymbianDeviceManager::instance()->getTcfPort(m_serialPort);
m_codaDevice = SymbianUtils::SymbianDeviceManager::instance()->getCodaDevice(m_serialPort);
bool ok = m_codaDevice && m_codaDevice->device()->isOpen();
if (!ok) {
......@@ -333,7 +333,7 @@ void CodaRunControl::finishRunControl()
m_runningProcessId.clear();
if (m_codaDevice) {
disconnect(m_codaDevice.data(), 0, this, 0);
SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_codaDevice);
SymbianUtils::SymbianDeviceManager::instance()->releaseCodaDevice(m_codaDevice);
}
m_state = StateUninit;
emit finished();
......@@ -344,7 +344,7 @@ QMessageBox *CodaRunControl::createCodaWaitingMessageBox(QWidget *parent)
const QString title = tr("Waiting for CODA");
const QString text = tr("Qt Creator is waiting for the CODA application to connect.<br>"
"Please make sure the application is running on "
"your mobile phone and the right IP address and port are "
"your mobile phone and the right IP address and/or port are "
"configured in the project settings.");
QMessageBox *mb = new QMessageBox(QMessageBox::Information, title, text, QMessageBox::Cancel, parent);
return mb;
......
......@@ -41,6 +41,7 @@
#include <symbianutils/launcher.h>
#include <symbianutils/bluetoothlistener.h>
#include <symbianutils/symbiandevicemanager.h>
#include <codadevice.h>
#include "trkruncontrol.h"
......@@ -74,6 +75,8 @@ namespace Internal {
const char STARTING_DRIVE_LETTER = 'C';
const char LAST_DRIVE_LETTER = 'Z';
static const quint32 CODA_UID = 0x20021f96;
QString formatDriveText(const S60DeployConfiguration::DeviceDrive &drive)
{
char driveLetter = QChar::toUpper(static_cast<ushort>(drive.first));
......@@ -84,6 +87,39 @@ QString formatDriveText(const S60DeployConfiguration::DeviceDrive &drive)
return QString("%1:%2 kB").arg(driveLetter).arg(drive.second);
}
void startTable(QString &text)
{
const char startTableC[] = "<html></head><body><table>";
if (text.contains(startTableC))
return;
text.append(startTableC);
}
void finishTable(QString &text)
{
const char stopTableC[] = "</table></body></html>";
text.replace(stopTableC, QLatin1String(""));
text.append(stopTableC);
}
void addToTable(QTextStream &stream, const QString &key, const QString &value)
{
const char tableRowStartC[] = "<tr><td><b>";
const char tableRowSeparatorC[] = "</b></td><td>";
const char tableRowEndC[] = "</td></tr>";
stream << tableRowStartC << key << tableRowSeparatorC << value << tableRowEndC;
}
void addErrorToTable(QTextStream &stream, const QString &key, const QString &value)
{
const char tableRowStartC[] = "<tr><td><b>";
const char tableRowSeparatorC[] = "</b></td><td>";
const char tableRowEndC[] = "</td></tr>";
const char errorSpanStartC[] = "<span style=\"font-weight:600; color:red; \">";
const char errorSpanEndC[] = "</span>";
stream << tableRowStartC << errorSpanStartC << key << tableRowSeparatorC << value << errorSpanEndC << tableRowEndC;
}
S60DeployConfigurationWidget::S60DeployConfigurationWidget(QWidget *parent)
: ProjectExplorer::DeployConfigurationWidget(parent),
m_detailsWidget(new Utils::DetailsWidget),
......@@ -188,6 +224,7 @@ void S60DeployConfigurationWidget::init(ProjectExplorer::DeployConfiguration *dc
QHBoxLayout *infoHBoxLayout = new QHBoxLayout;
m_deviceInfoLabel->setWordWrap(true);
m_deviceInfoLabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
m_deviceInfoLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
infoHBoxLayout->addWidget(m_deviceInfoLabel);
infoHBoxLayout->addWidget(m_deviceInfoButton);
m_deviceInfoButton->setIcon(qApp->style()->standardIcon(QStyle::SP_MessageBoxInformation));
......@@ -306,7 +343,8 @@ void S60DeployConfigurationWidget::updateSerialDevices()
const QString newPortName = device(newIndex).portName();
m_deployConfiguration->setSerialPortName(newPortName);
}
if (m_deployConfiguration->communicationChannel() != S60DeployConfiguration::CommunicationTrkSerialConnection)
if (m_deployConfiguration->communicationChannel() != S60DeployConfiguration::CommunicationTrkSerialConnection
&& m_deployConfiguration->communicationChannel() != S60DeployConfiguration::CommunicationCodaSerialConnection)
m_deviceInfoButton->setEnabled(false);
}
......@@ -455,10 +493,10 @@ void S60DeployConfigurationWidget::slotWaitingForTrkClosed()
void S60DeployConfigurationWidget::updateDeviceInfo()
{
//TODO: No CODA device info! Implement it when it is available
if (m_deployConfiguration->communicationChannel() == S60DeployConfiguration::CommunicationTrkSerialConnection) {
QTC_ASSERT(!m_infoLauncher, return)
setDeviceInfoLabel(tr("Connecting..."));
setDeviceInfoLabel(tr("Connecting..."));
// Do a launcher run with the ping protocol. Prompt to connect and
// go asynchronous afterwards to pop up launch trk box if a timeout occurs.
QString message;
......@@ -496,9 +534,185 @@ void S60DeployConfigurationWidget::updateDeviceInfo()
}
// Wait for either timeout or results
m_deviceInfoButton->setEnabled(false);
} else if (m_deployConfiguration->communicationChannel() == S60DeployConfiguration::CommunicationCodaSerialConnection) {
setDeviceInfoLabel(tr("Connecting..."));
const SymbianUtils::SymbianDevice commDev = currentDevice();
m_codaInfoDevice = SymbianUtils::SymbianDeviceManager::instance()->getCodaDevice(commDev.portName());
if (!m_codaInfoDevice->device()->isOpen()) {
setDeviceInfoLabel(m_codaInfoDevice->device()->errorString(), true);
return;
}
//TODO error handling - for now just throw the command at coda
m_codaInfoDevice->sendSymbianOsDataGetQtVersionCommand(Coda::CodaCallback(this, &S60DeployConfigurationWidget::getQtVersionCommandResult));
m_deviceInfoButton->setEnabled(false);
} else
setDeviceInfoLabel(tr("Information about the device is not available when using CODA."), true);
setDeviceInfoLabel(tr("Currently there is no information about device for this connection type."), true);
}
void S60DeployConfigurationWidget::getQtVersionCommandResult(const Coda::CodaCommandResult &result)
{
if (result.type == Coda::CodaCommandResult::FailReply) {
setDeviceInfoLabel(tr("No device information available"), true);
m_deviceInfoButton->setEnabled(true);
return;
} else if (result.type == Coda::CodaCommandResult::CommandErrorReply){
QString message;
startTable(message);
QTextStream str(&message);
addErrorToTable(str, tr("Qt version: "), tr("Not installed on device"));
finishTable(message);
setDeviceInfoLabel(message, false);
} else {
QString resultString;
if (result.values.count()) {
QHash<QString, QVariant> obj = result.values[0].toVariant().toHash();
QString ver = obj.value("qVersion").toString();
startTable(resultString);
QTextStream str(&resultString);
addToTable(str, tr("Qt version: "), ver);
QString systemVersion;
int symVer = obj.value("symbianVersion").toInt();
// Ugh why won't QSysInfo define these on non-symbian builds...
switch (symVer) {
case 10:
systemVersion.append("Symbian OS v9.2");
break;
case 20:
systemVersion.append("Symbian OS v9.3");
break;
case 30:
systemVersion.append("Symbian OS v9.4 / Symbian^1");
break;
case 40:
systemVersion.append("Symbian^2");
break;
case 50:
systemVersion.append("Symbian^3");
break;
case 60:
systemVersion.append("Symbian^4");
break;
default:
systemVersion.append(tr("Unrecognised Symbian version 0x%1").arg(symVer, 0, 16));
break;
}
systemVersion.append(", ");
int s60Ver = obj.value("s60Version").toInt();
switch (s60Ver) {
case 10:
systemVersion.append("S60 3rd Edition Feature Pack 1");
break;
case 20:
systemVersion.append("S60 3rd Edition Feature Pack 2");
break;
case 30:
systemVersion.append("S60 5th Edition");
break;
case 40:
systemVersion.append("S60 5th Edition Feature Pack 1");
break;
case 50:
systemVersion.append("S60 5th Edition Feature Pack 2");
break;
default:
systemVersion.append(tr("Unrecognised S60 version 0x%1").arg(symVer, 0, 16));
break;
}
addToTable(str, tr("OS version: "), systemVersion);
finishTable(resultString);
}
setDeviceInfoLabel(resultString);
}
m_codaInfoDevice->sendSymbianOsDataGetRomInfoCommand(Coda::CodaCallback(this, &S60DeployConfigurationWidget::getRomInfoResult));
}
void S60DeployConfigurationWidget::getRomInfoResult(const Coda::CodaCommandResult &result)
{
if (result.type == Coda::CodaCommandResult::SuccessReply && result.values.count()) {
QString resultString = m_deviceInfoLabel->text();
startTable(resultString);
QTextStream str(&resultString);
QVariantHash obj = result.values[0].toVariant().toHash();
QString romVersion = obj.value("romVersion", tr("unknown")).toString();
romVersion.replace('\n', " "); // The ROM string is split across multiple lines, for some reason.
addToTable(str, tr("ROM version: "), romVersion);
QString pr = obj.value("prInfo").toString();
if (pr.length())
addToTable(str, tr("Release:"), pr);
finishTable(resultString);
setDeviceInfoLabel(resultString);
}
QList<quint32> packagesOfInterest;
packagesOfInterest.append(CODA_UID);
m_codaInfoDevice->sendSymbianInstallGetPackageInfoCommand(Coda::CodaCallback(this, &S60DeployConfigurationWidget::getInstalledPackagesResult), packagesOfInterest);
}
void S60DeployConfigurationWidget::getInstalledPackagesResult(const Coda::CodaCommandResult &result)
{
if (result.type == Coda::CodaCommandResult::SuccessReply && result.values.count()) {
QString resultString = m_deviceInfoLabel->text();
startTable(resultString);
QTextStream str(&resultString);
QVariantList resultsList = result.values[0].toVariant().toList();
foreach (const QVariant& var, resultsList) {
QVariantHash obj = var.toHash();
if (obj.value("uid").toString().toUInt(0, 16) == CODA_UID) {
if (!obj.value("error").isNull()) {
// How can coda not be installed? Presumably some UID wrongness...
addErrorToTable(str, tr("CODA version: "), tr("Error reading CODA version"));
} else {
QVariantList version = obj.value("version").toList();
addToTable(str, tr("CODA version: "),
QString("%1.%2.%3").arg(version[0].toInt())
.arg(version[1].toInt())
.arg(version[2].toInt()));
}
}
}
finishTable(resultString);
setDeviceInfoLabel(resultString);
}
QStringList keys;
keys << QLatin1String("EDisplayXPixels");
keys << QLatin1String("EDisplayYPixels");
//keys << "EMemoryRAMFree";
m_codaInfoDevice->sendSymbianOsDataGetHalInfoCommand(Coda::CodaCallback(this, &S60DeployConfigurationWidget::getHalResult), keys);
}
void S60DeployConfigurationWidget::getHalResult(const Coda::CodaCommandResult &result)
{
if (result.type == Coda::CodaCommandResult::SuccessReply && result.values.count()) {
QString resultString = m_deviceInfoLabel->text();
QVariantList resultsList = result.values[0].toVariant().toList();
int x = 0;
int y = 0;
foreach (const QVariant& var, resultsList) {
QVariantHash obj = var.toHash();
if (obj.value("name").toString() == "EDisplayXPixels")
x = obj.value("value").toInt();
else if (obj.value("name").toString() == "EDisplayYPixels")
y = obj.value("value").toInt();
}
if (x && y) {
startTable(resultString);
QTextStream str(&resultString);
addToTable(str, tr("Screen size: "), QString("%1x%2").arg(x).arg(y));
finishTable(resultString);
setDeviceInfoLabel(resultString);
}
}
// Done with collecting info
m_deviceInfoButton->setEnabled(true);
SymbianUtils::SymbianDeviceManager::instance()->releaseCodaDevice(m_codaInfoDevice);
}
} // namespace Internal
} // namespace Qt4ProjectManager
......@@ -61,6 +61,11 @@ namespace SymbianUtils {
class SymbianDevice;
}
namespace Coda {
class CodaDevice;
struct CodaCommandResult;
}
namespace Qt4ProjectManager {
namespace Internal {
......@@ -102,6 +107,11 @@ private:
QWidget * createCommunicationChannel();
void getQtVersionCommandResult(const Coda::CodaCommandResult &result);
void getRomInfoResult(const Coda::CodaCommandResult &result);
void getInstalledPackagesResult(const Coda::CodaCommandResult &result);
void getHalResult(const Coda::CodaCommandResult &result);
S60DeployConfiguration *m_deployConfiguration;
Utils::DetailsWidget *m_detailsWidget;
QComboBox *m_serialPortsCombo;
......@@ -117,6 +127,7 @@ private:
Utils::IpAddressLineEdit *m_ipAddress;
QRadioButton *m_trkRadioButton;
QRadioButton *m_codaRadioButton;
QSharedPointer<Coda::CodaDevice> m_codaInfoDevice;
};
} // namespace Internal
......
......@@ -317,7 +317,7 @@ void S60DeployStep::stop()
} else {
if (m_codaDevice) {
disconnect(m_codaDevice.data(), 0, this, 0);
SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_codaDevice);
SymbianUtils::SymbianDeviceManager::instance()->releaseCodaDevice(m_codaDevice);
}
}
emit finished(false);
......@@ -384,7 +384,7 @@ void S60DeployStep::startDeployment()
}
} else if (m_channel == S60DeployConfiguration::CommunicationCodaSerialConnection) {
appendMessage(tr("Deploying application to '%1'...").arg(m_serialPortFriendlyName), false);
m_codaDevice = SymbianUtils::SymbianDeviceManager::instance()->getTcfPort(m_serialPortName);
m_codaDevice = SymbianUtils::SymbianDeviceManager::instance()->getCodaDevice(m_serialPortName);
bool ok = m_codaDevice && m_codaDevice->device()->isOpen();
if (!ok) {
QString deviceError = tr("No such port");
......@@ -442,7 +442,7 @@ void S60DeployStep::run(QFutureInterface<bool> &fi)
if (m_codaDevice) {
disconnect(m_codaDevice.data(), 0, this, 0);
SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_codaDevice);
SymbianUtils::SymbianDeviceManager::instance()->releaseCodaDevice(m_codaDevice);
}
delete m_eventLoop;
......
......@@ -936,8 +936,6 @@ void CodaDevice::sendProcessStartCommand(const CodaCallback &callBack,
const QString sysBin = QLatin1String("c:/sys/bin");
const QString binaryFileName = slashPos == -1 ? binaryIn : binaryIn.mid(slashPos + 1);
// Fixup: Does argv[0] convention exist on Symbian?
arguments.push_front(binaryFileName);
if (workingDirectory.isEmpty())
workingDirectory = sysBin;
......@@ -1316,8 +1314,7 @@ void CodaDevice::sendRegistersSetCommand(const CodaCallback &callBack,
value, cookie);
}
//static const char outputListenerIDC[] = "org.eclipse.cdt.debug.edc.ui.ProgramOutputConsoleLogger";
static const char outputListenerIDC[] = "ProgramOutputConsoleLogger"; //TODO: this one might be the correct one
static const char outputListenerIDC[] = "ProgramOutputConsoleLogger";
void CodaDevice::sendLoggingAddListenerCommand(const CodaCallback &callBack,
const QVariant &cookie)
......@@ -1346,6 +1343,34 @@ void CodaDevice::sendSymbianOsDataFindProcessesCommand(const CodaCallback &callB
sendCodaMessage(MessageWithReply, SymbianOSData, "findRunningProcesses", data, callBack, cookie);
}
void CodaDevice::sendSymbianOsDataGetQtVersionCommand(const CodaCallback &callBack,
const QVariant &cookie)
{
sendCodaMessage(MessageWithReply, SymbianOSData, "getQtVersion", QByteArray(), callBack, cookie);
}
void CodaDevice::sendSymbianOsDataGetRomInfoCommand(const CodaCallback &callBack,
const QVariant &cookie)
{
sendCodaMessage(MessageWithReply, SymbianOSData, "getRomInfo", QByteArray(), callBack, cookie);
}
void CodaDevice::sendSymbianOsDataGetHalInfoCommand(const CodaCallback &callBack,
const QStringList &keys,
const QVariant &cookie)
{
QByteArray data;
JsonInputStream str(data);
str << '[';
for (int i = 0; i < keys.count(); ++i) {
if (i)
str << ',';
str << keys[i];
}
str << ']';
sendCodaMessage(MessageWithReply, SymbianOSData, "getHalInfo", data, callBack, cookie);
}
void Coda::CodaDevice::sendFileSystemOpenCommand(const Coda::CodaCallback &callBack,
const QByteArray &name,
unsigned flags,
......@@ -1409,4 +1434,24 @@ void Coda::CodaDevice::sendSymbianInstallUIInstallCommand(const Coda::CodaCallba
str << file;
sendCodaMessage(MessageWithReply, SymbianInstallService, "installWithUI", data, callBack, cookie);
}
void Coda::CodaDevice::sendSymbianInstallGetPackageInfoCommand(const Coda::CodaCallback &callBack,
const QList<quint32> &packages,
const QVariant &cookie)
{
QByteArray data;
JsonInputStream str(data);
str << '[';
for (int i = 0; i < packages.count(); ++i) {
if (i)
str << ',';
QString pkgString;
pkgString.setNum(packages[i], 16);
str << pkgString;
}
str << ']';
sendCodaMessage(MessageWithReply, SymbianInstallService, "getPackageInfo", data, callBack, cookie);
}
} // namespace Coda
......@@ -131,11 +131,6 @@ http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Services
* Commands can be sent along with callbacks that are passed a
* CodaCommandResult and an opaque QVariant cookie. In addition, events are emitted.
*
* Note: As of 11.8.2010, TCF Trk 4.0.5 does not currently support 'Registers::getm'
* (get multiple registers). So, CodaDevice emulates it by sending a sequence of
* single commands. As soon as 'Registers::getm' is natively supported, all code
* related to 'FakeRegisterGetm' should be removed. The workaround requires that
* the register name is known.
* CODA notes:
* - Commands are accepted only after receiving the Locator Hello event
* - Serial communication initiation sequence:
......@@ -351,6 +346,10 @@ public:
const QByteArray &file,
const QVariant &cookie = QVariant());
void sendSymbianInstallGetPackageInfoCommand(const Coda::CodaCallback &callBack,
const QList<quint32> &packages,
const QVariant &cookie = QVariant());
void sendLoggingAddListenerCommand(const CodaCallback &callBack,
const QVariant &cookie = QVariant());
......@@ -363,6 +362,16 @@ public:
const QByteArray &uid,
const QVariant &cookie = QVariant());
void sendSymbianOsDataGetQtVersionCommand(const CodaCallback &callBack,
const QVariant &cookie = QVariant());
void sendSymbianOsDataGetRomInfoCommand(const CodaCallback &callBack,
const QVariant &cookie = QVariant());
void sendSymbianOsDataGetHalInfoCommand(const CodaCallback &callBack,
const QStringList &keys = QStringList(),
const QVariant &cookie = QVariant());
// Settings
void sendSettingsEnableLogCommand();
......
......@@ -415,6 +415,45 @@ QByteArray JsonValue::toString(bool multiline, int indent) const
return result;
}
QVariant JsonValue::toVariant() const
{
switch (m_type) {
case String:
return QString(m_data);
case Number: {
bool ok;
qint64 val = QString(m_data).toLongLong(&ok);
if (ok)
return val;
return QVariant();
}
case Object: {
QHash<QString, QVariant> hash;
for (int i = 0; i < m_children.size(); ++i) {
QString name(m_children[i].name());
QVariant val = m_children[i].toVariant();
hash.insert(name, val);
}
return hash;
}
case Array: {
QList<QVariant> list;
for (int i = 0; i < m_children.size(); ++i) {
list.append(m_children[i].toVariant());
}
return list;
}
case Boolean:
return data() == QByteArray("true");
case Invalid:
case NullObject:
default:
return QVariant();
}
}
void JsonValue::fromString(const QByteArray &ba)
{
const char *from = ba.constBegin();
......
......@@ -87,6 +87,8 @@ public:
void fromString(const QByteArray &str);
void setStreamOutput(const QByteArray &name, const QByteArray &content);
QVariant toVariant() const;
private:
static QByteArray parseCString(const char *&from, const char *to);
static QByteArray parseNumber(const char *&from, const char *to);
......
......@@ -355,7 +355,7 @@ SymbianDeviceManager::TrkDevicePtr
return rc;
}
CodaDevicePtr SymbianDeviceManager::getTcfPort(const QString &port)
CodaDevicePtr SymbianDeviceManager::getCodaDevice(const QString &port)
{
ensureInitialized();
const int idx = findByPortName(port);
......@@ -419,7 +419,7 @@ void SymbianDeviceManager::customEvent(QEvent *event)
}
}
void SymbianDeviceManager::releaseTcfPort(CodaDevicePtr &port)
void SymbianDeviceManager::releaseCodaDevice(CodaDevicePtr &port)
{
if (port) {
// Check if this was the last reference to the port, if so close it after a short delay
......@@ -613,4 +613,106 @@ SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDeviceManager &sdm)
return d;
}
} // namespace SymbianUtilsInternal
OstChannel *SymbianDeviceManager::getOstChannel(const QString &port, uchar channelId)
{
CodaDevicePtr coda = getCodaDevice(port);
if (coda.isNull() || !coda->device()->isOpen())
return 0;
return new OstChannel(coda, channelId);
}