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