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 IN & OUT Reports through Control & Interrupt transfer

Hi,

dig around with/for HID reports, i ran into a strange problem within a WinXP test application that i wrote.

Following configuration:
1 (non compound) device with
1 config with
1 interface (HID) with
2 endpoints wheras
1 interrupt in (ep1) and
1 interrupt out (ep2)

Setting and requesting the reports through control transfer (ep0) works like a charme, but with interrupt transfers the host application first sets an report without any problem, but the request of the following in interrupt leads to a problem. I figured out that the in interrupt terminates on the wrong (ep2) endpoint.
within the win api i used readfile in an overlapped mode, but there is no chance to define a endpoint. why isn't the interface interpreted correctly by the hostapp? or is there something to define elsewhere?

thx & kr

Parents
  • > in fact it looks like a "normal" time out within the host, and therefor the tranfer is CHANCELLED.

    PC HID device driver doesn't set timeout on the interrupt IN endpoint (EP).

    As I'm not using USBLyzer usually, I don't know how it looks like exactly (though sniffers display is almost similar)
    For confirmation, I made up a HID device, which does just enumeration but nothing else.
    And ran it on USBLyzer (trial version) and on a hardware bus analyzer.
    The device is left connected for 10 min after enumeration.

    Hardware bus analyzer:
    - After enumeration, NAKs to the interrupt IN EP repeated at the rate of bInterval for these 10 min seamlessly.
    USBLyzer:
    - After enumeration, URB "Bulk or Interrupt Transfer" is issued to the interrupt IN EP, immediately.
    But no completion appears, including (Canceled), for this 10 min.

    Next, I modified the device firmware to put STALL to the interrupt IN EP, 1 sec after enumeration.
    Here is the USBLyzer trace

    URB  0051        1:42:26.306 Bulk or Interrupt Transfer 1024 bytes buffer in 01:00:81 85673DE8h USBPDO-5 usbhub 8561EE48h
    URB  0052        1:42:26.306 Bulk or Interrupt Transfer 1024 bytes buffer in 01:00:81 85673DE8h USBPDO-5 usbhub 8564D5C8h
    ...
    ...
    URB  0070-0051   1:42:27.134 Bulk or Interrupt Transfer                   in 01:00:81 85673DE8h USBPDO-5 usbhub 8561EE48h Unsuccessful (Stall PID)
    KmIO 0071        1:42:27.134 Internal USB Get Port Status                             85673DE8h USBPDO-5 usbhub 8562B880h
    KmIO 0072-0071   1:42:27.134 Internal USB Get Port Status                             85673DE8h USBPDO-5 usbhub 8562B880h Success
    URB  0073        1:42:27.134 Abort Pipe                                      01:00:81 85673DE8h USBPDO-5 usbhub 8562B880h
    URB  0074-0052   1:42:27.134 Bulk or Interrupt Transfer                   in 01:00:81 85673DE8h USBPDO-5 usbhub 8564D5C8h Cancelled (Canceled)
    URB  0075-0073   1:42:27.134 Abort Pipe                                      01:00:81 85673DE8h USBPDO-5 usbhub 8562B880h Success (Success)
    


    The hardware bus analyzer caught STALL exactly.
    USBLyzer reports "Unsuccessful (Stall PID) - USBD_STATUS_STALL_PID" for STALL from the device.
    At the same time, it reports "Cancelled (Canceled) - USBD_STATUS_CANCELED" to the paired URB.

    OK, "Cancelled" doesn't mean STALL. Instead, it means canceled (USBD_STATUS_CANCELED) by HID device driver.
    Anyway, this pattern doesn't match to your trace.

    "Cancelled" is caused by the PC side.
    Selective Suspend?
    Please post more trace around "Cancelled", including PnP events.



    > Back to the source some questions:
    > .) report size is 64(id1-in/out) / 1024(id2-in) byte
    > .) therefor the hostapp has to malloc a buffer of that size
    > .) sending an out report by writing the id (1) in the first byte leads to 63 byte data
    > .) requesting an in report also writing the id (1 or 2) in the first byte leads to an 63 or 1023 byte report (always stored in a 1024 byte "frame" within the host's memory)

    > right?

    Yes. PC HID driver works so.

    Tsuneo

Reply
  • > in fact it looks like a "normal" time out within the host, and therefor the tranfer is CHANCELLED.

    PC HID device driver doesn't set timeout on the interrupt IN endpoint (EP).

    As I'm not using USBLyzer usually, I don't know how it looks like exactly (though sniffers display is almost similar)
    For confirmation, I made up a HID device, which does just enumeration but nothing else.
    And ran it on USBLyzer (trial version) and on a hardware bus analyzer.
    The device is left connected for 10 min after enumeration.

    Hardware bus analyzer:
    - After enumeration, NAKs to the interrupt IN EP repeated at the rate of bInterval for these 10 min seamlessly.
    USBLyzer:
    - After enumeration, URB "Bulk or Interrupt Transfer" is issued to the interrupt IN EP, immediately.
    But no completion appears, including (Canceled), for this 10 min.

    Next, I modified the device firmware to put STALL to the interrupt IN EP, 1 sec after enumeration.
    Here is the USBLyzer trace

    URB  0051        1:42:26.306 Bulk or Interrupt Transfer 1024 bytes buffer in 01:00:81 85673DE8h USBPDO-5 usbhub 8561EE48h
    URB  0052        1:42:26.306 Bulk or Interrupt Transfer 1024 bytes buffer in 01:00:81 85673DE8h USBPDO-5 usbhub 8564D5C8h
    ...
    ...
    URB  0070-0051   1:42:27.134 Bulk or Interrupt Transfer                   in 01:00:81 85673DE8h USBPDO-5 usbhub 8561EE48h Unsuccessful (Stall PID)
    KmIO 0071        1:42:27.134 Internal USB Get Port Status                             85673DE8h USBPDO-5 usbhub 8562B880h
    KmIO 0072-0071   1:42:27.134 Internal USB Get Port Status                             85673DE8h USBPDO-5 usbhub 8562B880h Success
    URB  0073        1:42:27.134 Abort Pipe                                      01:00:81 85673DE8h USBPDO-5 usbhub 8562B880h
    URB  0074-0052   1:42:27.134 Bulk or Interrupt Transfer                   in 01:00:81 85673DE8h USBPDO-5 usbhub 8564D5C8h Cancelled (Canceled)
    URB  0075-0073   1:42:27.134 Abort Pipe                                      01:00:81 85673DE8h USBPDO-5 usbhub 8562B880h Success (Success)
    


    The hardware bus analyzer caught STALL exactly.
    USBLyzer reports "Unsuccessful (Stall PID) - USBD_STATUS_STALL_PID" for STALL from the device.
    At the same time, it reports "Cancelled (Canceled) - USBD_STATUS_CANCELED" to the paired URB.

    OK, "Cancelled" doesn't mean STALL. Instead, it means canceled (USBD_STATUS_CANCELED) by HID device driver.
    Anyway, this pattern doesn't match to your trace.

    "Cancelled" is caused by the PC side.
    Selective Suspend?
    Please post more trace around "Cancelled", including PnP events.



    > Back to the source some questions:
    > .) report size is 64(id1-in/out) / 1024(id2-in) byte
    > .) therefor the hostapp has to malloc a buffer of that size
    > .) sending an out report by writing the id (1) in the first byte leads to 63 byte data
    > .) requesting an in report also writing the id (1 or 2) in the first byte leads to an 63 or 1023 byte report (always stored in a 1024 byte "frame" within the host's memory)

    > right?

    Yes. PC HID driver works so.

    Tsuneo

Children
  • hi,

    short answer only because i'm out of time today. i think i found a minor problem because the CHANCELLED disappered within the actual devstate. But the major problem still appears when an IN REPORT is requested through the interrupt ep. I now receive the interrupt within the dsp - fifo of the ep was loaded - but there is a permanent UNDERRUN. An underrun during the enumeration is ok (leads to an open transaction as mentioned above)

    Things i've changed until now:
    .) As mentioned before recode the STALL/NAK behaviour of ep's => should be OK now
    .) doublecheck the ZLPs => OK
    .) doublecheck the fifo loading => OK (hopefully) i will check this again tomorrow.

    i will post a longer trace tomorrow also.

    kr

  • Hi Tsuneo,

    did some checks on the source, but didn't find any further problem. But to be sure please confirm or correct the following IN REPORT using interrupt ep.
    .) report descriptor with in 2 reports different size & directions (as above) .)1 in/out(64) .)2 in(1024)
    .) during enum host gets HID CAPS and therefore adds one byte (why? i though the 64 is with id)
    .) the device writes data into the ep fifo and signals readiness (TX_READY). when data is smaller then the max packet size of the ep nothing has to be done. if data is bigger than maxp also nothing has to be done. only when the data size is a multiple of the maxp an aditional ZLP has to be sent.
    .) host writing report id in the first byte of buffer and readfile() from device.

    many thx!

  • > .) during enum host gets HID CAPS and therefore adds one byte (why? i though the 64 is with id)

    For this report descriptor (copied from the trace), HidP_GetCaps return these size,
    HIDP_CAPS.InputReportByteLength = 64 (= 1 ID + 63 body) bytes
    HIDP_CAPS.OutputReportByteLength = 1024 (= 1 ID + 1023 body, the greatest) bytes

    Interface 0 HID Report Descriptor Vendor-Defined 1
    Item Tag (Value) Raw Data
    Usage Page (Vendor-Defined 1) 06 00 FF
    Usage (Vendor-Defined 1) 09 01
    Collection (Application) A1 01
        Logical Minimum (0) 15 00
        Logical Maximum (255) 26 FF 00
        Report Size (8) 75 08
        Report ID (1) 85 01
        Report Count (63) 96 3F 00
        Usage (Vendor-Defined 1) 09 01
        Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
        Usage (Vendor-Defined 1) 09 01
        Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 91 02
        Report ID (2) 85 02
        Report Count (1023) 96 FF 03
        Usage (Vendor-Defined 1) 09 01
        Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
    End Collection C0
    

    > .) the device writes data into the ep fifo and signals readiness (TX_READY). when data is smaller then the max packet size of the ep nothing has to be done.
    fine.

    > if data is bigger than maxp also nothing has to be done.
    Don't write greater size than endpoint wMaxPacketSize to the endpoint.
    The rest is written when the next IN endpoint interrupt comes.

    > only when the data size is a multiple of the maxp an aditional ZLP has to be sent.
    When you send the input report of shorter size, it's fine.
    For the greatest size report, ZLP is not required.

    > .) host writing report id in the first byte of buffer and readfile() from device.
    No.
    Host can't specify coming report.
    Host always passes a buffer of the greatest size (+ report ID).
    When ReadFile returns, the first byte shows the report ID of received report.

    Tsuneo