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

Some fundamental questions regarding the USB HID example

Hi there!
I'm still trying to get around USB HID communication. To that end I've added Keil's HIB example to my project (some LPC2478). Since it's lacking the buttons and LEDs that the example is expecting, I've slightly modified the user interface: the data provided by my device is the RTC's seconds, while the data sent to the device gets output to the LCD. Now everything is fine, data gets transferred to the PC every 32ms (as specified by the descriptor).

My general questions are:
1. In terms of the example project, do I work in usbuser.c or hiduser.c? I've commented out HID_GetReport and HID_SetReport, and still my device works. So obviously what's being called is USB_EndPoint1. Why is it that I have to declare my device an HID, and in the end the HID stuff doesn't even execute?
2. The USB Set Configuration Request is issued once, during enumeration, isn't it?
3. After reading a lot of Tsuneo's posts, I think there's two different ways that I can transfer data to/from the device: either via the control endpoint, or via the endpoints specified in my descriptor. So why do I even go through the trouble of defining my own endpoints?
5. How does "one interrupt-type data transfer" proceed? I think, it's something like: - the PC sends an InReport to the device, causing a USB_EVT_OUT there which leads to the execution of USB_EndPoint1. - Now by some magic, USB_EndPoint1 is called again with an argument of USB_EVT_IN. Is this somehow similar to reality?

Any answers would be greatly appreciated. I'm struggling with Axelson's USB Complete, with lots of forum threads (thanks, Tsuneo), but can't yet get a grip on this whole USB business.

Kind regards,
Peter

Parents Reply Children
  • Maybe, you didn't yet read the posts I told to you on your another post.
    Here is excerpts from the posts.



    http://www.keil.com/forum/15613/
    24-Sep-2009 17:48 GMT

    Even if your PC application doesn't read any input report, HID device driver (*1) repeats IN transactions at the specified interval without break.

    I'll show you how HID example handles the interrupt IN endpoint.

    This is an excerpt from KEIL HID implementation.
    LPC2368 / LPC2378 USB HID (Human Interface Device) Example
    http://www.keil.com/download/docs/335.asp

    usbuser.c
    
    #if USB_CONFIGURE_EVENT
    void USB_Configure_Event (void) {
    
      if (USB_Configuration) {                  /* Check if USB is configured */
        GetInReport();
        USB_WriteEP(0x81, &InReport, sizeof(InReport));
      }
    }
    #endif
    
    void USB_EndPoint1 (DWORD event) {
    
      switch (event) {
        case USB_EVT_IN:
          GetInReport();
          USB_WriteEP(0x81, &InReport, sizeof(InReport));
          break;
      }
    }
    

    USB_Configure_Event() is called when Set_Configuration request comes from host on enumeration. In this routine, an input report is loaded to the EP1 IN buffer using USB_WriteEP(). This report is the first one. When host starts to repeat IN transactions just after enumeration, this report is sent to the host. And then, USB interrupt occurs at the IN EP1.

    On this interrupt, USB_EndPoint1() is called.
    This routine fills the endpoint buffer with a report using USB_WriteEP().
    This report is sent to host at the next IN transaction after the specified interval (bInterval).
    Another endpoint interrupt occurs, and USB_EndPoint1() is called again.

    In this way, USB_EndPoint1() is called repeatedly, at bInterval.

    If you put nothing to the endpoint buffer in USB_EndPoint1(), what happens?
    No report is sent to the host, and no endpoint interrupt occurs.
    The sequence stops, USB_EndPoint1() is never called any more,
    until you fill the endpoint buffer with USB_WriteEP().

    (*1) Actually, it is the host controller which repeats IN transactions periodically. HID device driver keeps IN transfer, putting one after another.



    26-Sep-2009 03:46 GMT
    The evil of this HID example is that it gives a fixed idea - read/write of endpoint buffer should be done just in the endpoint ISR. It's wrong. Rather, read/write in the endpoint ISR is a rare case in the real world code.

    You may call USB_WriteEP(), at any where, at any timing as you like (unless the EP buffer is still occupied by the last write). For example, you may call USB_WriteEP() in a timer ISR, which scans ports for keypads. You may call in ADC ISR, just when a sensor input shows change.

    These ISRs should have the same priority (FAST/SLOW) as USB ISR, so that USB_WriteEP() calls from both ISRs don't interrupt each other. When you call USB_WriteEP() on main line code, disable USB interrupt temporarily around USB_WriteEP() call. Or make a SWI which calls USB_WriteEP().

    Tsuneo