How to interface with a Stream Deck device.
The device uses the HID protocol to communicate with its software.
The number of keys can be determined from the HID device descriptors. There is currently no known provision to determine their layout or size. The buttons on the current version of the device (1.0) are arranged in a grid and numbered from top right through to bottom left as follows:
------------------------
| 05 | 04 | 03 | 02 | 01 |
|----|----|----|----|----|
| 10 | 09 | 08 | 07 | 06 |
|----|----|----|----|----|
| 15 | 14 | 13 | 12 | 11 |
------------------------
Note: the Stream Deck Mini was recently announced, with six buttons. I'll incorporate information about this device as and when I am able.
0B 63 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00
The brightness on the device is controlled with PWM. This results in a non-linear correlation between set percentage and perceived brightness, and lower values have the most effect.
PC = PERCENTAGE (0-100)
05 55 aa d1 01 PC 00 00 00 00 00 00 00 00 00 00
00
Images are 72x72 pixels (5184 pixels total) arranged in a BGR format with 3 bytes per pixel (15552 bytes total).
Images are sent to the device in two packets, the first containing 2583 pixels (7749 bytes) and the second containing the remaining 2601 pixels (7803 bytes). Each packet is a total of 8191 bytes.
Each packet comprises a header and a chunk of image data. The header contains:
- The index of the key being set (zero based)
- The packet sequence number (one-based)
- The previous packet's sequence number (zero if there is no previous packet).
The first packet also contains some extra information that the second does not, the purpose of which is currently unknown.
Including headers, each image packet is exactly 8191 bytes, padded with zeros where appropriate. This leaves up to 8121 bytes available for image data in the first packet and 8175 bytes in the second, but for some reason the official software only sends a maximum of 7749 in the first packet and whatever is left in the second.
I'm assuming that either the device assumes the first packet will contain this amount of data, or that one of the values in the header specifies how long it will be. Experimentation needed.
SE = PACKET SEQUENCE NUMBER
PR = PREVOUS PACKET SEQUENCE NUMBER
KI = KEY INDEX
02 01 SE 00 PR KI 00 00 00 00 00 00 00 00 00 00
Includes 54 bytes of "extra" information.
.. HEADER
42 4d f6 3c 00 00 00 00 00 00 36 00 00 00 28 00
00 00 48 00 00 00 48 00 00 00 01 00 18 00 00 00
00 00 c0 3c 00 00 13 0e 00 00 13 0e 00 00 00 00
00 00 00 00 00 00
.. 7749 BYTES OF IMAGE
.. ZERO PADDING UP TO 8191 BYTES
.. HEADER
.. REMAINING BYTES OF IMAGE
.. ZERO PADDING UP TO 8191 BYTES
BYTE 6 ONWARDS CONTAINS SERIAL
03 55 aa d3 03 41 4c 31 32 48 31 41 30 37 38 31
36
BYTE 6 ONWARDS CONTAINS STRING VERSION
04 55 aa d4 04 31 2e 30 2e 31 37 30 31 33 33 00
00
When any keys are pressed or released, the device sends an interrupt containing a bit map of the all the current key states. Presumably this means that multiple buttons can be pressed at once, though I haven't yet tested this.
01 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00
00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00
Communication between the device and host can be snooped using Wireshark. Please read this page for information on seting up USB capture.
When snooping USB you'll find that there's a lot of chatter from your hubs and other devices, and
you'll need to filter it all out to isolate the StreamDeck. To do this, begin by filtering for
usb.idVendor == 0x0fd9 && usb.idProduct == 0x0060
, which will give you information about the
device. Then simply filter "USB device index" to show the relevant packets for your device.
There are some findings i would like to share ..
#1, there is a V1 and V2 of the original Streamdeck. They do not use the same protocol
#2, i received 'V1' style hardware but it has V2 electronics .. so it will need to speak the V2 protocol.
---> easy to detect. if you check the USB capabilities (lsusb -v on linux) the V1 uses 8191 Bytes transfer size out, the V2 uses 1024 Bytes
#3, this 54 bytes 'extra header' is actually well understandable. it is the BMP header of a BMP button file (described for example on wikipedia).
#4, with V2 devices, and the changed protocol, the device will still accept BMP icons but also jpeg icons
#5, i think the number of buttons is returned in the button event message in byte 3 (contains 15 for the original, to be seen on other devices)
I have implemented basic interfacing in lua, using /dev/hidraw0, no special libraries needed for that (but there is no way to send feature reports that way at least not that i am aware of).