Search code examples
clibusb

What role does wValue play when interactive with "USB HID Red Visual Indicator" over USB?


unsigned char command = strcmp("on", argv[1]) == 0 ? 0x02 : 0x00;

// From Delcom documentation
unsigned char buffer[] = { 
    0x65, // 8 byte packet size
    0x0C, // Command type
    command, // DataLSB - Command parameter
    0xFF, // DataMSB - Command parameter
    0x00, // HID, first byte
    0x00, // HID, second byte
    0x00, // HID, third byte
    0x00  // HID, fourth byte
};

libusb_control_transfer (
    devh,
    0x21, // bmRequestType (host to device)
    0x09, // bRequest (set configuration)
    0x0635, // wValue (configuration value)
    0x000, // wIndex
    buffer, // Data / message
    sizeof(buffer), // wLength, Number of bytes to be sent
    0 // Timeout
);

I've bought a Delcom usb controlled light to hook up to our build server, but it turned out that the C example provided by Delcom no longer compiled on Ubuntu 14.04 so I figured that it would be a good opportunity to learn a bit C as well as a bit about how USB works.

After finding a Ruby implementation for a similar Delcom device I was able to control the gadget via my C program, but I would like to understand a bit more about how this works. The comment added to the code above is the result of hours of searching and reading, but there are still a lot of blanks to be filled in :-)

  1. What role does wValue (0x0635) play? Is it a standardized configuration (argument to bRequest / SET_CONFIGURATION)?
  2. wIndex (0x000) - Does it mean that data should be read from the start? Why would this be needed?
  3. Why is there a need for an argument like wLength? '
  4. Have I made any other incorrect assumptions in the comments?

Hope this question isn't too fuzzy for Stackoverflow :-)

The gadget in question: http://www.delcomproducts.com/productdetails.asp?PartNumber=904402


Solution

  • bmRequestType is more than the direction of the transfer. It also indicates the type of request, here a Class request, and the recipient, here an interface.

    When the recipient is an interface, wIndex represents the interface number. An USB device can have multiple interfaces of different classes.

    bRequest = 0x09 would mean SET_CONFIGURATION if it was a standard device request.

    For a HID class request, bRequest = 0x09 means a SET_REPORT request (see HID document, section 7.2 and the rest for more about HID reports).

    How wValue is interpreted depends on the request. For a SET_REPORT request, it represent the report type in the high byte and the report ID in the low byte.

    Report type is 0x01=Input, 0x02=Output, 0x03=Feature, 0x04-FF=Reserved. So in your case I guess it is specific to this device.

    The data is the "report".

    What reports contain can be defined in standard HID usage tables, like for standard keyboards, mice ... But it doesn't have to be.

    For the length passed as argument, that is the same as in many C functions : the data argument is a unsigned char *, a pointer, the size can't be known if you don't pass it. You can use sizeof because your buffer is an array.