USBJoystick - mouse-pointer and keyboard synthesis
======================================================

How USBJoystick makes a joystick drive the RISC OS keyboard and mouse
pointer: binding a physical button or an axis direction to a keypress, and
binding axes/buttons to mouse-pointer movement and mouse buttons.

Design principle: **additive, alongside the real devices.** Synthesised
keys sit next to a real keyboard, and synthesised mouse movement nudges the
*same* desktop pointer the real mouse controls, both live at once. We do NOT
become a separate selectable pointer device.



Keyboard synthesis (c.keys)
------------------------------
Keys are injected via KeyV, the same vector a real USB keyboard drives:

    OS_CallAVector  R0 = KeyV_KeyDown (2) / KeyV_KeyUp (1)
                    R1 = RISC OS internal KeyNo (Global/Keyboard.h)
                    R9 = KEYV (&13)

To *inject* keys we only call the vector - we do NOT claim KeyV (claiming
is for being a keyboard: receiving LED/enable reasons and getting kernel
auto-repeat). A held KeyDown reads as down via the kernel's key-state table
(OS_Byte 121/129), which is what games poll, so no auto-repeat handling is
needed for held directions.

The configured codes (key_up/down/left/right, key_buttons[]) are KeyNo
values used directly as R1 - no HID-usage translation.

c.keys tracks, per slot, the actual KeyNo currently held for each source
(4 axis directions + each physical button), so it emits KeyV events only on
a change, releases the right key if a mapping changes mid-press, and can
release everything on detach/finalise (so keys never stick). Axis-direction
"pressed" uses the 8-bit mapped stick with the same digital dead-zone
thresholds as encode_stick_serial_port (c.joyswis).


Mouse buttons (c.mouse)
--------------------------
Mouse buttons are injected via KeyV as pseudo-keys:

KeyNo_LeftMouse   &70 (Select)
KeyNo_CentreMouse &71 (Menu)
KeyNo_RightMouse  &72 (Adjust)

same OS_CallAVector KeyV convention as keyboard, edge-detected against
previous state.


Mouse movement (c.mouse) 
---------------------------
The canonical way to add RELATIVE movement to the shared pointer, coexisting
with the real mouse, is PointerV reason 3 (Report), pushed via OS_CallAVector.
This is similar to USBDriver.

There is no PointerV Claim and no PointerReason_Request handler.

The kernel does mouse-step scaling and bounds-clamping; there is no kernel
acceleration.


Persistence
--------------
Key and mouse mappings persist via the config store (doc.Config: keyaxes,
keybuttons, mouse) - no extra work needed as these are extended. The runtime
behaviour above is independent of whether a mapping came from auto-map,
a *command/SWI, or the saved config.
