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 /**   PIMA 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_pima.h"
29 #include "ux_host_stack.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_host_class_pima_object_close                    PORTABLE C      */
37 /*                                                           6.1.10       */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function closes an object,                                     */
45 /*  INPUT                                                                 */
46 /*                                                                        */
47 /*    pima                                       Pointer to pima class    */
48 /*    pima_session                               Pointer to pima session  */
49 /*    object_handle                              The object handle        */
50 /*    object                                     Pointer to object info   */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    Completion Status                                                   */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    _ux_host_stack_transfer_request            Transfer request         */
59 /*    _ux_host_stack_transfer_request_abort      Abort transfer           */
60 /*    _ux_host_stack_endpoint_reset              Reset endpoint           */
61 /*    _ux_host_semaphore_get                     Get semaphore            */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    USB application                                                     */
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 /*                                            prefixed UX to MS_TO_TICK,  */
74 /*                                            resulting in version 6.1    */
75 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
76 /*                                            refined macros names,       */
77 /*                                            resulting in version 6.1.10 */
78 /*                                                                        */
79 /**************************************************************************/
_ux_host_class_pima_object_close(UX_HOST_CLASS_PIMA * pima,UX_HOST_CLASS_PIMA_SESSION * pima_session,ULONG object_handle,UX_HOST_CLASS_PIMA_OBJECT * object)80 UINT  _ux_host_class_pima_object_close(UX_HOST_CLASS_PIMA *pima,
81                                         UX_HOST_CLASS_PIMA_SESSION *pima_session,
82                                         ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object)
83 {
84 
85 UX_TRANSFER                         *transfer_request;
86 UCHAR                                 *ptp_payload;
87 ULONG                                requested_length;
88 UINT                                status;
89 
90     UX_PARAMETER_NOT_USED(object_handle);
91 
92     /* If trace is enabled, insert this event into the trace buffer.  */
93     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_OBJECT_CLOSE, pima, object, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
94 
95     /* Check if this session is valid or not.  */
96     if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER)
97         return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN);
98 
99     /* Check if this session is opened or not.  */
100     if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED)
101         return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN);
102 
103     /* Check if the object is already closed.  */
104     if (object -> ux_host_class_pima_object_state != UX_HOST_CLASS_PIMA_OBJECT_STATE_OPENED)
105         return (UX_HOST_CLASS_PIMA_RC_OBJECT_ALREADY_CLOSED );
106 
107     /* Close the object.  */
108     object -> ux_host_class_pima_object_state = UX_HOST_CLASS_PIMA_OBJECT_STATE_CLOSED;
109 
110     /* If the transfer was not ended prematurely, we need to do the status phase.  */
111     if ( object -> ux_host_class_pima_object_transfer_status == UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_COMPLETED)
112     {
113 
114         /* The transfer for this transaction is now inactive.  */
115         object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_INACTIVE;
116 
117         /* Check if we had a ZLP condition during the data phase.  */
118         if (pima -> ux_host_class_pima_zlp_flag != UX_HOST_CLASS_PIMA_ZLP_NONE)
119         {
120 
121             /* We had a ZLP, so we now expect a zero length packet prior to the status phase.
122                We need to determine the direction.  */
123             if (pima -> ux_host_class_pima_zlp_flag == UX_HOST_CLASS_PIMA_ZLP_IN)
124 
125                 /* We use the Bulk In pipe for receiving the zlp.  */
126                 transfer_request =  &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request;
127 
128             else
129 
130                 /* We use the Bulk Out pipe for sending the zlp.  */
131                 transfer_request =  &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request;
132 
133             /* Initialize the payload to zero length. */
134             transfer_request -> ux_transfer_request_data_pointer =  UX_NULL;
135             transfer_request -> ux_transfer_request_requested_length =  0;
136 
137             /* Reset the ZLP now.  */
138             pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_NONE;
139 
140             /* Send request to HCD layer.  */
141             status =  _ux_host_stack_transfer_request(transfer_request);
142 
143             /* If the transfer is successful, we need to wait for the transfer request to be completed.  */
144             if (status == UX_SUCCESS)
145             {
146 
147                 /* Wait for the completion of the transfer request.  */
148                 status =  _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT));
149 
150                 /* If the semaphore did not succeed we probably have a time out.  */
151                 if (status != UX_SUCCESS)
152                 {
153 
154                     /* All transfers pending need to abort. There may have been a partial transfer.  */
155                     _ux_host_stack_transfer_request_abort(transfer_request);
156 
157                     /* The endpoint was halted by a transfer error and needs to be reset.  */
158                     _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint);
159 
160                     /* The endpoint was halted by a transfer error  and needs to be reset.  */
161                     _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint);
162 
163                     /* There was an error, return to the caller.  */
164                     return(status);
165                 }
166             }
167         }
168 
169         /* We use the Bulk In pipe for receiving the response payload.  */
170         transfer_request =  &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request;
171 
172         /* Get the pointer to the ptp payload.  */
173         ptp_payload =  pima -> ux_host_class_pima_container ;
174 
175         /* Calculate the requested length for this payload.  */
176         requested_length =  UX_HOST_CLASS_PIMA_RESPONSE_HEADER_SIZE;
177 
178         /* Initialize the transfer_request.  */
179         transfer_request -> ux_transfer_request_data_pointer =  ptp_payload;
180         transfer_request -> ux_transfer_request_requested_length =  requested_length;
181 
182         /* Send request to HCD layer.  */
183         status =  _ux_host_stack_transfer_request(transfer_request);
184 
185         /* If the transfer is successful, we need to wait for the transfer request to be completed.  */
186         if (status == UX_SUCCESS)
187         {
188 
189             /* Wait for the completion of the transfer request.  */
190             status =  _ux_host_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT));
191 
192             /* If the semaphore did not succeed we probably have a time out.  */
193             if (status != UX_SUCCESS)
194             {
195 
196                 /* All transfers pending need to abort. There may have been a partial transfer.  */
197                 _ux_host_stack_transfer_request_abort(transfer_request);
198 
199                 /* The endpoint was halted by a transfer error and needs to be reset.  */
200                 _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint);
201 
202                 /* The endpoint was halted by a transfer error  and needs to be reset.  */
203                 _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint);
204 
205                 /* There was an error, return to the caller.  */
206                 return(status);
207             }
208         }
209         else
210         {
211 
212             /* There was a non transfer error, no partial transfer to be checked */
213             return(status);
214         }
215 
216     }
217 
218     /* The transfer for this transaction is now inactive.  */
219     object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_INACTIVE;
220 
221     /* Return completion status.  */
222     return(UX_SUCCESS);
223 }
224 
225 /**************************************************************************/
226 /*                                                                        */
227 /*  FUNCTION                                               RELEASE        */
228 /*                                                                        */
229 /*    _uxe_host_class_pima_object_close                   PORTABLE C      */
230 /*                                                           6.3.0        */
231 /*  AUTHOR                                                                */
232 /*                                                                        */
233 /*    Yajun Xia, Microsoft Corporation                                    */
234 /*                                                                        */
235 /*  DESCRIPTION                                                           */
236 /*                                                                        */
237 /*    This function checks errors in pima object close function call.     */
238 /*                                                                        */
239 /*  INPUT                                                                 */
240 /*                                                                        */
241 /*    pima                                       Pointer to pima class    */
242 /*    pima_session                               Pointer to pima session  */
243 /*    object_handle                              The object handle        */
244 /*    object                                     Pointer to object info   */
245 /*                                                                        */
246 /*  OUTPUT                                                                */
247 /*                                                                        */
248 /*    Completion Status                                                   */
249 /*                                                                        */
250 /*  CALLS                                                                 */
251 /*                                                                        */
252 /*    _ux_host_class_pima_object_close      Close pima object             */
253 /*                                                                        */
254 /*  CALLED BY                                                             */
255 /*                                                                        */
256 /*    USB application                                                     */
257 /*                                                                        */
258 /*  RELEASE HISTORY                                                       */
259 /*                                                                        */
260 /*    DATE              NAME                      DESCRIPTION             */
261 /*                                                                        */
262 /*  10-31-2023        Yajun xia             Initial Version 6.3.0         */
263 /*                                                                        */
264 /**************************************************************************/
_uxe_host_class_pima_object_close(UX_HOST_CLASS_PIMA * pima,UX_HOST_CLASS_PIMA_SESSION * pima_session,ULONG object_handle,UX_HOST_CLASS_PIMA_OBJECT * object)265 UINT  _uxe_host_class_pima_object_close(UX_HOST_CLASS_PIMA *pima,
266                                         UX_HOST_CLASS_PIMA_SESSION *pima_session,
267                                         ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object)
268 {
269 
270     /* Sanity checks.  */
271     if ((pima == UX_NULL) || (pima_session == UX_NULL) || (object == UX_NULL))
272         return(UX_INVALID_PARAMETER);
273 
274     /* Call the actual object close function.  */
275     return(_ux_host_class_pima_object_close(pima, pima_session, object_handle, object));
276 }