USB Host polling rate issues

Figured out its something about reading the USB host shield.
I think its somewhere at void USBHIDParser::in_data(const Transfer_t *transfer) - hid.cpp, might be that packets are not properly read?

Setting mouse.move directly results in 1000hz.
 
As the person who created this thread, that their issue was resolved and that maybe you should create your own thread with as much information as possible.

Again with things like: I am pretty sure you are not testing the same way as mentioned...

Is your issue that the Model 0 mouse is not reporting 1000 times per second or that your
code reporting to the PC is not reporting 1000 times per second?
 
I tried to do that, although Paul locked that thread.
Its "Model 0 mouse is not reporting 1000 times per second" to the Teensy.
USBHost_t36 probably requires some editing, I think from 8 bit support to 16 bit support.
 
Let's continue it here. After the mess of ICS5200 threads (I have them again on my workbench - going to test this weekend) I want to prevent this situation where we get duplicate threads.

Regarding the polling rate, I recently ran the USB transmit speed benchmark and noticed it was running at only about half speed.

https://github.com/PaulStoffregen/USB-Serial-Print-Speed-Test/blob/master/usb_serial_print_speed.ino

But I'm trying it again with Ubuntu 20.04 and USB Type "Keyboard + Mouse + Joystick" and I'm getting 15455 lines/sec. At 33 bytes per line, that's about 510000 bytes per second, which is approx 8000 packets per second with 64 bytes per packet. Can't seem to reproduce the half speed result now.

I did end up getting one of those Model O mice to test this. It's sitting right behind me in a box of USB devices for testing the host library.
 
Paul,

For what it is worth, I was hacking around with a simple sketch:
Code:
#include <USBHost_t36.h>

USBHost usb_host;
USBHIDParser hid1(usb_host);
USBHIDParser hid2(usb_host);
USBHub hub(usb_host);

MouseController mouse_in(usb_host);

void setup() {
  // USB IN
  while (!Serial && millis() < 4000) ;
  Serial.begin(115200);
  Serial.println("Test mouse reads");
  usb_host.begin();
}

void loop() {
  elapsedMicros em = 0;
  uint32_t count_mouse_reads = 0;
  while (count_mouse_reads < 1000) {
    usb_host.Task();
    if (mouse_in.available())
    {
#if 0
      // Proxy Mouse
      Serial.print("Mouse: buttons = ");
      Serial.print(mouse_in.getButtons());
      Serial.print(",  mouseX = ");
      Serial.print(mouse_in.getMouseX());
      Serial.print(",  mouseY = ");
      Serial.print(mouse_in.getMouseY());
      Serial.print(",  wheel = ");
      Serial.print(mouse_in.getWheel());
      Serial.print(",  wheelH = ");
      Serial.print(mouse_in.getWheelH());
      Serial.println();
#endif      
      count_mouse_reads++;
      mouse_in.mouseDataClear();
    }
  }
  Serial.println((uint32_t)em);
  delay(250);
}

Where at first I did not think it was working, but then later I found it only output messages when the state changed...

Output: when I move the mouse a lot...
Code:
Test mouse reads
76819003
2036999
2043999
2042999
First one does not count as I waited a bit to start moving mouse...
But from this, it looks like it is polling at about 500 times per second...

Some Debug output, from the HID Dump program with debug turned on...
Code:
USB HID Device Info Program

This Sketch shows information about plugged in HID devices

*** You can control the output by simple character input to Serial ***
R - Turns on or off showing the raw data
C - Toggles showing changed data only on or off
<anything else> - toggles showing the Hid formatted breakdown of the data

USB2 PLL running
 reset waited 6
USBHS_ASYNCLISTADDR = 0
USBHS_PERIODICLISTBASE = 2000C000
periodictable = 2000C000
port change: 10001803
    connect
  begin reset
port change: 10001005
  port enabled
  end recovery
new_Device: 12 Mbit/sec
new_Pipe
enumeration:
enumeration:
enumeration:
Device Descriptor:
  12 01 10 01 00 00 00 08 8A 25 36 00 09 01 01 02 00 01 
    VendorID = 258A, ProductID = 0036, Version = 0109
    Class/Subclass/Protocol = 0 / 0 / 0
    Number of Configurations = 1
enumeration:
enumeration:
Manufacturer: SINOWEALTH
enumeration:
Product: Wired Gaming Mouse
enumeration:
Config data length = 59
enumeration:
Configuration Descriptor:
  09 02 3B 00 02 01 00 A0 F0 
    NumInterfaces = 2
    ConfigurationValue = 1
  09 04 00 00 01 03 01 02 00 
    Interface = 0
    Number of endpoints = 1
    Class/Subclass/Protocol = 3(HID) / 1(Boot) / 2(Mouse)
  09 21 11 01 00 01 22 47 00 
    HID, 1 report descriptor
  07 05 81 03 08 00 01 
    Endpoint = 1 IN
    Type = Interrupt
    Max Size = 8
    Polling Interval = 1
  09 04 01 00 01 03 01 01 00 
    Interface = 1
    Number of endpoints = 1
    Class/Subclass/Protocol = 3(HID) / 1(Boot) / 1(Keyboard)
  09 21 11 01 00 01 22 D5 00 
    HID, 1 report descriptor
  07 05 82 03 08 00 01 
    Endpoint = 2 IN
    Type = Interrupt
    Max Size = 8
    Polling Interval = 1
enumeration:
USBHub memory usage = 960
USBHub claim_device this=20007300
USBHub memory usage = 960
USBHub claim_device this=200076C0

USBDeviceInfo claim this=20006CA8

****************************************
** Device Level **
  vid=258A
  pid=36
  bDeviceClass = 0
  bDeviceSubClass = 0
  bDeviceProtocol = 0
09 04 00 00 01 03 01 02 00 09 21 11 01 00 01 22 47 00 07 05 81 03 08 00 01 09 04 01 00 01 03 01
01 00 09 21 11 01 00 01 22 D5 00 07 05 82 03 08 00 01 
HIDParser claim this=20006020
HIDParser claim this=20006660
HIDParser claim this=2000ACE0
HIDParser claim this=20004920
HIDParser claim this=20006CC0
Descriptor 4 = INTERFACE

USBDeviceInfo claim this=20006CA8

****************************************
** Interface Level **
09 04 00 00 01 03 01 02 00 09 21 11 01 00 01 22 47 00 07 05 81 03 08 00 01 09 04 01 00 01 03 01
01 00 09 21 11 01 00 01 22 D5 00 07 05 82 03 08 00 01 
 bInterfaceNumber = 0
 number end points = 1
 bInterfaceClass =    3
 bInterfaceSubClass = 1
    HID (BOOT)
 bInterfaceProtocol = 2
report descriptor size = 71
  endpoint = 81
    attributes = 3 Interrupt
    size = 8
    interval = 1
HIDParser claim this=20006020
 bInterfaceNumber =   0
 bInterfaceClass =    3
 bInterfaceSubClass = 1
 bInterfaceProtocol = 2
HID Parser Claim: 09 04 00 00 01 03 01 02 00 09 21 11 01 00 01 22 47 00 07 05 81 03 08 00 01 09 04 01 00 01 03 01 01 00 09 21 11 01 00 01 22 D5 00 07 05 82 03 08 00 01 
report descriptor size = 71
Single endpoint HID:
  endpoint = 81
   size = 8
   interval = 1
new_Pipe

Edit: but again could not tell from description so far if issue he is seeing is with the USB type of Mouse... Or with USBHost...
 
USBHost.

I tried to do the triangle mouse movement while mouse.available(), that worked with 1000hz.
Just when reading values from USBHost and passing them over, I get 500hz.
 
USBHost.

I tried to do the triangle mouse movement while mouse.available(), that worked with 1000hz.
Just when reading values from USBHost and passing them over, I get 500hz.

As I mentioned in the previous post, that the USBHostappears to only returning 500hz...

Sorry, it has not been a high priority item for me, So hopefully Paul will find a solution.

There is one thing I am curious to try here, in that maybe at 1000hz only having one input transfer/buffer may not be sufficient...
So I may try a quick and dirty hack to HIDParser of setting up 2nd Input buffer, transfer and see if it helps.
 
For what it is worth,

I pushed up a new Branch of USBHost_t36: https://github.com/KurtE/USBHost_t36/tree/USBHidParser_2_input_transfers

Where I added second buffer (Record2) and an extra InputTransfer.

And then with a slightly modified version of posted sketch:
Code:
#include <USBHost_t36.h>

USBHost usb_host;
USBHIDParser hid1(usb_host);
USBHIDParser hid2(usb_host);
USBHub hub(usb_host);

MouseController mouse_in(usb_host);

void setup() {
  // USB IN
  while (!Serial && millis() < 4000) ;
  Serial.begin(115200);
  Serial.println("Test mouse reads");
  usb_host.begin();
}

void loop() {
  elapsedMicros em = 0;
  uint32_t count_mouse_reads = 0;
  while (count_mouse_reads < 1000) {
    usb_host.Task();
    if (mouse_in.available())
    {
#if 0
      // Proxy Mouse
      Serial.print("Mouse: buttons = ");
      Serial.print(mouse_in.getButtons());
      Serial.print(",  mouseX = ");
      Serial.print(mouse_in.getMouseX());
      Serial.print(",  mouseY = ");
      Serial.print(mouse_in.getMouseY());
      Serial.print(",  wheel = ");
      Serial.print(mouse_in.getWheel());
      Serial.print(",  wheelH = ");
      Serial.print(mouse_in.getWheelH());
      Serial.println();
#endif
      count_mouse_reads++;
      mouse_in.mouseDataClear();
    }
  }
  uint32_t delta_time = em;
  Serial.print(delta_time);
  Serial.print(" ");
  Serial.println((1000000.0 / (float)delta_time) * 1000.0, 2);
  delay(250);
}
With it setting up to have two Input transfers queued, the number of Hz went up from about 500 to >900.

Code:
Test mouse reads
2830003 353.36
1085998 920.81
1106998 903.34
1099998 909.09
1075998 929.37
1079998 925.93
1077998 927.65

Paul is it worth it to add a second 64 byte Record for this plus an extra transfer? Note: The transfers are only 8 bytes I think, so could try to instead of Report and Report2, that if transfer size is < half of Report Size than double buffer...

EDIT: actually If I move the mouse real fast... Then it shows near 1000...
Code:
1037998 963.39
1033998 967.12
1002998 997.01
1010998 989.12
1016998 983.29
1019998 980.39

Edit2: @mcrc - You might try using my branch mentioned or simply copy down the two modified files (USBHost_t36.h, hid.cpp)
 
Last edited:
Will try in a few minutes! That sounds promising.
Thank you for all your efforts.

Edit: Works perfectly fine!
 
Last edited:
There seems to be an issue when trying to use teensy as mouse proxy and the polling rate. When running the example code from kurt it indeed does go up as high as 1000, however by just adding Mouse.move(mouse_in.getMouseX(),mouse_in.getMouseY()); within the mouse.available condition it cuts the polling rate down to a max of 500.
 
Last edited:
Any idea why it locks back to 500hz when forcing 12 mbit in usb.c?

Code:
 USB1_PORTSC1 |= USB_PORTSC1_PFSC; // force 12 Mbit/sec
 
If I am not mistaken..

Let's say you're Endpoint descriptor has the interval property set to 0x01 on 12Mbit that's a polling rate of 1000.
On 100 Mbit the value of 0x01 is (I forgot the actual value) I think it's 250 nano seconds or something.

So if you had a polling rate of 1000 on 100Mbit dropping down to 12 Mbit will reduce the polling rate speed and you'll need to modify the Endpoint descriptor to match.
 
This actually changes only when I force enable/disable the 12mbit above (12mbit: 1ms, 100mbit: 125us)
I need to have 12mbit with 1ms interval there, and 1000hz (not 500hz).
 
Last edited:
Well if you have 1ms interval rate on your endpoint description that at least isn't the issue.
How are you verifying the polling rate? I am running on 12Mbit and 150mhz clockspeed and still have 1000Hz.
 
Ah I used the same testing site, I use an attachReceive instead of mouse_in.available() maybe the difference is there.
 
Mind sharing some code?
I only see attachReceive on raw usb HID.

Ahh yes, It's been a while, I thought attachReceive was on all the classes.. Long story short, I used the Raw controller.
I didn't care about parsing, I just take the input from the mouse and forward it to the emulated mouse.
 
Well, cant do that :(
Need a interpreted solution

But if you could post your raw hid forward code, I'd appreciate that.
 
Last edited:
As for intercepting before the HID code decodes each packet. We are doing that with the Wacom Tablet code we have been playing with on a different thread. Code is up at: https://github.com/KurtE/WacomController

If you implement a class derived from: USBHIDInput
like Mouse is,

You can implement the method:
bool WacomController::hid_process_in_data(const Transfer_t *transfer)

Obviously, your class name will likely be different. But this is called each time we receive a packet from the device.
If your code processes the data directly and returns a logical true, the main HID parsing code will not run on that packet.

We are doing that in the Tablet code as if for example you look at the Linux Code for Wacom tablets done by Wacom, it more or less says that their HID descriptor is more or less useless to properly process the data...
 
Yeah, but individually parsing HID packets myself will only work for specific devices.
Really just need the 500hz fix on forcing 12mbit for the MouseController.
 
Note: I have not played at all with forcing slow mode: The code
Code:
 USB1_PORTSC1 |= USB_PORTSC1_PFSC; // force 12 Mbit/sec

Is for the USB communications from the Teensy to the PC (i.e.) not to do with USB devices talking to the USB Host.

You might have some luck trying to turn it on in the USB Host code:

That is if you look at ehci.cpp in the USBHost_t36 library you will see:
Code:
	//USBHS_PORTSC1 |= USBHS_PORTSC_PFSC; // force 12 Mbit/sec
You might uncomment that and see if it changes anything
 
Just tried, does not work. Now my polling rate is 250hz when both are forced.
I mean Mouse to Teensy communication should be at max, just need the teensy to pc communication at 12mbit.
Im thinking the Teensy to PC Communication needs a certain flag for 1000hz on 12mbit, not sure.
 
Back
Top