Search code examples
usbendpointhiddescriptor

Handling OUT report endpoint (USB HID)


I've programmed a LPC11U14 microcontroller to act as a USB HID Keyboard. It works just fine, but I can't get the LED's to work. I've created the appropriate descriptors, and I can also (via USBlyzer) see that the host sends the OUT control transfer. I just don't know where and how to handle the OUT report.

I can turn on and off the LED's when I press Caps Lock, Num Lock or Scroll Lock, but they all light up regardless of which of the three buttons I press. It's as if I don't receive a value of which button was pressed, but only that a button was pressed.

Here's my HID report descriptor:

const Int8U HidReportDescriptor[] =
{      
    0x05, 0x01, // Generic dekstop
    0x09, 0x06, // Keyboard
    0xA1, 0x01, // Application

    0x05, 0x07, // Usage Page; Key Codes
    0x19, 0xE0, // Usage minimum; 224
    0x29, 0xE7, // Usage maximum; 231
    0x15, 0x00, // Logical minimum; 0 
    0x25, 0x01, // Logical maximum; 1
    0x75, 0x01, // Report size; 1
    0x95, 0x08, // Report count; 8
    0x81, 0x02, // Input (Data, Variable, Absolute); Modifier byte

    0x95, 0x01, // Report count; 1
    0x75, 0x08, // Report size; 8
    0x81, 0x01, // Input (Constant); Reserved byte
    0x95, 0x03, // Report count; 5
    0x75, 0x01, // Report size; 1
    0x05, 0x08, // Usage page, page # for LED's
    0x19, 0x01, // Usage minimum; 1
    0x29, 0x03, // Usage maximum; 5
    0x91, 0x02, // Output (Data, Variable, Absolute); LED report
    0x95, 0x01, // Report count; 1
    0x75, 0x05, // Report size; 3
    0x91, 0x01, // Output (Constant); LED report padding

    0x95, 0x06, // Report count; 6
    0x75, 0x08, // Report size; 8
    0x15, 0x00, // Logical minimum; 0
    0x26, 0xFF, 0x00, // Logical maximum; 101
    0x05, 0x07, // Usage Page; Key Codes
    0x19, 0x00, // Usage minimum; 0
    0x2A, 0xFF, 0x00, // Usage maximum; 101
    0x81, 0x00, // Input (Data, Array); Key arrays (6 bytes)

    0xC0        // End collection
};

In my "usb_hooks" file there's all the different functions that get called when communicating via USB. When using breakpoints to track down the function used when I press e.g. the Num Lock button, this function is called:

/*************************************************************************
 * Function Name: USB_CLASS_REQUEST_HOOK
 * Parameters: USB_Endpoint_t EP
 *
 * Return: UsbCommStatus_t
 *
 * Description: Called when class request receiving
 *
 *************************************************************************/
UsbCommStatus_t USB_CLASS_REQUEST_HOOK (pUsbSetupPacket_t pSetup)
{
  //Add code here ...
  return(UsbClassHidRequest(pSetup));
  //return(UsbFault);
}

Also, when checking the pSetup setup package, none of it's variables change. They all have the same value regardless of which button I press. pSetup contains the following:

typedef union _UsbSetupPacket_t
{
  Int8U Data[8];
  struct {
    UsbRequestType_t  mRequestType;
    Int8U             bRequest;
    TwoBytes_t        wValue;
    TwoBytes_t        wIndex;
    TwoBytes_t        wLength;
  };
} UsbSetupPacket_t, * pUsbSetupPacket_t;

Any suggestions where and how to read the endpoint correctly?


Solution

  • After a lot of debugging and register/memory checking, I found that control endpoints (and other stuff) were saved in extern Int8U USB_PacketMemory[2048]; By reading byte 128 I could get the status of the LED's and then make a function that turned them on/off accordingly.

    void setLeds(int ledValue) {  
      switch (ledValue) {
      case 0x00:
        GPIOSetBitValue(0, 23, 0); 
        GPIOSetBitValue(1, 13, 0); 
        GPIOSetBitValue(1, 14, 0); 
        break; 
      case 0x01:
        // and so on...
        break;
      }
    }