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

HID CONTROL TRANSFERS

Something curious is happening with my USB HID device.

It is a Full-speed Device. The curious thing is that my VB software transfers 64 bytes of data (EP0 CONTROL TRANSFER) to the device only one time each 05 SOF signals of the USB line. So, instead of 64 KB/s I am only having 64/5 Kb/s data transfer rate.

I have even set my VB software to run in High priority mode - So it has nothing to do with Windows priorities.

Would anyone have a clue how I can increase the data transfer rate ?

Parents
  • Hi, Tsuneo,

    Ok. Thanks. Indeed you are right. I forgot that the 03 CONTROL TRANSFER stages take up 03 FRAMES. Strange that the HID specification says that it can reach 64 KBytes/sec date rate. Since, HID´s only use CONTROL TRANSFERS as DATA OUT, I don´t see how they can achieve 64 KB/sec.

    To use the OUT1PIPE, I would have to write a specific device driver, wouldn´t I ? I don´t know how to write Device Drivers. Would you know how I can achieve a higher data rate without having to write a specific device driver ?

    Thanks

    Antonio

Reply
  • Hi, Tsuneo,

    Ok. Thanks. Indeed you are right. I forgot that the 03 CONTROL TRANSFER stages take up 03 FRAMES. Strange that the HID specification says that it can reach 64 KBytes/sec date rate. Since, HID´s only use CONTROL TRANSFERS as DATA OUT, I don´t see how they can achieve 64 KB/sec.

    To use the OUT1PIPE, I would have to write a specific device driver, wouldn´t I ? I don´t know how to write Device Drivers. Would you know how I can achieve a higher data rate without having to write a specific device driver ?

    Thanks

    Antonio

Children
  • > Since, HID´s only use CONTROL TRANSFERS as DATA OUT, I don´t see how they can achieve 64 KB/sec.

    HID interface can have an interrupt OUT endpoint, optionally.
    The rate assumes this pipe.

    > To use the OUT1PIPE, I would have to write a specific device driver, wouldn´t I ?

    The default HID device drivers on PC support the interrupt OUT pipe, on most of major OS (Windows, MacOS X, Linux hiddev).

    For Windows, WriteFile() to the HID device is redirected to the interrupt OUT pipe, when the device has this pipe.
    HidD_SetOutputReport() and HidD_GetInputReport() always issue Control transfer, which carries Set_Report()/Get_Report(), respectively.

    Tsuneo

  • Even over an interrupt OUT endpoint on the HID interface, you need to send a large report at a time, to achieve 64 kBytes/sec (64000 bytes/sec). When your PC app sends 64 bytes report repeatedly, each WriteFile() call takes scheduling overhead of 1-2 USB frames (1-2 ms).

    For example, declare 4 Kbytes output report on the report descriptor,
    and send this report in single WriteFile() call from the PC app. The PC host controller splits the transfer into 64-bytes packets (wMaxPacketSize of the interrupt OUT endpoint). The HID device receives the 64-bytes packets 64 times (64 x 64 = 4096) at the interrupt OUT endpoint. This transfer also takes 1-2 ms overhead at the first packet. But following packets are sent without overhead. (of course, bInterval of the endpoint is set to 1 ms)

    If you want to have two or more output reports of different size, apply report ID to each output report.

    Tsuneo

  • Hi, Tsuneo,

    Vey good hint. I will implement that and will let you know the results.

    Thank you

    Antonio

  • Hi, Tsuneo,

    My HID Device has an EP2IN pipe (64 bytes,Interrupt, 10 ms poll time) and EP1OUT PIPE (64 bytes, Interrupt, 1 ms poll time) and the EP0 PIPE.

    I know it has been correctly configured because I have a USB PACKET ANALYZER and the enumeration does correctly define the EP1OUT pipe.

    Even by defining a big report out (128 Bytes for a test) and using the writefile command has transfered the bytes to the device by using the control transfer instead of the EP1OUT PIPE. should I define a bigger report to have WRITEFILE and the HID drivers choose EP1OUT ? In that case, how can I define a big report in the report descriptor - My understanding is that afeter 95h I have only one byte to define the size of the output report ...

    Antonio

  • > My HID Device has an EP2IN pipe (64 bytes,Interrupt, 10 ms poll time) and EP1OUT PIPE (64 bytes, Interrupt, 1 ms poll time) and the EP0 PIPE.
    > Even by defining a big report out (128 Bytes for a test) and using the writefile command has transfered the bytes to the device by using the control transfer instead of the EP1OUT PIPE.

    Sound like the EP1OUT PIPE is not recognized by the HID device driver on the PC.

    Using USBView, read out the descriptors from the device.
    And post the result.

    MS USBView on FTDI site
    www.ftdichip.com/.../usbview.zip

    Tsuneo

  • In fact that is very strange.
    The USB Packet analyzer (Plugged to another computer) does recognize the enumeration and tells me that the device has 02 endpoints. EP2IN AND EP1OUT. But the USBVIEW utility shows the EP2IN as the only pipe abailable. Not EP1OUT. If I inver the order in which the descriptors are sent to the host, then EP1OUT recognized by the host, but not EP2IN. It seems to be a wrong total number of bytes in the configuration descriptor declaration, but I recounted the number of byte and they are correctly described and asked for (29h = 41 bytes)
    Below please find the result of USB VIEW and the descriptors.

    Device Descriptor:
    bcdUSB: 0x0110
    bDeviceClass: 0x00
    bDeviceSubClass: 0x00
    bDeviceProtocol: 0x00
    bMaxPacketSize0: 0x40 (64)
    idVendor: 0x0B6A (Maxim Integrated Products)
    idProduct: 0x7889
    bcdDevice: 0x1234
    iManufacturer: 0x01
    iProduct: 0x02
    iSerialNumber: 0x03
    bNumConfigurations: 0x01

    ConnectionStatus: DeviceConnected
    Current Config Value: 0x01
    Device Bus Speed: Full
    Device Address: 0x01
    Open Pipes: 1

    Endpoint Descriptor:
    bEndpointAddress: 0x82 IN
    Transfer Type: Interrupt
    wMaxPacketSize: 0x0040 (64)
    bInterval: 0x0A

    DESCRIPTORS THAT I USE (In Hexadecimal)

    DEVICE_DESCRIPTOR
    12
    01
    10
    01
    00
    00
    00
    40
    6A
    0B
    89
    78
    34
    12
    01
    02
    03
    01

    CONFIGURATION_DESCRIPTOR
    09
    02
    29
    00
    01
    01
    00
    E0
    01

    'INTERFACE DESCRIPTOR
    09
    04
    00
    00
    01
    03
    00
    00
    00

    'HID CLASS DESCRIPTOR
    09
    21
    10
    01
    00
    01
    22
    1C
    00

    'ENDPOINT DESCRIPTOR EP2IN
    07
    05
    82
    03
    40
    00
    0A

    'ENDPOINT DESCRIPTOR EP1OUT
    07
    05
    01
    03
    40
    00
    01

    REPORT DESCRIPTOR
    06
    A0
    FF
    09
    01
    A1
    01
    09
    01
    15
    00
    25
    FF
    75
    08
    95
    40' INPUT REPORT LENGHT
    81
    00
    09
    02
    75
    08
    95
    80' OUTPUT REPORT LENGHT
    91
    00
    C0

  • The wTotalLength field of the configuration descriptor is fine.
    But your interface descriptor claims just single endpoint :-)

    'INTERFACE DESCRIPTOR
    09
    04
    00
    00
    01 <---- bNumEndpoints, 02 for two endpoints
    03
    00
    00
    00

    Report descriptor is revised as follows.

            db 06h, 00h, ffh           ; USAGE_PAGE (Vendor Defined Page 1)
            db 09h, 01h                ; USAGE (Vendor Usage  1)
            db a1h, 01h                ; COLLECTION (Application)
                                       ;; ---- common globals ----
            db 15h, 00h                ;   LOGICAL_MINIMUM (0)
            db 26h, ffh,  0h           ;   LOGICAL_MAXIMUM (255)
            db 75h, 08h                ;   REPORT_SIZE (8)
                                       ;; ---- input report ----
            db 95h, 40h                ;   REPORT_COUNT (64)
            db 09h, 01h                ;   USAGE (Vendor Usage  1)
            db 81h, 02h                ;   INPUT (Data,Var,Abs)
                                       ;; ---- output report ----
            db 95h, 80h                ;   REPORT_COUNT (128)
            db 09h, 01h                ;   USAGE (Vendor Usage  1)
            db 91h, 02h                ;   OUTPUT (Data,Var,Abs)
            db c0h                     ; END_COLLECTION
    


    Tsuneo

  • Hi, Tsuneo,

    It worked. I cannot thank you enough. You took a truck out of my back !!!!

    Just a last question. How can I declare the output report as having, say, 4096 bytes - (Or 1000h Bytes).
    The field after the 95h can only be one byte long isn´t it true ?

    Thanks

    Antonio

  • Make it using "HID Descriptor Tool" from USB.org

    HID Descriptor Tool
    www.usb.org/.../dt2_4.zip

    char ReportDescriptor[28] = {
        0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 1)
        0x09, 0x01,                    // USAGE (Vendor Usage  1)
        0xa1, 0x01,                    // COLLECTION (Application)
                                       // ---- common globals ----
        0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
        0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
        0x75, 0x08,                    //   REPORT_SIZE (8)
                                       // ---- input report ----
        0x95, 0x40,                    //   REPORT_COUNT (64)
        0x09, 0x01,                    //   USAGE (Vendor Usage  1)
        0x81, 0x02,                    //   INPUT (Data,Var,Abs)
                                       // ---- output report ----
        0x96, 0x00, 0x10,              //   REPORT_COUNT (4096)    <--------
        0x09, 0x01,                    //   USAGE (Vendor Usage  1)
        0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
        0xc0                           // END_COLLECTION
    };
    


    Tsuneo

  • IT WORKED !!! Thank you so much.

    If you ever need anything please let me know.

    Regards,

    Antonio

  • Hi, Tsuneo,

    How can I define a second output report in the report descriptor so that I can also send only 64 Bytes (Only one packet) instead of always having to send the 4096 bytes of the big report ?

    Thanks

    Antonio

  • > How can I define a second output report in the report descriptor so that I can also send only 64 Bytes (Only one packet) instead of always having to send the 4096 bytes of the big report ?

    Define more than single input/output report using Report ID on the report descriptor.

    char ReportDescriptor[36] = {
        0x06, 0x00, 0xff,              // USAGE_PAGE (Vendor Defined Page 1)
        0x09, 0x01,                    // USAGE (Vendor Usage  1)
        0xa1, 0x01,                    // COLLECTION (Application)
                                       // ---- common globals ----
        0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
        0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
        0x75, 0x08,                    //   REPORT_SIZE (8)
                                       // ---- input report 1 ----
        0x85, 0x01,                    //   REPORT_ID (1)
        0x95, 0x3f,                    //   REPORT_COUNT (63)
        0x09, 0x01,                    //   USAGE (Vendor Usage  1)
        0x81, 0x02,                    //   INPUT (Data,Var,Abs)
                                       // ---- output report 1 ----
        0x09, 0x01,                    //   USAGE (Vendor Usage  1)
        0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
                                       // ---- output report 2 ----
        0x85, 0x02,                    //   REPORT_ID (2)
        0x96, 0x00, 0x10,              //   REPORT_COUNT (4096)
        0x09, 0x01,                    //   USAGE (Vendor Usage  1)
        0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
        0xc0                           // END_COLLECTION
    };
    

    Each report precedes 1 byte report ID, for both of input and output.

    Tsuneo

  • Hi, tsuneo,

    You should write a book on USB, my friend. It would certainly be better than the John Hide´s and Jan Axelson´s books.

    Thanks once more

    Antonio

  • Hi, Tsuneo,

    I still have a problem:

    This is how microsoft´s USBVIEW sees the device:

    Device Descriptor:
    bcdUSB: 0x0110
    bDeviceClass: 0x00
    bDeviceSubClass: 0x00
    bDeviceProtocol: 0x00
    bMaxPacketSize0: 0x40 (64)
    idVendor: 0x0B6A (Maxim Integrated Products)
    idProduct: 0x7889
    bcdDevice: 0x1234
    iManufacturer: 0x01
    iProduct: 0x02
    iSerialNumber: 0x03
    bNumConfigurations: 0x01

    ConnectionStatus: DeviceConnected
    Current Config Value: 0x01
    Device Bus Speed: Full
    Device Address: 0x02
    Open Pipes: 2

    Endpoint Descriptor:
    bEndpointAddress: 0x82 IN
    Transfer Type: Interrupt
    wMaxPacketSize: 0x0040 (64)
    bInterval: 0x0A

    Endpoint Descriptor:
    bEndpointAddress: 0x01 OUT
    Transfer Type: Interrupt
    wMaxPacketSize: 0x0040 (64)
    bInterval: 0x01

    According to your hints, I used the following report descriptor

    Report Descriptor:

    06 00 FF
    09 01
    A1 01
    ‘globals
    15 00
    26 FF 00
    75 08
    ‘input report - I guess #0
    85 01
    95 40
    09 01
    81 02
    ‘output report #1
    09 01
    91 02
    ‘output report #2
    85 03
    96 00 10
    09 01
    91 02
    C0

    I can send corretly 64 bytes Through report #1 and 4096 bytes through report #2

    But although the device really sends an IN PACKET (I have a USB Packet analyzer in the USB line and I can see the IN PACKET being read and acknowlodged by the host), the Readfile function does not get the data and keep giving me a return of 0 bytes read …

    What can going wrong ?

    Antonio

  • > I can send corretly 64 bytes Through report #1 and 4096 bytes through report #2

    You've changed the report descriptor as follows,

    06 00 FF   // USAGE_PAGE (Vendor Defined Page 1)
    09 01      // USAGE (Vendor Usage  1)
    A1 01      // COLLECTION (Application)
    ‘globals
    15 00      //   LOGICAL_MINIMUM (0)
    26 FF 00   //   LOGICAL_MAXIMUM (255)
    75 08      //   REPORT_SIZE (8)
    ‘input report - I guess #0
    85 01      //   REPORT_ID (1)
    95 40      //   REPORT_COUNT (64)     <------
    09 01      //   USAGE (Vendor Usage  1)
    81 02      //   INPUT (Data,Var,Abs)
    ‘output report #1
    09 01      //   USAGE (Vendor Usage  1)
    91 02      //   OUTPUT (Data,Var,Abs)
    ‘output report #2
    85 03      //   REPORT_ID (3)         <------
    96 00 10   //   REPORT_COUNT (4096)
    09 01      //   USAGE (Vendor Usage  1)
    91 02      //   OUTPUT (Data,Var,Abs)
    C0         // END_COLLECTION
    

    With this report descriptor,
    On the device side, the output report ID 1 is received in 65 bytes.
    The first byte is Report ID (1 byte = 0x01), and 64 bytes body follows.
    It is split into two transactions (64, 1).
    In above post, I've chosen 63 byte for this output report, to keep it in single transaction.

    Similarly, report ID 3 is received in 4097 bytes, 1 byte report ID + 4096 bytes body

    > ‘input report - I guess #0

    Report ID 0 is reserved for the default - when no report ID appears on the report descriptor.
    To define report ID explicitly, arbitrary number, other than 0, is selected.

    > the Readfile function does not get the data and keep giving me a return of 0 bytes read ...

    As the format of the coming input report is wrong, HID device driver drops the report.

    The device sends 65 bytes input report, one byte report ID (1), following 64 bytes body.
    This report is sent in two transactions (64, 1).

    If you want to send it in single transaction, set the length (REPORT_COUNT) to 63.

    Tsuneo