I'm implementing an HID class device and have based my program on the HID USB program supplied by Keil. I'm new to USB but am a fairly experienced programmer otherwise.
I have got a basic program working fine bit with single byte input and output reports. I've tested the functionality using a client called SimpleHIDWrite.exe
I need to expand both in and out reports to 8 bytes each to communicate with the host. Has anybody successfully modified this example program or does anyone have any advice on how to do it properly?
My guess is that I need to edit the report descriptor and also set up the inreport and outreport as arrays. Is there anything I need to watch out for?
My target is the LPC2141.
Any advice or information would be much appreciated!
Thanks, Gareth.
Hi Tsuneo,
I implemented the changes but it does not seem to be working quite right. I used SimpleHIDWrite to test the new application (loop back on EP1). I hope this is okay? The repeated IN reports have stopped - in fact I did not appear to be receiving any reports at the PC. What I expected to see was the written command followed by a single identical report being read back from the device. I could see the written report but no read report - hence my assessment that the changes are not working ...
I am working with 8 byte packets IN and OUT so I have ...
usbcfg.h #define USB_MAX_PACKET0 8
usbdesc.c /* USB Configuration Descriptor */ /* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor) */ const U8 USB_ConfigDescriptor[] = { /* Configuration 1 */ USB_CONFIGUARTION_DESC_SIZE, /* bLength */ USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL( /* wTotalLength */ USB_CONFIGUARTION_DESC_SIZE + USB_INTERFACE_DESC_SIZE + HID_DESC_SIZE + USB_ENDPOINT_DESC_SIZE + // added USB_ENDPOINT_DESC_SIZE // added ), 0x01, /* bNumInterfaces */ 0x01, /* bConfigurationValue: 0x01 is used to select this configuration */ 0x00, /* iConfiguration: no string to describe this configuration */ USB_CONFIG_BUS_POWERED /*|*/ /* bmAttributes */ /*USB_CONFIG_REMOTE_WAKEUP*/, USB_CONFIG_POWER_MA(100), /* bMaxPower, device power consumption is 100 mA */ /* Interface 0, Alternate Setting 0, HID Class */ USB_INTERFACE_DESC_SIZE, /* bLength */ USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */ 0x00, /* bInterfaceNumber */ 0x00, /* bAlternateSetting */ // 0x01, /* bNumEndpoints */ 0x02, /* bNumEndpoints */ USB_DEVICE_CLASS_HUMAN_INTERFACE, /* bInterfaceClass */ HID_SUBCLASS_NONE, /* bInterfaceSubClass */ HID_PROTOCOL_NONE, /* bInterfaceProtocol */ 0x04, /* iInterface */ /* HID Class Descriptor */ /* HID_DESC_OFFSET = 0x0012 */ HID_DESC_SIZE, /* bLength */ HID_HID_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL(0x0100), /* 1.00 */ /* bcdHID */ 0x00, /* bCountryCode */ 0x01, /* bNumDescriptors */ HID_REPORT_DESCRIPTOR_TYPE, /* bDescriptorType */ WBVAL(HID_REPORT_DESC_SIZE), /* wDescriptorLength */ /* Endpoint, HID Interrupt In */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_IN(1), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ // WBVAL(0x0004), /* wMaxPacketSize */ WBVAL(0x0008), /* wMaxPacketSize */ 0x20, /* 32ms */ /* bInterval */ // 0x01, /* 1ms */ /* bInterval */ /* Endpoint, HID Interrupt Out */ USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_OUT(1), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ // WBVAL(0x0004), /* wMaxPacketSize */ WBVAL(0x0008), /* wMaxPacketSize */ 0x20, /* 32ms */ /* bInterval */ // 0x01, /* 1ms */ /* bInterval */ /* Terminator */ 0 /* bLength */ };
usbuser.c static OS_SEM USB_IN_EP1_Semaphore; // semaphore for IN EP1 /* * USB Endpoint 1 Task * Handles USB Endpoint 1 Events */ #if (USB_EP_EVENT & (1 << 1)) __task void USB_EndPoint1 (void) { U16 evt; U32 report_size; // added for (;;) { os_evt_wait_or(0xFFFF, 0xFFFF); /* Wait for an Event */ evt = os_evt_get(); /* Get Event Flags */ if (evt & USB_EVT_OUT) { // OUT EP1 interrupt comes report_size = USB_ReadEP( HID_EP_OUT, &OutReport[0] ); // read out the output report // usually, your firmware parse the output report, here // in this snippet, just copy output report to input one directly, for loopback // SetOutReport(); memcpy( InReport, OutReport, report_size ); // send an input report to IN EP os_sem_wait( USB_IN_EP1_Semaphore, 0xffff ); // wait until IN EP is available // USB_WriteEP( HID_EP_IN, InReport, HID_INPUT_REPORT_BYTES ); // pass it to the endpoint USB_WriteEP( HID_EP_IN, InReport, sizeof(InReport) ); // pass it to the endpoint } if (evt & USB_EVT_IN) { os_sem_send( USB_IN_EP1_Semaphore ); // IN EP1 is free /* GetInReport(); // USB_WriteEP(HID_EP_IN, &InReport, sizeof(InReport)); USB_WriteEP(HID_EP_IN, &InReport[0], sizeof(InReport)); */ } } } #endif /* * USB Core Task * Handles USB Core Events */ __task void USB_Core (void) { #if (USB_CONFIGURE_EVENT || USB_INTERFACE_EVENT || USB_FEATURE_EVENT) U16 evt; #endif for (;;) { os_evt_wait_or(0xFFFF, 0xFFFF); /* Wait for an Event */ #if (USB_CONFIGURE_EVENT || USB_INTERFACE_EVENT || USB_FEATURE_EVENT) evt = os_evt_get(); /* Get Event Flags */ #endif #if USB_CONFIGURE_EVENT if (evt & USB_EVT_SET_CFG) { if (USB_Configuration) { /* Check if USB is configured */ os_sem_init( USB_IN_EP1_Semaphore, 1 ); // IN EP1 is available now /* GetInReport(); // USB_WriteEP(HID_EP_IN, &InReport, sizeof(InReport)); USB_WriteEP(HID_EP_IN, &InReport[0], sizeof(InReport)); */ } } #endif #if USB_INTERFACE_EVENT if (evt & USB_EVT_SET_IF) { } #endif #if USB_FEATURE_EVENT if (evt & USB_EVT_SET_FEATURE) { } if (evt & USB_EVT_CLR_FEATURE) { } #endif } }