usb-hid: bind an absolute pointer, and plumb EV_ABS through

Groundwork for usb-tablet, which is the fix for the guest cursor and the
host's never being in the same place: a PS/2 mouse reports how far it
moved, two pointers accumulating deltas independently drift apart, and no
amount of care in the compositor can make them agree. An absolute device
reports where it is, so they coincide by construction.

  - the HID driver no longer matches the boot subclass only. usb-tablet
    declares subclass 0 and was refused at the door; hid_probe decides
    what an interface actually is, and still declines what it cannot make
    sense of.
  - a non-boot HID interface is taken to be an absolute pointer and is
    not asked for boot protocol, which it does not have -- that request
    failing is what stopped it binding.
  - tablet_report decodes the fixed 6-byte layout (buttons, 16-bit X,
    16-bit Y, wheel) and scales the logical range to pixels there,
    because it is the only place that knows the range.
  - input_mouse_abs reports EV_ABS/ABS_X/ABS_Y so a reader can tell an
    absolute position from a delta, and mouse_set_abs places the pointer
    rather than nudging it.
  - Schcom treats EV_ABS as authoritative and EV_REL as a nudge.

The device binds and identifies correctly: "usb-hid: tablet (absolute) on
slot 1, endpoint 0x81 every 4 ms".

It is NOT finished, and QEMU_INPUT is empty by default because of it. No
reports have yet been observed arriving on the tablet's interrupt
endpoint, so making it the default pointer would trade a cursor that
drifts for one that does not move at all. Opt in with

  make qemu QEMU_INPUT='-device qemu-xhci,id=xhci -device usb-tablet,bus=xhci.0'

Next step is to find out why nothing arrives: whether the first transfer
is queued but never completes, whether a completion needs re-arming for
this endpoint, or whether QEMU is not routing motion to the tablet at all
(`info mice`).

bootcheck 108 [ok], schcom-test passes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Nexoniarz 2026-08-10 18:27:01 +02:00
commit 8b7b8df74f
9 changed files with 174 additions and 11 deletions

View file

@ -134,6 +134,23 @@ QEMU = qemu-system-x86_64
# virtio-gpu wins the display class, stdvga carries the splash and text console.
QEMU_DISPLAY = -vga std -device virtio-gpu-pci
# An absolute pointing device, on an xHCI controller.
#
# A PS/2 mouse is relative, so inside a VM the guest cursor and the host's
# accumulate independently and drift apart -- they are simply never in the same
# place. usb-tablet reports where the pointer *is*, so the two coincide.
#
# EMPTY BY DEFAULT, and that is not an oversight. The driver binds the tablet
# and identifies it correctly, but no reports have yet been observed arriving
# on its interrupt endpoint -- so switching the default pointer to it would
# replace a cursor that drifts with one that does not move. Opt in while
# working on it:
#
# make qemu QEMU_INPUT='-device qemu-xhci,id=xhci -device usb-tablet,bus=xhci.0'
#
# See kernel/drivers/usb/hid/usb_hid.c, tablet_report().
QEMU_INPUT ?=
# -----------------------------------------------------------------------
# Cross-compilation: clang everywhere it can be had
#
@ -433,7 +450,7 @@ $(OVMF_VARS):
chmod u+w $@
qemu-uefi: esp $(BUILD)/schfs.img $(OVMF_CODE) $(OVMF_VARS)
$(QEMU) -machine pc-i440fx-9.2 -drive if=pflash,format=raw,unit=0,readonly=on,file=$(OVMF_CODE) -drive if=pflash,format=raw,unit=1,file=$(OVMF_VARS) -drive file=fat:rw:$(BUILD)/esp,index=0,media=disk -drive file=$(BUILD)/schfs.img,format=raw,index=1,media=disk -m 1G -smp 1 -cpu qemu64,+rdtscp -serial mon:stdio $(QEMU_DISPLAY)
$(QEMU) -machine pc-i440fx-9.2 -drive if=pflash,format=raw,unit=0,readonly=on,file=$(OVMF_CODE) -drive if=pflash,format=raw,unit=1,file=$(OVMF_VARS) -drive file=fat:rw:$(BUILD)/esp,index=0,media=disk -drive file=$(BUILD)/schfs.img,format=raw,index=1,media=disk -m 1G -smp 1 -cpu qemu64,+rdtscp -serial mon:stdio $(QEMU_DISPLAY) $(QEMU_INPUT)
# Build the ramdisk-root variant. This is a target rather than just
# "make RAMROOT=1" because toggling RAMROOT changes CFLAGS (-DRAMDISK_ROOT),
@ -920,12 +937,12 @@ schcom-test: schos.img $(BUILD)/schfs.img
sh tools/posix/schcom_test.sh
qemu-kvm: schos.img $(BUILD)/schfs.img
$(QEMU) -enable-kvm -serial mon:stdio $(QEMU_DISPLAY) -cpu host \
$(QEMU) -enable-kvm -serial mon:stdio $(QEMU_DISPLAY) $(QEMU_INPUT) -cpu host \
-hda schos.img -hdb $(BUILD)/schfs.img \
-m 1G -smp 2 -machine pc-i440fx-9.2
qemu: schos.img $(BUILD)/schfs.img
$(QEMU) -serial mon:stdio $(QEMU_DISPLAY) -cpu qemu64,+rdtscp \
$(QEMU) -serial mon:stdio $(QEMU_DISPLAY) $(QEMU_INPUT) -cpu qemu64,+rdtscp \
-hda schos.img -hdb $(BUILD)/schfs.img \
-m 1G -smp 2 -machine pc-i440fx-9.2