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 multiple packet problem

Trying to send an InReport > 64 bytes. Read all threads(thanks Tsuneo) but still not working. That is too say, I'm using SimpleHIDWrite as my tester, 64-byte packets work fine. If I run this code, sending a 65-byte In Report using 2-packets, I get from SimplHIDWrite "Get Report Error: CRC mismatch (17)". Any help much appreciated!

BOOL HID_GetReport (void)
{

// ReportID = SetupPacket.wValue.WB.L;
switch (SetupPacket.wValue.WB.H)
{
    case HID_REPORT_INPUT:
        //We've been asked to report, go get report and send 1st packet
        GetInReport();
        //memcpy(&EP0Buf[0],(u8*)&MyInReport[0],sizeof(MyInReport));
        //memcpy(&EP0Buf[0],(u8*)&MyInReport[0],64);
        break;
    case HID_REPORT_OUTPUT:
        return (FALSE);          // Not Supported
    case HID_REPORT_FEATURE:
        /* EP0Buf[] = ...; */
        /* break; */
        return (FALSE);          // Not Supported
 }
        return (TRUE);
}


*******************************************************************

void GetInReport (void)
{

        // Check if PBINT is pressed
        if((IOPIN0 & PBINT) == 0)
        {       //just add some data for now
                MyInReport[0] = 0xC1;
                MyInReport[1] = 0xD1;
                MyInReport[63] = 0x63;
        }
        else
        {       //just add some data for now
                MyInReport[0] = 0xC0;
                MyInReport[1] = 0xD0;
                MyInReport[63] = 0x63;
        }
        VICIntEnClr  |= 0x00400000;            // Disable USB Interrupt
        USB_WriteEP(0x81, &MyInReport[0], 64); //Send 1st packet, 64 bytes
        iNextInPacket = 1;                     //Set flag for EP1 ISR
        VICIntEnable |= 0x00400000;            // Enable USB Interrupt

}

***********************************************************************

void USB_EndPoint1 (DWORD event)
{

        switch (event)
        {
                case USB_EVT_IN:
                    if(iNextInPacket)
                    {  //OK, more data, send second packet (1-byte, total of 65-byte report)
                          iNextInPacket = 0;
                          USB_WriteEP(0x81, &MyInReport[64], 1);
                    }
                    break;
        }
}

Parents Reply Children
  • You don't touch to your MCU type number, but Keil's USB stack is almost common for various MCUs, except for the low-level routines. Get_Report process is also common. I picked up LPC17xx USBHID code here.

    The problem lies in Keil's HID implementation.

    USBHID example expects that the input report is loaded in InReport[] in GetInReport().
    The report is copied to EP0Buf[] at HID_GetReport(), as follows.

    hiduser.c
    
    uint32_t HID_GetReport (void) {
    
      /* ReportID = SetupPacket.wValue.WB.L; */
      switch (SetupPacket.wValue.WB.H) {
        case HID_REPORT_INPUT:
          GetInReport();
          EP0Buf[0] = InReport;
          break;
    

    In USB_EndPoint0(), The address of EP0Buf[] is registered to EP0Data.pData after HID_GetReport() call. And then, the stack code takes care of the rest, including multi-packets transfer.

    usbcore.c
    
    void USB_EndPoint0 (uint32_t event) {
    
      switch (event) {
        case USB_EVT_SETUP:
          USB_SetupStage();
          USB_DirCtrlEP(SetupPacket.bmRequestType.BM.Dir);
          EP0Data.Count = SetupPacket.wLength;     /* Number of bytes to transfer */
          switch (SetupPacket.bmRequestType.BM.Type) {
            ...
            ...
    #if USB_CLASS
            case REQUEST_CLASS:
              switch (SetupPacket.bmRequestType.BM.Recipient) {
                ...
                case REQUEST_TO_INTERFACE:
    #if USB_HID
                  if (SetupPacket.wIndex.WB.L == USB_HID_IF_NUM) {           /* IF number correct? */
                    switch (SetupPacket.bRequest) {
                      case HID_REQUEST_GET_REPORT:
                        if (HID_GetReport()) {
                          EP0Data.pData = EP0Buf;   // <----------- the problem is here
                          USB_DataInStage();                                 /* send requested data */
                          goto setup_class_ok;
                        }
                        break;
    

    However, the size of EP0Buf[] is 64 bytes, at most. LPC17xx example sets it to 8.

    usbcfg.h
    #define USB_MAX_PACKET0     8
    
    usbcore.c
    uint8_t  EP0Buf[USB_MAX_PACKET0];
    

    The implementation of Control Transfer process supports multi-packets transfer, successfully. But above HID implementation spoils it. You may improve it as follows.

    hiduser.c
    
    uint32_t HID_GetReport (void) {
    
      /* ReportID = SetupPacket.wValue.WB.L; */
      switch (SetupPacket.wValue.WB.H) {
        case HID_REPORT_INPUT:
            //
            // fill your_custom_buffer[] with a input report, here
            //
            EP0Data.pData = your_custom_buffer;   // pass your buffer to the stack
    

    And comment "EP0Data.pData = EP0Buf;" line on USB_EndPoint0()

    usbcore.c
    
    void USB_EndPoint0 (uint32_t event) {
       ...
                      case HID_REQUEST_GET_REPORT:
                        if (HID_GetReport()) {
                   //     EP0Data.pData = EP0Buf;  // comment this line
                          USB_DataInStage();                                 /* send requested data */
    

    Tsuneo

  • Thanks, controller is LPC2148. I understand your fix and attempted, still get error from SimpleHIDWrite of "GET REPORT ERROR: Data error (cyclic redundancy error) (17)". We never even get to the HID_GetReport() code. Must be that it errors when attempting to do a GetReport call of > 64 bytes?
    Anyway, couldn't your fix just be to increase the size of EP0Buf?