Hi,
I'm on the board MCB1700. I took the example of Keil (C:\Keil\ARM\Boards\Keil\MCB1700\RL\USB\RTX_HID) I modify the code following the instructions in this forum : http://www.keil.com/forum/17770/ It works well with 64 bytes, but when I change to 300 bytes, It does not work. The device is not well recognized.
This is what I changed.
usbdesc.c /* 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(0x012c), /* wMaxPacketSize */<----- 300 bytes 0x01, /* 1ms */ /* bInterval */ /* Endpoint, HID Interrupt Out */ // rajout EP OUT USB_ENDPOINT_DESC_SIZE, /* bLength */ USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */ USB_ENDPOINT_OUT(1), /* bEndpointAddress */ USB_ENDPOINT_TYPE_INTERRUPT, /* bmAttributes */ WBVAL(0x012c), /* wMaxPacketSize */<----- 300 bytes 0x01, /* 1ms */ /* bInterval */
hid.h #define HID_ReportCountS(x) 0x96,(x&0xFF),((x>>8)&0xFF) //add to the table HID_ReportDescriptor[]
hiduser.h /* HID report size (count) */ #define HID_INPUT_REPORT_BYTES 300 /* size of report in Bytes */ #define HID_OUTPUT_REPORT_BYTES 300 /* size of report in Bytes */ #define HID_FEATURE_REPORT_BYTES 300 /* size of report in Bytes */
Here is the configuration on the PC side using the software USB View.
Device Descriptor: bcdUSB: 0x0200 bDeviceClass: 0x00 bDeviceSubClass: 0x00 bDeviceProtocol: 0x00 bMaxPacketSize0: 0x40 (64) idVendor: 0xC251 idProduct: 0x2201 bcdDevice: 0x0100 iManufacturer: 0x01 0x0409: "Keil Software" iProduct: 0x02 0x0409: "Keil MCB1700 HID" iSerialNumber: 0x03 0x0409: "0001A0000000" bNumConfigurations: 0x01 ConnectionStatus: DeviceConnected Current Config Value: 0x00 Device Bus Speed: Full Device Address: 0x02 Open Pipes: 0 Configuration Descriptor: wTotalLength: 0x0029 bNumInterfaces: 0x01 bConfigurationValue: 0x01 iConfiguration: 0x00 bmAttributes: 0x80 (Bus Powered ) MaxPower: 0x32 (100 Ma) Interface Descriptor: bInterfaceNumber: 0x00 bAlternateSetting: 0x00 bNumEndpoints: 0x02 bInterfaceClass: 0x03 (HID) bInterfaceSubClass: 0x00 bInterfaceProtocol: 0x00 iInterface: 0x04 0x0409: "HID" HID Descriptor: bcdHID: 0x0100 bCountryCode: 0x00 bNumDescriptors: 0x01 bDescriptorType: 0x22 wDescriptorLength: 0x0024 Endpoint Descriptor: bEndpointAddress: 0x81 IN Transfer Type: Interrupt wMaxPacketSize: 0x012C (300) bInterval: 0x01 Endpoint Descriptor: bEndpointAddress: 0x01 OUT Transfer Type: Interrupt wMaxPacketSize: 0x012C (300) bInterval: 0x01
And with the software USBlyser, i don't see the "Interface 0 HID Report Descriptor". (I have an exclamation-mark on the USB) I searched the forum but I found nothing for my problem. if someone has an idea? thank you.
HID device can exchange reports greater than 64 bytes. But wMaxPacketSize of the interrupt endpoints can't go over 64 bytes (on Full-Speed) - It's the reason why your device fails enumeration. On the firmware, such a large report is split into 64 bytes packets, and the packets are exchanged over the interrupt endpoints. Host application sends / receives such large report in a single write/read call. On the PC, host controller splits / gather packets.
For the details, see this topic. This topic is also applied to lpc1768, without any change.
USB HID reports longer than 64 bytes on lpc2141 http://www.keil.com/forum/12679/
Tsuneo
Hi Tsuneo,
thank you, I realized my mistake.
Now, I fixed my wMaxPacketSize IN and OUT at 0x0040 (64bytes) and my PC fully recognize my USB-HID.
I come now to send the PC to the LPC more than 64 bytes, but not the LPC to the PC.
Here is my example :
__task void USB_EndPoint1 (void) { U16 evt; static U32 report_size=0; 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[report_size] ); // read out the output report if(report_size==HID_OUTPUT_REPORT_BYTES) { memcpy(InReport, OutReport, report_size ); report_size=0; 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 } } if (evt & USB_EVT_IN) // IN EP1 interrupt comes os_sem_send( USB_IN_EP1_Semaphore ); // IN EP1 is free } }
When I look with USBlyzer, it warns me of bytes that will come but I do not see them. Reception is not acknowledged.
I understand that the packets are mince by 64. But the function USB_WriteEP() does not cut in blocks of 64? do support the function more than 64 bytes? do I change it?
U32 USB_WriteEP (U32 EPNum, U8 *pData, U32 cnt) { U32 n; os_mut_wait(USB_HW_Mutex, 0xFFFF); LPC_USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_WR_EN; LPC_USB->USBTxPLen = cnt; for (n = 0; n < (cnt + 3) / 4; n++) { LPC_USB->USBTxData = *((__packed U32 *)pData); pData += 4; } LPC_USB->USBCtrl = 0; WrCmdEP(EPNum, CMD_VALID_BUF); os_mut_release(USB_HW_Mutex); return (cnt); }
> But the function USB_WriteEP() does not cut in blocks of 64?
No it doesn't. USB_WriteEP() sends a packet, up to 64 bytes (wMaxPacketSize). Like the OUT endpoint, your firmware has to split the report into 64 bytes packets. Each packets is passed to USB_WriteEP() in USB_EVT_IN
__task void USB_EndPoint1 (void) { U16 evt; static U32 out_report_size = 0; static U32 in_report_size = 0; U32 in_index; U32 in_send_size; 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 // read out the output report out_report_size += USB_ReadEP( HID_EP_OUT, &OutReport[out_report_size] ); if(out_report_size == HID_OUTPUT_REPORT_BYTES) { // wait until IN EP is available os_sem_wait( USB_IN_EP1_Semaphore, 0xffff ); // now, IN EP and its context is available memcpy(InReport, OutReport, out_report_size ); in_report_size = out_report_size; in_index = 0; out_report_size = 0; // force EP1 IN interrupt manually LPC_USB->USBEpIntSet = 1 << EPAdr(HID_EP_IN); } } if (evt&USB_EVT_IN) { // IN EP1 interrupt comes if ( in_report_size == 0 ) { // this interrupt is caused by the last packet? os_sem_send( USB_IN_EP1_Semaphore ); // IN EP1 is free } else { // there remains bytes to be sent in_send_size = HID_IN_EP_MAXPACKET_SIZE; // pick up a packet size if ( in_report_size < HID_IN_EP_MAXPACKET_SIZE ) { in_send_size = in_report_size; } // pass it to the endpoint USB_WriteEP( HID_EP_IN, InReport + in_index, in_send_size ); in_report_size -= in_send_size; // move counter and index by sent size in_index += in_send_size; } } }
Aha, missed on this line
static U32 in_index;
hi tsuneo,
thank for you help.
If I fixed my reports a 64 and I send several packets, there is no real difference ?