Поддержка MacOS (проверено в Tahoe)

This commit is contained in:
2026-09-06 17:13:34 +08:00
parent 57c4e80f0d
commit 4515b39090
24 changed files with 590 additions and 65 deletions
+26 -2
View File
@@ -18,6 +18,30 @@ Feature-репорты через hidraw ioctl (`HIDIOCSFEATURE`/`HIDIOCGFEATURE
**usbhid не отцепляется** — печать никогда не прерывается.
pyusb-вариант НЕ использовать (отцеплял драйвер).
### macOS (экспериментально, класс `KatanaMacOS`)
Тот же протокол поверх IOKit напрямую (ctypes, без сторонних библиотек):
`IOHIDDeviceSetReport` / `IOHIDDeviceGetReport` с `kIOHIDReportTypeFeature` —
семантика 1:1 с hidraw, feature-репорты rid=0, 64 байта данных.
Устройство ищется через `IOServiceGetMatchingServices("IOHIDDevice")` + `IOHIDDeviceGetProperty`:
выбирается клавиатура 0C45:8006 с PrimaryUsagePage=1, PrimaryUsage=6 (boot keyboard = интерфейс 0).
Выбор транспорта автоматический по `sys.platform` (`open_katana()`): darwin → IOKit, остальное → hidraw.
Грабли macOS (все проверены на железе):
- у IOKit своя нумерация типов репортов: Input=0, Output=1, **Feature=2**;
с Output прошивка отвечает мусором (1 байт `04`);
- `IOServiceMatching` возвращает CFDictionaryRef — без явного `restype = c_void_p`
ctypes обрезает указатель и процесс падает segfault'ом;
- `IOHIDDeviceGetProperty` принимает IOHIDDeviceRef (от `IOHIDDeviceCreate`),
а не registry entry — с entry процесс падает segfault'ом;
плоских `idVendor` в свойствах реестра нет — только через GetProperty;
- доступ к HID-клавиатурам выдаётся вручную: Системные настройки → Конфиденциальность и безопасность → «Input Monitoring» для приложения-терминала, затем перезапуск терминала;
- Karabiner-Elements (и подобные утилиты) захватывает клавиатуры монопольно — пока он работает, `IOHIDDeviceOpen` возвращает `kIOReturnExclusiveAccess` (0xE00002C5); проверено диагностикой `misc/iokit_probe.py`;
- `reset` (pyusb) на macOS работает (проверено: USB port reset проходит);
- udev-правило не нужно.
Проверка на железе (macOS, Karabiner выключен): mode/paint/keys/remap/macro/reset — работают.
## Общая транзакция (все команды)
```
@@ -65,7 +89,7 @@ CLI: `--rainbow`, `--direction north-south|south-north|east-west|west-east`.
- Яркость масштабирует per-key цвета: 15/15 → `ee` (238), 1/15 → `0f`.
- Режим 0x80 отображает таблицу per-key (см. ниже) — это и есть «кастом».
### Таблица режимов (описания вендорской утилиты, docs/COLOR-MODES.md)
### Таблица режимов (описания вендорской утилиты, docs/color-modes.md)
Номер = байт [0] payload.
«моно/спектр» — режим рисует одиночный цвет или полный спектр независимо от него.
@@ -535,7 +559,7 @@ ACTION: мышь (`lmb`/`mouse1`, `rmb`/`mouse2`, `mmb`/`mouse3`, `back`/`mouseb
Шорткаты редактора (тип `02`) тоже сняты и реализованы (дамп keybind-editor).
Горячие клавиши (тип `02`, маска модификаторов в байте [1]) сняты по дампу keybind-hotkeys и реализованы (`HOTKEY_KEYS`/`HOTKEY_MODIFIERS`, `remap --key KEY=MOD+KEY`).
Осталось: другие типы действий (Fn-слой) и чтение таблицы.
5. ~~Демо-скрипты (радуга, волна) поверх per-key API + живое чтение f5~~ — ЗАВЕРШЕНО, методика описана и проверена ([EXTENDING.md](EXTENDING.md)): таблица обновляется живьём в режиме 0x80, ~1 кадр/с.
5. ~~Демо-скрипты (радуга, волна) поверх per-key API + живое чтение f5~~ — ЗАВЕРШЕНО, методика описана и проверена ([extending.md](extending.md)): таблица обновляется живьём в режиме 0x80, ~1 кадр/с.
6. ~~Макросы: запись содержимого и привязка~~ — ЗАВЕРШЕНО (канал 04 19 + записи `[06, ...]` в 04 11, команда `macro`, см. «Макросы»).
Осталось: чтение содержимого, коллизия кодов 05/06, стрелки Up/Down, остальные медиа-коды.