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 /** Host Sierra Wireless AR module 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_swar.h"
29 #include "ux_host_stack.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_host_class_swar_write PORTABLE C */
37 /* 6.1.11 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function writes to the swar interface. The call is blocking */
45 /* and only returns when there is either an error or when the transfer */
46 /* is complete. */
47 /* */
48 /* INPUT */
49 /* */
50 /* swar Pointer to swar class */
51 /* data_pointer Pointer to data to write */
52 /* requested_length Length of data to write */
53 /* actual_length Actual length of data written */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* Completion Status */
58 /* */
59 /* CALLS */
60 /* */
61 /* _ux_host_stack_class_instance_verify Verify the class instance */
62 /* _ux_host_stack_transfer_request Process transfer request */
63 /* _ux_host_stack_transfer_request_abort Abort transfer request */
64 /* _ux_host_semaphore_get Get protection semaphore */
65 /* _ux_host_semaphore_put Release protection semaphore */
66 /* */
67 /* CALLED BY */
68 /* */
69 /* Application */
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 /* refined macros names, */
80 /* resulting in version 6.1.10 */
81 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
82 /* fixed standalone compile, */
83 /* resulting in version 6.1.11 */
84 /* */
85 /**************************************************************************/
_ux_host_class_swar_write(UX_HOST_CLASS_SWAR * swar,UCHAR * data_pointer,ULONG requested_length,ULONG * actual_length)86 UINT _ux_host_class_swar_write(UX_HOST_CLASS_SWAR *swar, UCHAR * data_pointer,
87 ULONG requested_length, ULONG *actual_length)
88 {
89
90 UX_TRANSFER *transfer_request;
91 UINT status;
92 ULONG transfer_request_length;
93
94 /* If trace is enabled, insert this event into the trace buffer. */
95 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_SWAR_WRITE, swar, data_pointer, requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
96
97 /* Ensure the instance is valid. */
98 if(_ux_host_stack_class_instance_verify((UCHAR *) _ux_system_host_class_swar_name, (VOID *) swar) != UX_SUCCESS)
99 {
100
101 /* Error trap. */
102 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN);
103
104 /* If trace is enabled, insert this event into the trace buffer. */
105 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, swar, 0, 0, UX_TRACE_ERRORS, 0, 0)
106
107 return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
108 }
109
110 /* Protect thread reentry to this instance. */
111 status = _ux_host_semaphore_get(&swar -> ux_host_class_swar_semaphore, UX_WAIT_FOREVER);
112 if (status != UX_SUCCESS)
113 return(status);
114
115 /* Start by resetting the actual length of the transfer. */
116 *actual_length = 0;
117
118 /* Get the pointer to the bulk out endpoint transfer request. */
119 transfer_request = &swar -> ux_host_class_swar_bulk_out_endpoint -> ux_endpoint_transfer_request;
120
121 /* Perform a transfer on the bulk out endpoint until either the transfer is
122 completed or when there is an error. */
123 do
124 {
125
126 /* Program the maximum authorized length for this transfer_request. */
127 if (requested_length > transfer_request -> ux_transfer_request_maximum_length)
128 transfer_request_length = transfer_request -> ux_transfer_request_maximum_length;
129 else
130 transfer_request_length = requested_length;
131
132 /* Initialize the transfer_request. */
133 transfer_request -> ux_transfer_request_data_pointer = data_pointer;
134 transfer_request -> ux_transfer_request_requested_length = transfer_request_length;
135
136 /* Perform the transfer. */
137 status = _ux_host_stack_transfer_request(transfer_request);
138
139 /* If the transfer is successful, we need to wait for the transfer request to be completed. */
140 if (status == UX_SUCCESS)
141 {
142
143 /* Wait for the completion of the transfer request. */
144 status = _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_SWAR_CLASS_TRANSFER_TIMEOUT);
145
146 /* If the semaphore did not succeed we probably have a time out. */
147 if (status != UX_SUCCESS)
148 {
149
150 /* All transfers pending need to abort. There may have been a partial transfer. */
151 _ux_host_stack_transfer_request_abort(transfer_request);
152
153 /* Update the length of the actual data transferred. We do this after the
154 abort of the transfer_request in case some data actually went out. */
155 *actual_length += transfer_request -> ux_transfer_request_actual_length;
156
157 /* Unprotect thread reentry to this instance. */
158 _ux_host_semaphore_put(&swar -> ux_host_class_swar_semaphore);
159
160 /* Set the completion code. */
161 transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT;
162
163 /* Error trap. */
164 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT);
165
166 /* If trace is enabled, insert this event into the trace buffer. */
167 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0)
168
169 /* There was an error, return to the caller. */
170 return(UX_TRANSFER_TIMEOUT);
171 }
172 }
173 else
174 {
175
176 /* Unprotect thread reentry to this instance. */
177 _ux_host_semaphore_put(&swar -> ux_host_class_swar_semaphore);
178
179 /* There was a non transfer error, no partial transfer to be checked */
180 return(status);
181 }
182
183 /* Update the length of the transfer. Normally all the data has to be sent. */
184 *actual_length += transfer_request -> ux_transfer_request_actual_length;
185
186 /* Check for completion of transfer. If the transfer is partial, return to caller.
187 The transfer is marked as successful but the caller will need to check the length
188 actually sent and determine if a partial transfer is OK. */
189 if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length)
190 {
191
192 /* Unprotect thread reentry to this instance. */
193 _ux_host_semaphore_put(&swar -> ux_host_class_swar_semaphore);
194
195 /* Return success. */
196 return(UX_SUCCESS);
197 }
198
199 /* Update the data pointer for next transfer. */
200 data_pointer += transfer_request_length;
201
202 /* Update what is left to send out. */
203 requested_length -= transfer_request_length;
204
205 } while (requested_length != 0);
206
207
208 /* Unprotect thread reentry to this instance. */
209 _ux_host_semaphore_put(&swar -> ux_host_class_swar_semaphore);
210
211 /* We get here when all the transfers went through without errors. */
212 return(UX_SUCCESS);
213 }
214
215
216 /**************************************************************************/
217 /* */
218 /* FUNCTION RELEASE */
219 /* */
220 /* _uxe_host_class_swar_write PORTABLE C */
221 /* 6.3.0 */
222 /* AUTHOR */
223 /* */
224 /* Chaoqiong Xiao, Microsoft Corporation */
225 /* */
226 /* DESCRIPTION */
227 /* */
228 /* This function checks errors in SWAR write function call. */
229 /* */
230 /* INPUT */
231 /* */
232 /* swar Pointer to SWAR class */
233 /* data_pointer Pointer to data to write */
234 /* requested_length Length of data to write */
235 /* actual_length Actual length of data written */
236 /* */
237 /* OUTPUT */
238 /* */
239 /* Status */
240 /* */
241 /* CALLS */
242 /* */
243 /* _ux_host_class_swar_write SWAR write */
244 /* */
245 /* CALLED BY */
246 /* */
247 /* Application */
248 /* */
249 /* RELEASE HISTORY */
250 /* */
251 /* DATE NAME DESCRIPTION */
252 /* */
253 /* 10-31-2023 Chaoqiong Xiao Initial Version 6.3.0 */
254 /* */
255 /**************************************************************************/
_uxe_host_class_swar_write(UX_HOST_CLASS_SWAR * swar,UCHAR * data_pointer,ULONG requested_length,ULONG * actual_length)256 UINT _uxe_host_class_swar_write(UX_HOST_CLASS_SWAR *swar, UCHAR *data_pointer,
257 ULONG requested_length, ULONG *actual_length)
258 {
259
260 /* Sanity checks. */
261 if ((swar == UX_NULL) ||
262 ((data_pointer == UX_NULL) && (requested_length != 0)) ||
263 (actual_length == UX_NULL))
264 {
265 return(UX_INVALID_PARAMETER);
266 }
267
268 /* Invoke SWAR write function. */
269 return(_ux_host_class_swar_write(swar, data_pointer, requested_length, actual_length));
270 }
271