|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the tools applications of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "launcher.h" |
|
43 #include "trkutils.h" |
|
44 #include "trkutils_p.h" |
|
45 #include "trkdevice.h" |
|
46 #include "bluetoothlistener.h" |
|
47 |
|
48 #include <QtCore/QTimer> |
|
49 #include <QtCore/QDateTime> |
|
50 #include <QtCore/QVariant> |
|
51 #include <QtCore/QDebug> |
|
52 #include <QtCore/QQueue> |
|
53 #include <QtCore/QFile> |
|
54 #include <QtCore/QScopedPointer> |
|
55 |
|
56 namespace trk { |
|
57 |
|
58 struct LauncherPrivate { |
|
59 struct CopyState { |
|
60 QString sourceFileName; |
|
61 QString destinationFileName; |
|
62 uint copyFileHandle; |
|
63 QScopedPointer<QByteArray> data; |
|
64 int position; |
|
65 }; |
|
66 |
|
67 explicit LauncherPrivate(const TrkDevicePtr &d); |
|
68 |
|
69 TrkDevicePtr m_device; |
|
70 QByteArray m_trkReadBuffer; |
|
71 Launcher::State m_state; |
|
72 |
|
73 void logMessage(const QString &msg); |
|
74 // Debuggee state |
|
75 Session m_session; // global-ish data (process id, target information) |
|
76 |
|
77 CopyState m_copyState; |
|
78 QString m_fileName; |
|
79 QStringList m_commandLineArgs; |
|
80 QString m_installFileName; |
|
81 int m_verbose; |
|
82 Launcher::Actions m_startupActions; |
|
83 bool m_closeDevice; |
|
84 }; |
|
85 |
|
86 LauncherPrivate::LauncherPrivate(const TrkDevicePtr &d) : |
|
87 m_device(d), |
|
88 m_state(Launcher::Disconnected), |
|
89 m_verbose(0), |
|
90 m_closeDevice(true) |
|
91 { |
|
92 if (m_device.isNull()) |
|
93 m_device = TrkDevicePtr(new TrkDevice); |
|
94 } |
|
95 |
|
96 Launcher::Launcher(Actions startupActions, |
|
97 const TrkDevicePtr &dev, |
|
98 QObject *parent) : |
|
99 QObject(parent), |
|
100 d(new LauncherPrivate(dev)) |
|
101 { |
|
102 d->m_startupActions = startupActions; |
|
103 connect(d->m_device.data(), SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(handleResult(trk::TrkResult))); |
|
104 connect(this, SIGNAL(finished()), d->m_device.data(), SLOT(close())); |
|
105 } |
|
106 |
|
107 Launcher::~Launcher() |
|
108 { |
|
109 logMessage("Shutting down.\n"); |
|
110 delete d; |
|
111 } |
|
112 |
|
113 Launcher::State Launcher::state() const |
|
114 { |
|
115 return d->m_state; |
|
116 } |
|
117 |
|
118 void Launcher::setState(State s) |
|
119 { |
|
120 if (s != d->m_state) { |
|
121 d->m_state = s; |
|
122 emit stateChanged(s); |
|
123 } |
|
124 } |
|
125 |
|
126 void Launcher::addStartupActions(trk::Launcher::Actions startupActions) |
|
127 { |
|
128 d->m_startupActions = Actions(d->m_startupActions | startupActions); |
|
129 } |
|
130 |
|
131 void Launcher::setTrkServerName(const QString &name) |
|
132 { |
|
133 d->m_device->setPort(name); |
|
134 } |
|
135 |
|
136 QString Launcher::trkServerName() const |
|
137 { |
|
138 return d->m_device->port(); |
|
139 } |
|
140 |
|
141 TrkDevicePtr Launcher::trkDevice() const |
|
142 { |
|
143 return d->m_device; |
|
144 } |
|
145 |
|
146 void Launcher::setFileName(const QString &name) |
|
147 { |
|
148 d->m_fileName = name; |
|
149 } |
|
150 |
|
151 void Launcher::setCopyFileName(const QString &srcName, const QString &dstName) |
|
152 { |
|
153 d->m_copyState.sourceFileName = srcName; |
|
154 d->m_copyState.destinationFileName = dstName; |
|
155 } |
|
156 |
|
157 void Launcher::setInstallFileName(const QString &name) |
|
158 { |
|
159 d->m_installFileName = name; |
|
160 } |
|
161 |
|
162 void Launcher::setCommandLineArgs(const QStringList &args) |
|
163 { |
|
164 d->m_commandLineArgs = args; |
|
165 } |
|
166 |
|
167 void Launcher::setSerialFrame(bool b) |
|
168 { |
|
169 d->m_device->setSerialFrame(b); |
|
170 } |
|
171 |
|
172 bool Launcher::serialFrame() const |
|
173 { |
|
174 return d->m_device->serialFrame(); |
|
175 } |
|
176 |
|
177 |
|
178 bool Launcher::closeDevice() const |
|
179 { |
|
180 return d->m_closeDevice; |
|
181 } |
|
182 |
|
183 void Launcher::setCloseDevice(bool c) |
|
184 { |
|
185 d->m_closeDevice = c; |
|
186 } |
|
187 |
|
188 bool Launcher::startServer(QString *errorMessage) |
|
189 { |
|
190 errorMessage->clear(); |
|
191 if (d->m_verbose) { |
|
192 const QString msg = QString::fromLatin1("Port=%1 Executable=%2 Arguments=%3 Package=%4 Remote Package=%5 Install file=%6") |
|
193 .arg(trkServerName(), d->m_fileName, |
|
194 d->m_commandLineArgs.join(QString(QLatin1Char(' '))), |
|
195 d->m_copyState.sourceFileName, d->m_copyState.destinationFileName, d->m_installFileName); |
|
196 logMessage(msg); |
|
197 } |
|
198 if (d->m_startupActions & ActionCopy) { |
|
199 if (d->m_copyState.sourceFileName.isEmpty()) { |
|
200 qWarning("No local filename given for copying package."); |
|
201 return false; |
|
202 } else if (d->m_copyState.destinationFileName.isEmpty()) { |
|
203 qWarning("No remote filename given for copying package."); |
|
204 return false; |
|
205 } |
|
206 } |
|
207 if (d->m_startupActions & ActionInstall && d->m_installFileName.isEmpty()) { |
|
208 qWarning("No package name given for installing."); |
|
209 return false; |
|
210 } |
|
211 if (d->m_startupActions & ActionRun && d->m_fileName.isEmpty()) { |
|
212 qWarning("No remote executable given for running."); |
|
213 return false; |
|
214 } |
|
215 if (!d->m_device->isOpen() && !d->m_device->open(errorMessage)) |
|
216 return false; |
|
217 if (d->m_closeDevice) { |
|
218 connect(this, SIGNAL(finished()), d->m_device.data(), SLOT(close())); |
|
219 } else { |
|
220 disconnect(this, SIGNAL(finished()), d->m_device.data(), 0); |
|
221 } |
|
222 setState(Connecting); |
|
223 // Set up the temporary 'waiting' state if we do not get immediate connection |
|
224 QTimer::singleShot(1000, this, SLOT(slotWaitingForTrk())); |
|
225 d->m_device->sendTrkInitialPing(); |
|
226 d->m_device->sendTrkMessage(TrkDisconnect); // Disconnect, as trk might be still connected |
|
227 d->m_device->sendTrkMessage(TrkSupported, TrkCallback(this, &Launcher::handleSupportMask)); |
|
228 d->m_device->sendTrkMessage(TrkCpuType, TrkCallback(this, &Launcher::handleCpuType)); |
|
229 d->m_device->sendTrkMessage(TrkVersions, TrkCallback(this, &Launcher::handleTrkVersion)); |
|
230 if (d->m_startupActions != ActionPingOnly) |
|
231 d->m_device->sendTrkMessage(TrkConnect, TrkCallback(this, &Launcher::handleConnect)); |
|
232 return true; |
|
233 } |
|
234 |
|
235 void Launcher::slotWaitingForTrk() |
|
236 { |
|
237 // Set temporary state if we are still in connected state |
|
238 if (state() == Connecting) |
|
239 setState(WaitingForTrk); |
|
240 } |
|
241 |
|
242 void Launcher::handleConnect(const TrkResult &result) |
|
243 { |
|
244 if (result.errorCode()) { |
|
245 emit canNotConnect(result.errorString()); |
|
246 return; |
|
247 } |
|
248 setState(Connected); |
|
249 if (d->m_startupActions & ActionCopy) |
|
250 copyFileToRemote(); |
|
251 else if (d->m_startupActions & ActionInstall) |
|
252 installRemotePackageSilently(); |
|
253 else if (d->m_startupActions & ActionRun) |
|
254 startInferiorIfNeeded(); |
|
255 } |
|
256 |
|
257 void Launcher::setVerbose(int v) |
|
258 { |
|
259 d->m_verbose = v; |
|
260 d->m_device->setVerbose(v); |
|
261 } |
|
262 |
|
263 void Launcher::logMessage(const QString &msg) |
|
264 { |
|
265 if (d->m_verbose) |
|
266 qDebug() << "LAUNCHER: " << qPrintable(msg); |
|
267 } |
|
268 |
|
269 void Launcher::terminate() |
|
270 { |
|
271 switch (state()) { |
|
272 case DeviceDescriptionReceived: |
|
273 case Connected: |
|
274 if (d->m_session.pid) { |
|
275 QByteArray ba; |
|
276 appendShort(&ba, 0x0000, TargetByteOrder); |
|
277 appendInt(&ba, d->m_session.pid, TargetByteOrder); |
|
278 d->m_device->sendTrkMessage(TrkDeleteItem, TrkCallback(this, &Launcher::handleRemoteProcessKilled), ba); |
|
279 return; |
|
280 } |
|
281 if (d->m_copyState.copyFileHandle) |
|
282 closeRemoteFile(true); |
|
283 disconnectTrk(); |
|
284 break; |
|
285 case Disconnected: |
|
286 break; |
|
287 case Connecting: |
|
288 case WaitingForTrk: |
|
289 setState(Disconnected); |
|
290 emit finished(); |
|
291 break; |
|
292 } |
|
293 } |
|
294 |
|
295 void Launcher::handleRemoteProcessKilled(const TrkResult &result) |
|
296 { |
|
297 Q_UNUSED(result) |
|
298 disconnectTrk(); |
|
299 } |
|
300 |
|
301 QString Launcher::msgStopped(uint pid, uint tid, uint address, const QString &why) |
|
302 { |
|
303 return QString::fromLatin1("Process %1, thread %2 stopped at 0x%3: %4"). |
|
304 arg(pid).arg(tid).arg(address, 0, 16). |
|
305 arg(why.isEmpty() ? QString::fromLatin1("<Unknown reason>") : why); |
|
306 } |
|
307 |
|
308 bool Launcher::parseNotifyStopped(const QByteArray &dataBA, |
|
309 uint *pid, uint *tid, uint *address, |
|
310 QString *why /* = 0 */) |
|
311 { |
|
312 if (why) |
|
313 why->clear(); |
|
314 *address = *pid = *tid = 0; |
|
315 if (dataBA.size() < 12) |
|
316 return false; |
|
317 const char *data = dataBA.data(); |
|
318 *address = extractInt(data); |
|
319 *pid = extractInt(data + 4); |
|
320 *tid = extractInt(data + 8); |
|
321 if (why && dataBA.size() >= 14) { |
|
322 const unsigned short len = extractShort(data + 12); |
|
323 if (len > 0) |
|
324 *why = QString::fromLatin1(data + 14, len); |
|
325 } |
|
326 return true; |
|
327 } |
|
328 |
|
329 void Launcher::handleResult(const TrkResult &result) |
|
330 { |
|
331 QByteArray prefix = "READ BUF: "; |
|
332 QByteArray str = result.toString().toUtf8(); |
|
333 if (result.isDebugOutput) { // handle application output |
|
334 logMessage("APPLICATION OUTPUT: " + result.data); |
|
335 emit applicationOutputReceived(result.data); |
|
336 return; |
|
337 } |
|
338 switch (result.code) { |
|
339 case TrkNotifyAck: |
|
340 break; |
|
341 case TrkNotifyNak: { // NAK |
|
342 logMessage(prefix + "NAK: " + str); |
|
343 //logMessage(prefix << "TOKEN: " << result.token); |
|
344 logMessage(prefix + "ERROR: " + errorMessage(result.data.at(0))); |
|
345 break; |
|
346 } |
|
347 case TrkNotifyStopped: { // Notified Stopped |
|
348 QString reason; |
|
349 uint pc; |
|
350 uint pid; |
|
351 uint tid; |
|
352 parseNotifyStopped(result.data, &pid, &tid, &pc, &reason); |
|
353 logMessage(prefix + msgStopped(pid, tid, pc, reason)); |
|
354 emit(processStopped(pc, pid, tid, reason)); |
|
355 d->m_device->sendTrkAck(result.token); |
|
356 break; |
|
357 } |
|
358 case TrkNotifyException: { // Notify Exception (obsolete) |
|
359 logMessage(prefix + "NOTE: EXCEPTION " + str); |
|
360 d->m_device->sendTrkAck(result.token); |
|
361 break; |
|
362 } |
|
363 case TrkNotifyInternalError: { // |
|
364 logMessage(prefix + "NOTE: INTERNAL ERROR: " + str); |
|
365 d->m_device->sendTrkAck(result.token); |
|
366 break; |
|
367 } |
|
368 |
|
369 // target->host OS notification |
|
370 case TrkNotifyCreated: { // Notify Created |
|
371 /* |
|
372 const char *data = result.data.data(); |
|
373 byte error = result.data.at(0); |
|
374 byte type = result.data.at(1); // type: 1 byte; for dll item, this value is 2. |
|
375 uint pid = extractInt(data + 2); // ProcessID: 4 bytes; |
|
376 uint tid = extractInt(data + 6); //threadID: 4 bytes |
|
377 uint codeseg = extractInt(data + 10); //code address: 4 bytes; code base address for the library |
|
378 uint dataseg = extractInt(data + 14); //data address: 4 bytes; data base address for the library |
|
379 uint len = extractShort(data + 18); //length: 2 bytes; length of the library name string to follow |
|
380 QByteArray name = result.data.mid(20, len); // name: library name |
|
381 |
|
382 logMessage(prefix + "NOTE: LIBRARY LOAD: " + str); |
|
383 logMessage(prefix + "TOKEN: " + result.token); |
|
384 logMessage(prefix + "ERROR: " + int(error)); |
|
385 logMessage(prefix + "TYPE: " + int(type)); |
|
386 logMessage(prefix + "PID: " + pid); |
|
387 logMessage(prefix + "TID: " + tid); |
|
388 logMessage(prefix + "CODE: " + codeseg); |
|
389 logMessage(prefix + "DATA: " + dataseg); |
|
390 logMessage(prefix + "LEN: " + len); |
|
391 logMessage(prefix + "NAME: " + name); |
|
392 */ |
|
393 |
|
394 if (result.data.size() < 10) |
|
395 break; |
|
396 QByteArray ba; |
|
397 ba.append(result.data.mid(2, 8)); |
|
398 d->m_device->sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE"); |
|
399 //d->m_device->sendTrkAck(result.token) |
|
400 break; |
|
401 } |
|
402 case TrkNotifyDeleted: { // NotifyDeleted |
|
403 const ushort itemType = (unsigned char)result.data.at(1); |
|
404 const ushort len = result.data.size() > 12 ? extractShort(result.data.data() + 10) : ushort(0); |
|
405 const QString name = len ? QString::fromAscii(result.data.mid(12, len)) : QString(); |
|
406 logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3"). |
|
407 arg(QString::fromAscii(prefix)).arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS")). |
|
408 arg(name)); |
|
409 d->m_device->sendTrkAck(result.token); |
|
410 if (itemType == 0 // process |
|
411 && result.data.size() >= 10 |
|
412 && d->m_session.pid == extractInt(result.data.data() + 6)) { |
|
413 disconnectTrk(); |
|
414 } |
|
415 break; |
|
416 } |
|
417 case TrkNotifyProcessorStarted: { // NotifyProcessorStarted |
|
418 logMessage(prefix + "NOTE: PROCESSOR STARTED: " + str); |
|
419 d->m_device->sendTrkAck(result.token); |
|
420 break; |
|
421 } |
|
422 case TrkNotifyProcessorStandBy: { // NotifyProcessorStandby |
|
423 logMessage(prefix + "NOTE: PROCESSOR STANDBY: " + str); |
|
424 d->m_device->sendTrkAck(result.token); |
|
425 break; |
|
426 } |
|
427 case TrkNotifyProcessorReset: { // NotifyProcessorReset |
|
428 logMessage(prefix + "NOTE: PROCESSOR RESET: " + str); |
|
429 d->m_device->sendTrkAck(result.token); |
|
430 break; |
|
431 } |
|
432 default: { |
|
433 logMessage(prefix + "INVALID: " + str); |
|
434 break; |
|
435 } |
|
436 } |
|
437 } |
|
438 |
|
439 QString Launcher::deviceDescription(unsigned verbose) const |
|
440 { |
|
441 return d->m_session.deviceDescription(verbose); |
|
442 } |
|
443 |
|
444 void Launcher::handleTrkVersion(const TrkResult &result) |
|
445 { |
|
446 if (result.errorCode() || result.data.size() < 5) { |
|
447 if (d->m_startupActions == ActionPingOnly) { |
|
448 setState(Disconnected); |
|
449 emit finished(); |
|
450 } |
|
451 return; |
|
452 } |
|
453 d->m_session.trkAppVersion.trkMajor = result.data.at(1); |
|
454 d->m_session.trkAppVersion.trkMinor = result.data.at(2); |
|
455 d->m_session.trkAppVersion.protocolMajor = result.data.at(3); |
|
456 d->m_session.trkAppVersion.protocolMinor = result.data.at(4); |
|
457 setState(DeviceDescriptionReceived); |
|
458 // Ping mode: Log & Terminate |
|
459 if (d->m_startupActions == ActionPingOnly) { |
|
460 qWarning("%s", qPrintable(deviceDescription())); |
|
461 setState(Disconnected); |
|
462 emit finished(); |
|
463 } |
|
464 } |
|
465 |
|
466 void Launcher::handleFileCreation(const TrkResult &result) |
|
467 { |
|
468 if (result.errorCode() || result.data.size() < 6) { |
|
469 emit canNotCreateFile(d->m_copyState.destinationFileName, result.errorString()); |
|
470 disconnectTrk(); |
|
471 return; |
|
472 } |
|
473 const char *data = result.data.data(); |
|
474 d->m_copyState.copyFileHandle = extractInt(data + 2); |
|
475 QFile file(d->m_copyState.sourceFileName); |
|
476 file.open(QIODevice::ReadOnly); |
|
477 d->m_copyState.data.reset(new QByteArray(file.readAll())); |
|
478 d->m_copyState.position = 0; |
|
479 file.close(); |
|
480 continueCopying(); |
|
481 } |
|
482 |
|
483 void Launcher::handleCopy(const TrkResult &result) |
|
484 { |
|
485 if (result.errorCode() || result.data.size() < 4) { |
|
486 closeRemoteFile(true); |
|
487 emit canNotWriteFile(d->m_copyState.destinationFileName, result.errorString()); |
|
488 disconnectTrk(); |
|
489 } else { |
|
490 continueCopying(extractShort(result.data.data() + 2)); |
|
491 } |
|
492 } |
|
493 |
|
494 void Launcher::continueCopying(uint lastCopiedBlockSize) |
|
495 { |
|
496 int size = d->m_copyState.data->length(); |
|
497 d->m_copyState.position += lastCopiedBlockSize; |
|
498 if (size == 0) |
|
499 emit copyProgress(100); |
|
500 else { |
|
501 int percent = qMin((d->m_copyState.position*100)/size, 100); |
|
502 emit copyProgress(percent); |
|
503 } |
|
504 if (d->m_copyState.position < size) { |
|
505 QByteArray ba; |
|
506 appendInt(&ba, d->m_copyState.copyFileHandle, TargetByteOrder); |
|
507 appendString(&ba, d->m_copyState.data->mid(d->m_copyState.position, 2048), TargetByteOrder, false); |
|
508 d->m_device->sendTrkMessage(TrkWriteFile, TrkCallback(this, &Launcher::handleCopy), ba); |
|
509 } else { |
|
510 closeRemoteFile(); |
|
511 } |
|
512 } |
|
513 |
|
514 void Launcher::closeRemoteFile(bool failed) |
|
515 { |
|
516 QByteArray ba; |
|
517 appendInt(&ba, d->m_copyState.copyFileHandle, TargetByteOrder); |
|
518 appendDateTime(&ba, QDateTime::currentDateTime(), TargetByteOrder); |
|
519 d->m_device->sendTrkMessage(TrkCloseFile, |
|
520 failed ? TrkCallback() : TrkCallback(this, &Launcher::handleFileCopied), |
|
521 ba); |
|
522 d->m_copyState.data.reset(); |
|
523 d->m_copyState.copyFileHandle = 0; |
|
524 d->m_copyState.position = 0; |
|
525 } |
|
526 |
|
527 void Launcher::handleFileCopied(const TrkResult &result) |
|
528 { |
|
529 if (result.errorCode()) |
|
530 emit canNotCloseFile(d->m_copyState.destinationFileName, result.errorString()); |
|
531 if (d->m_startupActions & ActionInstall) |
|
532 installRemotePackageSilently(); |
|
533 else if (d->m_startupActions & ActionRun) |
|
534 startInferiorIfNeeded(); |
|
535 else |
|
536 disconnectTrk(); |
|
537 } |
|
538 |
|
539 void Launcher::handleCpuType(const TrkResult &result) |
|
540 { |
|
541 logMessage("HANDLE CPU TYPE: " + result.toString()); |
|
542 if(result.errorCode() || result.data.size() < 7) |
|
543 return; |
|
544 //---TRK------------------------------------------------------ |
|
545 // Command: 0x80 Acknowledge |
|
546 // Error: 0x00 |
|
547 // [80 03 00 04 00 00 04 00 00 00] |
|
548 d->m_session.cpuMajor = result.data.at(1); |
|
549 d->m_session.cpuMinor = result.data.at(2); |
|
550 d->m_session.bigEndian = result.data.at(3); |
|
551 d->m_session.defaultTypeSize = result.data.at(4); |
|
552 d->m_session.fpTypeSize = result.data.at(5); |
|
553 d->m_session.extended1TypeSize = result.data.at(6); |
|
554 //d->m_session.extended2TypeSize = result.data[6]; |
|
555 } |
|
556 |
|
557 void Launcher::handleCreateProcess(const TrkResult &result) |
|
558 { |
|
559 if (result.errorCode()) { |
|
560 emit canNotRun(result.errorString()); |
|
561 disconnectTrk(); |
|
562 return; |
|
563 } |
|
564 // 40 00 00] |
|
565 //logMessage(" RESULT: " + result.toString()); |
|
566 // [80 08 00 00 00 01 B5 00 00 01 B6 78 67 40 00 00 40 00 00] |
|
567 const char *data = result.data.data(); |
|
568 d->m_session.pid = extractInt(data + 1); |
|
569 d->m_session.tid = extractInt(data + 5); |
|
570 d->m_session.codeseg = extractInt(data + 9); |
|
571 d->m_session.dataseg = extractInt(data + 13); |
|
572 if (d->m_verbose) { |
|
573 const QString msg = QString::fromLatin1("Process id: %1 Thread id: %2 code: 0x%3 data: 0x%4"). |
|
574 arg(d->m_session.pid).arg(d->m_session.tid).arg(d->m_session.codeseg, 0, 16). |
|
575 arg(d->m_session.dataseg, 0 ,16); |
|
576 logMessage(msg); |
|
577 } |
|
578 emit applicationRunning(d->m_session.pid); |
|
579 QByteArray ba; |
|
580 appendInt(&ba, d->m_session.pid); |
|
581 appendInt(&ba, d->m_session.tid); |
|
582 d->m_device->sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE"); |
|
583 } |
|
584 |
|
585 void Launcher::handleWaitForFinished(const TrkResult &result) |
|
586 { |
|
587 logMessage(" FINISHED: " + stringFromArray(result.data)); |
|
588 setState(Disconnected); |
|
589 emit finished(); |
|
590 } |
|
591 |
|
592 void Launcher::handleSupportMask(const TrkResult &result) |
|
593 { |
|
594 if (result.errorCode() || result.data.size() < 32) |
|
595 return; |
|
596 const char *data = result.data.data() + 1; |
|
597 |
|
598 QString str = QLatin1String("SUPPORTED: "); |
|
599 for (int i = 0; i < 32; ++i) { |
|
600 //str.append(" [" + formatByte(data[i]) + "]: "); |
|
601 for (int j = 0; j < 8; ++j) { |
|
602 if (data[i] & (1 << j)) { |
|
603 str.append(QString::number(i * 8 + j, 16)); |
|
604 str.append(QLatin1Char(' ')); |
|
605 } |
|
606 } |
|
607 } |
|
608 logMessage(str); |
|
609 } |
|
610 |
|
611 void Launcher::cleanUp() |
|
612 { |
|
613 // |
|
614 //---IDE------------------------------------------------------ |
|
615 // Command: 0x41 Delete Item |
|
616 // Sub Cmd: Delete Process |
|
617 //ProcessID: 0x0000071F (1823) |
|
618 // [41 24 00 00 00 00 07 1F] |
|
619 QByteArray ba(2, char(0)); |
|
620 appendInt(&ba, d->m_session.pid); |
|
621 d->m_device->sendTrkMessage(TrkDeleteItem, TrkCallback(), ba, "Delete process"); |
|
622 |
|
623 //---TRK------------------------------------------------------ |
|
624 // Command: 0x80 Acknowledge |
|
625 // Error: 0x00 |
|
626 // [80 24 00] |
|
627 |
|
628 //---IDE------------------------------------------------------ |
|
629 // Command: 0x1C Clear Break |
|
630 // [1C 25 00 00 00 0A 78 6A 43 40] |
|
631 |
|
632 //---TRK------------------------------------------------------ |
|
633 // Command: 0xA1 Notify Deleted |
|
634 // [A1 09 00 00 00 00 00 00 00 00 07 1F] |
|
635 //---IDE------------------------------------------------------ |
|
636 // Command: 0x80 Acknowledge |
|
637 // Error: 0x00 |
|
638 // [80 09 00] |
|
639 |
|
640 //---TRK------------------------------------------------------ |
|
641 // Command: 0x80 Acknowledge |
|
642 // Error: 0x00 |
|
643 // [80 25 00] |
|
644 |
|
645 //---IDE------------------------------------------------------ |
|
646 // Command: 0x1C Clear Break |
|
647 // [1C 26 00 00 00 0B 78 6A 43 70] |
|
648 //---TRK------------------------------------------------------ |
|
649 // Command: 0x80 Acknowledge |
|
650 // Error: 0x00 |
|
651 // [80 26 00] |
|
652 |
|
653 |
|
654 //---IDE------------------------------------------------------ |
|
655 // Command: 0x02 Disconnect |
|
656 // [02 27] |
|
657 // sendTrkMessage(0x02, TrkCallback(this, &Launcher::handleDisconnect)); |
|
658 //---TRK------------------------------------------------------ |
|
659 // Command: 0x80 Acknowledge |
|
660 // Error: 0x00 |
|
661 } |
|
662 |
|
663 void Launcher::disconnectTrk() |
|
664 { |
|
665 d->m_device->sendTrkMessage(TrkDisconnect, TrkCallback(this, &Launcher::handleWaitForFinished)); |
|
666 } |
|
667 |
|
668 void Launcher::copyFileToRemote() |
|
669 { |
|
670 emit copyingStarted(); |
|
671 QByteArray ba; |
|
672 ba.append(char(10)); |
|
673 appendString(&ba, d->m_copyState.destinationFileName.toLocal8Bit(), TargetByteOrder, false); |
|
674 d->m_device->sendTrkMessage(TrkOpenFile, TrkCallback(this, &Launcher::handleFileCreation), ba); |
|
675 } |
|
676 |
|
677 void Launcher::installRemotePackageSilently() |
|
678 { |
|
679 emit installingStarted(); |
|
680 QByteArray ba; |
|
681 ba.append('C'); |
|
682 appendString(&ba, d->m_installFileName.toLocal8Bit(), TargetByteOrder, false); |
|
683 d->m_device->sendTrkMessage(TrkInstallFile, TrkCallback(this, &Launcher::handleInstallPackageFinished), ba); |
|
684 } |
|
685 |
|
686 void Launcher::handleInstallPackageFinished(const TrkResult &result) |
|
687 { |
|
688 if (result.errorCode()) { |
|
689 emit canNotInstall(d->m_installFileName, result.errorString()); |
|
690 disconnectTrk(); |
|
691 return; |
|
692 } else { |
|
693 emit installingFinished(); |
|
694 } |
|
695 if (d->m_startupActions & ActionRun) { |
|
696 startInferiorIfNeeded(); |
|
697 } else { |
|
698 disconnectTrk(); |
|
699 } |
|
700 } |
|
701 |
|
702 QByteArray Launcher::startProcessMessage(const QString &executable, |
|
703 const QStringList &arguments) |
|
704 { |
|
705 // It's not started yet |
|
706 QByteArray ba; |
|
707 appendShort(&ba, 0, TargetByteOrder); // create new process |
|
708 ba.append(char(0)); // options - currently unused |
|
709 if(arguments.isEmpty()) { |
|
710 appendString(&ba, executable.toLocal8Bit(), TargetByteOrder); |
|
711 return ba; |
|
712 } |
|
713 // Append full command line as one string (leading length information). |
|
714 QByteArray commandLineBa; |
|
715 commandLineBa.append(executable.toLocal8Bit()); |
|
716 commandLineBa.append('\0'); |
|
717 commandLineBa.append(arguments.join(QString(QLatin1Char(' '))).toLocal8Bit()); |
|
718 appendString(&ba, commandLineBa, TargetByteOrder); |
|
719 return ba; |
|
720 } |
|
721 |
|
722 void Launcher::startInferiorIfNeeded() |
|
723 { |
|
724 emit startingApplication(); |
|
725 if (d->m_session.pid != 0) { |
|
726 logMessage("Process already 'started'"); |
|
727 return; |
|
728 } |
|
729 d->m_device->sendTrkMessage(TrkCreateItem, TrkCallback(this, &Launcher::handleCreateProcess), |
|
730 startProcessMessage(d->m_fileName, d->m_commandLineArgs)); // Create Item |
|
731 } |
|
732 |
|
733 void Launcher::resumeProcess(uint pid, uint tid) |
|
734 { |
|
735 QByteArray ba; |
|
736 appendInt(&ba, pid, BigEndian); |
|
737 appendInt(&ba, tid, BigEndian); |
|
738 d->m_device->sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE"); |
|
739 } |
|
740 } // namespace trk |