From ba0d2122e2d029e0da099e0b49ca0b2f5684e877 Mon Sep 17 00:00:00 2001 From: Kajtek Lau Date: Wed, 6 May 2026 18:19:55 -0700 Subject: [PATCH] fix(hid): Store client instance per-device instead of per-class --- .../src/ux_host_class_hid_client_search.c | 88 ++++++++++++------- .../src/ux_host_class_hid_deactivate.c | 79 +++++++++-------- 2 files changed, 97 insertions(+), 70 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 bf688853b..7aa9296fe 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 @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** HID Class */ /** */ @@ -30,36 +30,36 @@ #include "ux_host_stack.h" -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_host_class_hid_client_search PORTABLE C */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_client_search PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ +/* */ /* This function searches for a HID client that wants to own this HID */ -/* device. */ -/* */ -/* INPUT */ -/* */ -/* hid Pointer to HID class */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* (ux_host_class_hid_client_handler) HID client handler */ -/* */ -/* CALLED BY */ -/* */ -/* HID Class */ +/* device. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_host_class_hid_client_handler) HID client handler */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_client_search(UX_HOST_CLASS_HID *hid) @@ -77,10 +77,10 @@ UX_HOST_CLASS_HID_CLIENT_COMMAND hid_client_command; hid_client_command.ux_host_class_hid_client_command_instance = 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_QUERY; - + /* Dereference the client pointer into a HID client pointer. */ hid_client = (UX_HOST_CLASS_HID_CLIENT *) hid -> ux_host_class_hid_class -> ux_host_class_client; - + /* If the hid_client pointer is NULL, the array of clients was not initialized. */ if (hid_client == UX_NULL) { @@ -93,7 +93,7 @@ UX_HOST_CLASS_HID_CLIENT_COMMAND hid_client_command; return(UX_HOST_CLASS_HID_UNKNOWN); } - + /* We need to parse the hid client driver table to find a registered client. */ for (hid_client_index = 0; hid_client_index < UX_HOST_CLASS_HID_MAX_CLIENTS; hid_client_index++) { @@ -104,24 +104,44 @@ UX_HOST_CLASS_HID_CLIENT_COMMAND hid_client_command; /* Call the HID client with a query command. */ status = hid_client -> ux_host_class_hid_client_handler(&hid_client_command); - + /* Have we found a HID client? */ 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 + using a single local_instance. */ + UX_HOST_CLASS_HID_CLIENT *hid_client_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 into the per-instance copy + and NULL the local instance. */ + _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. */ if (status != UX_SUCCESS) + { hid -> ux_host_class_hid_client = UX_NULL; - + _ux_utility_memory_free(hid_client_instance); + } + /* Return completion status. */ return(status); } @@ -129,7 +149,7 @@ UX_HOST_CLASS_HID_CLIENT_COMMAND hid_client_command; /* Try the next HID client. */ hid_client++; - } + } /* Error trap. */ _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_UNKNOWN); 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 eab333f2e..10f15a6b9 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 @@ -12,8 +12,8 @@ /**************************************************************************/ /**************************************************************************/ -/** */ -/** USBX Component */ +/** */ +/** USBX Component */ /** */ /** HID Class */ /** */ @@ -30,44 +30,44 @@ #include "ux_host_stack.h" -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _ux_host_class_hid_deactivate PORTABLE C */ +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_deactivate PORTABLE C */ /* 6.1.10 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ -/* */ +/* */ /* This function is called when this instance of the HID has been */ -/* removed from the bus either directly or indirectly. The interrupt */ -/* pipe will be destroyed and the instanced removed. */ -/* */ -/* INPUT */ -/* */ -/* command Pointer to command */ -/* */ -/* OUTPUT */ -/* */ -/* Completion Status */ -/* */ -/* CALLS */ -/* */ -/* (ux_host_class_hid_client_handler) HID client handler */ -/* _ux_host_class_hid_instance_clean HID instance clean */ -/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* removed from the bus either directly or indirectly. The interrupt */ +/* pipe will be destroyed and the instanced removed. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_host_class_hid_client_handler) HID client handler */ +/* _ux_host_class_hid_instance_clean HID instance clean */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ /* _ux_host_stack_endpoint_transfer_abort */ -/* Abort transfer */ -/* _ux_utility_memory_free Release memory block */ -/* _ux_host_semaphore_delete Delete semaphore */ -/* _ux_host_semaphore_get Get semaphore */ -/* */ -/* CALLED BY */ -/* */ -/* HID Class */ +/* Abort transfer */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_host_semaphore_delete Delete semaphore */ +/* _ux_host_semaphore_get Get semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ /* */ /**************************************************************************/ UINT _ux_host_class_hid_deactivate(UX_HOST_CLASS_COMMAND *command) @@ -138,17 +138,23 @@ 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); /* The enumeration thread needs to sleep a while to allow the application or the class that may be using endpoints to exit properly. */ - _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + _ux_host_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); /* Destroy the instance. */ _ux_host_stack_class_instance_destroy(hid -> ux_host_class_hid_class, (VOID *) hid); @@ -160,7 +166,7 @@ UINT status; that the device is removed. */ if (_ux_system_host -> ux_system_host_change_function != UX_NULL) { - + /* Inform the application the device is removed. */ _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, hid -> ux_host_class_hid_class, (VOID *) hid); } @@ -175,5 +181,6 @@ UINT status; _ux_utility_memory_free(hid); /* Return successful completion. */ - return(UX_SUCCESS); + return(UX_SUCCESS); } +