Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Tobias Hunger
qt-creator
Commits
d7ca39da
Commit
d7ca39da
authored
Dec 08, 2010
by
Friedemann Kleint
Browse files
Symbian/CODA: Add infrastructure for serial communication.
Add USB protocol and chunking.
parent
c4e49138
Changes
4
Hide whitespace changes
Inline
Side-by-side
src/shared/symbianutils/tcftrkdevice.cpp
View file @
d7ca39da
...
...
@@ -29,6 +29,7 @@
#include "tcftrkdevice.h"
#include "json.h"
#include "trkutils.h"
#include <QtNetwork/QAbstractSocket>
#include <QtCore/QDebug>
...
...
@@ -40,7 +41,62 @@
enum
{
debug
=
0
};
static
const
char
messageTerminatorC
[]
=
"
\003\001
"
;
static
const
char
wlanMessageTerminatorC
[]
=
"
\003\001
"
;
// Serial Ping: 0xfc,0x1f
static
const
char
serialPingC
[]
=
"
\xfc\x1f
"
;
// Serial Pong: 0xfc,0xf1, followed by version info
static
const
char
serialPongC
[]
=
"
\xfc\xf1
"
;
static
const
char
locatorAnswerC
[]
=
"E
\0
Locator
\0
Hello
\0
[
\"
Locator
\"
]"
;
static
const
unsigned
serialChunkLength
=
0x400
;
// 1K max USB router
static
const
int
maxSerialMessageLength
=
0x10000
;
// give chunking scheme
// Create USB router frame
static
inline
void
encodeSerialFrame
(
const
QByteArray
&
data
,
QByteArray
*
target
)
{
target
->
append
(
char
(
0x01
));
target
->
append
(
char
(
0x92
));
// CODA serial message ID
appendShort
(
target
,
ushort
(
data
.
size
()),
trk
::
BigEndian
);
target
->
append
(
data
);
}
// Split in chunks of 1K according to CODA protocol chunking
static
inline
QByteArray
encodeUsbSerialMessage
(
const
QByteArray
&
dataIn
)
{
static
const
int
chunkSize
=
serialChunkLength
-
2
;
// 2 Header bytes
const
int
size
=
dataIn
.
size
();
QByteArray
frame
;
// Do we need to split?
if
(
size
<
chunkSize
)
{
// Nope, all happy.
frame
.
reserve
(
size
+
4
);
encodeSerialFrame
(
dataIn
,
&
frame
);
return
frame
;
}
// Split.
unsigned
chunkCount
=
size
/
chunkSize
;
if
(
size
%
chunkSize
)
chunkCount
++
;
if
(
debug
)
qDebug
(
"Serial: Splitting message of %d bytes into %u chunks of %d"
,
size
,
chunkCount
,
chunkSize
);
frame
.
reserve
((
4
+
serialChunkLength
)
*
chunkCount
);
int
pos
=
0
;
for
(
unsigned
c
=
chunkCount
-
1
;
pos
<
size
;
c
--
)
{
QByteArray
chunk
;
// chunk with long message start/continuation code
chunk
.
reserve
(
serialChunkLength
);
chunk
.
append
(
pos
?
char
(
0
)
:
char
(
0xfe
));
chunk
.
append
(
char
(
static_cast
<
unsigned
char
>
(
c
)));
// Avoid any signedness issues.
const
int
chunkEnd
=
qMin
(
pos
+
chunkSize
,
size
);
chunk
.
append
(
dataIn
.
mid
(
pos
,
chunkEnd
-
pos
));
encodeSerialFrame
(
chunk
,
&
frame
);
pos
=
chunkEnd
;
}
if
(
debug
>
1
)
qDebug
(
"Serial chunked:
\n
%s"
,
qPrintable
(
tcftrk
::
formatData
(
frame
)));
return
frame
;
}
namespace
tcftrk
{
// ------------- TcfTrkCommandError
...
...
@@ -272,11 +328,12 @@ struct TcfTrkDevicePrivate {
TokenWrittenMessageMap
m_writtenMessages
;
QVector
<
QByteArray
>
m_registerNames
;
QVector
<
QByteArray
>
m_fakeGetMRegisterValues
;
bool
m_serialFrame
;
};
TcfTrkDevicePrivate
::
TcfTrkDevicePrivate
()
:
m_messageTerminator
(
m
essageTerminatorC
),
m_verbose
(
0
),
m_token
(
0
)
m_messageTerminator
(
wlanM
essageTerminatorC
),
m_verbose
(
0
),
m_token
(
0
)
,
m_serialFrame
(
false
)
{
}
...
...
@@ -380,7 +437,12 @@ void TcfTrkDevice::slotDeviceSocketStateChanged()
static
inline
QString
debugMessage
(
QByteArray
message
,
const
char
*
prefix
=
0
)
{
message
.
replace
(
'\0'
,
'|'
);
const
bool
isBinary
=
!
message
.
isEmpty
()
&&
message
.
at
(
0
)
<
0
;
if
(
isBinary
)
{
message
=
message
.
toHex
();
// Some serial special message
}
else
{
message
.
replace
(
'\0'
,
'|'
);
}
const
QString
messageS
=
QString
::
fromLatin1
(
message
);
return
prefix
?
(
QLatin1String
(
prefix
)
+
messageS
)
:
messageS
;
...
...
@@ -388,30 +450,101 @@ static inline QString debugMessage(QByteArray message, const char *prefix = 0)
void
TcfTrkDevice
::
slotDeviceReadyRead
()
{
d
->
m_readBuffer
+=
d
->
m_device
->
readAll
();
const
QByteArray
newData
=
d
->
m_device
->
readAll
();
d
->
m_readBuffer
+=
newData
;
if
(
debug
)
qDebug
(
"ReadBuffer: %s"
,
qPrintable
(
trk
::
stringFromArray
(
newData
)));
if
(
d
->
m_serialFrame
)
{
deviceReadyReadSerial
();
}
else
{
deviceReadyReadWLAN
();
}
}
// Find a serial header in input stream '0x1', '0x92', 'lenH', 'lenL'
// and return message position and size.
static
inline
QPair
<
int
,
int
>
findSerialHeader
(
const
QByteArray
&
in
)
{
const
int
size
=
in
.
size
();
const
char
header1
=
0x1
;
const
char
header2
=
char
(
0x92
);
// Header should in theory always be at beginning of
// buffer. Warn if there are bogus data in-between.
for
(
int
pos
=
0
;
pos
<
size
;
)
{
if
(
pos
+
4
<
size
&&
in
.
at
(
pos
)
==
header1
&&
in
.
at
(
pos
+
1
)
==
header2
)
{
const
int
length
=
trk
::
extractShort
(
in
.
constData
()
+
2
);
return
QPair
<
int
,
int
>
(
pos
+
4
,
length
);
}
// Find next
pos
=
in
.
indexOf
(
header1
,
pos
+
1
);
qWarning
(
"Bogus data received on serial line: %s
\n
"
"Frame Header at: %d"
,
qPrintable
(
trk
::
stringFromArray
(
in
)),
pos
);
if
(
pos
<
0
)
break
;
}
return
QPair
<
int
,
int
>
(
-
1
,
-
1
);
}
void
TcfTrkDevice
::
deviceReadyReadSerial
()
{
do
{
// Extract message (pos,len)
const
QPair
<
int
,
int
>
messagePos
=
findSerialHeader
(
d
->
m_readBuffer
);
if
(
messagePos
.
first
<
0
)
break
;
// Do we have the complete message?
const
int
messageEnd
=
messagePos
.
first
+
messagePos
.
second
;
if
(
messageEnd
>
d
->
m_readBuffer
.
size
())
break
;
const
QByteArray
message
=
d
->
m_readBuffer
.
mid
(
messagePos
.
first
,
messagePos
.
second
);
// Is thing a ping/pong response
if
(
debug
>
1
)
qDebug
(
"Serial message: at %d (%d bytes) of %d: %s"
,
messagePos
.
first
,
messagePos
.
second
,
d
->
m_readBuffer
.
size
(),
qPrintable
(
trk
::
stringFromArray
(
message
)));
if
(
message
.
startsWith
(
serialPongC
))
{
const
QString
version
=
QString
::
fromLatin1
(
message
.
mid
(
sizeof
(
serialPongC
)
-
1
));
emitLogMessage
(
QString
::
fromLatin1
(
"Serial connection from '%1'"
).
arg
(
version
));
emit
serialPong
(
version
);
// Answer with locator.
writeMessage
(
QByteArray
(
locatorAnswerC
,
sizeof
(
locatorAnswerC
)));
}
else
{
processMessage
(
message
);
}
d
->
m_readBuffer
.
remove
(
0
,
messageEnd
);
}
while
(
d
->
m_readBuffer
.
isEmpty
());
checkSendQueue
();
// Send off further messages
}
void
TcfTrkDevice
::
deviceReadyReadWLAN
()
{
// Take complete message off front of readbuffer.
do
{
const
int
messageEndPos
=
d
->
m_readBuffer
.
indexOf
(
d
->
m_messageTerminator
);
const
int
messageEndPos
=
d
->
m_readBuffer
.
indexOf
(
d
->
m_messageTerminator
);
if
(
messageEndPos
==
-
1
)
break
;
if
(
messageEndPos
==
0
)
{
// TCF TRK 4.0.5 emits empty messages on errors.
emitLogMessage
(
QString
::
fromLatin1
(
"An empty TCF TRK message has been received."
));
}
else
{
const
QByteArray
message
=
d
->
m_readBuffer
.
left
(
messageEndPos
);
if
(
debug
)
qDebug
(
"Read %d bytes:
\n
%s"
,
message
.
size
(),
qPrintable
(
formatData
(
message
)));
if
(
const
int
errorCode
=
parseMessage
(
message
))
{
emitLogMessage
(
QString
::
fromLatin1
(
"Parse error %1 : %2"
).
arg
(
errorCode
).
arg
(
debugMessage
(
message
)));
if
(
debug
)
qDebug
(
"Parse error %d for %d bytes:
\n
%s"
,
errorCode
,
message
.
size
(),
qPrintable
(
formatData
(
message
)));
}
processMessage
(
d
->
m_readBuffer
.
left
(
messageEndPos
));
}
d
->
m_readBuffer
.
remove
(
0
,
messageEndPos
+
d
->
m_messageTerminator
.
size
());
}
while
(
!
d
->
m_readBuffer
.
isEmpty
());
checkSendQueue
();
// Send off further message
checkSendQueue
();
// Send off further messages
}
void
TcfTrkDevice
::
processMessage
(
const
QByteArray
&
message
)
{
if
(
debug
)
qDebug
(
"Read %d bytes:
\n
%s"
,
message
.
size
(),
qPrintable
(
formatData
(
message
)));
if
(
const
int
errorCode
=
parseMessage
(
message
))
{
emitLogMessage
(
QString
::
fromLatin1
(
"Parse error %1 : %2"
).
arg
(
errorCode
).
arg
(
debugMessage
(
message
)));
if
(
debug
)
qDebug
(
"Parse error %d for %d bytes:
\n
%s"
,
errorCode
,
message
.
size
(),
qPrintable
(
formatData
(
message
)));
}
}
// Split \0-terminated message into tokens, skipping the initial type character
...
...
@@ -551,8 +684,6 @@ int TcfTrkDevice::parseTcfCommandReply(char type, const QVector<QByteArray> &tok
return
0
;
}
static
const
char
locatorAnswerC
[]
=
"E
\0
Locator
\0
Hello
\0
[
\"
Locator
\"
]"
;
int
TcfTrkDevice
::
parseTcfEvent
(
const
QVector
<
QByteArray
>
&
tokens
)
{
// Event: Ignore the periodical heartbeat event, answer 'Hello',
...
...
@@ -572,9 +703,10 @@ int TcfTrkDevice::parseTcfEvent(const QVector<QByteArray> &tokens)
// Parse known events, emit signals
QScopedPointer
<
TcfTrkEvent
>
knownEvent
(
TcfTrkEvent
::
parseEvent
(
service
,
tokens
.
at
(
1
),
values
));
if
(
!
knownEvent
.
isNull
())
{
// Answer hello event
.
// Answer hello event
(WLAN)
if
(
knownEvent
->
type
()
==
TcfTrkEvent
::
LocatorHello
)
writeMessage
(
QByteArray
(
locatorAnswerC
,
sizeof
(
locatorAnswerC
)));
if
(
!
d
->
m_serialFrame
)
writeMessage
(
QByteArray
(
locatorAnswerC
,
sizeof
(
locatorAnswerC
)));
emit
tcfEvent
(
*
knownEvent
);
}
emit
genericTcfEvent
(
service
,
tokens
.
at
(
1
),
values
);
...
...
@@ -600,6 +732,16 @@ unsigned TcfTrkDevice::verbose() const
return
d
->
m_verbose
;
}
bool
TcfTrkDevice
::
serialFrame
()
const
{
return
d
->
m_serialFrame
;
}
void
TcfTrkDevice
::
setSerialFrame
(
bool
s
)
{
d
->
m_serialFrame
=
s
;
}
void
TcfTrkDevice
::
setVerbose
(
unsigned
v
)
{
d
->
m_verbose
=
v
;
...
...
@@ -625,6 +767,17 @@ bool TcfTrkDevice::checkOpen()
return
true
;
}
void
TcfTrkDevice
::
sendSerialPing
()
{
if
(
!
checkOpen
())
return
;
setSerialFrame
(
true
);
writeMessage
(
QByteArray
(
serialPingC
,
qstrlen
(
serialPingC
)),
false
);
if
(
d
->
m_verbose
)
emitLogMessage
(
QLatin1String
(
"Ping..."
));
}
void
TcfTrkDevice
::
sendTcfTrkMessage
(
MessageType
mt
,
Services
service
,
const
char
*
command
,
const
char
*
commandParameters
,
// may contain '\0'
int
commandParametersLength
,
...
...
@@ -673,18 +826,29 @@ void TcfTrkDevice::sendTcfTrkMessage(MessageType mt, Services service, const cha
}
// Enclose in message frame and write.
void
TcfTrkDevice
::
writeMessage
(
QByteArray
data
)
void
TcfTrkDevice
::
writeMessage
(
QByteArray
data
,
bool
ensureTerminating0
)
{
if
(
!
checkOpen
())
return
;
if
(
d
->
m_serialFrame
&&
data
.
size
()
>
maxSerialMessageLength
)
{
qCritical
(
"Attempt to send large message (%d bytes) exceeding the "
"limit of %d bytes over serial channel. Skipping."
,
data
.
size
(),
maxSerialMessageLength
);
return
;
}
if
(
d
->
m_verbose
)
emitLogMessage
(
debugMessage
(
data
,
"TCF <-"
));
// Ensure \0-termination which easily gets lost in QByteArray CT.
if
(
!
data
.
endsWith
(
'\0'
))
if
(
ensureTerminating0
&&
!
data
.
endsWith
(
'\0'
))
data
.
append
(
'\0'
);
data
+=
d
->
m_messageTerminator
;
if
(
d
->
m_serialFrame
)
{
data
=
encodeUsbSerialMessage
(
data
);
}
else
{
data
+=
d
->
m_messageTerminator
;
}
if
(
debug
>
1
)
qDebug
(
"Writing:
\n
%s"
,
qPrintable
(
formatData
(
data
)));
...
...
src/shared/symbianutils/tcftrkdevice.h
View file @
d7ca39da
...
...
@@ -132,11 +132,20 @@ http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Services
* 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:
* Send serial ping from host sendSerialPing() -> receive pong response with
* version information -> Send Locator Hello Event -> Receive Locator Hello Event
* -> Commands are accepted.
* - WLAN communication initiation sequence:
* Receive Locator Hello Event from CODA -> Commands are accepted.
*/
class
SYMBIANUTILS_EXPORT
TcfTrkDevice
:
public
QObject
{
Q_PROPERTY
(
unsigned
verbose
READ
verbose
WRITE
setVerbose
)
Q_PROPERTY
(
bool
serialFrame
READ
serialFrame
WRITE
setSerialFrame
)
Q_OBJECT
public:
// Flags for FileSystem:open
...
...
@@ -163,6 +172,8 @@ public:
virtual
~
TcfTrkDevice
();
unsigned
verbose
()
const
;
bool
serialFrame
()
const
;
void
setSerialFrame
(
bool
);
// Mapping of register names to indices for multi-requests.
// Register names can be retrieved via 'Registers:getChildren' (requires
...
...
@@ -174,6 +185,9 @@ public:
IODevicePtr
takeDevice
();
void
setDevice
(
const
IODevicePtr
&
dp
);
// Serial Only: Initiate communication. Will emit serialPong() signal with version.
void
sendSerialPing
();
// Send with parameters from string (which may contain '\0').
void
sendTcfTrkMessage
(
MessageType
mt
,
Services
service
,
const
char
*
command
,
...
...
@@ -338,6 +352,7 @@ public:
signals:
void
genericTcfEvent
(
int
service
,
const
QByteArray
&
name
,
const
QVector
<
tcftrk
::
JsonValue
>
&
value
);
void
tcfEvent
(
const
tcftrk
::
TcfTrkEvent
&
knownEvent
);
void
serialPong
(
const
QString
&
codaVersion
);
void
logMessage
(
const
QString
&
);
void
error
(
const
QString
&
);
...
...
@@ -351,11 +366,15 @@ private slots:
void
slotDeviceReadyRead
();
private:
void
deviceReadyReadSerial
();
void
deviceReadyReadWLAN
();
bool
checkOpen
();
void
checkSendQueue
();
void
writeMessage
(
QByteArray
data
);
void
writeMessage
(
QByteArray
data
,
bool
ensureTerminating0
=
true
);
void
emitLogMessage
(
const
QString
&
);
int
parseMessage
(
const
QByteArray
&
);
inline
int
parseMessage
(
const
QByteArray
&
);
void
processMessage
(
const
QByteArray
&
message
);
int
parseTcfCommandReply
(
char
type
,
const
QVector
<
QByteArray
>
&
tokens
);
int
parseTcfEvent
(
const
QVector
<
QByteArray
>
&
tokens
);
// Send with parameters from string (which may contain '\0').
...
...
tests/tools/codaclient/codaclient.pro
View file @
d7ca39da
DEFINES
+=
SYMBIANUTILS_INCLUDE_PRI
include
(..
/../../
qtcreator
.
pri
)
include
(..
/../../
src
/
shared
/
symbianutils
/
symbianutils
.
pri
)
#
include
(..
/../../
src
/
libs
/
3
rdparty
/
qextserialport
/
qextserialport
.
pri
)
QT
+=
core
gui
network
TARGET
=
codaclient
...
...
tests/tools/codaclient/codaclientapplication.cpp
View file @
d7ca39da
...
...
@@ -29,6 +29,10 @@
#include "codaclientapplication.h"
#ifdef HAS_SERIALPORT
# include <qextserialport/qextserialport.h>
#endif
#include "tcftrkdevice.h"
#include <QtNetwork/QTcpSocket>
#include <QtCore/QFile>
...
...
@@ -255,31 +259,27 @@ bool CodaClientApplication::start()
switch
(
m_mode
)
{
case
Launch
:
{
const
QString
args
=
m_launchArgs
.
join
(
QString
(
QLatin1Char
(
' '
)));
std
::
printf
(
"Launching 0x%x '%s '%s'
on %s:%hu
(debug: %d)
\n
"
,
std
::
printf
(
"Launching 0x%x '%s '%s' (debug: %d)
\n
"
,
m_launchUID
,
qPrintable
(
m_launchBinary
),
qPrintable
(
args
),
qPrintable
(
m_address
),
m_port
,
m_launchDebug
);
qPrintable
(
args
),
m_launchDebug
);
}
break
;
case
Install
:
std
::
printf
(
"Installing '%s' to '%s' on %s:%hu
\n
"
,
qPrintable
(
m_installSisFile
),
qPrintable
(
m_installTargetDrive
),
qPrintable
(
m_address
),
m_port
);
std
::
printf
(
"Installing '%s' to '%s'
\n
"
,
qPrintable
(
m_installSisFile
),
qPrintable
(
m_installTargetDrive
));
break
;
case
Put
:
std
::
printf
(
"Copying '%s' to '%s'
on %s:%hu
in chunks of %lluKB
\n
"
,
std
::
printf
(
"Copying '%s' to '%s' in chunks of %lluKB
\n
"
,
qPrintable
(
m_putLocalFile
),
qPrintable
(
m_putRemoteFile
),
qPrintable
(
m_address
),
m_port
,
m_putChunkSize
/
1024
);
m_putChunkSize
/
1024
);
break
;
case
Stat
:
std
::
printf
(
"Retrieving attributes of '%s' from %s:%hu
\n
"
,
qPrintable
(
m_statRemoteFile
),
qPrintable
(
m_address
),
m_port
);
std
::
printf
(
"Retrieving attributes of '%s'
\n
"
,
qPrintable
(
m_statRemoteFile
));
break
;
case
Invalid
:
break
;
}
// Start connection
const
QSharedPointer
<
QTcpSocket
>
tcfTrkSocket
(
new
QTcpSocket
);
m_trkDevice
.
reset
(
new
tcftrk
::
TcfTrkDevice
);
m_trkDevice
->
setVerbose
(
m_verbose
);
connect
(
m_trkDevice
.
data
(),
SIGNAL
(
error
(
QString
)),
...
...
@@ -288,9 +288,48 @@ bool CodaClientApplication::start()
this
,
SLOT
(
slotTrkLogMessage
(
QString
)));
connect
(
m_trkDevice
.
data
(),
SIGNAL
(
tcfEvent
(
tcftrk
::
TcfTrkEvent
)),
this
,
SLOT
(
slotTcftrkEvent
(
tcftrk
::
TcfTrkEvent
)));
m_trkDevice
->
setDevice
(
tcfTrkSocket
);
tcfTrkSocket
->
connectToHost
(
m_address
,
m_port
);
std
::
printf
(
"Connecting...
\n
"
);
if
(
m_address
.
startsWith
(
QLatin1String
(
"/dev"
))
||
m_address
.
startsWith
(
QLatin1String
(
"com"
),
Qt
::
CaseInsensitive
)
||
m_address
.
startsWith
(
QLatin1Char
(
'\\'
)))
{
#ifdef HAS_SERIALPORT
// Serial
#ifdef Q_OS_WIN
const
QString
fullPort
=
QextSerialPort
::
fullPortNameWin
(
m_address
);
#else
const
QString
fullPort
=
m_address
;
#endif
const
QSharedPointer
<
QextSerialPort
>
serialPort
(
new
QextSerialPort
(
fullPort
,
QextSerialPort
::
EventDriven
));
std
::
printf
(
"Opening port %s...
\n
"
,
qPrintable
(
fullPort
));
// Magic USB serial parameters
serialPort
->
setTimeout
(
2000
);
serialPort
->
setBaudRate
(
BAUD115200
);
serialPort
->
setFlowControl
(
FLOW_OFF
);
serialPort
->
setParity
(
PAR_NONE
);
serialPort
->
setDataBits
(
DATA_8
);
serialPort
->
setStopBits
(
STOP_1
);
m_trkDevice
->
setSerialFrame
(
true
);
m_trkDevice
->
setDevice
(
serialPort
);
// Grab all data from start
if
(
!
serialPort
->
open
(
QIODevice
::
ReadWrite
|
QIODevice
::
Unbuffered
))
{
std
::
fprintf
(
stderr
,
"Cannot open port: %s"
,
qPrintable
(
serialPort
->
errorString
()));
return
false
;
}
// Initiate communication
m_trkDevice
->
sendSerialPing
();
serialPort
->
flush
();
#else
std
::
fprintf
(
stderr
,
"Not implemented
\n
"
);
return
false
;
#endif
}
else
{
// TCP/IP
const
QSharedPointer
<
QTcpSocket
>
tcfTrkSocket
(
new
QTcpSocket
);
m_trkDevice
->
setDevice
(
tcfTrkSocket
);
tcfTrkSocket
->
connectToHost
(
m_address
,
m_port
);
std
::
printf
(
"Connecting to %s:%hu...
\n
"
,
qPrintable
(
m_address
),
m_port
);
}
return
true
;
}
...
...
@@ -399,8 +438,7 @@ void CodaClientApplication::handleFileSystemFStat(const tcftrk::TcfTrkCommandRes
}
else
{
std
::
fprintf
(
stderr
,
"FStat failed: %s
\n
"
,
qPrintable
(
result
.
toString
()));
}
m_trkDevice
->
sendFileSystemCloseCommand
(
tcftrk
::
TcfTrkCallback
(
this
,
&
CodaClientApplication
::
handleFileSystemClose
),
m_remoteFileHandle
);
closeRemoteFile
();
}
void
CodaClientApplication
::
handleFileSystemClose
(
const
tcftrk
::
TcfTrkCommandResult
&
result
)
...
...
@@ -490,12 +528,14 @@ void CodaClientApplication::doExit(int ex)
if
(
!
m_trkDevice
.
isNull
())
{
const
QSharedPointer
<
QIODevice
>
dev
=
m_trkDevice
->
device
();
if
(
QAbstractSocket
*
socket
=
qobject_cast
<
QAbstractSocket
*>
(
dev
.
data
()))
{
if
(
socket
->
state
()
==
QAbstractSocket
::
ConnectedState
)
socket
->
disconnectFromHost
();
}
else
{
if
(
dev
->
isOpen
())
dev
->
close
();
if
(
!
dev
.
isNull
())
{
if
(
QAbstractSocket
*
socket
=
qobject_cast
<
QAbstractSocket
*>
(
dev
.
data
()))
{
if
(
socket
->
state
()
==
QAbstractSocket
::
ConnectedState
)
socket
->
disconnectFromHost
();
}
else
{
if
(
dev
->
isOpen
())
dev
->
close
();
}
}
}
std
::
printf
(
"Exiting (%d)
\n
"
,
ex
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment