When my PC is not reading the HID events, the Arduino is slowed down.

I have an Arduino Micro that is acting as a HID device for a Linux PC.

I use this call to send the HID values:

HID().SendReport(1, _values, sizeof(_values));

This works in principle, but I noticed this issue:

If my Linux PC is not actively reading the events from the Arduino, then the Arduino is slowed down. My rotary encoders are missing signals, is one symptom.

But as soon as I read the events with my Linux PC, the Arduino loop() runs at full speed again.

I suspect that this is due to recv/send time out delays in the USB core code? Because I noticed this in USBCore.cpp:

        u8 timeout = 250;               // 250ms timeout on send? TODO

Anyway, I tried to solve this issue in the following manners:

Check for configuration and suspension with:

     if (USBDevice.configured())
      if (!USBDevice.isSuspended())

Which did not work.

I also tried monitoring the increments of the frame number:

  // See if USB shows activity.
  static uint8_t prev_fr_num = UDFNUML;
  static uint8_t num_times_idle = 0;
  uint8_t fr_num = UDFNUML;
  if (fr_num == prev_fr_num )
    if (num_times_idle < 255)
    num_times_idle = 0;
    prev_fr_num = fr_num;

And then only send if num_times_idle is smaller than a threshold. Again, this did not help.

The only way to make it fast, is by reading the events with linux, like so:

$ jstest /dev/input/js0

or alternatively:

$ evtest /dev/input/event5

How can I have the USB HID stuff not slow down my loop code when the PC is not paying attention?



I solved this by exposing the USB_SendSpace() information in the HID API.

That way, code that uses the HID API can decide not to send anything if there is no space left in the send buffer.

Details on the implementation are here.