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