hathach / tinyusb

An open source cross-platform USB stack for embedded system
https://www.tinyusb.org
MIT License
5.08k stars 1.07k forks source link

Mouse poll rate cannot go over 500Hz on MacBook with Apple Silicon #1705

Open ViRb3 opened 2 years ago

ViRb3 commented 2 years ago

Operating System

MacOS 12.6/13.0, MacBook Pro 2021 M1 Max

Board

Raspberry Pi Pico, RP2040

Firmware

Modified from usb/device/dev_hid_composite

What happened ?

I am trying to simulate a mouse moving at 1000Hz poll rate with the Raspberry Pi Pico. With the default descriptors, I am getting a polling rate of 250Hz. I changed the polling interval from 5 to 1 and I got 1000Hz on my MacBook 2020 with Intel CPU, as well as my Windows laptop, but only 500Hz on my two MacBook 2021 with Apple CPU:

https://github.com/hathach/tinyusb/blob/154821acc02f8c7917ed7e94318de0a26f883b75/examples/device/hid_composite/src/usb_descriptors.c#L114

This leads me to believe that the problem is in the descriptors that TinyUSB uses by default. I verify the polling rate using this website:

With my gaming mouse, it reports 1000Hz. With my cheap mouse, it reports 100Hz. I was also able to simulate 1000Hz using CircuitPython by applying this patch:

CircuitPython code, 1000Hz:

import usb_hid

mouse = usb_hid.Device.MOUSE
mouse_move_report = bytearray(4)

mouse_move_report[1] = 1
mouse_move_report[2] = 1

while True:
    mouse.send_report(mouse_move_report)

TinyUSB code, 500Hz:

int main(void)
{
  board_init();
  tusb_init();

  while (1)
  {
    tud_task();
    // skip if hid is not ready yet
    if ( !tud_hid_ready() ) continue;
    tud_hid_mouse_report(REPORT_ID_MOUSE, 0, 1, 1, 0, 0);
  }

  return 0;
}

I figured this might be a configuration issue, so to the best of my abilities I cloned the following properties from CircuitPython:

Sadly, none of this changes anything. Here are my sources from CircuitPython:

Thanks!

How to reproduce ?

int main(void)
{
  board_init();
  tusb_init();

  while (1)
  {
    tud_task();
    // skip if hid is not ready yet
    if ( !tud_hid_ready() ) continue;
    tud_hid_mouse_report(REPORT_ID_MOUSE, 0, 1, 1, 0, 0);
  }

  return 0;
}

Test in:

Debug Log as txt file

No response

Screenshots

No response

I have checked existing issues, dicussion and documentation

sonodima commented 3 months ago

I am currently experiencing the same issue. By any chance, did you find what was wrong with it?

ViRb3 commented 3 months ago

Unfortunately no, had to pause my project until a solution is found. Still hoping that happens one day.

sonodima commented 2 months ago

I tested Adafruit's TinyUSB abstraction for Arduino and it can reach 1kHz with the RP2040, even on the M1 Pro.

For now (unfortunately) I think I'll have settle with that for my project. It might be worth it to take a look at their implementation though.

sonodima commented 2 months ago

After further testing, I noticed that disabling the USB CDC Serial (which is enabled by default) in the Adafruit TinyUSB library results in the polling rate to get limited to 500Hz on macOS. On Windows it's still 1KHz, and that is consistent with the problems we had before using TinyUSB directly.

If the USB CDC Serial is enabled, it has zero problems reaching the full 1KHz on both macOS and Windows.