This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

USB HID reports longer than 64 bytes on lpc2141

Hi everyone,

I'm working on a custom system monitoring device and have a requirement for a USB HID input report longer than 64 bytes. From what I've read, it's possible to send it as multiple transactions but I can't figure out how to make Keil's USBHID sample code do it.

Any ideas?

Thanks,
Jason

Parents
  • Report Descriptor
    This report descriptor defines 191 bytes Input and 150 bytes Output report

    #define INREPORT_SIZE    191
    #define OUTREPORT_SIZE   150
    
    /* HID Report Descriptor */
    const BYTE HID_ReportDescriptor[] = {
      HID_UsagePageVendor( 0x00                                   ),
      HID_Usage(           0x01                                   ),
      HID_Collection(      HID_Application                        ),
        HID_LogicalMin(    0                                      ),
        HID_LogicalMaxS(   0xFF                                   ),
        HID_ReportSize(    8                                      ),  // bits
        HID_ReportCount(   INREPORT_SIZE                          ),  // bytes
        HID_Usage(         0x01                                   ),
        HID_Input(         HID_Data | HID_Variable | HID_Absolute ),
        HID_ReportCount(   OUTREPORT_SIZE                         ),  // bytes
        HID_Usage(         0x01                                   ),
        HID_Output(        HID_Data | HID_Variable | HID_Absolute ),
      HID_EndCollection,
    };
    

    HID_ReportCount() macro supports upto 255 (single byte) as its parameter.
    For more bytes (up to 0xFFFF), apply this HID_ReportCountS() macro (two bytes)

    #define HID_ReportCountS(x)     0x96,(x&0xFF),((x>>8)&0xFF)
    

    I don't know what is the reliable maximum report size on Windows, but I recommend you less than or equal to 4 Kbytes (page size of PCI bus).



    Split the input report
    The report is split by wMaxPacketSize (endpoint descriptor) of the endpoint. It's usually 64 bytes for full-speed HID device, but confirm your descriptor definition.

    Above 191 bytes report is split into three transactions,

    64, 64, 63

    Above report descriptor defines no report ID. Then, this division is fine.
    If you use any report ID for more input-report formats, the report is preceded by the report ID, the division becomes as follows.

    (1byte report ID + 63), 64, 64

    If any other input report longer than this one is defined, this report transfer should be terminated by ZLP (Zero-Length Packet), because the last transaction matches to wMaxPacketSize

    (1byte report ID + 63), 64, 64, ZLP

    The largest report don't need to terminate with ZLP, even when it ends up with wMaxPacketSize transaction.

    Complicated? :-)



    Endpoint handling
    When the hardware finishes to collect whole data for the report, the firmware makes up the entire report on a buffer. The first transaction (64 bytes) is put to the endpoint buffer using USB_WriteEP(), in the data acquisition routine. See this post for the details.

    "HID Mouse keeps sending unneeded data!"
    http://www.keil.com/forum/docs/thread11531.asp

    The second and later transactions are handled in the endpoint ISR, USB_EndPointN. This ISR is called when the endpoint buffer becomes empty by a successful transaction. Every time the USB_EndPointN is called, put the next transaction, if any, by USB_WriteEP().

    You have to fiddle several flags and counter to make this work as expected.

    Tsuneo

Reply
  • Report Descriptor
    This report descriptor defines 191 bytes Input and 150 bytes Output report

    #define INREPORT_SIZE    191
    #define OUTREPORT_SIZE   150
    
    /* HID Report Descriptor */
    const BYTE HID_ReportDescriptor[] = {
      HID_UsagePageVendor( 0x00                                   ),
      HID_Usage(           0x01                                   ),
      HID_Collection(      HID_Application                        ),
        HID_LogicalMin(    0                                      ),
        HID_LogicalMaxS(   0xFF                                   ),
        HID_ReportSize(    8                                      ),  // bits
        HID_ReportCount(   INREPORT_SIZE                          ),  // bytes
        HID_Usage(         0x01                                   ),
        HID_Input(         HID_Data | HID_Variable | HID_Absolute ),
        HID_ReportCount(   OUTREPORT_SIZE                         ),  // bytes
        HID_Usage(         0x01                                   ),
        HID_Output(        HID_Data | HID_Variable | HID_Absolute ),
      HID_EndCollection,
    };
    

    HID_ReportCount() macro supports upto 255 (single byte) as its parameter.
    For more bytes (up to 0xFFFF), apply this HID_ReportCountS() macro (two bytes)

    #define HID_ReportCountS(x)     0x96,(x&0xFF),((x>>8)&0xFF)
    

    I don't know what is the reliable maximum report size on Windows, but I recommend you less than or equal to 4 Kbytes (page size of PCI bus).



    Split the input report
    The report is split by wMaxPacketSize (endpoint descriptor) of the endpoint. It's usually 64 bytes for full-speed HID device, but confirm your descriptor definition.

    Above 191 bytes report is split into three transactions,

    64, 64, 63

    Above report descriptor defines no report ID. Then, this division is fine.
    If you use any report ID for more input-report formats, the report is preceded by the report ID, the division becomes as follows.

    (1byte report ID + 63), 64, 64

    If any other input report longer than this one is defined, this report transfer should be terminated by ZLP (Zero-Length Packet), because the last transaction matches to wMaxPacketSize

    (1byte report ID + 63), 64, 64, ZLP

    The largest report don't need to terminate with ZLP, even when it ends up with wMaxPacketSize transaction.

    Complicated? :-)



    Endpoint handling
    When the hardware finishes to collect whole data for the report, the firmware makes up the entire report on a buffer. The first transaction (64 bytes) is put to the endpoint buffer using USB_WriteEP(), in the data acquisition routine. See this post for the details.

    "HID Mouse keeps sending unneeded data!"
    http://www.keil.com/forum/docs/thread11531.asp

    The second and later transactions are handled in the endpoint ISR, USB_EndPointN. This ISR is called when the endpoint buffer becomes empty by a successful transaction. Every time the USB_EndPointN is called, put the next transaction, if any, by USB_WriteEP().

    You have to fiddle several flags and counter to make this work as expected.

    Tsuneo

Children