Open Stream Deck

Протокол OSD1

USB HID-отчёты, команды рисования, поток между отчётами, Feature report и статус устройства.

Протокол OSD1 версии 1 связывает приложение с прошивкой. Хост отправляет поток команд, устройство отвечает нажатиями и статусом.

USB HID

ПараметрЗначение
VID:PID1209:0001
bcdDevice0200
ManufacturerOpen Stream Deck
ProductOSD AKP153R
SerialOSD153R00001
InputReport ID 1, 19 байт
OutputReport ID 2, 1024 байта
FeatureReport ID 3 и 0x7E, по 32 байта
Endpoint IN0x82
Endpoint OUT0x01

Размер отчёта включает байт Report ID. Размер USB-пакета 64 байта в Full Speed и 512 байт в High Speed. Один HID-отчёт может передаваться несколькими пакетами.

Output report

СмещениеРазмерЗначение
012
12Длина полезных данных, little endian
3до 1021Поток команд

Бит 15 поля длины означает SYNC. Парсер сбрасывает предыдущую незавершённую команду и начинает новую с первого байта полезных данных. Сам бит в значение длины не входит.

Полезные данные нескольких отчётов образуют непрерывный поток. Команда, аргументы и пиксели могут пересекать границы отчётов. Все многобайтные числа передаются в порядке little endian.

Команды

OpcodeКомандаАргументы
00NOPНет
01CANVASaddress:u32
02BLITx:u16 y:u16 width:u16 height:u16, затем width × height × 2 байт RGB565
03FILLx:u16 y:u16 width:u16 height:u16 color:u16
04LINEx0:u16 y0:u16 x1:u16 y1:u16 color:u16
05CIRCLEx:u16 y:u16 radius:u16 color:u16 fill:u8
06FRAMEx:u16 y:u16 width:u16 height:u16 color:u16
07COPYsource:u32 sx:u16 sy:u16 destination:u32 dx:u16 dy:u16 width:u16 height:u16
08BRIGHTpercent:u8, значение ограничивается диапазоном 0..100
09FENCEid:u32
0ABOOTmagic:8 равно ASCII OSDBOOT!, переход в загрузчик

Canvas 0 соответствует экрану. Координаты нативные, ширина canvas 480 пикселей. BLIT принимает построчный RGB565. FRAME рисует контур толщиной один пиксель. COPY копирует область между canvas через BTE.

Очередь и поток

Очередь содержит 24 слота, из которых доступно 23. Основной цикл обрабатывает до четырёх отчётов за проход. Если пиксельный поток не продвигается дольше 1000 мс, парсер сбрасывается.

FENCE возвращает идентификатор последней обработанной команды во входном отчёте. Для нового изображения хост передаёт полную последовательность команд и не полагается на восстановление оборванного потока.

Input report

СмещениеРазмерЗначение
011
12Битовая карта 15 клавиш
31Счётчик изменений клавиш по модулю 256
44Идентификатор последнего FENCE
81Бит 0: была ошибка протокола с момента запуска
9..1810Нули

Отчёт отправляется при изменении состояния клавиш, при FENCE и после новой USB-конфигурации. Бит 0 соответствует верхней левой кнопке, бит 14 нижней правой.

Feature report 3

СмещениеЗначение
0Report ID 3
1..4ASCII OSD1
5Версия протокола
6..8Major, minor и patch прошивки
9..10Ширина панели, u16
11..12Высота панели, u16
1316
14Число клавиш, 15
1516
16Число слотов очереди, 24
17Возможности: бит 0 отвечает за команду BOOT
18..31Нули

Feature report 0x7E

СмещениеЗначение
0Report ID 0x7E
1..4ASCII OSDD
5Стадия инициализации дисплея
6Код ошибки дисплея
7Флаги: бит 0 клавиши готовы, бит 1 дисплей готов, бит 2 High Speed, бит 3 пиксельный поток активен
8Занятые слоты очереди
9Максимальная заполненность очереди
10..11Необработанная битовая карта клавиш
12..15Число отчётов
16..19Число команд
20..23Число ошибок протокола
24Opcode последней ошибки
25Причина последней ошибки
26Стадия запуска приложения
28..31Время работы в миллисекундах

Заставка

После включения прошивка показывает анимацию из буфера SDRAM по адресу 0x600000. Canvas 0 при этом продолжает принимать команды хоста, и хост рисует первый кадр как обычно, не дожидаясь окончания анимации.

  1. Ячейки 6 × 3 (пять столбцов клавиш и три секции боковой полосы) заливаются цветом #222222 по змейке: верхний ряд слева направо, средний справа налево, нижний слева направо.
  2. Шрифтом Inter SemiBold побуквенно проявляются надписи OPEN (ячейки с 1 по 4), STREAM (ячейки с 7 по 12) и DECK (ячейки с 13 по 16). Ячейки нумеруются слева направо и сверху вниз.
  3. Первое рисование хоста в canvas 0 считается готовностью. После проявления и паузы 150 мс ячейки раскрываются из центра, показывая содержимое canvas 0 поверх надписи.
  4. Отображение переключается на canvas 0, и буфер 0x600000 больше не используется.

Пока идёт анимация, парсер на каждом кадре (каждые 15 мс) останавливается на ближайшей границе команды. Текущий BLIT дописывается до конца, следующая команда ждёт. Поток хоста при этом не теряется.

Без хоста заставка остаётся на экране. Новое нажатие кнопки запускает игру.