1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
31 **************************************************************************/
36 #include "symbianutils_global.h"
37 #include "codamessage.h"
41 #include <QtCore/QObject>
42 #include <QtCore/QSharedPointer>
43 #include <QtCore/QVector>
44 #include <QtCore/QVariant>
45 #include <QtCore/QStringList>
46 #include <QtCore/QDateTime>
55 struct CodaDevicePrivate;
58 /* Command error handling in CODA:
59 * 1) 'Severe' errors (JSON format, parameter format): Coda emits a
60 * nonstandard message (\3\2 error parameters) and closes the connection.
61 * 2) Protocol errors: 'N' without error message is returned.
62 * 3) Errors in command execution: 'R' with a CODA error hash is returned
63 * (see CodaCommandError). */
65 /* Error code return in 'R' reply to command
66 * (see top of 'Services' documentation). */
67 struct SYMBIANUTILS_EXPORT CodaCommandError {
71 operator bool() const { return isError(); }
72 QString toString() const;
73 void write(QTextStream &str) const;
74 bool parse(const QVector<Json::JsonValue> &values);
76 quint64 timeMS; // Since 1.1.1970
78 QByteArray format; // message
79 // 'Alternative' meaning, like altOrg="POSIX"/altCode=<some errno>
80 QByteArray alternativeOrganization;
81 qint64 alternativeCode;
84 /* Answer to a CODA command passed to the callback. */
85 struct SYMBIANUTILS_EXPORT CodaCommandResult {
88 SuccessReply, // 'R' and no error -> all happy.
89 CommandErrorReply, // 'R' with CodaCommandError received
90 ProgressReply, // 'P', progress indicator
91 FailReply // 'N' Protocol NAK, severe error
94 explicit CodaCommandResult(Type t = SuccessReply);
95 explicit CodaCommandResult(char typeChar, Services service,
96 const QByteArray &request,
97 const QVector<Json::JsonValue> &values,
98 const QVariant &cookie);
100 QString toString() const;
101 QString errorString() const;
102 operator bool() const { return type == SuccessReply || type == ProgressReply; }
104 static QDateTime codaTimeToQDateTime(quint64 codaTimeMS);
109 CodaCommandError commandError;
110 QVector<Json::JsonValue> values;
114 // Response to stat/fstat
115 struct SYMBIANUTILS_EXPORT CodaStatResponse
121 QDateTime accessTime;
124 typedef Coda::Callback<const CodaCommandResult &> CodaCallback;
126 /* CodaDevice: CODA communication helper using an asynchronous QIODevice
127 * implementing the CODA protocol according to:
128 http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Specification.html
129 http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Services.html
130 * Commands can be sent along with callbacks that are passed a
131 * CodaCommandResult and an opaque QVariant cookie. In addition, events are emitted.
134 * - Commands are accepted only after receiving the Locator Hello event
135 * - Serial communication initiation sequence:
136 * Send serial ping from host sendSerialPing() -> receive pong response with
137 * version information -> Send Locator Hello Event -> Receive Locator Hello Event
138 * -> Commands are accepted.
139 * - WLAN communication initiation sequence:
140 * Receive Locator Hello Event from CODA -> Commands are accepted.
143 class SYMBIANUTILS_EXPORT CodaDevice : public QObject
145 Q_PROPERTY(unsigned verbose READ verbose WRITE setVerbose)
146 Q_PROPERTY(bool serialFrame READ serialFrame WRITE setSerialFrame)
149 // Flags for FileSystem:open
150 enum FileSystemOpenFlags
152 FileSystem_TCF_O_READ = 0x00000001,
153 FileSystem_TCF_O_WRITE = 0x00000002,
154 FileSystem_TCF_O_APPEND = 0x00000004,
155 FileSystem_TCF_O_CREAT = 0x00000008,
156 FileSystem_TCF_O_TRUNC = 0x00000010,
157 FileSystem_TCF_O_EXCL = 0x00000020
163 MessageWithoutReply, /* Non-standard: "Settings:set" command does not reply */
167 typedef QSharedPointer<QIODevice> IODevicePtr;
169 explicit CodaDevice(QObject *parent = 0);
170 virtual ~CodaDevice();
172 unsigned verbose() const;
173 bool serialFrame() const;
174 void setSerialFrame(bool);
176 // Mapping of register names to indices for multi-requests.
177 // Register names can be retrieved via 'Registers:getChildren' (requires
178 // context id to be stripped).
179 QVector<QByteArray> registerNames() const;
180 void setRegisterNames(const QVector<QByteArray>& n);
182 IODevicePtr device() const;
183 IODevicePtr takeDevice();
184 void setDevice(const IODevicePtr &dp);
186 // Serial Only: Initiate communication. Will emit serialPong() signal with version.
187 void sendSerialPing(bool pingOnly = false);
189 // Send with parameters from string (which may contain '\0').
190 void sendCodaMessage(MessageType mt, Services service, const char *command,
191 const char *commandParameters, int commandParametersLength,
192 const CodaCallback &callBack = CodaCallback(),
193 const QVariant &cookie = QVariant());
195 void sendCodaMessage(MessageType mt, Services service, const char *command,
196 const QByteArray &commandParameters,
197 const CodaCallback &callBack = CodaCallback(),
198 const QVariant &cookie = QVariant());
200 // Convenience messages: Start a process
201 void sendProcessStartCommand(const CodaCallback &callBack,
202 const QString &binary,
204 QStringList arguments = QStringList(),
205 QString workingDirectory = QString(),
206 bool debugControl = true,
207 const QStringList &additionalLibraries = QStringList(),
208 const QVariant &cookie = QVariant());
210 // Just launch a process, don't attempt to attach the debugger to it
211 void sendRunProcessCommand(const CodaCallback &callBack,
212 const QString &processName,
213 QStringList arguments = QStringList(),
214 const QVariant &cookie = QVariant());
216 // Preferred over Processes:Terminate by CODA.
217 void sendRunControlTerminateCommand(const CodaCallback &callBack,
218 const QByteArray &id,
219 const QVariant &cookie = QVariant());
221 // TODO: In CODA 4.1.13 the Terminate option does order CODA to kill
222 // a process and CODA reports contextRemoved but does not kill the process
223 void sendProcessTerminateCommand(const CodaCallback &callBack,
224 const QByteArray &id,
225 const QVariant &cookie = QVariant());
227 // Non-standard: Remove executable from settings.
228 // Probably needs to be called after stopping. This command has no response.
229 void sendSettingsRemoveExecutableCommand(const QString &binaryIn,
231 const QStringList &additionalLibraries = QStringList(),
232 const QVariant &cookie = QVariant());
234 void sendRunControlSuspendCommand(const CodaCallback &callBack,
235 const QByteArray &id,
236 const QVariant &cookie = QVariant());
238 // Resume / Step (see RunControlResumeMode).
239 void sendRunControlResumeCommand(const CodaCallback &callBack,
240 const QByteArray &id,
241 RunControlResumeMode mode,
242 unsigned count /* = 1, currently ignored. */,
243 quint64 rangeStart, quint64 rangeEnd,
244 const QVariant &cookie = QVariant());
246 // Convenience to resume a suspended process
247 void sendRunControlResumeCommand(const CodaCallback &callBack,
248 const QByteArray &id,
249 const QVariant &cookie = QVariant());
251 void sendBreakpointsAddCommand(const CodaCallback &callBack,
253 const QVariant &cookie = QVariant());
255 void sendBreakpointsRemoveCommand(const CodaCallback &callBack,
256 const QByteArray &id,
257 const QVariant &cookie = QVariant());
259 void sendBreakpointsRemoveCommand(const CodaCallback &callBack,
260 const QVector<QByteArray> &id,
261 const QVariant &cookie = QVariant());
263 void sendBreakpointsEnableCommand(const CodaCallback &callBack,
264 const QByteArray &id,
266 const QVariant &cookie = QVariant());
268 void sendBreakpointsEnableCommand(const CodaCallback &callBack,
269 const QVector<QByteArray> &id,
271 const QVariant &cookie = QVariant());
274 void sendMemoryGetCommand(const CodaCallback &callBack,
275 const QByteArray &contextId,
276 quint64 start, quint64 size,
277 const QVariant &cookie = QVariant());
279 void sendMemorySetCommand(const CodaCallback &callBack,
280 const QByteArray &contextId,
281 quint64 start, const QByteArray& data,
282 const QVariant &cookie = QVariant());
284 // Get register names (children of context).
285 // It is possible to recurse from thread id down to single registers.
286 void sendRegistersGetChildrenCommand(const CodaCallback &callBack,
287 const QByteArray &contextId,
288 const QVariant &cookie = QVariant());
291 void sendRegistersGetCommand(const CodaCallback &callBack,
292 const QByteArray &contextId,
294 const QVariant &cookie);
296 void sendRegistersGetMCommand(const CodaCallback &callBack,
297 const QByteArray &contextId,
298 const QVector<QByteArray> &ids,
299 const QVariant &cookie = QVariant());
301 // Convenience to get a range of register "R0" .. "R<n>".
302 // Cookie will be an int containing "start".
303 void sendRegistersGetMRangeCommand(const CodaCallback &callBack,
304 const QByteArray &contextId,
305 unsigned start, unsigned count);
308 void sendRegistersSetCommand(const CodaCallback &callBack,
309 const QByteArray &contextId,
311 const QByteArray &value, // binary value
312 const QVariant &cookie = QVariant());
314 void sendRegistersSetCommand(const CodaCallback &callBack,
315 const QByteArray &contextId,
316 unsigned registerNumber,
317 const QByteArray &value, // binary value
318 const QVariant &cookie = QVariant());
321 void sendFileSystemOpenCommand(const CodaCallback &callBack,
322 const QByteArray &name,
323 unsigned flags = FileSystem_TCF_O_READ,
324 const QVariant &cookie = QVariant());
326 void sendFileSystemFstatCommand(const CodaCallback &callBack,
327 const QByteArray &handle,
328 const QVariant &cookie = QVariant());
330 void sendFileSystemWriteCommand(const CodaCallback &callBack,
331 const QByteArray &handle,
332 const QByteArray &data,
334 const QVariant &cookie = QVariant());
336 void sendFileSystemCloseCommand(const CodaCallback &callBack,
337 const QByteArray &handle,
338 const QVariant &cookie = QVariant());
341 void sendSymbianInstallSilentInstallCommand(const CodaCallback &callBack,
342 const QByteArray &file,
343 const QByteArray &targetDrive,
344 const QVariant &cookie = QVariant());
346 void sendSymbianInstallUIInstallCommand(const CodaCallback &callBack,
347 const QByteArray &file,
348 const QVariant &cookie = QVariant());
350 void sendSymbianInstallGetPackageInfoCommand(const Coda::CodaCallback &callBack,
351 const QList<quint32> &packages,
352 const QVariant &cookie = QVariant());
354 void sendLoggingAddListenerCommand(const CodaCallback &callBack,
355 const QVariant &cookie = QVariant());
357 void sendSymbianUninstallCommand(const Coda::CodaCallback &callBack,
358 const quint32 package,
359 const QVariant &cookie = QVariant());
362 void sendSymbianOsDataGetThreadsCommand(const CodaCallback &callBack,
363 const QVariant &cookie = QVariant());
365 void sendSymbianOsDataFindProcessesCommand(const CodaCallback &callBack,
366 const QByteArray &processName,
367 const QByteArray &uid,
368 const QVariant &cookie = QVariant());
370 void sendSymbianOsDataGetQtVersionCommand(const CodaCallback &callBack,
371 const QVariant &cookie = QVariant());
373 void sendSymbianOsDataGetRomInfoCommand(const CodaCallback &callBack,
374 const QVariant &cookie = QVariant());
376 void sendSymbianOsDataGetHalInfoCommand(const CodaCallback &callBack,
377 const QStringList &keys = QStringList(),
378 const QVariant &cookie = QVariant());
380 // DebugSessionControl
381 void sendDebugSessionControlSessionStartCommand(const CodaCallback &callBack,
382 const QVariant &cookie = QVariant());
384 void sendDebugSessionControlSessionEndCommand(const CodaCallback &callBack,
385 const QVariant &cookie = QVariant());
388 void sendSettingsEnableLogCommand();
390 void writeCustomData(char protocolId, const QByteArray &aData);
392 static QByteArray parseMemoryGet(const CodaCommandResult &r);
393 static QVector<QByteArray> parseRegisterGetChildren(const CodaCommandResult &r);
394 static CodaStatResponse parseStat(const CodaCommandResult &r);
397 void genericCodaEvent(int service, const QByteArray &name, const QVector<Json::JsonValue> &value);
398 void codaEvent(const Coda::CodaEvent &knownEvent);
399 void unknownEvent(uchar protocolId, const QByteArray& data);
400 void serialPong(const QString &codaVersion);
402 void logMessage(const QString &);
403 void error(const QString &);
406 void setVerbose(unsigned v);
409 void slotDeviceError();
410 void slotDeviceSocketStateChanged();
411 void slotDeviceReadyRead();
414 void deviceReadyReadSerial();
415 void deviceReadyReadTcp();
418 void checkSendQueue();
419 void writeMessage(QByteArray data, bool ensureTerminating0 = true);
420 void emitLogMessage(const QString &);
421 inline int parseMessage(const QByteArray &);
422 void processMessage(const QByteArray &message);
423 inline void processSerialMessage(const QByteArray &message);
424 int parseCodaCommandReply(char type, const QVector<QByteArray> &tokens);
425 int parseCodaEvent(const QVector<QByteArray> &tokens);
428 QPair<int, int> findSerialHeader(QByteArray &in);
429 CodaDevicePrivate *d;
434 #endif // CODAENGINE_H