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 /**************************************************************************/
15 /** */
16 /** USBX Component */
17 /** */
18 /** HID Class */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23
24 /* Include necessary system files. */
25
26 #define UX_SOURCE_CODE
27
28 #include "ux_api.h"
29 #include "ux_host_class_hid.h"
30 #include "ux_host_stack.h"
31
32
33 #if defined(UX_HOST_STANDALONE)
34
35 extern UINT ux_host_class_hid_report_set_buffer_allocate(
36 UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report,
37 UCHAR **allocated);
38
39
40 /**************************************************************************/
41 /* */
42 /* FUNCTION RELEASE */
43 /* */
44 /* _ux_host_class_hid_report_set_run PORTABLE C */
45 /* 6.1.12 */
46 /* AUTHOR */
47 /* */
48 /* Chaoqiong Xiao, Microsoft Corporation */
49 /* */
50 /* DESCRIPTION */
51 /* */
52 /* This function sets a report (input/output/feature) to the device. */
53 /* The report can be either decompressed by the stack or raw. */
54 /* */
55 /* This function is for standalone mode. */
56 /* */
57 /* INPUT */
58 /* */
59 /* hid Pointer to HID class */
60 /* client_report Pointer to client report */
61 /* */
62 /* OUTPUT */
63 /* */
64 /* Completion Status */
65 /* */
66 /* CALLS */
67 /* */
68 /* _ux_host_class_hid_report_compress Compress HID report */
69 /* _ux_host_stack_class_instance_verify Verify the instance is valid */
70 /* _ux_host_stack_transfer_run Process transfer states */
71 /* _ux_utility_memory_allocate Allocate memory block */
72 /* _ux_utility_memory_copy Copy memory block */
73 /* _ux_utility_memory_free Release memory block */
74 /* */
75 /* CALLED BY */
76 /* */
77 /* Application */
78 /* HID Class */
79 /* */
80 /* RELEASE HISTORY */
81 /* */
82 /* DATE NAME DESCRIPTION */
83 /* */
84 /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */
85 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
86 /* added interrupt OUT support,*/
87 /* resulting in version 6.1.12 */
88 /* */
89 /**************************************************************************/
_ux_host_class_hid_report_set_run(UX_HOST_CLASS_HID * hid,UX_HOST_CLASS_HID_CLIENT_REPORT * client_report)90 UINT _ux_host_class_hid_report_set_run(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report)
91 {
92
93 UX_INTERRUPT_SAVE_AREA
94 UX_DEVICE *device;
95 UX_ENDPOINT *control_endpoint;
96 UX_TRANSFER *transfer_request;
97 UCHAR *report_buffer;
98 UX_HOST_CLASS_HID_REPORT *hid_report;
99 UINT status;
100
101
102 /* If trace is enabled, insert this event into the trace buffer. */
103 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_REPORT_SET, hid, client_report, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
104
105 /* Get the report pointer from the caller. */
106 hid_report = client_report -> ux_host_class_hid_client_report;
107
108 /* Ensure the instance is valid. */
109 if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS)
110 {
111
112 /* If trace is enabled, insert this event into the trace buffer. */
113 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0)
114
115 hid -> ux_host_class_hid_status = UX_HOST_CLASS_INSTANCE_UNKNOWN;
116 return(UX_STATE_EXIT);
117 }
118
119 /* Get device. */
120 device = hid -> ux_host_class_hid_device;
121
122 /* Sanity check. */
123 if (device == UX_NULL ||
124 device -> ux_device_handle != (ULONG)(ALIGN_TYPE)device)
125 {
126
127 /* If trace is enabled, insert this event into the trace buffer. */
128 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_HANDLE_UNKNOWN,
129 device, 0, 0, UX_TRACE_ERRORS, 0, 0)
130
131 hid -> ux_host_class_hid_status = UX_DEVICE_HANDLE_UNKNOWN;
132 return(UX_STATE_EXIT);
133 }
134
135 #if defined(UX_HOST_CLASS_HID_INTERRUPT_OUT_SUPPORT)
136
137 /* Check if there is an interrupt OUT endpoint. */
138 if (hid -> ux_host_class_hid_interrupt_out_endpoint != UX_NULL)
139 {
140
141 /* Transfer the report by using the interrupt OUT endpoint. */
142 transfer_request = &hid -> ux_host_class_hid_interrupt_out_endpoint -> ux_endpoint_transfer_request;
143 }
144 else
145 #endif
146 {
147
148 /* We need to get the default control endpoint transfer request pointer. */
149 control_endpoint = &device -> ux_device_control_endpoint;
150 transfer_request = &control_endpoint -> ux_endpoint_transfer_request;
151 }
152
153 /* Waiting transfer done. */
154 if (hid -> ux_host_class_hid_cmd_state == UX_STATE_WAIT)
155 {
156
157 /* Process background tasks. */
158 _ux_system_tasks_run();
159
160 /* Check if transfer is done. */
161 if (transfer_request -> ux_transfer_request_state < UX_STATE_WAIT)
162 {
163
164 /* Free allocated resource. */
165 _ux_utility_memory_free(hid -> ux_host_class_hid_allocated);
166 hid -> ux_host_class_hid_allocated = UX_NULL;
167
168 /* Unlock. */
169 hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK;
170 device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK;
171
172 /* We are done. */
173 hid -> ux_host_class_hid_cmd_state = UX_STATE_IDLE;
174 hid -> ux_host_class_hid_status =
175 transfer_request -> ux_transfer_request_completion_code;
176 return(UX_STATE_NEXT);
177 }
178
179 /* Keep waiting. */
180 return(UX_STATE_WAIT);
181 }
182
183 /* Check state or protection status. */
184 UX_DISABLE
185 if ((hid -> ux_host_class_hid_flags & UX_HOST_CLASS_HID_FLAG_LOCK) ||
186 (device -> ux_device_flags & UX_DEVICE_FLAG_LOCK))
187 {
188
189 /* Locked. */
190 UX_RESTORE
191 return(UX_STATE_LOCK);
192 }
193 hid -> ux_host_class_hid_flags |= UX_HOST_CLASS_HID_FLAG_LOCK;
194 device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK;
195 hid -> ux_host_class_hid_cmd_state = UX_STATE_WAIT;
196 UX_RESTORE
197
198 /* Build the report buffer for SET_REPORT request. */
199 status = ux_host_class_hid_report_set_buffer_allocate(hid, client_report, &report_buffer);
200 if (status != UX_SUCCESS)
201 {
202
203 /* If trace is enabled, insert this event into the trace buffer. */
204 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, status,
205 hid, client_report, 0, UX_TRACE_ERRORS, 0, 0)
206
207 /* Error code. */
208 hid -> ux_host_class_hid_status = status;
209
210 /* Unlock. */
211 hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK;
212 device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK;
213
214 /* State error. */
215 hid -> ux_host_class_hid_cmd_state = UX_STATE_ERROR;
216 return(UX_STATE_ERROR);
217 }
218 hid -> ux_host_class_hid_allocated = report_buffer;
219
220 /* Create a transfer request for the SET_REPORT request. */
221 transfer_request -> ux_transfer_request_data_pointer = report_buffer;
222 transfer_request -> ux_transfer_request_requested_length = hid_report -> ux_host_class_hid_report_byte_length;
223 transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_SET_REPORT;
224 transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
225 transfer_request -> ux_transfer_request_value = (UINT)((USHORT) hid_report -> ux_host_class_hid_report_id | (USHORT) hid_report -> ux_host_class_hid_report_type << 8);
226 transfer_request -> ux_transfer_request_index = hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber;
227 UX_TRANSFER_STATE_RESET(transfer_request);
228
229 /* Send request to HCD layer. */
230 status = _ux_host_stack_transfer_run(transfer_request);
231 if (status != UX_STATE_WAIT)
232 {
233 _ux_utility_memory_free(hid -> ux_host_class_hid_allocated);
234 hid -> ux_host_class_hid_allocated = UX_NULL;
235
236 hid -> ux_host_class_hid_status =
237 transfer_request -> ux_transfer_request_completion_code;
238
239 /* Unlock. */
240 hid -> ux_host_class_hid_flags &= ~UX_HOST_CLASS_HID_FLAG_LOCK;
241 device -> ux_device_flags &= ~UX_DEVICE_FLAG_LOCK;
242
243 hid -> ux_host_class_hid_cmd_state = (UCHAR)status;
244 }
245
246 /* Return the function status */
247 return(status);
248 }
249 #endif
250