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 }