OK, I believe figured out how the TCP bits work.
All "TCP" and "UDP" below are Logitech's funky "HID-UDP" and "HID-TCP" as
per my previous email. NOT the network protocols.
I've updated consnoop to print out the UDP packets contained within the TCP
packets. As an example, they look like this:
LEN: 07, FLAGS: SYN ACK, SEQ: 28, ACK: F1
Start Update: 00 04
That "Start Update" is the UDP packet inside the TCP packet.
One thing to know know... the remote sends tons and tons of duplicate
packets... the desktop software sends the occasional dupe, but rarely. Since
I count an ACK for each dupe, I'm not sure full transactional retrans are
really needed.
OK, here's my analysis of the traces (starting in UDP mode).
We send:
Initiate Update TCP Channel
And they respond (again in UDP):
Initiate Update TCP Channel Response 01
Easy enough. Once we receive that response, we're in TCP mode. Now we see
some of these:
LEN: 03, FLAGS: SYN, SEQ: F0, ACK: FF
LEN: 03, FLAGS: SYN, SEQ: F0, ACK: FF
...
The remote will spam us with SYN packets, until we send our first command:
LEN: 07, FLAGS: SYN ACK, SEQ: 28, ACK: F1
Start Update: 00 04 00
Note that our first command must:
* have SYN and ACK set
* Sets the ACK to SEQ+1 even though this violates their usual SEQ/ACK policy
* Can have a random SEQ
* Must embed the UDP command
In this case we're starting an update. The SW resends this 3 times until
it's acked by the remote:
LEN: 06, FLAGS: ACK, SEQ: F1, ACK: 2D
Start Update Response
Note here that the SEQ formula is the standard I described yesterday:
SEQ = ACK
But ACK is off by 1. It should be:
ACK = SEQ + num data bytes
But that would be 28+4 = 2C, but it's 2D. I don't know why.
Anyway, then we send our next command:
LEN: 0A, FLAGS: ACK, SEQ: 2D, ACK: F4
Write Update Header: 65 26 0A 00 04 00
Our SEQ is their ACK, our ACK their SEQ +(7-4=3)=F1+3 = F4
Great. OK, they ack that:
LEN: 06, FLAGS: ACK, SEQ: F4, ACK: 34
Write Update Header Response
Then we start with our next command. This is the first one that spans packets:
LEN: 3F, FLAGS: ACK, SEQ: 34, ACK: F7
Write Update Data: 54 50 54 50 61 26 0D 00 00 17 00 00 8C AE 07 00
93 AE 07 00 2B AF 07 00 4A AF 07 00 C6 B0 07 00 D4 B0 07 00 88 B6 07 00 F5
B6 07 00 14 B7 07 00 35 B7 07 00 8E 96 08 00 1F A1 CD
They ACK it, surprisingly with another Start Update Respnse:
LEN: 06, FLAGS: ACK, SEQ: F7, ACK: 70
Start Update Response
They ACK 3F+1-4 = 0x70 - all the bytes. Good.
We send more:
LEN: 3F, FLAGS: ACK, SEQ: 70, ACK: FA
Write Update Data: 08 00 39 A7 08 00 D6 B7 08 00 D8 B7 08 00 52 B8
08 00 89 B8 08 00 99 BC 08 00 22 BD 08 00 62 BD 08 00 63 BD 08 00 00 00 00
00 00 00 00 57 4C 57 4C 39 88 00 01 75 8B 00 01 75 CD
And they ACK it, only at the TCP level:
LEN: 03, FLAGS: ACK, SEQ: FA, ACK: AC
and this repeats until we've sent all the data, our last packet is obviously
smaller:
LEN: 32, FLAGS: ACK, SEQ: 04, ACK: FA
Write Update Data: 01 2A FF FF 82 80 0F FF FF FF FF FF FF FF FF FF
FF FF FF F
F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 82 00 5E 8C 44 4B 44 4B 27
and their ack:
LEN: 03, FLAGS: ACK, SEQ: FA, ACK: 33
Then we go, hey, we're done:
LEN: 05, FLAGS: ACK, SEQ: 33, ACK: FA
Write Update Data Done: F1
And the remote responds:
LEN: 06, FLAGS: ACK, SEQ: FA, ACK: 35
Write Update Data Done Response
Again, following the SEQ/ACK semantics.
Interestingly, we then ack that:
LEN: 03, FLAGS: ACK, SEQ: 35, ACK: FD
Which they ack:
LEN: 03, FLAGS: ACK, SEQ: FD, ACK: 35
Which seems superflous given we then send a command with the same sequence
number:
LEN: 08, FLAGS: ACK, SEQ: 35, ACK: FD
Get Update Checksum: FF FF 04 00
It responds:
LEN: 08, FLAGS: ACK, SEQ: FD, ACK: 3A
Get Update Checksum Response: 01 0C 6E 00
We send our next command:
LEN: 07, FLAGS: ACK, SEQ: 3A, ACK: 02
Write Finish Update: 01 04 00
It acks:
LEN: 03, FLAGS: ACK, SEQ: 02, ACK: 3E
We ack:
LEN: 03, FLAGS: ACK, SEQ: 3E, ACK: 02
We then re-use this again, for our next command:
LEN: 06, FLAGS: ACK, SEQ: 02, ACK: 3E
Finish Update Response
It knows that's the end of the first part UDP command we got and thus will
close the TCP session (I'm guessing), and sends a FIN+ACK:
LEN: 03, FLAGS: FIN ACK, SEQ: 3E, ACK: 05
We ack that:
LEN: 03, FLAGS: ACK, SEQ: 3F, ACK: 06
It acks the ack:
LEN: 03, FLAGS: ACK, SEQ: 06, ACK: 3F
And we're out of the TCP session.
We then send a normal UDP packet (consnoop doesn't know how to parse this
since it still thinks it's in TCP mode, so this is manual parsing):
COMMAND_UPDATE_TIME
and it responds with:
COMMAND_UPDATE_TIME_RESPONSE
And that's the end of the trace.
--
Phil Dibowitz p...@ipom.com
Open Source software and tech docsInsanity Palace of Metallica
http://www.phildev.net/ http://www.ipom.com/
"Be who you are and say what you feel, because thos