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