Can't use endpoint 0x83 in LPCUSB? - SOLVED

I’m having a problem creating a composite USB HID with the LPCUSB stack. My device has 3 interfaces, each with 1 IN endpoint (0x81, 0x82, and 0x83). I can send data to a Windows PC just fine over endpoints 0x81, and 0x82; however, I can’t send anything over endpoint 0x83. It’s strange. I even tried switching endpoints 0x82 and 0x83 in the descriptor such that interface 1 used endpoint 0x83 and interface 2 used endpoint 0x82. That resulted in interface 2 working, while interface 1 did not. The code that writes to each of these endpoints is identical and I’ve traced through to ensure I’m specifying the correct endpoint when I write. I’ve also stepped through and ensured endpoint 0x83 is realized upon configuration by LPCUSB. The symptom, by the way, is if I write data to endpoint 0x83, no data arrives at the PC, and I never get an endpoint interrupt (I have endpoint interrupts enabled).

Anyone have any ideas? I assume that if I keep hunting around, I’ll find some minor logic error in my code that’s keeping this from working, but I figured I’d post in case anyone has seen this before or knows more about USB.

I’ve verified with various USB sniffers that no data is sent up on endpoint 0x83. Here’s my descriptor (which parses fine as a composite device and properly loads in Windows):

(Notes)

MAX_PACKET_SIZE0 is 64

DRV_HID_MAX_PACKET_SIZE is 64

INTR_IN_EP1 is 0x81

INTR_IN_EP2 is 0x82

INTR_IN_EP3 is 0x83

/* Device descriptor */
    18,
    DESC_DEVICE,
    LE_WORD(0x0110),            /* bcdUSB                       */
    0x00,                       /* bDeviceClass                 */
    0x00,                       /* bDeviceSubClass              */
    0x00,                       /* bDeviceProtocol              */
    MAX_PACKET_SIZE0,           /* bMaxPacketSize               */
    LE_WORD(0xFFFF),            /* idVendor                     */
    LE_WORD(0x1017),            /* idProduct                    */
    LE_WORD(0x0001),            /* bcdDevice                    */
    0x01,                       /* iManufacturer                */
    0x02,                       /* iProduct                     */
    0x03,                       /* iSerialNumber                */
    0x01,                       /* bNumConfigurations           */

/* Configuration descriptor */
    9,
    DESC_CONFIGURATION,
    LE_WORD(84),                /* wTotalLength                 */
    0x03,                       /* bNumInterfaces               */
    0x01,                       /* bConfigurationValue          */
    0x04,                       /* iConfiguration               */
    0x80,                       /* bmAttributes (bus-powered)   */
    0x32,                       /* bMaxPower (100mA)            */

/* Interface 0 descriptor */
    9,
    DESC_INTERFACE,
    0x00,                       /* bInterfaceNumber             */
    0x00,                       /* bAlternateSetting            */
    0x01,                       /* bNumEndPoints                */
    0x03,                       /* bInterfaceClass = HID        */
    0x00,                       /* bInterfaceSubClass           */
    0x00,                       /* bInterfaceProtocol           */
    0x05,                       /* iInterface                   */

/* HID Class descriptor */
    9,
    DESC_HID_HID,               /* bDescriptorType = HID        */
    LE_WORD(0x0111),            /* bcdHID                       */
    33,                         /* bCountryCode                 */
    0x01,                       /* bNumDescriptors = report     */
    DESC_HID_REPORT,            /* bDescriptorType              */
    LE_WORD(sizeof(hidReportDesc)),

/* EP 1 IN descriptor */
    7,
    DESC_ENDPOINT,
    INTR_IN_EP1,                        /* bEndpointAddress     */
    0x03,                               /* bmAttributes = INT   */
    LE_WORD(DRV_HID_MAX_PACKET_SIZE),   /* wMaxPacketSize       */
    1,                                  /* bInterval            */

/* Interface 1 descriptor */
    9,
    DESC_INTERFACE,
    0x01,                       /* bInterfaceNumber             */
    0x00,                       /* bAlternateSetting            */
    0x01,                       /* bNumEndPoints                */
    0x03,                       /* bInterfaceClass = HID        */
    0x00,                       /* bInterfaceSubClass           */
    0x00,                       /* bInterfaceProtocol           */
    0x06,                       /* iInterface                   */

/* HID Class descriptor */
    9,
    DESC_HID_HID,               /* bDescriptorType = HID        */
    LE_WORD(0x0111),            /* bcdHID                       */
    33,                         /* bCountryCode                 */
    0x01,                       /* bNumDescriptors = report     */
    DESC_HID_REPORT,            /* bDescriptorType              */
    LE_WORD(sizeof(hidReportDesc)),

/* EP 2 IN descriptor */
    7,
    DESC_ENDPOINT,
    INTR_IN_EP2,                        /* bEndpointAddress     */
    0x03,                               /* bmAttributes = INT   */
    LE_WORD(DRV_HID_MAX_PACKET_SIZE),   /* wMaxPacketSize       */
    1,                                  /* bInterval            */

/* Interface 2 descriptor */
    9,
    DESC_INTERFACE,
    0x02,                       /* bInterfaceNumber             */
    0x00,                       /* bAlternateSetting            */
    0x01,                       /* bNumEndPoints                */
    0x03,                       /* bInterfaceClass = HID        */
    0x00,                       /* bInterfaceSubClass           */
    0x00,                       /* bInterfaceProtocol           */
    0x07,                       /* iInterface                   */

/* HID Class descriptor */
    9,
    DESC_HID_HID,               /* bDescriptorType = HID        */
    LE_WORD(0x0111),            /* bcdHID                       */
    33,                         /* bCountryCode                 */
    0x01,                       /* bNumDescriptors = report     */
    DESC_HID_REPORT,            /* bDescriptorType              */
    LE_WORD(sizeof(hidReportDesc)),

/* EP 3 IN descriptor */
    7,
    DESC_ENDPOINT,
    INTR_IN_EP3,                        /* bEndpointAddress     */
    0x03,                               /* bmAttributes = INT   */
    LE_WORD(DRV_HID_MAX_PACKET_SIZE),   /* wMaxPacketSize       */
    1,                                  /* bInterval            */

Oh geez. I figured it out. I didn’t realize the LPC2148 had a fixed endpoint configuration. I read the USB portion of the LPC2148 manual starting from “Data Flow”–probably about 25 times. But I guess I skipped the first part containing the fixed endpoint configuration table. I remember briefly wondering how the USB engine knew how the endpoints were configured–but then decided it was magic and moved on. Argh.

So, I switched BULK 0x82 and ISOC 0x83 to the interrupt endpoints 0x84 and 0x87 & it’s working now.

Strange that I was getting interrupt traffic on 0x82 before though. Oh well.

Bertrik, if you happen to be reading this, I have an API suggestion: you might consider defining the various endpoints in “usbhw_lpc.h” with names that indicate their traffic types. Thanks, and thanks for the great library.

–Jerry