1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12 /**************************************************************************/
13 /** */
14 /** USBX Component */
15 /** */
16 /** Device HID Class */
17 /** */
18 /**************************************************************************/
19 /**************************************************************************/
20
21 #define UX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "ux_api.h"
27 #include "ux_device_class_hid.h"
28 #include "ux_device_stack.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_device_class_hid_initialize PORTABLE C */
36 /* 6.2.0 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function initializes the USB HID device. */
44 /* This function is called by the class register function. It is only */
45 /* done once. */
46 /* */
47 /* INPUT */
48 /* */
49 /* command Pointer to hid command */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* Completion Status */
54 /* */
55 /* CALLS */
56 /* */
57 /* _ux_utility_memory_allocate Allocate memory */
58 /* _ux_utility_memory_free Free memory */
59 /* _ux_device_thread_create Create thread */
60 /* _ux_device_thread_delete Delete thread */
61 /* _ux_utility_event_flags_create Create event flags group */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* USBX Source Code */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
72 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
73 /* used UX prefix to refer to */
74 /* TX symbols instead of using */
75 /* them directly, */
76 /* resulting in version 6.1 */
77 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
78 /* added standalone support, */
79 /* added interrupt OUT support,*/
80 /* resulting in version 6.1.10 */
81 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
82 /* resulting in version 6.1.11 */
83 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
84 /* added standalone receiver, */
85 /* fixed parameter/variable */
86 /* names conflict C++ keyword, */
87 /* resulting in version 6.1.12 */
88 /* 10-31-2022 Chaoqiong Xiao Modified comment(s), */
89 /* fixed compile warnings, */
90 /* resulting in version 6.2.0 */
91 /* */
92 /**************************************************************************/
_ux_device_class_hid_initialize(UX_SLAVE_CLASS_COMMAND * command)93 UINT _ux_device_class_hid_initialize(UX_SLAVE_CLASS_COMMAND *command)
94 {
95
96 UX_SLAVE_CLASS_HID *hid;
97 UX_SLAVE_CLASS_HID_PARAMETER *hid_parameter;
98 UX_SLAVE_CLASS *class_ptr;
99 UINT status = UX_SUCCESS;
100
101
102 /* Get the class container. */
103 class_ptr = command -> ux_slave_class_command_class_ptr;
104
105 /* Create an instance of the device hid class. */
106 hid = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_HID));
107
108 /* Check for successful allocation. */
109 if (hid == UX_NULL)
110 return(UX_MEMORY_INSUFFICIENT);
111
112 /* Save the address of the HID instance inside the HID container. */
113 class_ptr -> ux_slave_class_instance = (VOID *) hid;
114
115 #if !defined(UX_DEVICE_STANDALONE)
116
117 /* Allocate some memory for the thread stack. */
118 class_ptr -> ux_slave_class_thread_stack =
119 _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_DEVICE_CLASS_HID_THREAD_STACK_SIZE);
120
121 /* Check for successful allocation. */
122 if (class_ptr -> ux_slave_class_thread_stack == UX_NULL)
123 status = UX_MEMORY_INSUFFICIENT;
124
125 /* This instance needs to be running in a different thread. So start
126 a new thread. We pass a pointer to the class to the new thread. This thread
127 does not start until we have a instance of the class. */
128 if (status == UX_SUCCESS)
129 status = _ux_device_thread_create(&class_ptr -> ux_slave_class_thread, "ux_slave_hid_thread",
130 _ux_device_class_hid_interrupt_thread,
131 (ULONG) (ALIGN_TYPE) class_ptr, (VOID *) class_ptr -> ux_slave_class_thread_stack,
132 UX_DEVICE_CLASS_HID_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
133 UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
134 #else
135
136 /* Set task function. */
137 class_ptr -> ux_slave_class_task_function = _ux_device_class_hid_tasks_run;
138 #endif
139
140 /* Check the creation of this thread. */
141 if (status == UX_SUCCESS)
142 {
143
144 #if !defined(UX_DEVICE_STANDALONE)
145 UX_THREAD_EXTENSION_PTR_SET(&(class_ptr -> ux_slave_class_thread), class_ptr)
146 #endif
147
148 /* Get the pointer to the application parameters for the hid class. */
149 hid_parameter = command -> ux_slave_class_command_parameter;
150
151 /* Store all the application parameter information about the report. */
152 hid -> ux_device_class_hid_report_address = hid_parameter -> ux_device_class_hid_parameter_report_address;
153 hid -> ux_device_class_hid_report_length = hid_parameter -> ux_device_class_hid_parameter_report_length;
154 hid -> ux_device_class_hid_report_id = hid_parameter -> ux_device_class_hid_parameter_report_id;
155
156 /* Store the callback function. */
157 hid -> ux_device_class_hid_callback = hid_parameter -> ux_device_class_hid_parameter_callback;
158 hid -> ux_device_class_hid_get_callback = hid_parameter -> ux_device_class_hid_parameter_get_callback;
159
160 /* Create the event array. */
161 hid -> ux_device_class_hid_event_array = _ux_utility_memory_allocate_mulc_safe(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_HID_EVENT), UX_DEVICE_CLASS_HID_MAX_EVENTS_QUEUE);
162
163 /* Check for successful allocation. */
164 if (hid -> ux_device_class_hid_event_array != UX_NULL)
165 {
166
167 /* Initialize the head and tail of the notification round robin buffers.
168 At first, the head and tail are pointing to the beginning of the array. */
169 hid -> ux_device_class_hid_event_array_head = hid -> ux_device_class_hid_event_array;
170 hid -> ux_device_class_hid_event_array_tail = hid -> ux_device_class_hid_event_array;
171 hid -> ux_device_class_hid_event_array_end = hid -> ux_device_class_hid_event_array + UX_DEVICE_CLASS_HID_MAX_EVENTS_QUEUE;
172
173 /* Store the start and stop signals if needed by the application. */
174 hid -> ux_slave_class_hid_instance_activate = hid_parameter -> ux_slave_class_hid_instance_activate;
175 hid -> ux_slave_class_hid_instance_deactivate = hid_parameter -> ux_slave_class_hid_instance_deactivate;
176
177 /* By default no event wait timeout. */
178 hid -> ux_device_class_hid_event_wait_timeout = UX_WAIT_FOREVER;
179
180 #if !defined(UX_DEVICE_STANDALONE)
181
182 /* Create a event flag group for the hid class to synchronize with the event interrupt thread. */
183 status = _ux_utility_event_flags_create(&hid -> ux_device_class_hid_event_flags_group, "ux_device_class_hid_event_flag");
184
185 /* Check status. */
186 if (status != UX_SUCCESS)
187 status = UX_EVENT_ERROR;
188 else
189 #endif
190 {
191 #if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT)
192
193 #if !defined(UX_DEVICE_STANDALONE)
194
195 /* Create a mutex for reading reentry check. */
196 status = _ux_utility_mutex_create(&hid -> ux_device_class_hid_read_mutex,
197 "ux_device_class_hid_read_mutex");
198 if (status == UX_SUCCESS)
199 {
200 #endif
201
202 /* If receiver is enabled by parameter, initialize it. */
203 if (hid_parameter -> ux_device_class_hid_parameter_receiver_initialize)
204 {
205
206 /* Allocate buffer for receiver and receiver events. */
207 status = hid_parameter ->
208 ux_device_class_hid_parameter_receiver_initialize(hid,
209 hid_parameter,
210 &hid -> ux_device_class_hid_receiver);
211 }
212
213 /* Done success, return. */
214 if (status == UX_SUCCESS)
215 return(status);
216
217 #if !defined(UX_DEVICE_STANDALONE)
218
219 /* There is error, delete mutex. */
220 _ux_device_mutex_delete(&hid -> ux_device_class_hid_read_mutex);
221 }
222 else
223 status = UX_MUTEX_ERROR;
224
225 /* There is error, delete event flags. */
226 _ux_utility_event_flags_delete(&hid -> ux_device_class_hid_event_flags_group);
227 #endif
228 #else
229 return(status);
230 #endif
231
232 }
233
234 #if !defined(UX_DEVICE_STANDALONE) || defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT)
235
236 /* There is still initialization activities after array creation,
237 * and some error occurs in this stage. */
238 /* Free allocated event array memory. */
239 _ux_utility_memory_free(hid -> ux_device_class_hid_event_array);
240 #endif
241
242 }
243 else
244 status = UX_MEMORY_INSUFFICIENT;
245
246 #if !defined(UX_DEVICE_STANDALONE)
247
248 /* Delete thread. */
249 _ux_device_thread_delete(&class_ptr -> ux_slave_class_thread);
250 #endif
251 }
252 else
253 status = (UX_THREAD_ERROR);
254
255 #if !defined(UX_DEVICE_STANDALONE)
256
257 /* Free stack. */
258 if (class_ptr -> ux_slave_class_thread_stack)
259 _ux_utility_memory_free(class_ptr -> ux_slave_class_thread_stack);
260 #endif
261
262 /* Unmount instance. */
263 class_ptr -> ux_slave_class_instance = UX_NULL;
264
265 /* Free HID instance. */
266 _ux_utility_memory_free(hid);
267
268 /* Return completion status. */
269 return(status);
270 }
271
272