Files
tactility/.claude/skills/tactility-bluetooth/references/mouse-report-parsing.md
T
Adolfo Reyna 12035f2f39 chore: move firmware skills in-repo + AGENTS.md
- Migrates tactility-firmware and tactility-bluetooth from
  ~/.hermes/skills/ into .claude/skills/ for repo co-location
- Adds AGENTS.md with local workstation context, board table,
  board-direct build rule, Hermes PYTHONPATH pitfall, common
  Tactility pitfalls, and in-repo skill index

Refs: personal Gitea mirror
2026-07-17 09:51:08 -04:00

2.1 KiB

Mouse Report Parsing for Combo KB+Touchpad

Context

Session 2026-07-12, user device Fosmon Mini BT Keyboard + Touchpad (Amazon B00BX0YKX4, short link https://a.co/d/0fg4vprm). Field fix for Tactility HID Host.

Typical Reports

  • Keyboard: 8 bytes boot [mod, 0x00, key0..key5] optionally prefixed with Report ID 1 → 9 bytes [0x01, mod, 0, k0..k5]
  • Mouse/touchpad: 3-5 bytes [buttons, x_rel, y_rel, wheel, pan] optionally [ID, ...]
    • Fosmon: likely [btn, x, y, wheel] 4 bytes, Report ID 2 → notify [0x02, btn, x, y] or [btn, x, y, wheel]
  • Logitech high-res: 5 bytes packed 12-bit [btn, ?, x_low, x_hi_nibble|y_low_nibble, y_high]

Old Code Failure

if (len >=5) {
  raw_x = data[2] | ((data[3] & 0x0F)<<8); // treats wheel as nibble
  ...
}

For standard packet [0x01 btn, 0x05 dx, 0xFE dy (-2), 0x00 wheel, 0x00] → raw_x = 0xFE | (0x00<<8)=254 → sign-extend → large jump.

Fixed Code Snippet

static void hidHostHandleMouseReportInternal(const uint8_t* data, uint16_t len, uint8_t expected_report_id) {
  const uint8_t *p=data; uint16_t plen=len;
  if (expected_report_id!=0 && len>=2 && data[0]==expected_report_id) { p=data+1; plen=len-1; }
  if (plen<3) return;
  if (plen>=5) {
    int8_t std_dx=(int8_t)p[1], std_dy=(int8_t)p[2];
    int16_t raw_x12 = p[2] | ((p[3]&0x0F)<<8); if (raw_x12&0x0800) raw_x12|=0xF000;
    int16_t raw_y12 = (int16_t)((p[3]>>4)|(p[4]<<4)); if (raw_y12&0x0800) raw_y12|=0xF000;
    bool std_small = abs(std_dx)<=48 && abs(std_dy)<=48;
    bool s12_large = abs(raw_x12)>128 || abs(raw_y12)>128;
    // heuristic: small std + large 12 → std (touchpad)
    // large std pathological + plausible 12 <=300 → 12-bit (Logitech)
  } else { btn=p[0]&1; dx=(int8_t)p[1]; dy=(int8_t)p[2]; }
}

Keyboard ID Strip

Same pattern for keyboardInternal.

NOTIFY_RX Dispatch Update

Pass rpt.reportId to Internal variants. For Unknown type, compute effective_len stripping ID, then route by len >=8 keyboard else >=3 mouse.

Files Changed

  • Tactility/Source/bluetooth/BluetoothHidHost.cpp: added Internal variants, heuristic, ID strip, retry timer hid_autoconn_retry_timer, dual addr_type try