Skip to content

Commit 6ea0ac4

Browse files
committed
Add optional device hid changes protocol callback and host hid api to set/get protocol
This pull request adds host HID API functions to get and set the HID protocol (boot vs report mode) and introduces an optional callback for the device side when the protocol changes. - Added new host-side APIs ux_host_class_hid_protocol_set() and ux_host_class_hid_protocol_get() with error checking wrappers. - Added device-side optional callback ux_device_class_hid_set_protocol_callback that is invoked when the protocol changes - Added comprehensive test to verify the new protocol callback functionality
1 parent 515c9a4 commit 6ea0ac4

File tree

10 files changed

+958
-177
lines changed

10 files changed

+958
-177
lines changed

common/usbx_device_classes/inc/ux_device_class_hid.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ typedef struct UX_SLAVE_CLASS_HID_STRUCT
249249
UINT ux_device_class_hid_state;
250250
UINT (*ux_device_class_hid_callback)(struct UX_SLAVE_CLASS_HID_STRUCT *hid, UX_SLAVE_CLASS_HID_EVENT *);
251251
UINT (*ux_device_class_hid_get_callback)(struct UX_SLAVE_CLASS_HID_STRUCT *hid, UX_SLAVE_CLASS_HID_EVENT *);
252+
VOID (*ux_device_class_hid_set_protocol_callback)(struct UX_SLAVE_CLASS_HID_STRUCT *hid, ULONG protocol);
252253
VOID (*ux_slave_class_hid_instance_activate)(VOID *);
253254
VOID (*ux_slave_class_hid_instance_deactivate)(VOID *);
254255
UCHAR *ux_device_class_hid_report_address;
@@ -365,6 +366,10 @@ typedef struct UX_SLAVE_CLASS_HID_PARAMETER_STRUCT
365366
ULONG ux_device_class_hid_parameter_report_length;
366367
UINT (*ux_device_class_hid_parameter_callback)(struct UX_SLAVE_CLASS_HID_STRUCT *hid, UX_SLAVE_CLASS_HID_EVENT *);
367368
UINT (*ux_device_class_hid_parameter_get_callback)(struct UX_SLAVE_CLASS_HID_STRUCT *hid, UX_SLAVE_CLASS_HID_EVENT *);
369+
370+
/* Optional callback invoked when protocol changes (boot/report). */
371+
VOID (*ux_device_class_hid_parameter_set_protocol_callback)(struct UX_SLAVE_CLASS_HID_STRUCT *hid, ULONG protocol);
372+
368373
#if defined(UX_DEVICE_CLASS_HID_FLEXIBLE_EVENTS_QUEUE)
369374
ULONG ux_device_class_hid_parameter_event_max_number;
370375
ULONG ux_device_class_hid_parameter_event_max_length;

common/usbx_device_classes/src/ux_device_class_hid_control_request.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,15 +205,28 @@ UX_SLAVE_CLASS_HID *hid;
205205

206206
case UX_DEVICE_CLASS_HID_COMMAND_GET_PROTOCOL:
207207

208-
/* Send the protocol. */
208+
/* Send the protocol to host. */
209209
*transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR)hid -> ux_device_class_hid_protocol;
210210
_ux_device_stack_transfer_request(transfer_request, 1, request_length);
211211
break;
212212

213213
case UX_DEVICE_CLASS_HID_COMMAND_SET_PROTOCOL:
214214

215+
/* Check protocol must be 0 (Boot) or 1 (Report). */
216+
if ((request_value != UX_DEVICE_CLASS_HID_PROTOCOL_BOOT) &&
217+
(request_value != UX_DEVICE_CLASS_HID_PROTOCOL_REPORT))
218+
{
219+
/* Invalid value: not handled. */
220+
return(UX_ERROR);
221+
}
222+
215223
/* Accept the protocol. */
216224
hid -> ux_device_class_hid_protocol = request_value;
225+
226+
/* If there is a callback defined by the application, send the protocol to it. */
227+
if (hid -> ux_device_class_hid_set_protocol_callback != UX_NULL)
228+
hid -> ux_device_class_hid_set_protocol_callback(hid, request_value);
229+
217230
break;
218231

219232
default:
@@ -225,4 +238,3 @@ UX_SLAVE_CLASS_HID *hid;
225238
/* It's handled. */
226239
return(UX_SUCCESS);
227240
}
228-

common/usbx_device_classes/src/ux_device_class_hid_initialize.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* SPDX-License-Identifier: MIT
99
**************************************************************************/
1010

11+
1112
/**************************************************************************/
1213
/**************************************************************************/
1314
/** */
@@ -196,6 +197,7 @@ UCHAR *buffer;
196197
/* Store the callback function. */
197198
hid -> ux_device_class_hid_callback = hid_parameter -> ux_device_class_hid_parameter_callback;
198199
hid -> ux_device_class_hid_get_callback = hid_parameter -> ux_device_class_hid_parameter_get_callback;
200+
hid -> ux_device_class_hid_set_protocol_callback = hid_parameter -> ux_device_class_hid_parameter_set_protocol_callback;
199201

200202
#if defined(UX_DEVICE_CLASS_HID_FLEXIBLE_EVENTS_QUEUE)
201203

common/usbx_host_classes/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ target_sources(${PROJECT_NAME} PRIVATE
9393
${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_idle_get.c
9494
${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_idle_set.c
9595
${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_idle_set_run.c
96+
${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_protocol_set.c
97+
${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_protocol_get.c
9698
${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_instance_clean.c
9799
${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_interrupt_endpoint_search.c
98100
${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_item_data_get.c

common/usbx_host_classes/inc/ux_host_class_hid.h

Lines changed: 182 additions & 173 deletions
Large diffs are not rendered by default.
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/***************************************************************************
2+
* Copyright (c) 2025-present Eclipse ThreadX Contributors
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the MIT License which is available at
6+
* https://opensource.org/licenses/MIT.
7+
*
8+
* SPDX-License-Identifier: MIT
9+
**************************************************************************/
10+
11+
12+
/**************************************************************************/
13+
/**************************************************************************/
14+
/** */
15+
/** USBX Component */
16+
/** */
17+
/** Host HID Class */
18+
/** */
19+
/**************************************************************************/
20+
/**************************************************************************/
21+
22+
/* Include necessary system files. */
23+
24+
#define UX_SOURCE_CODE
25+
26+
#include "ux_api.h"
27+
#include "ux_host_class_hid.h"
28+
#include "ux_host_stack.h"
29+
30+
/**************************************************************************/
31+
/* */
32+
/* FUNCTION RELEASE */
33+
/* */
34+
/* _ux_host_class_hid_protocol_get PORTABLE C */
35+
/* */
36+
/* DESCRIPTION */
37+
/* */
38+
/* This function performs a GET_PROTOCOL to the HID device to read */
39+
/* current protocol (BOOT=0 or REPORT=1). */
40+
/* */
41+
/* INPUT */
42+
/* */
43+
/* hid Pointer to HID class */
44+
/* protocol Destination for protocol */
45+
/* */
46+
/* OUTPUT */
47+
/* */
48+
/* Completion Status */
49+
/* */
50+
/* CALLED BY */
51+
/* */
52+
/* Application */
53+
/* */
54+
/* RELEASE HISTORY */
55+
/* */
56+
/* DATE NAME DESCRIPTION */
57+
/* */
58+
/**************************************************************************/
59+
UINT _ux_host_class_hid_protocol_get(UX_HOST_CLASS_HID *hid, USHORT *protocol)
60+
{
61+
62+
UX_ENDPOINT *control_endpoint;
63+
UX_TRANSFER *transfer_request;
64+
UINT status;
65+
66+
/* Ensure the instance is valid. */
67+
if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS)
68+
{
69+
70+
/* If trace is enabled, insert this event into the trace buffer. */
71+
UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
72+
73+
#if defined(UX_HOST_STANDALONE)
74+
hid -> ux_host_class_hid_status = UX_HOST_CLASS_INSTANCE_UNKNOWN;
75+
#endif
76+
77+
return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
78+
}
79+
80+
/* Get the default control endpoint transfer request pointer. */
81+
control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint;
82+
transfer_request = &control_endpoint -> ux_endpoint_transfer_request;
83+
84+
#if !defined(UX_HOST_STANDALONE)
85+
86+
/* Protect thread reentry to this instance. */
87+
status = _ux_host_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER);
88+
if (status != UX_SUCCESS)
89+
return(status);
90+
91+
#endif
92+
93+
/* Create a transfer request for the GET_PROTOCOL request. */
94+
transfer_request -> ux_transfer_request_data_pointer = (UCHAR *) protocol;
95+
transfer_request -> ux_transfer_request_requested_length = 1;
96+
transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_GET_PROTOCOL;
97+
transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
98+
transfer_request -> ux_transfer_request_value = 0;
99+
transfer_request -> ux_transfer_request_index = hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber;
100+
101+
/* Send request to HCD layer. */
102+
status = _ux_host_stack_transfer_request(transfer_request);
103+
104+
#if !defined(UX_HOST_STANDALONE)
105+
/* Unprotect thread reentry to this instance. */
106+
_ux_host_semaphore_put(&hid -> ux_host_class_hid_semaphore);
107+
#endif
108+
109+
return(status);
110+
}
111+
112+
/**************************************************************************/
113+
/* */
114+
/* FUNCTION RELEASE */
115+
/* */
116+
/* _uxe_host_class_hid_protocol_get PORTABLE C */
117+
/* */
118+
/* DESCRIPTION */
119+
/* */
120+
/* This function checks errors in HID protocol get function call. */
121+
/* */
122+
/* INPUT */
123+
/* */
124+
/* hid Pointer to HID class */
125+
/* protocol Destination for protocol */
126+
/* */
127+
/* OUTPUT */
128+
/* */
129+
/* Status */
130+
/* */
131+
/**************************************************************************/
132+
UINT _uxe_host_class_hid_protocol_get(UX_HOST_CLASS_HID *hid, USHORT *protocol)
133+
{
134+
/* Sanity check. */
135+
if (hid == UX_NULL || protocol == UX_NULL)
136+
return(UX_INVALID_PARAMETER);
137+
138+
/* Invoke protocol get function. */
139+
return(_ux_host_class_hid_protocol_get(hid, protocol));
140+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/***************************************************************************
2+
* Copyright (c) 2025-present Eclipse ThreadX Contributors
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the MIT License which is available at
6+
* https://opensource.org/licenses/MIT.
7+
*
8+
* SPDX-License-Identifier: MIT
9+
**************************************************************************/
10+
11+
12+
/**************************************************************************/
13+
/**************************************************************************/
14+
/** */
15+
/** USBX Component */
16+
/** */
17+
/** Host HID Class */
18+
/** */
19+
/**************************************************************************/
20+
/**************************************************************************/
21+
22+
/* Include necessary system files. */
23+
24+
#define UX_SOURCE_CODE
25+
26+
#include "ux_api.h"
27+
#include "ux_host_class_hid.h"
28+
#include "ux_host_stack.h"
29+
30+
/**************************************************************************/
31+
/* */
32+
/* FUNCTION RELEASE */
33+
/* */
34+
/* _ux_host_class_hid_protocol_set PORTABLE C */
35+
/* */
36+
/* DESCRIPTION */
37+
/* */
38+
/* This function performs a SET_PROTOCOL to the HID device to switch */
39+
/* between BOOT (0) and REPORT (1) protocols. */
40+
/* */
41+
/* INPUT */
42+
/* */
43+
/* hid Pointer to HID class */
44+
/* protocol Protocol (BOOT/REPORT) */
45+
/* */
46+
/* OUTPUT */
47+
/* */
48+
/* Completion Status */
49+
/* */
50+
/* CALLED BY */
51+
/* */
52+
/* Application */
53+
/* */
54+
/* RELEASE HISTORY */
55+
/* */
56+
/* DATE NAME DESCRIPTION */
57+
/* */
58+
/**************************************************************************/
59+
UINT _ux_host_class_hid_protocol_set(UX_HOST_CLASS_HID *hid, USHORT protocol)
60+
{
61+
62+
UX_ENDPOINT *control_endpoint;
63+
UX_TRANSFER *transfer_request;
64+
UINT status;
65+
66+
/* Ensure the instance is valid. */
67+
if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS)
68+
{
69+
70+
/* If trace is enabled, insert this event into the trace buffer. */
71+
UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
72+
73+
#if defined(UX_HOST_STANDALONE)
74+
hid -> ux_host_class_hid_status = UX_HOST_CLASS_INSTANCE_UNKNOWN;
75+
#endif
76+
return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
77+
}
78+
79+
/* Get the default control endpoint transfer request pointer. */
80+
control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint;
81+
transfer_request = &control_endpoint -> ux_endpoint_transfer_request;
82+
83+
#if !defined(UX_HOST_STANDALONE)
84+
85+
/* Protect thread reentry to this instance. */
86+
status = _ux_host_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER);
87+
if (status != UX_SUCCESS)
88+
return(status);
89+
90+
#endif
91+
92+
/* Create a transfer request for the SET_PROTOCOL request. */
93+
transfer_request -> ux_transfer_request_data_pointer = UX_NULL;
94+
transfer_request -> ux_transfer_request_requested_length = 0;
95+
transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_SET_PROTOCOL;
96+
transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
97+
transfer_request -> ux_transfer_request_value = (UINT)protocol;
98+
transfer_request -> ux_transfer_request_index = hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber;
99+
100+
/* Send request to HCD layer. */
101+
status = _ux_host_stack_transfer_request(transfer_request);
102+
103+
#if !defined(UX_HOST_STANDALONE)
104+
/* Unprotect thread reentry to this instance. */
105+
_ux_host_semaphore_put(&hid -> ux_host_class_hid_semaphore);
106+
#endif
107+
108+
/* Return the function status. */
109+
return(status);
110+
}
111+
112+
/**************************************************************************/
113+
/* */
114+
/* FUNCTION RELEASE */
115+
/* */
116+
/* _uxe_host_class_hid_protocol_set PORTABLE C */
117+
/* */
118+
/* DESCRIPTION */
119+
/* */
120+
/* This function checks errors in HID protocol set function call. */
121+
/* */
122+
/* INPUT */
123+
/* */
124+
/* hid Pointer to HID class */
125+
/* protocol Protocol (BOOT/REPORT) */
126+
/* */
127+
/* OUTPUT */
128+
/* */
129+
/* Status */
130+
/* */
131+
/**************************************************************************/
132+
UINT _uxe_host_class_hid_protocol_set(UX_HOST_CLASS_HID *hid, USHORT protocol)
133+
{
134+
/* Sanity check. */
135+
if (hid == UX_NULL)
136+
return(UX_INVALID_PARAMETER);
137+
138+
/* Validate protocol value: must be BOOT(0) or REPORT(1). */
139+
if (protocol != UX_HOST_CLASS_HID_PROTOCOL_BOOT &&
140+
protocol != UX_HOST_CLASS_HID_PROTOCOL_REPORT)
141+
return(UX_INVALID_PARAMETER);
142+
143+
/* Invoke protocol set function. */
144+
return(_ux_host_class_hid_protocol_set(hid, protocol));
145+
}

test/cmake/usbx/regression/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ set(ux_class_hid_test_cases
139139
${SOURCE_DIR}/usbx_ux_device_class_hid_activate_test2.c
140140
${SOURCE_DIR}/usbx_ux_device_class_hid_activate_test3.c
141141
${SOURCE_DIR}/usbx_ux_device_class_hid_control_request_test.c
142+
${SOURCE_DIR}/usbx_ux_device_class_hid_set_protocol_callback_test.c
142143
${SOURCE_DIR}/usbx_ux_device_class_hid_initialize_test.c
143144
${SOURCE_DIR}/usbx_ux_device_class_hid_interrupt_thread_test2.c
144145
${SOURCE_DIR}/usbx_ux_device_class_hid_read_test.c

0 commit comments

Comments
 (0)