USBJoystick - desirable features / next steps
===============================================


Icons
-------
  The 'button' on/off icon JoySetup uses to illustrate buttons is bad.


Mouse pointer feel
--------------------
  Pointer movement works and coexists with the real mouse, but it is a
  crude fixed step applied once per USB packet, so pointer speed is tied
  to the USB report rate. It should instead be driven from a steady ticker
  that converts a sustained axis deflection into a proportional velocity,
  with a dead zone and a per-axis sensitivity (the sensitivity field
  already exists in the data but is not yet used), optionally through a
  response curve for fine control near centre.

  Drive it from a steady ticker (OS_CallEvery, ~2cs) that runs while mouse
  control is on:

  each tick read the mapped mouse axes' deflection and compute a small signed
  dx,dy = (deflection beyond a dead zone) * sensitivity, optionally through a
  squared curve for fine control near centre and speed at the edges, then push
  one Report.

  A per-axis sensitivity factor (to be added) would scale this; the
  kernel's mouse-step then applies on top. This decouples pointer speed from
  USB report rate.


Joy_ReadPipe
--------------
  The Teque/Krisalis "Joy" module's &CFFC3 SWI is currently a stub that
  returns without error and does nothing - the original behaviour it
  should replicate is not known. Needs the original documentation or a
  reference binary before it can be implemented properly.

  Much of this is handled by ADFFS in reality, as it can/will step-in and
  tweak any dubious game behaviour.  In the past, games have shipped with
  their own module, an compatibility across different modules+games was not
  a consideration.


ADC pointer-position reads
----------------------------
  The ADC/ADVAL emulation does not answer the pointer-position calls
  (ADVAL(-1)/(-2)); they pass straight through to the real OS. Decide
  whether the emulation should service these itself.


Per-binding ADC range
-----------------------
  An adc:<n> binding currently maps the whole axis min..max onto the ADC
  channel (Invert reverses it). The joystick_binding record reserves a 'param'
  field for a start/end sub-range so a binding could map only part of an
  axis onto a channel.

  Why would we do this?  Two reasons:

  1) A cheap single-axis pedal set where one physical axis runs accelerate
     and brake (with the centre being neither pressed).

  2) Saloon Cars Deluxe (the only game using the ADC for input?) requires:
     Channel 0: Steering, min=right max=left
     Channel 1: Accelerator, min=none max=full
     Channel 2: Brake, min=none, max=full
     Channel 3: Clutch, min=none, max=full

  Needs a grammar for the range in *USBJoystick_Map, the config bind= line,
  and use of param in binding_compile's ADC path.

  All of this needs adding into JoySetup too, perhaps with an option to
  display the live ADC channel/button data somwhere too.


Device capability detection
-----------------------------
  Joystick_DeviceInfo returns a capabilities bitfield (rumble, LED,
  battery, touchpad, sensors). Only the rumble bit is populated so far; the
  rest are reserved and read 0.


Per-game profiles
-------------------
  The config file already reserves a profile= key per device (written but
  ignored on read) for a future "same device, different mapping per game"
  feature. The file shape is in place; the runtime support is not.


Fuller internationalisation
-----------------------------

  The runtime OUTPUT a command prints when it runs (e.g. *USBJoystick_List,
  *USBJoystick_Mappings, *USBJoystick_Debug, *USBJoystick_Emulate) - these
  are plain printf() calls with no MessageTrans lookup.

  Moving those over would need parameterised message-token substitution, not
  just static text.


Free the USB scan buffer at init
----------------------------------
  module_initialise's usb_scan_devices() enumeration allocates a device
  list that is never freed. Harmless (once, at startup) but untidy; free
  it after the scan completes.

  Check what other USB drivers do here, as I have a feeling there may be a
  reason I didn't put the free() in straight away.


Local copies of USB definitions
---------------------------------
  Most USB constants and descriptor types come from the exported USBDriver
  headers (dev.usb.h.usb and USB.h.USBDevFS), but h.usb still defines a
  few things locally because USBDriver doesn't export them: the HID class
  definitions (usbhid - usage pages and usages, the HID descriptor and
  request codes) and the SuperSpeed endpoint-companion and BOS descriptor
  types. Drop each from h.usb if a future USBDriver exports it.

  The exported usb.h declares its 16-bit fields as uWord byte pairs, so
  they must be read with UGETW(). The compiler rejects most misuse, but
  a bare field passed to debug_printf() compiles and prints garbage.


Formalise our SWIs
--------------------
  Some new Joystick_ SWIs are defined here.  Get these formally accepted.


ROM buids
-----------
  In theory, USBJoystick could be baked-into a RISC OS 5 ROM image.  This
  needs testing, as it has never been tried.

  One immediate problem is in the handling of already-attached devices at
  boot-up.  The module would start before the boot sequence, so no Choices
  variables will be set up.  Therefore, any attached devices would follow the
  default behaviour of attaching and auto-mapping, rather than considering the
  user's own configuration (which may exist).

  There would need to be a mechanism to trigger a load later on in the Boot
  sequence.  Perhaps there is something we can attach to when the desktop is
  entered?  Or a 'kick' obey file could be created in PreDesk or Tasks which
  would perform a *USBJoystick_ReloadConfig?  This could be managed by the
  JoySetup plugin, so the user doesn't have to fiddle.


Rumble and device output
--------------------------
  Each of these needs a pad to test:
  - Xbox 360 wireless: confirm that a failed stop is retried and the repeated
    stop leaves no motor running, that clearing the stall makes writes
    reliable, and that rumble works.  A genuine wired pad tests the wired
    rumble packet.
  - Xbox 360 wireless: the meaning of 00 f8 02/03 and the scale of the
    battery level.
  - PlayStation 3: confirm the descriptor now parses, then the start-up and
    rumble.
  - PlayStation 4: confirm rumble.  Then PlayStation 5 rumble, and the
    PlayStation 4/5 lightbar.
  - A rumble SWI in SDL's shape (slot, low, high, duration in milliseconds),
    then an LED call, so an SDL backend is a thin wrapper.
  - JoySetup: capabilities, test buttons, strength sliders, and a global
    strength scale in the config (doc.Config reserves force-feedback
    defaults).

  Later, maybe:
  - *USBJoystick_SendFeature and *USBJoystick_GetFeature for experiments
  - battery level from the wireless packets
  - Xbox One / Series
  - HID Physical Interface Device force feedback


SDL support
-------------
  Also see doc.SDL.  To cover the gaps:

  1. Hats as their own thing:
       - Parse every hat item, not just the first, and treat the HID D-pad
         usages (up/down/left/right) as a hat too.  Note 4-way hats
         (logical max 3) as well as 8-way.
       - Store hats apart from the axes: per hat, the report item and a
         4-bit up/right/down/left state (SDL's hat mask shape).  A hat no
         longer takes two axis slots, so the "too many axes to support HAT"
         rejection, which currently discards the whole device, goes away.
       - Drop Joystick_Axis_HatX/HatY and is_digital from AxisInfo;
         num_axes then counts real axes only.
       - Report hats: DeviceInfo.num_hats is exact, and a new
         Joystick_HatValues SWI returns each hat's state.  It can take the
         reserved SWI &43F48, or the numbers can be shuffled.
       - Bindings: a hat is a binding source in two forms.
           * X/Y pair (-1/0/+1): what the classic mapping uses today, for
             slot axis targets.  On the 8-bit Joystick_Read axes it must
             still give +/-64.
           * Four direction sources (up/right/down/left): for button, key
             and mouse button targets.
         Auto-map defaults a hat to stick X/Y so classic behaviour is
         unchanged.  A hat is digital, so it is never an ADC source:
         remove c.adc's HAT snap to min/mid/max and the ADC_AXIS_HAT_*
         constants.
       - Up-rev the bindings file for the new source types; there is no
         need to migrate old files.
       - Also update cmdshow, JoySetup source rows, doc.APIs, doc.Bindings
         and utils.Acorn2Test.

  2. Attach serial: a per-slot value that changes on every attach, returned
     with Enumerate or DeviceInfo.  Append to the structs; DeviceInfo's
     size field covers growth.

  3. Device version (bcdDevice) as its own DeviceInfo field, not only inside
     the GUID bytes.

  4. Rumble SWI, then LED / player index (see "Rumble and device output").
     While SDL drives a slot's output, the rumble stop timer must leave that
     slot alone (multiple rumble SWIs, or an 'auto stop' parameter?).

  5. Raw report tier, shaped like hidapi so a RISC OS hidapi backend is thin:
       - get report descriptor
       - read the latest input report (the module already owns the read
         stream, so this can be shared rather than exclusive)
       - send an output report; send and get a feature report
     This lets SDL's own per-device drivers be reused for Xbox 360 and
     PlayStation pads, instead of this module describing each pad's layout.

  6. Later, only if wanted: a queue of every input report, for devices that
     need request/acknowledge exchanges (Switch, Xbox One).

  Not planned: telling SDL what each axis and button means (gamepad
  roles); SDL's database and drivers do that.  A report-descriptor call
  alone is not worth building ahead of the raw tier: SDL uses it from only
  one driver (Xbox One).

  Once the raw tier exists, SDL no longer needs the per-device rumble
  builders or the built-in Xbox 360 descriptor, but classic applications
  and JoySetup still do.

  Open:
    - Do SDL's drivers (PlayStation 3/4/5, Xbox 360) work from the latest
      report rather than a stream?  Needs the SDL backend author.
    - Is the raw tier exclusive, or shared with this module's own reads?
      Leaning towards shared.
