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

Expanding In/Out Reports on Keil USB HID example code

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.

Parents
  • 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
    
      }
    }
    
    
    

Reply
  • 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
    
      }
    }
    
    
    

Children
No data