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 /** Storage 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_storage.h"
29 #include "ux_host_stack.h"
30
31
32 #if defined(UX_HOST_STANDALONE)
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _ux_host_class_storage_check_run PORTABLE C */
38 /* 6.2.1 */
39 /* AUTHOR */
40 /* */
41 /* Chaoqiong Xiao, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function runs state machine to check and mount/unmount storage */
46 /* media for current locked logic unit number (LUN). */
47 /* */
48 /* It's valid only in standalone mode. */
49 /* It's non-blocking. */
50 /* */
51 /* Note it must be used in case following conditions are true: */
52 /* - storage insstance is live */
53 /* - storage is locked for specific LUN */
54 /* - if check is not started yet the main storage state must be idle */
55 /* */
56 /* INPUT */
57 /* */
58 /* storage Pointer to storage class */
59 /* */
60 /* OUTPUT */
61 /* */
62 /* Completion State Status */
63 /* UX_STATE_WAIT States started/in progress */
64 /* UX_STATE_NEXT Check is done, next call will */
65 /* start check again. */
66 /* */
67 /* CALLS */
68 /* */
69 /* _ux_system_error_handler The error trap */
70 /* _ux_system_tasks_run Run USB system tasks */
71 /* */
72 /* CALLED BY */
73 /* */
74 /* Storage Class */
75 /* */
76 /* RELEASE HISTORY */
77 /* */
78 /* DATE NAME DESCRIPTION */
79 /* */
80 /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */
81 /* 03-08-2023 Chaoqiong Xiao Modified comment(s), */
82 /* checked device state, */
83 /* resulting in version 6.2.1 */
84 /* */
85 /**************************************************************************/
_ux_host_class_storage_check_run(UX_HOST_CLASS_STORAGE * storage)86 UINT _ux_host_class_storage_check_run(UX_HOST_CLASS_STORAGE *storage)
87 {
88 UX_DEVICE *device;
89
90 #if defined UX_HOST_CLASS_STORAGE_STATE_CHECK_ENABLE
91 UX_INTERRUPT_SAVE_AREA
92
93 /* Check states - storage must be live, locked and main state machine idle. */
94 UX_DISABLE
95 if (storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_LIVE ||
96 (storage -> ux_host_class_storage_flags & UX_HOST_CLASS_STORAGE_FLAG_LOCK) == 0 ||
97 (storage -> ux_host_class_storage_op_state != UX_STATE_WAIT &&
98 storage -> ux_host_class_storage_state_state != UX_STATE_IDLE))
99 {
100 UX_RESTORE
101
102 /* Error trap. */
103 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NOT_READY);
104
105 /* The state is not ready for check operation. */
106 storage -> ux_host_class_storage_status = UX_TRANSFER_NOT_READY;
107 storage -> ux_host_class_storage_op_state = UX_STATE_RESET;
108 return(UX_STATE_ERROR);
109 }
110 UX_RESTORE
111 #endif
112
113 /* Get device. */
114 device = storage -> ux_host_class_storage_device;
115
116 switch(storage -> ux_host_class_storage_op_state)
117 {
118 case UX_STATE_IDLE:
119 case UX_STATE_ERROR:
120 case UX_STATE_RESET:
121
122 /* Setup states for immediate LUN check. */
123 storage -> ux_host_class_storage_flags |=
124 UX_HOST_CLASS_STORAGE_FLAG_CHECK_CURRENT;
125 storage -> ux_host_class_storage_check_lun =
126 (UCHAR)storage -> ux_host_class_storage_lun;
127 storage -> ux_host_class_storage_state_state =
128 UX_HOST_CLASS_STORAGE_STATE_TEST_READY;
129
130 /* Next : wait */
131 storage -> ux_host_class_storage_op_state = UX_STATE_WAIT;
132
133 /* Fall through. */
134 case UX_STATE_WAIT:
135
136 /* Run tasks, including transport task. */
137 _ux_system_host_tasks_run();
138
139 /* Check if device is still available. */
140 if (device -> ux_device_state != UX_DEVICE_CONFIGURED)
141 {
142
143 /* Instance should have been destroyed, just return. */
144 return(UX_STATE_EXIT);
145 }
146
147 /* In case state is not idle, check if it changes back. */
148 if (storage -> ux_host_class_storage_state_state == UX_STATE_IDLE)
149 {
150 storage -> ux_host_class_storage_op_state = UX_STATE_IDLE;
151 return(UX_STATE_NEXT);
152 }
153
154 /* Keep waiting. */
155 return(UX_STATE_WAIT);
156
157 /* Unexpected states. */
158 default:
159 storage -> ux_host_class_storage_op_state = UX_STATE_RESET;
160 break;
161 }
162
163 /* We should never be here. */
164 return(UX_STATE_EXIT);
165 }
166 #endif
167