Update README with features, flash space, and simulator fixes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-05 06:03:57 +00:00
parent 5786ab888b
commit 019e48a1cc
+84
View File
@@ -1,6 +1,90 @@
# ku1255cfw
Custom open firmware for the Lenovo KU-1255 compact USB keyboard
## Overview
The Lenovo ThinkPad Compact USB Keyboard with TrackPoint (KU-1255) uses a
Sonix SN8F2288FG 8-bit MCU with 12K words (24KB) flash and 512 bytes RAM.
The TrackPoint is connected via bit-banged I2C (P2.4 SCL, P2.5 SDA, address
0x2A, Synaptics proprietary protocol).
This firmware is a from-scratch rewrite based on the original by
[ranma](https://github.com/ranma/ku1255cfw), adding standalone middle-button
scroll and other missing features so the keyboard works fully without an
external converter.
## Features added over base firmware
### Middle-button scroll
3-state state machine (IDLE / UNDECIDED / SCROLLING) with 150ms timeout:
- **Short press** (<150ms): sends a normal middle click (deferred on release)
- **Hold + TrackPoint movement**: converts XY deltas to scroll wheel events
- **FN + middle button**: passes middle button through directly (no scroll logic)
### CapsLock LED feedback
Host LED output reports (SET_REPORT) are parsed and CapsLock state (bit 1) drives
the power LED on P5.3/PWM0 (active-low). The flasher magic byte sequence detection
is preserved.
### FN+F7 through FN+F12
| Key | Normal | With FN held |
|-----|--------|-------------|
| F7 | F7 | LGUI+P (display settings) |
| F8 | F8 | F8 (passthrough) |
| F9 | F9 | LGUI+I (settings) |
| F10 | F10 | LGUI (search) |
| F11 | F11 | LCTRL+LALT+TAB (task switch) |
| F12 | F12 | F12 (passthrough) |
### USB compliance fixes
- **HID GET_REPORT**: returns proper per-interface empty reports (8B keyboard / 5B mouse)
instead of stale buffer contents. Some OSes query this on resume from suspend.
- **SET/CLEAR FEATURE**: tracks DEVICE_REMOTE_WAKEUP state instead of just ACKing.
## Flash space
| Firmware | Words used | Free | Utilization |
|----------|-----------|------|-------------|
| OEM | 10,226 / 10,239 | 13 | 99.9% |
| This | 10,238 / 10,239 | 1 | 100.0% |
Key debouncing is not implemented (and not needed) — the 8ms scan cycle naturally
debounces scissor switches (<1ms bounce time). The OEM firmware also does not debounce.
## Flashing
Requires [vpelletier/dissn8](https://github.com/vpelletier/dissn8) tools.
1. Build: `asn8 main.s -o ku1255cfw.bin`
2. Enter bootloader: hold **Return** while plugging in the keyboard
3. Flash: `flashsn8 ku1255cfw.bin`
## Simulator testing
`test_scroll.py` runs 23 automated tests against the
[dissn8 simulator](https://github.com/vpelletier/dissn8) via the `ku1255_sim.py`
harness. Tests cover all scroll state transitions, deferred click timing, FN modifier
interaction, and edge cases (rapid clicks, timeout behavior).
**Note:** The simulator requires a fix for PnUR register read handlers (see below).
## Simulator fixes (for vpelletier/dissn8)
Running this firmware in the dissn8 simulator exposed three bugs:
1. **PnUR read handlers crash**`_volatile_dict` maps P0UR-P5UR read handlers to
`None`. B0BSET/B0BCLR (read-modify-write) on these registers causes
`TypeError: 'NoneType' object is not callable`. Fixed by adding `readPullUp()`
returning the latch value. Branch: `pnur_readpullup` (PR pending upstream).
2. **Hardcoded HID descriptor sizes**`ku1255_sim.py` assumed 0x51/0xD3 byte
HID report descriptors (OEM sizes). This firmware uses 91/61 bytes. Fixed by
parsing sizes dynamically from the config descriptor.
3. **Wrong HID descriptor recipient** — HID report descriptor requests must use
interface recipient (0x81), not device (0x80), per USB spec. The OEM firmware
happened to accept both.
## Dev setup
- [OpenViszla](https://github.com/openvizsla/ov_ftdi) USB protocol analyzer
- 5V-tolerant PL2303 UART interface (e.g. https://www.adafruit.com/product/954)