HID input demo

The HID Input Demo is a simple device driver that accepts reports from HID-compliant gamepads and joysticks and translates them into Screen API events.

The driver primarily consists of:
  • joystick_demo.h — Defines the client_report_t and client_ctrl_t custom types, which are used for custom data associated with reports and data storage, respectively.
  • joystick_demo.c — Implements a simple HID device driver. It sets up the following connections and interactions:
    • Defines devices that it wants to receive reports from as all using wildcard macro for vendor ID, product ID, and version fields of the hidd_device_ident_t.
      • It's possible to override the wildcard and select specific vendor and product IDs using -v and -d program arguments.
    • Registers the implementation functions using hidd_funcs_t:
      • hid_insertion()
        • Invoked by libhiddi after driver is started - this allows driver to receive notifications about devices it has not yet seen - and when a new USB device is inserted.
      • hid_removal()
      • hid_report()
        • Invoked by libhiddi when an attached report has data.
      • hid_async_report()
        • Would be called when libhiddi receives an event from io-hid server, which is not one of insertion, removal, or report; however, io-hid does any other events at this time.
    • Defines HID server connection parameters with default server location using hidd_connect_parm_t.
      • It's possible to override the server location using -s program argument.
    • Performs Screen API-required setup.
    • Registers handler for SIGTERM and SIGKILL signals, and ignores SIGHUP and SIGPWR signals.
    • Links the callback functions and device request with connection parameters.
    • Connects to the server using hidd_connect().
    • Loops until killed, sleeping for 10 seconds at a time.

hid_insertion()

This callback allows the driver to select the devices it is interested in and to attach device reports, which will later be delivered using the hid_report() callback. This function is invoked by libhiddi once for each device present when the driver is started, and for each device inserted while driver is running. It:

  1. Iterates through root level collections, inspecting their usage page, looking for HIDD_USAGE_JOYSTICK, HIDD_USAGE_GAMEPAD, or HIDD_USAGE_MOUSE.

  2. When it finds collection it is interested in, it finds all report instances in that collection and all of its sub-collections and for each report instance:

    1. Attaches the report, requesting that extra memory be allocated for the client_report_t instance and for button data:
      hidd_report_attach( connection, 
                          device_instance,
                          report_instance,
                          0,
                          sizeof(client_report_t) + 
                          ((max_but *3 * 3) * sizeof(_int32)),
                          &report )
    2. Retrieves pointer to the allocated instance using hidd_report_extra().

    3. Sets data in the client_report_t to be later used in the report callback.

hid_report()

This function is invoked by libhiddi for every report received. It extracts data from the report, translates it into Screen API data, and sends it to the active window.

The hid_report() function is primarily divided between three other functions within the source file:

  • handle_joystick()

    • Retrieves data from HID report: x and y axis, hat switch or rotational axis, and currently pressed buttons.

    • Determines which buttons where pressed, held, or released.

    • Calls either:

      • send_joystick_data_event(), for Logitech Wingman Precision Gamepad (released 2001), or

      • send_joystick_data_poll(), for all other devices.

  • send_joystick_data_poll() and send_joystick_data_event()

    • Set screen event type to SCREEN_EVENT_GAMEPAD.

    • Set screen event data to value based on the buttons pressed, held, released.

    • Send the screen event to the window that has input focus on the display.

    • These functions re-use a single global instance of screen_event_t, initialized during screen setup, to send screen events.

Box visualizer

The demo also uses a box visualizer application to render a simple box that responds to joystick movements and button presses. This application draws a white box on black background and loops waiting for Screen events.

Every time the application receives a SCREEN_EVENT_GAMEPAD, it updates the box size and position, and re-draws the box.

Page updated: