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 /**   Storage 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_storage.h"
30 #include "ux_host_stack.h"
31 
32 
33 #if defined(UX_HOST_STANDALONE)
34 
35 
36 #ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT
37 #error Storage legacy protocols not supported in standlone mode
38 #endif
39 
40 #define UX_HOST_CLASS_STORAGE_PROTOCOL_GET(s)                                   \
41     ((s) -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol)
42 #define UX_HOST_CLASS_STORAGE_PROTOCOL_IS_BO(s)                                 \
43     (UX_HOST_CLASS_STORAGE_PROTOCOL_GET(s) == UX_HOST_CLASS_STORAGE_PROTOCOL_BO)
44 #define UX_HOST_CLASS_STORAGE_PROTOCOL_IS_CB(s)                                 \
45     (UX_HOST_CLASS_STORAGE_PROTOCOL_GET(s) == UX_HOST_CLASS_STORAGE_PROTOCOL_CB)
46 #define UX_HOST_CLASS_STORAGE_PROTOCOL_IS_CBI(s)                                \
47     (UX_HOST_CLASS_STORAGE_PROTOCOL_GET(s) == UX_HOST_CLASS_STORAGE_PROTOCOL_CBI)
48 
49 static inline VOID _ux_host_class_storage_transport_cbw(UX_HOST_CLASS_STORAGE *storage);
50 static inline VOID _ux_host_class_storage_transport_csw(UX_HOST_CLASS_STORAGE *storage);
51 static inline VOID _ux_host_class_storage_transport_trans_exit(UX_HOST_CLASS_STORAGE *storage);
52 static inline VOID _ux_host_class_storage_transport_trans_error(UX_HOST_CLASS_STORAGE *storage);
53 static inline VOID _ux_host_class_storage_transport_trans_next(UX_HOST_CLASS_STORAGE *storage);
54 static inline VOID _ux_host_class_storage_transport_trans_in_next(UX_HOST_CLASS_STORAGE *storage);
55 static inline VOID _ux_host_class_storage_transport_trans_out_next(UX_HOST_CLASS_STORAGE *storage);
56 static inline VOID _ux_host_class_storage_transport_status(UX_HOST_CLASS_STORAGE *storage);
57 static inline VOID _ux_host_class_storage_transport_ms_reset(UX_HOST_CLASS_STORAGE *storage);
58 static inline VOID _ux_host_class_storage_transport_ep_reset(UX_HOST_CLASS_STORAGE *storage);
59 
60 
61 /**************************************************************************/
62 /*                                                                        */
63 /*  FUNCTION                                               RELEASE        */
64 /*                                                                        */
65 /*    _ux_host_class_storage_transport_run                PORTABLE C      */
66 /*                                                           6.2.0        */
67 /*  AUTHOR                                                                */
68 /*                                                                        */
69 /*    Chaoqiong Xiao, Microsoft Corporation                               */
70 /*                                                                        */
71 /*  DESCRIPTION                                                           */
72 /*                                                                        */
73 /*    This function is the transport layer for all protocols. It perform  */
74 /*    the error recovery and retries if needed.                           */
75 /*                                                                        */
76 /*    It's valid only with standalone mode.                               */
77 /*    It's non-blocking.                                                  */
78 /*                                                                        */
79 /*  INPUT                                                                 */
80 /*                                                                        */
81 /*    storage                               Pointer to storage class      */
82 /*                                                                        */
83 /*  OUTPUT                                                                */
84 /*                                                                        */
85 /*    Completion Status                                                   */
86 /*                                                                        */
87 /*  CALLS                                                                 */
88 /*                                                                        */
89 /*    (ux_host_class_storage_transport)     Class storage transport       */
90 /*                                                                        */
91 /*  CALLED BY                                                             */
92 /*                                                                        */
93 /*    Storage Class                                                       */
94 /*                                                                        */
95 /*  RELEASE HISTORY                                                       */
96 /*                                                                        */
97 /*    DATE              NAME                      DESCRIPTION             */
98 /*                                                                        */
99 /*  01-31-2022     Chaoqiong Xiao           Initial Version 6.1.10        */
100 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
101 /*                                            fixed parameter/variable    */
102 /*                                            names conflict C++ keyword, */
103 /*                                            resulting in version 6.1.12 */
104 /*  10-31-2022     Chaoqiong Xiao           Modified comment(s),          */
105 /*                                            improved internal logic,    */
106 /*                                            resulting in version 6.2.0  */
107 /*                                                                        */
108 /**************************************************************************/
_ux_host_class_storage_transport_run(UX_HOST_CLASS_STORAGE * storage)109 UINT  _ux_host_class_storage_transport_run(UX_HOST_CLASS_STORAGE *storage)
110 {
111 UINT                    status;
112 UCHAR                   state;
113 INT                     immediate_state = UX_TRUE;
114 
115     while(immediate_state)
116     {
117         state = storage -> ux_host_class_storage_trans_state;
118         switch(state)
119         {
120         case UX_STATE_RESET:
121             storage -> ux_host_class_storage_trans_retry = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RETRY;
122             storage -> ux_host_class_storage_sense_code = 0;
123             storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_CBW;
124 
125             /* Start the command immediately.  */
126             /* Fall through.  */
127         case UX_HOST_CLASS_STORAGE_TRANS_CBW:
128             _ux_host_class_storage_transport_cbw(storage);
129             continue;
130 
131         case UX_HOST_CLASS_STORAGE_TRANS_CSW:
132             _ux_host_class_storage_transport_csw(storage);
133             continue;
134 
135         case UX_HOST_CLASS_STORAGE_TRANS_REQ_SENSE:
136             status = _ux_host_class_storage_request_sense(storage);
137             if (status == UX_SUCCESS)
138                 continue;
139 
140             /* Failed to issue request sense.  */
141             storage -> ux_host_class_storage_status = status;
142             storage -> ux_host_class_storage_trans_state = UX_STATE_IDLE;
143             return(UX_STATE_ERROR);
144 
145         case UX_HOST_CLASS_STORAGE_TRANS_IN_NEXT:
146             _ux_host_class_storage_transport_trans_in_next(storage);
147             continue;
148 
149         case UX_HOST_CLASS_STORAGE_TRANS_OUT_NEXT:
150             _ux_host_class_storage_transport_trans_out_next(storage);
151             continue;
152 
153         case UX_HOST_CLASS_STORAGE_TRANS_WAIT:
154             status = _ux_host_stack_transfer_run(storage -> ux_host_class_storage_trans);
155 
156             /* Next cases.  */
157             if (status == UX_STATE_NEXT || status == UX_STATE_IDLE)
158             {
159                 _ux_host_class_storage_transport_trans_next(storage);
160                 continue;
161             }
162 
163             /* Exit cases.  */
164             if (status < UX_STATE_IDLE)
165             {
166                 _ux_host_class_storage_transport_trans_exit(storage);
167                 return(UX_STATE_EXIT);
168             }
169 
170             /* Error cases.  */
171             if (status < UX_STATE_NEXT)
172             {
173                 _ux_host_class_storage_transport_trans_error(storage);
174                 continue;
175             }
176 
177             /* Wait.  */
178             return(UX_STATE_WAIT);
179 
180         case UX_HOST_CLASS_STORAGE_TRANS_STATUS:
181             _ux_host_class_storage_transport_status(storage);
182             continue;
183 
184         case UX_HOST_CLASS_STORAGE_TRANS_MS_RESET:
185             _ux_host_class_storage_transport_ms_reset(storage);
186             continue;
187 
188         case UX_HOST_CLASS_STORAGE_TRANS_EP_RESET:
189             _ux_host_class_storage_transport_ep_reset(storage);
190             continue;
191 
192         case UX_STATE_IDLE:
193             return(UX_STATE_NEXT);
194         case UX_STATE_EXIT:
195             return(UX_STATE_EXIT);
196 
197         default:
198             break;
199         }
200 
201         /* Invalid unhandled state, break the loop.  */
202         immediate_state = UX_FALSE;
203     }
204 
205     /* Unexpected state, fatal error.  */
206     storage -> ux_host_class_storage_status = UX_ERROR;
207     storage -> ux_host_class_storage_trans_state = UX_STATE_EXIT;
208     return(UX_STATE_EXIT);
209 }
_ux_host_class_storage_transport_cbw(UX_HOST_CLASS_STORAGE * storage)210 static inline VOID _ux_host_class_storage_transport_cbw(UX_HOST_CLASS_STORAGE *storage)
211 {
212 UX_ENDPOINT         *endpoint;
213 UX_TRANSFER         *trans;
214 
215     /* Prepare BulkOUT CBW transfer.  */
216     endpoint = storage -> ux_host_class_storage_bulk_out_endpoint;
217     trans = &endpoint -> ux_endpoint_transfer_request;
218     trans -> ux_transfer_request_data_pointer = storage -> ux_host_class_storage_cbw;
219     trans -> ux_transfer_request_requested_length = UX_HOST_CLASS_STORAGE_CBW_LENGTH;
220 
221     /* Next : wait transfer done.  */
222     UX_TRANSFER_STATE_RESET(trans);
223     storage -> ux_host_class_storage_trans = trans;
224     storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_WAIT;
225     storage -> ux_host_class_storage_trans_stage = UX_HOST_CLASS_STORAGE_STAGE_CBW;
226 }
_ux_host_class_storage_transport_csw(UX_HOST_CLASS_STORAGE * storage)227 static inline VOID _ux_host_class_storage_transport_csw(UX_HOST_CLASS_STORAGE *storage)
228 {
229 UX_ENDPOINT         *endpoint;
230 UX_TRANSFER         *trans;
231 
232     /* Prepare BulkIN CSW transfer.  */
233     endpoint = storage -> ux_host_class_storage_bulk_in_endpoint;
234     trans = &endpoint -> ux_endpoint_transfer_request;
235     trans -> ux_transfer_request_data_pointer = storage -> ux_host_class_storage_csw;
236     trans -> ux_transfer_request_requested_length = UX_HOST_CLASS_STORAGE_CSW_LENGTH;
237 
238     UX_TRANSFER_STATE_RESET(trans);
239     storage -> ux_host_class_storage_trans = trans;
240     storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_WAIT;
241     storage -> ux_host_class_storage_trans_stage = UX_HOST_CLASS_STORAGE_STAGE_CSW;
242 }
_ux_host_class_storage_transport_trans_exit(UX_HOST_CLASS_STORAGE * storage)243 static inline VOID _ux_host_class_storage_transport_trans_exit(UX_HOST_CLASS_STORAGE *storage)
244 {
245 UCHAR                   *cbw = (UCHAR *) storage -> ux_host_class_storage_cbw;
246 UCHAR                   *cb = cbw + UX_HOST_CLASS_STORAGE_CBW_CB;
247 
248     /* If request sense in progress, response buffer should be freed.  */
249     if (*(cb + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_OPERATION) ==
250         UX_HOST_CLASS_STORAGE_SCSI_REQUEST_SENSE)
251     {
252 
253         /* Free sense buffer and restore data pointer.  */
254         _ux_utility_memory_free(storage -> ux_host_class_storage_trans_data);
255         storage -> ux_host_class_storage_trans_data =
256                                 storage -> ux_host_class_storage_trans_data_bak;
257 
258         /* Restore CBW.  */
259         _ux_utility_memory_copy(storage -> ux_host_class_storage_cbw,
260                                 storage -> ux_host_class_storage_saved_cbw,
261                                 UX_HOST_CLASS_STORAGE_CBW_LENGTH); /* Use case of memcpy is verified. */
262     }
263 
264     /* It's exit.  */
265     storage -> ux_host_class_storage_trans_state = UX_STATE_EXIT;
266 }
_ux_host_class_storage_transport_trans_error(UX_HOST_CLASS_STORAGE * storage)267 static inline VOID _ux_host_class_storage_transport_trans_error(UX_HOST_CLASS_STORAGE *storage)
268 {
269 UX_TRANSFER             *trans = storage -> ux_host_class_storage_trans;
270 UCHAR                   stage = storage -> ux_host_class_storage_trans_stage;
271     if (trans -> ux_transfer_request_completion_code == UX_TRANSFER_STALLED)
272     {
273 
274         /* In case CBW stall, send MS Reset.  */
275         if (stage & UX_HOST_CLASS_STORAGE_STAGE_CBW)
276         {
277             storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_MS_RESET;
278             return;
279         }
280         /* In case DATA/CSW stall, reset endpoint and try again.  */
281         if (stage <= UX_HOST_CLASS_STORAGE_STAGE_CSW)
282         {
283 
284             /* Check retry.  */
285             if (storage -> ux_host_class_storage_trans_retry)
286             {
287                 storage -> ux_host_class_storage_trans_retry --;
288                 storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_EP_RESET;
289             }
290             else
291             {
292                 storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_MS_RESET;
293             }
294             return;
295         }
296 
297         /* In other case, control transfer error.  */
298         storage -> ux_host_class_storage_status = UX_ERROR;
299         storage -> ux_host_class_storage_trans_state = UX_STATE_EXIT;
300         return;
301     }
302     else
303     {
304 
305         /* Perform MS Reset.  */
306         storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_MS_RESET;
307     }
308 }
_ux_host_class_storage_transport_trans_next(UX_HOST_CLASS_STORAGE * storage)309 static inline VOID _ux_host_class_storage_transport_trans_next(UX_HOST_CLASS_STORAGE *storage)
310 {
311 UCHAR                   stage = storage -> ux_host_class_storage_trans_stage;
312 UCHAR                   *cbw = storage -> ux_host_class_storage_cbw;
313 ULONG                   len = _ux_utility_long_get(cbw + UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH);
314 UCHAR                   flags = *(cbw + UX_HOST_CLASS_STORAGE_CBW_FLAGS);
315 UX_ENDPOINT             *endpoint;
316 UX_TRANSFER             *trans;
317 UX_HCD                  *hcd;
318 
319     /* Check transfer completion code.  */
320     trans = storage -> ux_host_class_storage_trans;
321     if (UX_SUCCESS != trans -> ux_transfer_request_completion_code)
322     {
323         _ux_host_class_storage_transport_trans_error(storage);
324         return;
325     }
326 
327     if (stage == UX_HOST_CLASS_STORAGE_STAGE_CBW)
328     {
329 
330         if (len == 0)
331         {
332 
333             /* There is no data, start CSW.  */
334             storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_CSW;
335             return;
336         }
337 
338         /* Reset transfer count.  */
339         storage -> ux_host_class_storage_data_phase_length = 0;
340         if (flags & UX_HOST_CLASS_STORAGE_DATA_IN)
341         {
342 
343             /* Data IN.  */
344             endpoint = storage -> ux_host_class_storage_bulk_in_endpoint;
345             storage -> ux_host_class_storage_trans = &endpoint -> ux_endpoint_transfer_request;
346             storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_IN_NEXT;
347             return;
348         }
349 
350         /* Data OUT.  */
351         endpoint = storage -> ux_host_class_storage_bulk_out_endpoint;
352         storage -> ux_host_class_storage_trans = &endpoint -> ux_endpoint_transfer_request;
353         storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_OUT_NEXT;
354         return;
355     }
356     if (stage == UX_HOST_CLASS_STORAGE_STAGE_DATA)
357     {
358         if (flags & UX_HOST_CLASS_STORAGE_DATA_IN)
359             storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_IN_NEXT;
360         else
361             storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_OUT_NEXT;
362         return;
363     }
364     if (stage == UX_HOST_CLASS_STORAGE_STAGE_CSW)
365     {
366         storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_STATUS;
367         return;
368     }
369     if (stage == UX_HOST_CLASS_STORAGE_STAGE_MS_RESET)
370     {
371 
372         /* Issue EPReset(OUT) then EPReset(IN) after MSReset().  */
373         endpoint = storage -> ux_host_class_storage_bulk_out_endpoint;
374         storage -> ux_host_class_storage_trans = &endpoint -> ux_endpoint_transfer_request;
375         storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_EP_RESET;
376         return;
377     }
378     if (stage & UX_HOST_CLASS_STORAGE_STAGE_EP_RESET)
379     {
380 
381         /* Reset endpoint in HCD level.  */
382         /* Pickup HCD pointer.  */
383         hcd = UX_DEVICE_HCD_GET(storage -> ux_host_class_storage_device);
384 
385         /* Get endpoint instance.  */
386         trans = storage -> ux_host_class_storage_trans;
387         endpoint = (trans -> ux_transfer_request_index & UX_ENDPOINT_DIRECTION) ?
388                             storage -> ux_host_class_storage_bulk_in_endpoint :
389                             storage -> ux_host_class_storage_bulk_out_endpoint;
390 
391         /* Call HCD entry function.  */
392         hcd -> ux_hcd_entry_function(hcd, UX_HCD_RESET_ENDPOINT, endpoint);
393 
394         /* Check if it's part of MSReset() - OUT - IN.  */
395         if (stage & UX_HOST_CLASS_STORAGE_STAGE_MS_RESET)
396         {
397 
398             /* If it's last step, transport is done with error.  */
399             if (trans -> ux_transfer_request_index & UX_ENDPOINT_DIRECTION)
400             {
401 
402                 storage -> ux_host_class_storage_trans_state = UX_STATE_IDLE;
403             }
404             else
405             {
406 
407                 /* BulkIN endpoint reset.  */
408                 endpoint = storage -> ux_host_class_storage_bulk_in_endpoint;
409                 storage -> ux_host_class_storage_trans = &endpoint -> ux_endpoint_transfer_request;
410                 storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_EP_RESET;
411             }
412         }
413         else
414         {
415 
416             storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_CSW;
417         }
418         return;
419     }
420 }
_ux_host_class_storage_transport_trans_in_next(UX_HOST_CLASS_STORAGE * storage)421 static inline VOID _ux_host_class_storage_transport_trans_in_next(UX_HOST_CLASS_STORAGE *storage)
422 {
423 UCHAR               *cbw = storage -> ux_host_class_storage_cbw;
424 UX_TRANSFER         *trans = storage -> ux_host_class_storage_trans;
425 ULONG               requested_length;
426 
427     /* Get total data length.  */
428     requested_length = _ux_utility_long_get(cbw + UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH);
429 
430     /* Check if it's start of DATA phase.  */
431     if (storage -> ux_host_class_storage_trans_stage == UX_HOST_CLASS_STORAGE_STAGE_DATA)
432     {
433 
434         /* Update transferred data length.  */
435         storage -> ux_host_class_storage_data_phase_length +=
436                                     trans -> ux_transfer_request_actual_length;
437 
438         /* Check if all data is done.  */
439         if ((storage -> ux_host_class_storage_data_phase_length >= requested_length) ||
440             (trans -> ux_transfer_request_actual_length < trans -> ux_transfer_request_requested_length))
441         {
442 
443             /* Start CSW.  */
444             storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_CSW;
445             return;
446         }
447     }
448     else
449     {
450 
451         /* Initialize the request for data phase.  */
452         storage -> ux_host_class_storage_trans_stage = UX_HOST_CLASS_STORAGE_STAGE_DATA;
453     }
454 
455 
456     /* There is data remains, continue transfer.  */
457     requested_length -= storage -> ux_host_class_storage_data_phase_length;
458 
459     /* Limit max transfer size.  */
460     if (requested_length > UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE)
461         requested_length = UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE;
462 
463     /* Update transfer.  */
464     UX_TRANSFER_STATE_RESET(trans);
465     trans -> ux_transfer_request_requested_length = requested_length;
466     trans -> ux_transfer_request_data_pointer =
467                             storage -> ux_host_class_storage_trans_data +
468                             storage -> ux_host_class_storage_data_phase_length;
469     storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_WAIT;
470 }
_ux_host_class_storage_transport_trans_out_next(UX_HOST_CLASS_STORAGE * storage)471 static inline VOID _ux_host_class_storage_transport_trans_out_next(UX_HOST_CLASS_STORAGE *storage)
472 {
473 UCHAR               *cbw = storage -> ux_host_class_storage_cbw;
474 UX_TRANSFER         *trans = storage -> ux_host_class_storage_trans;
475 ULONG               requested_length;
476 
477     /* Get total data length.  */
478     requested_length = _ux_utility_long_get(cbw + UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH);
479 
480     /* Check if it's start of DATA phase.  */
481     if (storage -> ux_host_class_storage_trans_stage == UX_HOST_CLASS_STORAGE_STAGE_DATA)
482     {
483         /* Update data count.  */
484         storage -> ux_host_class_storage_data_phase_length +=
485                                 trans -> ux_transfer_request_requested_length;
486 
487         /* Check if all data is done.  */
488         if (storage -> ux_host_class_storage_data_phase_length >= requested_length)
489         {
490 
491             /* Start CSW.  */
492             storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_CSW;
493             return;
494         }
495     }
496     else
497     {
498 
499         /* Initialize the request for data phase.  */
500         storage -> ux_host_class_storage_trans_stage = UX_HOST_CLASS_STORAGE_STAGE_DATA;
501     }
502 
503     /* There is data remains, continue transfer.  */
504     requested_length -= storage -> ux_host_class_storage_data_phase_length;
505 
506     /* Limit max transfer size.  */
507     if (requested_length > UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE)
508         requested_length = UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE;
509 
510     /* Update transfer.  */
511     UX_TRANSFER_STATE_RESET(trans);
512     trans -> ux_transfer_request_requested_length = requested_length;
513     trans -> ux_transfer_request_data_pointer =
514                             storage -> ux_host_class_storage_trans_data +
515                             storage -> ux_host_class_storage_data_phase_length;
516     storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_WAIT;
517 }
_ux_host_class_storage_transport_status(UX_HOST_CLASS_STORAGE * storage)518 static inline VOID _ux_host_class_storage_transport_status(UX_HOST_CLASS_STORAGE *storage)
519 {
520 UCHAR                   *cbw = storage -> ux_host_class_storage_cbw;
521 UCHAR                   *cb = cbw + UX_HOST_CLASS_STORAGE_CBW_CB;
522 UCHAR                   *resp = storage -> ux_host_class_storage_trans_data;
523 ULONG                   sense_code;
524 UCHAR                   csw_status;
525 
526     /* Get CSW status code.  */
527     csw_status = storage -> ux_host_class_storage_csw[UX_HOST_CLASS_STORAGE_CSW_STATUS];
528 
529     /* Check if it's request sense.  */
530     if (*(cb + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_OPERATION) == UX_HOST_CLASS_STORAGE_SCSI_REQUEST_SENSE)
531     {
532 
533         /* Restore command data pointer.  */
534         storage -> ux_host_class_storage_trans_data =
535                                 storage -> ux_host_class_storage_trans_data_bak;
536 
537         /* Get sense code from response buffer.  */
538         sense_code = UX_HOST_CLASS_STORAGE_SENSE_STATUS(
539                 (ULONG) *(resp + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_SENSE_KEY),
540                 (ULONG) *(resp + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE),
541                 (ULONG) *(resp + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE_QUALIFIER));
542 
543         /* Free buffer allocated for sense response.  */
544         _ux_utility_memory_free(resp);
545 
546         /* Passed, keep previous status and done.  */
547         if (csw_status == UX_HOST_CLASS_STORAGE_CSW_PASSED)
548         {
549 
550             /* Store the sense code in the storage instance.  */
551             storage -> ux_host_class_storage_sense_code =  sense_code;
552 
553             /* Now we are done.  */
554             storage -> ux_host_class_storage_trans_state = UX_STATE_IDLE;
555             return;
556         }
557 
558         /* There is issue, do MSReset() and transport done.  */
559         storage -> ux_host_class_storage_trans_status = UX_HOST_CLASS_STORAGE_CSW_PHASE_ERROR;
560         storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_MS_RESET;
561         return;
562     }
563 
564     /* Save status.  */
565     storage -> ux_host_class_storage_trans_status = csw_status;
566 
567     /* Success.  */
568     if (csw_status == UX_HOST_CLASS_STORAGE_CSW_PASSED)
569     {
570         storage -> ux_host_class_storage_status = UX_SUCCESS;
571         storage -> ux_host_class_storage_trans_state = UX_STATE_IDLE;
572         return;
573     }
574 
575     /* There is error.  */
576     storage -> ux_host_class_storage_status = UX_ERROR;
577 
578     /* Fail.  */
579     if (csw_status == UX_HOST_CLASS_STORAGE_CSW_FAILED)
580     {
581         storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_REQ_SENSE;
582         return;
583     }
584 
585     /* Fatal/phase error.  */
586     storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_MS_RESET;
587     return;
588 }
_ux_host_class_storage_transport_ms_reset(UX_HOST_CLASS_STORAGE * storage)589 static inline VOID _ux_host_class_storage_transport_ms_reset(UX_HOST_CLASS_STORAGE *storage)
590 {
591 UX_INTERFACE            *interface_ptr;
592 UX_ENDPOINT             *endpoint;
593 UX_TRANSFER             *trans;
594 
595     /* Prepare MSReset()  */
596     interface_ptr = storage -> ux_host_class_storage_interface;
597     endpoint = &storage -> ux_host_class_storage_device -> ux_device_control_endpoint;
598     trans = &endpoint -> ux_endpoint_transfer_request;
599 
600     /* Create a transfer_request for the RESET request.  */
601     trans -> ux_transfer_request_data_pointer =     UX_NULL;
602     trans -> ux_transfer_request_requested_length = 0;
603     trans -> ux_transfer_request_function =         UX_HOST_CLASS_STORAGE_RESET;
604     trans -> ux_transfer_request_type =             UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
605     trans -> ux_transfer_request_value =            0;
606     trans -> ux_transfer_request_index  =           interface_ptr -> ux_interface_descriptor.bInterfaceNumber;
607 
608     UX_TRANSFER_STATE_RESET(trans);
609     storage -> ux_host_class_storage_trans = trans;
610     storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_WAIT;
611     storage -> ux_host_class_storage_trans_stage = UX_HOST_CLASS_STORAGE_STAGE_MS_RESET;
612 }
_ux_host_class_storage_transport_ep_reset(UX_HOST_CLASS_STORAGE * storage)613 static inline VOID _ux_host_class_storage_transport_ep_reset(UX_HOST_CLASS_STORAGE *storage)
614 {
615 UX_ENDPOINT             *endpoint;
616 UX_TRANSFER             *trans;
617 ULONG                   endpoint_address;
618 
619     /* Clear halt for current transfer.  */
620 
621     /* Get endpoint address.  */
622     endpoint = storage -> ux_host_class_storage_trans -> ux_transfer_request_endpoint;
623     endpoint_address = endpoint -> ux_endpoint_descriptor.bEndpointAddress;
624 
625     /* Send ClearEndpointFeature(EP, Halt).  */
626     endpoint = &storage -> ux_host_class_storage_device -> ux_device_control_endpoint;
627     trans = &endpoint -> ux_endpoint_transfer_request;
628 
629     /* Create a transfer_request for the CLEAR_FEATURE request.  */
630     trans -> ux_transfer_request_data_pointer =     UX_NULL;
631     trans -> ux_transfer_request_requested_length = 0;
632     trans -> ux_transfer_request_function =         UX_CLEAR_FEATURE;
633     trans -> ux_transfer_request_type =             UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_ENDPOINT;
634     trans -> ux_transfer_request_value =            UX_ENDPOINT_HALT;
635     trans -> ux_transfer_request_index =            endpoint_address;
636 
637     UX_TRANSFER_STATE_RESET(trans);
638     storage -> ux_host_class_storage_trans = trans;
639     storage -> ux_host_class_storage_trans_state = UX_HOST_CLASS_STORAGE_TRANS_WAIT;
640     storage -> ux_host_class_storage_trans_stage |= UX_HOST_CLASS_STORAGE_STAGE_EP_RESET;
641 }
642 #endif
643