summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKajtek Lau <[email protected]>2026-06-04 13:03:06 -0700
committerGitHub <[email protected]>2026-06-04 16:03:06 -0400
commita5fd35face7c364b00fd2fdecbac0c3ca45f659b (patch)
treef25f4188e95e6d7eb3601a34315ebaed9bb6c109
parent94cdd1e0e34573dac3f2c5dadb1c4f68a2857435 (diff)
fix(hid): Store client instance per-device instead of per-class (#262)
* fix(hid): Store client instance per-device instead of per-class * Address review feedback on per-instance HID client copy Three issues fixed, discovered during maintainer review: 1. Memory leak in standalone activation error path (entry.c): _ux_host_class_hid_client_activate_wait() set hid_client to NULL without freeing the per-instance copy allocated in client_search. The HID_ENUM_ERROR handler destroys the hid struct without freeing hid_client, so the copy was leaked on every standalone activation failure. Fixed by freeing hid_client before clearing it. 2. Variable declared inside if-block (client_search.c): hid_client_instance was declared inside the if (status == UX_SUCCESS) block, which is a C99 feature. USBX targets C89/C90 embedded toolchains. Moved to the top of the function with other locals. 3. Trailing whitespace throughout both changed files: The PR introduced trailing spaces on most comment-block lines. Reverted all affected lines to their original whitespace. Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Frédéric Desbiens <[email protected]> Co-authored-by: Copilot <[email protected]>
-rw-r--r--common/usbx_host_classes/src/ux_host_class_hid_client_search.c30
-rw-r--r--common/usbx_host_classes/src/ux_host_class_hid_deactivate.c8
-rw-r--r--common/usbx_host_classes/src/ux_host_class_hid_entry.c1
3 files changed, 34 insertions, 5 deletions
diff --git a/common/usbx_host_classes/src/ux_host_class_hid_client_search.c b/common/usbx_host_classes/src/ux_host_class_hid_client_search.c
index bf68885..902cd55 100644
--- a/common/usbx_host_classes/src/ux_host_class_hid_client_search.c
+++ b/common/usbx_host_classes/src/ux_host_class_hid_client_search.c
@@ -56,6 +56,9 @@
/* CALLS */
/* */
/* (ux_host_class_hid_client_handler) HID client handler */
+/* _ux_utility_memory_allocate Allocate memory block */
+/* _ux_utility_memory_copy Copy memory block */
+/* _ux_utility_memory_free Release memory block */
/* */
/* CALLED BY */
/* */
@@ -66,6 +69,7 @@ UINT _ux_host_class_hid_client_search(UX_HOST_CLASS_HID *hid)
{
UX_HOST_CLASS_HID_CLIENT *hid_client;
+UX_HOST_CLASS_HID_CLIENT *hid_client_instance;
ULONG hid_client_index;
UINT status;
UX_HOST_CLASS_HID_CLIENT_COMMAND hid_client_command;
@@ -109,18 +113,36 @@ UX_HOST_CLASS_HID_CLIENT_COMMAND hid_client_command;
if (status == UX_SUCCESS)
{
+ /* Allocate a per-instance copy of the client struct so that each HID
+ device gets its own local_instance pointer. This prevents multiple
+ devices of the same type from sharing a single local_instance. */
+ hid_client_instance = (UX_HOST_CLASS_HID_CLIENT *)
+ _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,
+ sizeof(UX_HOST_CLASS_HID_CLIENT));
+ if (hid_client_instance == UX_NULL)
+ return(UX_MEMORY_INSUFFICIENT);
+
+ /* Copy the registered client entry and clear the local instance
+ to avoid carrying a stale pointer from a prior activation. */
+ _ux_utility_memory_copy(hid_client_instance, hid_client,
+ sizeof(UX_HOST_CLASS_HID_CLIENT));
+ hid_client_instance -> ux_host_class_hid_client_local_instance = UX_NULL;
+
/* Update the command to activate the client. */
hid_client_command.ux_host_class_hid_client_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE;
- /* Memorize the client for this HID device. */
- hid -> ux_host_class_hid_client = hid_client;
+ /* Store the per-instance client on this HID device. */
+ hid -> ux_host_class_hid_client = hid_client_instance;
/* Call the HID client with an activate command. */
- status = hid_client -> ux_host_class_hid_client_handler(&hid_client_command);
+ status = hid_client_instance -> ux_host_class_hid_client_handler(&hid_client_command);
- /* Unmount the client if activation fail. */
+ /* Unmount the client if activation failed. */
if (status != UX_SUCCESS)
+ {
hid -> ux_host_class_hid_client = UX_NULL;
+ _ux_utility_memory_free(hid_client_instance);
+ }
/* Return completion status. */
return(status);
diff --git a/common/usbx_host_classes/src/ux_host_class_hid_deactivate.c b/common/usbx_host_classes/src/ux_host_class_hid_deactivate.c
index eab333f..d3db9ac 100644
--- a/common/usbx_host_classes/src/ux_host_class_hid_deactivate.c
+++ b/common/usbx_host_classes/src/ux_host_class_hid_deactivate.c
@@ -138,11 +138,17 @@ UINT status;
hid_client_command.ux_host_class_hid_client_command_instance = (VOID *) hid;
hid_client_command.ux_host_class_hid_client_command_container = (VOID *) hid -> ux_host_class_hid_class;
hid_client_command.ux_host_class_hid_client_command_request = UX_HOST_CLASS_COMMAND_DEACTIVATE;
-
+
/* Call the HID client with a deactivate command if there was a client registered. */
if (hid -> ux_host_class_hid_client != UX_NULL)
+ {
hid -> ux_host_class_hid_client -> ux_host_class_hid_client_handler(&hid_client_command);
+ /* Free the per-instance client copy allocated in _ux_host_class_hid_client_search. */
+ _ux_utility_memory_free(hid -> ux_host_class_hid_client);
+ hid -> ux_host_class_hid_client = UX_NULL;
+ }
+
/* Clean all the HID memory fields. */
_ux_host_class_hid_instance_clean(hid);
diff --git a/common/usbx_host_classes/src/ux_host_class_hid_entry.c b/common/usbx_host_classes/src/ux_host_class_hid_entry.c
index 0902432..9acc9d3 100644
--- a/common/usbx_host_classes/src/ux_host_class_hid_entry.c
+++ b/common/usbx_host_classes/src/ux_host_class_hid_entry.c
@@ -456,6 +456,7 @@ UINT status;
/* Error. */
if (status < UX_STATE_NEXT)
{
+ _ux_utility_memory_free(hid -> ux_host_class_hid_client);
hid -> ux_host_class_hid_client = UX_NULL;
hid -> ux_host_class_hid_status = UX_DEVICE_ENUMERATION_FAILURE;
hid -> ux_host_class_hid_enum_state = UX_HOST_CLASS_HID_ENUM_ERROR;