USB-HID Gamepad with MSP430 USB API - Issue with Descriptors

318 Views Asked by At

I am trying to emulate a USB-HID gamepad/controller using the MSP430 with 7-14 analog inputs but I had trouble getting the descriptors right for my custom USB-HID device.

I came across this code online: https://github.com/TI-FIRST/MSP430-Gamepad which worked great to get the MSP430 up and running as a gamepad with only 8 analog inputs.

The main.c file contains instructions to change the report structure:

  • This example functions as a gamepad on the host. The gamepad has a HID report as described in
  • report_desc_HID0 variable in descriptors.c. Please note that if this report structure is
  • changed then the following lengths need to be updated -
    1. #define report_desc_size_HID0 in descriptors.h needs to be updated with descriptor size
    1. report_desc_size and report_len_input need t be updated in descriptors.c
  • As is this demo will enumerate with 18 bytes of input report and 2 bytes of output report
  • The input and output report structures for the gamepad as described in USB_gamepad.h
  • The input reports are used to report ADC values and status of buttons (GPIO)
  • The output report is used to set/reset indicators (GPIO)

The descriptors currently in the descriptors.c file are:

UsagePage(USB_HID_GENERIC_DESKTOP),
Usage(USB_HID_JOYSTICK),
Collection(USB_HID_APPLICATION),
//
// The axis for the controller.
//
UsagePage(USB_HID_GENERIC_DESKTOP),
Usage (USB_HID_POINTER),
Collection (USB_HID_PHYSICAL),

    //
    // The X, Y and Z values which are specified as 8-bit absolute
    // position values.
    //
    Usage (USB_HID_X),
    Usage (USB_HID_Y),
    Usage (USB_HID_Z),
    Usage (USB_HID_RX),
    Usage (USB_HID_RY),
    Usage (USB_HID_RZ),
    Usage (USB_HID_SLIDER),
    Usage (USB_HID_DIAL),
    //
    // 8 16-bit absolute values.
    //
    ReportSize(16),
    ReportCount(8),
    Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE |
          USB_HID_INPUT_ABS),

    //
    // Max 32 buttons.
    //
    UsagePage(USB_HID_BUTTONS),
    UsageMinimum(1),
    UsageMaximum(NUM_BUTTONS),
    LogicalMinimum(0),
    LogicalMaximum(1),
    PhysicalMinimum(0),
    PhysicalMaximum(1),

    //
    // 8 - 1 bit values for the buttons.
    //
    ReportSize(1),
    ReportCount(32),
    Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE |
          USB_HID_INPUT_ABS),

     //
     // Max 16 indicator bits
     //
     UsagePage(USB_HID_BUTTONS),
     UsageMinimum(1),
     UsageMaximum(NUM_INDICATORS),
     LogicalMinimum(0),
     LogicalMaximum(1),
     PhysicalMinimum(0),
     PhysicalMaximum(1),

     //
     // 8 - 1 bit values for the leds.
     //
     ReportSize(1),
     ReportCount(16),
     Output(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE |
           USB_HID_INPUT_ABS),

EndCollection,
EndCollection

I would like to change it to 14 16-bit analog inputs like this:

UsagePage(USB_HID_GENERIC_DESKTOP),
Usage(USB_HID_JOYSTICK),
Collection(USB_HID_APPLICATION),
//
// The axis for the controller.
//
UsagePage(USB_HID_GENERIC_DESKTOP),
Usage (USB_HID_POINTER),
Collection (USB_HID_PHYSICAL),

    //
    // The X, Y and Z values which are specified as 8-bit absolute
    // position values.
    //
    Usage (USB_HID_X),
    Usage (USB_HID_Y),
    Usage (USB_HID_Z),
    Usage (USB_HID_RX),
    Usage (USB_HID_RY),
    Usage (USB_HID_RZ),
    Usage (USB_HID_SLIDER),
    Usage (USB_HID_DIAL),
    Usage (USB_HID_VX),
    Usage (USB_HID_VY),
    Usage (USB_HID_VZ),
    Usage (USB_HID_VRX),
    Usage (USB_HID_VRY),
    Usage (USB_HID_VRZ),
    //
    // 8 16-bit absolute values.
    //
    ReportSize(16),
    ReportCount(14),
    Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE |
          USB_HID_INPUT_ABS),

    //
    // Max 32 buttons.
    //
    UsagePage(USB_HID_BUTTONS),
    UsageMinimum(1),
    UsageMaximum(6),
    LogicalMinimum(0),
    LogicalMaximum(1),
    PhysicalMinimum(0),
    PhysicalMaximum(1),

    //
    // 8 - 1 bit values for the buttons.
    //
    ReportSize(1),
    ReportCount(32),
    Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE |
          USB_HID_INPUT_ABS),

     //
     // Max 16 indicator bits
     //
     UsagePage(USB_HID_BUTTONS),
     UsageMinimum(1),
     UsageMaximum(6),
     LogicalMinimum(0),
     LogicalMaximum(1),
     PhysicalMinimum(0),
     PhysicalMaximum(1),

     //
     // 8 - 1 bit values for the leds.
     //
     ReportSize(1),
     ReportCount(16),
     Output(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE |
           USB_HID_INPUT_ABS),

EndCollection,
EndCollection

However, I cannot figure out how to calculate the length/size/bytes of the descriptor. I tried going through the USB-HID spec (Device Class Definition for HID 1.11 | USB-IF) which states that items have a byte prefix, but I can't really figure out which items to count and how they add up. Apologies but I am very inexperienced in USB.

Would someone be able look at the code, and let me know what values I need in report_desc_size, report_len_input in the descriptor files plus anything else I need to change to expand the functionality of this code for 14 16-bit analog inputs.

P.S. To replicate and see the working gamepad, just upload the code to a dev kit and search 'Set up USB Game Controllers' on Windows, which should recognize it as a gamepad if everything is running correctly and the reports are being accepted.

1

There are 1 best solutions below

0
On

The size of the report descriptor is sizeof(report_desc_HID0). For convenience I'd recommend restructuring the code so you compute the descriptor length at compile time instead of hard-coding it.

You're using macros to construct the descriptor, and each macro adds a fixed number of bytes. You've added six new Usage items, each of which expands to two bytes:

#define Usage(ui8Value)          0x09, ((ui8Value) & 0xff)

If the original descriptor is 80 bytes, I'd guess the new descriptor size is 92 bytes.