-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implemented rate limiter for HID reports. #39
Conversation
Added new config variables for KConfig: -) enabling rate limiter -) set interval in microseconds -) Either accumulate mouse movements or discard reports when sent too fast
main/ble_hidd_demo_main.c
Outdated
/// discard any packets. If we get them too fast, many of them are still sent with the current values. | ||
#if CONFIG_MODULE_USERATELIMITER | ||
//check interval, jst to be sure use the absolute value of the subtraction. | ||
if(abs(esp_timer_get_time() - cmdBuffer->lastTimeHIDCommandSent) > timeIntervalHIDCommand) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it guaranteed that the last (accumulated) data or button actions get sent if the rate limiter is active?
or can it happen that the last accumulated values are only sent when the next burst of mouse commands come in ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good question. My intention was, that even if the rate limiter is active, most (but not all) commands will be sent.
I guess it is very unlikely, that e.g., the button release report is sent as last one of too much (only in this case it would trigger the rate limiter).
If we would implement any async mechanism for sending the last movement values and mouse buttons, it would increase the complexity quite much:
- New timer (I suggest a FreeRTOS timer)
- Callback structure
- Detecting if the timer should be started (how could we know in this command processor that this would be the last command?)
If we really need the proper transmission of every last movement value, I could implement it.
Nevertheless, I think if some external device hits the rate limiter, the chance of dropped values is quite high.
An easier approach:
If the rate limiter hits, just check if the button values have changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a button state tracker, which sends the button values if they change, even if the report is received out of the interval.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think that the rate limiter will always cause an unwanted behaviour if we do not guarantee that the most recent accumulated data is sent as soon as possible. for example: if movement data stays "in the pipeline" it will influence the next burst of mouse activities which come in, which might cause unintended deflection of the mouse cursor.
You could throw away acculumeted data if there was a pause, but IMO the only "clean" method to implement this is to trigger a timeout (a bit longer than the selected update rate) for a callback function where we check if accumulated coordinates are in the pipeline an send them if necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I will implement the accumulation in a different way:
- In
uart_parse_command
I will just accumulate the mouse values - A timer (endless loop) will check the accumulated values on a regular timebase (-> use the rate limiter value) and
send any accumulated values.
do you think this is working :-)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good :-)
in case the accumulator is empty, the report could be sent immediately in order to avoid unnecessary delay/jitter.
main/ble_hidd_demo_main.c
Outdated
if(cmdBuffer->accumValues[i] < -6000) cmdBuffer->accumValues[i] = -6000; | ||
} | ||
#else /* CONFIG_MODULE_RATELIMITERACCUMULATE */ | ||
ESP_LOGI(EXT_UART_TAG,"Rate limit: discard mouse report"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might create a whole lot of log messages in case of slower rate limits.
maybe limit that output, too ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this output to log level verbose, which is off by default.
main/Kconfig.projbuild
Outdated
config MODULE_RATELIMITERACCUMULATE | ||
bool "Accumulate mouse HID packets if rate limiter hits (NOT RECOMMENDED)" | ||
depends on MODULE_USERATELIMITER | ||
default n | ||
help | ||
If enabled, relative mouse movements are accumulated and | ||
sent on next occasion. If disabled, the HID report is discarded. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this feature should be disabled by default. I had many cases, that this accumulation winds up and there is no reasonable mouse movement possible....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i do not understand this comment...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
L75: default n
and not default y
:-)
…(LED report), closing #38 : - Added report ID for LEDs - Added callback event type for LED - Fixed the characteristic & added write no response (according to espressif/esp-idf#5369 THX @robinkrens for the hint!)
Added new config variables for KConfig: -) enabling rate limiter -) set interval in microseconds -) Either accumulate mouse movements or discard reports when sent too fast
…umulate mode not finished! Implemented a timer based solution for accumulating mode.
- moved to esp_hidd_prf_api.c - changed default values for time interval in KConfig - Implemented rate limiter callback - Fixed signed int8 problem - Synchronizing the accumulated values with a binary semaphore
I've moved all the rate limiter stuff to the esp_hidd_prf_api.c file, because it is more reasonable to it there. Every packet is sent via the timer, because the default value is set to 500us, which is half the time of the USB request (1ms). |
OK! And it we could make the rate limit adjustable via uart / a new FlipMouse AT-command (eg. AT BC to transfer bluetooth commands to the esp32 - for example "AT BC $RA 80" for setting the rate limiter to 80 ms) ? |
I don't know if we should remove it completely. |
if we do not remove it, it will compromise the function of the rate limiter inside the esp32 add-on (becuaes it just drops commands), IMO the best implementation for the FlipMouse would be to limit the rate of commands as soon as possible (before USB or BT actions are created). |
This PR is also ~2years old and we don't have any problems with rate limiting. |
Added new config variables for KConfig:
-) enabling rate limiter
-) set interval in microseconds
-) Either accumulate mouse movements or discard reports when sent too fast