Files
ku1255cfw/README.md
T
2026-04-05 06:03:57 +00:00

3.8 KiB

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, 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 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 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 sizesku1255_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

PCB photo