1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
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 /** HID Class */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22
23 /* Include necessary system files. */
24
25 #define UX_SOURCE_CODE
26
27 #include "ux_api.h"
28 #include "ux_host_class_hid.h"
29 #include "ux_host_stack.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_host_class_hid_activate PORTABLE C */
37 /* 6.1.12 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function performs the enumeration of the HID class. */
45 /* */
46 /* INPUT */
47 /* */
48 /* command Pointer to command */
49 /* */
50 /* OUTPUT */
51 /* */
52 /* Completion Status */
53 /* */
54 /* CALLS */
55 /* */
56 /* _ux_host_class_hid_client_search HID client search */
57 /* _ux_host_class_hid_configure Configure HID */
58 /* _ux_host_class_hid_descriptor_parse Parse descriptor */
59 /* _ux_host_class_hid_interrupt_endpoint_search Search endpoint */
60 /* _ux_host_class_hid_instance_clean Clean up instance resources */
61 /* _ux_host_stack_class_instance_create Create class instance */
62 /* _ux_host_stack_class_instance_destroy Destroy class instance */
63 /* _ux_utility_memory_allocate Allocate memory block */
64 /* _ux_utility_memory_free Free memory */
65 /* _ux_host_semaphore_create Create semaphore */
66 /* */
67 /* CALLED BY */
68 /* */
69 /* HID Class */
70 /* */
71 /* RELEASE HISTORY */
72 /* */
73 /* DATE NAME DESCRIPTION */
74 /* */
75 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
76 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
77 /* resulting in version 6.1 */
78 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
79 /* added standalone support, */
80 /* resulting in version 6.1.10 */
81 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
82 /* fixed parameter/variable */
83 /* names conflict C++ keyword, */
84 /* resulting in version 6.1.12 */
85 /* */
86 /**************************************************************************/
_ux_host_class_hid_activate(UX_HOST_CLASS_COMMAND * command)87 UINT _ux_host_class_hid_activate(UX_HOST_CLASS_COMMAND *command)
88 {
89
90 UX_INTERFACE *interface_ptr;
91 UX_HOST_CLASS_HID *hid;
92 UINT status;
93
94
95 /* The HID is always activated by the interface descriptor and not the
96 device descriptor. */
97 interface_ptr = (UX_INTERFACE *) command -> ux_host_class_command_container;
98
99 /* Instantiate this HID class */
100 hid = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,sizeof(UX_HOST_CLASS_HID));
101 if (hid == UX_NULL)
102 return(UX_MEMORY_INSUFFICIENT);
103
104 /* Store the class container into this instance. */
105 hid -> ux_host_class_hid_class = command -> ux_host_class_command_class_ptr;
106
107 /* Store the interface container into the HID class instance. */
108 hid -> ux_host_class_hid_interface = interface_ptr;
109
110 /* Store the device container into the HID class instance. */
111 hid -> ux_host_class_hid_device = interface_ptr -> ux_interface_configuration -> ux_configuration_device;
112
113 /* This instance of the device must also be stored in the interface container. */
114 interface_ptr -> ux_interface_class_instance = (VOID *) hid;
115
116 /* Create this class instance. */
117 _ux_host_stack_class_instance_create(command -> ux_host_class_command_class_ptr, (VOID *) hid);
118
119 #if defined(UX_HOST_STANDALONE)
120
121 /* Set class tasks function. */
122 hid -> ux_host_class_hid_class -> ux_host_class_task_function = _ux_host_class_hid_tasks_run;
123
124 /* Set activate state to first step. */
125 hid -> ux_host_class_hid_enum_state = UX_STATE_WAIT;
126
127 status = UX_SUCCESS;
128 return(status);
129 #else
130
131 /* Configure the HID. */
132 status = _ux_host_class_hid_configure(hid);
133
134 /* If configure is done success, goes on. */
135 if (status == UX_SUCCESS)
136 {
137
138 /* Get the HID descriptor and parse it. */
139 status = _ux_host_class_hid_descriptor_parse(hid);
140 }
141
142 /* If HID descriptor parse is done success, goes on. */
143 if (status == UX_SUCCESS)
144 {
145
146 /* Search the HID interrupt endpoint but do not start it. */
147 status = _ux_host_class_hid_interrupt_endpoint_search(hid);
148 }
149
150 /* If HID interrupt endpoint is found, goes on. */
151 if (status == UX_SUCCESS)
152 {
153
154 /* Create the semaphore to protect multiple threads from accessing the same
155 storage instance. */
156 status = _ux_host_semaphore_create(&hid -> ux_host_class_hid_semaphore, "ux_host_class_hid_semaphore", 1);
157
158 if (status == UX_SUCCESS)
159 {
160
161 /* If all is fine, try to locate the HID client for this HID device. */
162 _ux_host_class_hid_client_search(hid);
163
164 /* Mark the HID class as live now. */
165 hid -> ux_host_class_hid_state = UX_HOST_CLASS_INSTANCE_LIVE;
166
167 /* We may need to inform the application if a function has been programmed in the system structure. */
168 if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
169 {
170
171 /* Call system change function. */
172 _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid);
173 }
174
175 /* If trace is enabled, insert this event into the trace buffer. */
176 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_ACTIVATE, hid, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
177
178 /* If trace is enabled, register this object. */
179 UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, hid, 0, 0, 0)
180
181 /* Return completion code. */
182 return(status);
183 }
184 else
185 {
186 status = UX_SEMAPHORE_ERROR;
187 }
188 }
189
190 /* Clean interrupt endpoint. */
191 if (hid -> ux_host_class_hid_interrupt_endpoint &&
192 hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer)
193 _ux_utility_memory_free(hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer);
194
195 /* Clean instance. */
196 _ux_host_class_hid_instance_clean(hid);
197
198 /* Error, destroy the class instance and return error code. */
199 _ux_host_stack_class_instance_destroy(hid -> ux_host_class_hid_class, (VOID *) hid);
200
201 /* Unmount instance. */
202 interface_ptr -> ux_interface_class_instance = UX_NULL;
203
204 /* Free instance. */
205 _ux_utility_memory_free(hid);
206
207 /* Return error code. */
208 return(status);
209
210 #endif
211 }
212
213