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 /** Device Storage Class */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define UX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "ux_api.h"
29 #include "ux_device_class_storage.h"
30 #include "ux_device_stack.h"
31
32 /* Define the Slave Storage Class Inquiry data : DO NOT CHANGE THE LENGTH OF THESE ITEMS */
33
34 UCHAR _ux_system_slave_class_storage_vendor_id[] = "AzureRTO";
35 UCHAR _ux_system_slave_class_storage_product_id[] = "USBX storage dev";
36 UCHAR _ux_system_slave_class_storage_product_rev[] = "2000";
37 UCHAR _ux_system_slave_class_storage_product_serial[] = "12345678901234567890";
38
39 /**************************************************************************/
40 /* */
41 /* FUNCTION RELEASE */
42 /* */
43 /* _ux_device_class_storage_initialize PORTABLE C */
44 /* 6.1.10 */
45 /* AUTHOR */
46 /* */
47 /* Chaoqiong Xiao, Microsoft Corporation */
48 /* */
49 /* DESCRIPTION */
50 /* */
51 /* This function initializes the USB storage device. */
52 /* */
53 /* INPUT */
54 /* */
55 /* command Pointer to storage command */
56 /* */
57 /* OUTPUT */
58 /* */
59 /* Completion Status */
60 /* */
61 /* CALLS */
62 /* */
63 /* _ux_utility_memory_allocate Allocate memory */
64 /* _ux_utility_memory_free Free memory */
65 /* _ux_device_thread_create Create thread */
66 /* _ux_device_thread_delete Delete thread */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* Device Storage Class */
71 /* */
72 /* RELEASE HISTORY */
73 /* */
74 /* DATE NAME DESCRIPTION */
75 /* */
76 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
77 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
78 /* used UX prefix to refer to */
79 /* TX symbols instead of using */
80 /* them directly, */
81 /* resulting in version 6.1 */
82 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
83 /* added standalone support, */
84 /* resulting in version 6.1.10 */
85 /* */
86 /**************************************************************************/
_ux_device_class_storage_initialize(UX_SLAVE_CLASS_COMMAND * command)87 UINT _ux_device_class_storage_initialize(UX_SLAVE_CLASS_COMMAND *command)
88 {
89
90 UINT status = UX_SUCCESS;
91 UX_SLAVE_CLASS_STORAGE *storage;
92 UX_SLAVE_CLASS_STORAGE_PARAMETER *storage_parameter;
93 UX_SLAVE_CLASS *class_inst;
94 ULONG lun_index;
95
96
97 /* Get the pointer to the application parameters for the storage class. */
98 storage_parameter = command -> ux_slave_class_command_parameter;
99
100 /* Ensure the number of LUN declared by the caller does not exceed the
101 max number allowed for LUN storage. */
102 if (storage_parameter -> ux_slave_class_storage_parameter_number_lun > UX_MAX_SLAVE_LUN)
103 return UX_ERROR;
104
105 /* Get the class container. */
106 class_inst = command -> ux_slave_class_command_class_ptr;
107
108 /* Create an instance of the device storage class. */
109 storage = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_STORAGE));
110
111 /* Check for successful allocation. */
112 if (storage == UX_NULL)
113 return(UX_MEMORY_INSUFFICIENT);
114
115 #if !defined(UX_DEVICE_STANDALONE)
116
117 /* Allocate some memory for the thread stack. */
118 class_inst -> ux_slave_class_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE);
119
120 /* If it's OK, create thread. */
121 if (class_inst -> ux_slave_class_thread_stack != UX_NULL)
122
123 /* This instance needs to be running in a different thread. So start
124 a new thread. We pass a pointer to the class to the new thread. This thread
125 does not start until we have a instance of the class. */
126 status = _ux_device_thread_create(&class_inst -> ux_slave_class_thread, "ux_slave_storage_thread",
127 _ux_device_class_storage_thread,
128 (ULONG) (ALIGN_TYPE) class_inst, (VOID *) class_inst -> ux_slave_class_thread_stack,
129 UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS,
130 UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START);
131 else
132 status = UX_MEMORY_INSUFFICIENT;
133 #else
134
135 /* Save tasks run entry. */
136 class_inst -> ux_slave_class_task_function = _ux_device_class_storage_tasks_run;
137
138 status = UX_SUCCESS;
139 #endif
140
141 /* If thread resources allocated, go on. */
142 if (status == UX_SUCCESS)
143 {
144
145 UX_THREAD_EXTENSION_PTR_SET(&(class_inst -> ux_slave_class_thread), class_inst)
146
147 /* Store the number of LUN declared. */
148 storage -> ux_slave_class_storage_number_lun = storage_parameter -> ux_slave_class_storage_parameter_number_lun;
149
150 /* Copy each individual LUN parameters. */
151 for (lun_index = 0; lun_index < storage -> ux_slave_class_storage_number_lun; lun_index++)
152 {
153
154 /* Check block length size. */
155 if (storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_block_length > UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE)
156 {
157 /* Cannot proceed. */
158 status = (UX_MEMORY_INSUFFICIENT);
159 break;
160 }
161
162 /* Store all the application parameter information about the media. */
163 storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_last_lba = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_last_lba;
164 storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_block_length = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_block_length;
165 storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_type = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_type;
166 storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_removable_flag = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_removable_flag;
167 storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_read_only_flag = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_read_only_flag;
168 storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_read = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_read;
169 storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_flush = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_flush;
170 storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_write = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_write;
171 storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_status = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_status;
172 storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_notification = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_notification;
173 }
174
175 /* If it's OK, complete it. */
176 if (status == UX_SUCCESS)
177 {
178
179 /* Store the start and stop signals if needed by the application. */
180 storage -> ux_slave_class_storage_instance_activate = storage_parameter -> ux_slave_class_storage_instance_activate;
181 storage -> ux_slave_class_storage_instance_deactivate = storage_parameter -> ux_slave_class_storage_instance_deactivate;
182
183 /* Store the vendor id, product id, product revision and product serial. */
184 if (storage_parameter -> ux_slave_class_storage_parameter_vendor_id)
185 storage -> ux_slave_class_storage_vendor_id = storage_parameter -> ux_slave_class_storage_parameter_vendor_id;
186 else
187 storage -> ux_slave_class_storage_vendor_id = _ux_system_slave_class_storage_vendor_id;
188
189 if (storage_parameter -> ux_slave_class_storage_parameter_product_id)
190 storage -> ux_slave_class_storage_product_id = storage_parameter -> ux_slave_class_storage_parameter_product_id;
191 else
192 storage -> ux_slave_class_storage_product_id = _ux_system_slave_class_storage_product_id;
193
194 if (storage_parameter -> ux_slave_class_storage_parameter_product_rev)
195 storage -> ux_slave_class_storage_product_rev = storage_parameter -> ux_slave_class_storage_parameter_product_rev;
196 else
197 storage -> ux_slave_class_storage_product_rev = _ux_system_slave_class_storage_product_rev;
198
199 if (storage_parameter -> ux_slave_class_storage_parameter_product_serial)
200 storage -> ux_slave_class_storage_product_serial = storage_parameter -> ux_slave_class_storage_parameter_product_serial;
201 else
202 storage -> ux_slave_class_storage_product_serial = _ux_system_slave_class_storage_product_serial;
203
204 /* Save the address of the STORAGE instance inside the STORAGE container. */
205 class_inst -> ux_slave_class_instance = (VOID *) storage;
206
207 return(UX_SUCCESS);
208 }
209
210 /* Free thread resources. */
211 _ux_device_thread_delete(&class_inst -> ux_slave_class_thread);
212 }
213
214 #if !defined(UX_DEVICE_STANDALONE)
215 if (class_inst -> ux_slave_class_thread_stack != UX_NULL)
216 _ux_utility_memory_free(&class_inst -> ux_slave_class_thread_stack);
217 #endif
218
219 /* Free instance. */
220 _ux_utility_memory_free(storage);
221
222 /* Return completion status. */
223 return(status);
224 }
225
226