fix(hid): Store client instance per-device instead of per-class#262
Open
kajteklau wants to merge 1 commit into
Open
fix(hid): Store client instance per-device instead of per-class#262kajteklau wants to merge 1 commit into
kajteklau wants to merge 1 commit into
Conversation
Author
|
Hi, sorry I made a mistake when signing the ECA. It should be fixed now. Please let me know what can I do to contribute. -- Kajtek |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
USBX HID Shared Client Instance Pointer Bug
Target Repo
eclipse-threadx/usbx(MIT license, Category A Simple Contribution)Symptom
This bug surfaces when a user plugs in two or more HID devices of the same class to the hub tree. Removing any one HID device of a given type (keyboard or mouse) causes all remaining devices of that type to stop reporting input. Callbacks write into freed memory.
Background: The Global Client Table
At startup, the application registers HID client types (keyboard, mouse) by calling
ux_host_class_hid_client_register(). This function allocates a single flat array ofUX_HOST_CLASS_HID_CLIENTstructs, stored atclass->ux_host_class_clienton theUX_HOST_CLASScontainer for HID. In this application there are two entries:Each entry holds a handler function pointer (e.g.
ux_host_class_hid_keyboard_entry) and aVOID *ux_host_class_hid_client_local_instancefield intended to point to the per-device instance (e.g.UX_HOST_CLASS_HID_KEYBOARD).Original Code: Device Activation Sequence
When a USB HID device enumerates, the middleware creates a per-interface
UX_HOST_CLASS_HIDstruct (hid) and calls_ux_host_class_hid_client_search(hid). This function:_ux_host_class_hid_keyboard_activate).The activate handler then:
hid_client = hid->ux_host_class_hid_clientUX_HOST_CLASS_HID_KEYBOARDstruct (keyboard_instance)The problem:
hid_clientpoints to the shared table entry. Every keyboard shares the same entry. Thelocal_instancefield is a single pointer — the last keyboard to activate overwrites it.Original Code: Device Deactivation Sequence
When a device is unplugged,
_ux_host_class_hid_keyboard_deactivate()runs:hid_client = hid->ux_host_class_hid_client(shared entry)keyboard_instance = hid_client->local_instanceThe deactivation has no other way to find the keyboard instance. The address was only
ever stored in one place:
hid_client->local_instanceon the shared table entry.Failure Sequence (Two Keyboards, A and B)
Keyboard B's interrupt reports continue to arrive, but the callback writes into freed memory. The result is silent data loss and memory leak.
Fix
Instead of storing a pointer to the shared table entry, allocate a per-instance copy of the client struct so each HID device gets its own
local_instancepointer.In
_ux_host_class_hid_client_search()(lines 119–155):The copy inherits the handler function pointer and name from the shared entry but has its own
local_instancefield.local_instanceis explicitly set to NULL so the copy doesn't carry a stale pointer from a previous activation of the same device type. The activate handler then writes the freshly allocated keyboard instance to this privatecopy's
local_instance.In
_ux_host_class_hid_deactivate(), the per-instance copy is freed after the client deactivate handler runs:Fixed Sequence (Two Keyboards, A and B)
Files Changed
common/usbx_host_classes/src/ux_host_class_hid_client_search.c(lines 119–155)common/usbx_host_classes/src/ux_host_class_hid_deactivate.cMemory Cost
One additional
sizeof(UX_HOST_CLASS_HID_CLIENT)allocation (~40 bytes) per connectedHID device. Freed on device removal.