unusual-thoughts / etincelle

Client / Server for Devialet Phantom / Spark protocol
6 stars 3 forks source link

Devialet Spark Protocol reverse engineering

Initial discovery using UDP beacon on port 24242 (Discovery.dll)

Request:

00000000: 4456 4c01 5748 4f3f                      DVL.WHO?

Response:

                                     serial length
                                     ┌┐ 
00000000: 4456 4c01 4845 5245 0000 00## **** ****  DVL.HERE...#**** 
00000010: **** **** **** **** **        └────────  *********
          ─────────────────────┘          serial

Then Spark establishes first TCP connection (including service WhatsUp.Registry), also on port 24242

On exit:

00000000: 4456 4c01 4259 4521 0000 00## **** ****  DVL.BYE!...#****
00000010: **** **** **** **** **                   *********

Protobuf encapsulation format for RPC requests/responses:

C2 01 00 00 00 00
<always empty>
C2 01 00 00 00 <length>
<Devialet.CallMeMaybe.Request or Devialet.CallMeMaybe.Reponse>
...                     ┐ Usually these are absent, as there is only one
C2 01 00 00 00 <length> │ protobuf for requests or responses. But a special 
<nth protobuf>          │ RPC that lists all properties uses them
...                     ┘ 
C2 00 00 00 00 <length> (note second byte == 0)
<last protobuf>

protobuf encapsulation format for RPC events:

C3 01 00 00 00 00
<always empty>
C3 01 00 00 00 10 (length of 16 byte UID)                    ┐
<16 byte UID> (same as Devialet.CallMeMaybe.Event.serverId)  │ extra UID field
C3 01 00 00 00 00                                            │
<always empty>                                               ┘
C3 01 00 00 00 <length>
<Devialet.CallMeMaybe.Event>
C3 00 00 00 00 <length> (note second byte == 0)
<payload protobuf>

The first RPC is Devialet.CallMeMaybe.Connection.openConnection() that returns the services on this endpoint (== port)

Devialet.WhatsUp.Registry keeps an updated list of endpoints and their services, that can be used to discover new services, and is present on the initial endpoint on port 24242.

MP3 uploading and playback done via HTTP using service PickUpThePieces

Apparently (see disassembly of CmmClient.dll), messages use RFC4122 UUIDS (https://en.wikipedia.org/wiki/Universally_unique_identifier)

requestIds are RCF4122 version 4 apparently. the 3 msb bits of byte 8 are 101 or 100 (http://doc.qt.io/qt-4.8/quuid.html#variant-field). the 4 msb bits of byte 6 are 0100 -> random

List of services