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 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_host_class_storage_configure                    PORTABLE C      */
38 /*                                                           6.1          */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function calls the USBX stack to do a SET_CONFIGURATION to the */
46 /*    storage device. Once the storage is configured, its interface will  */
47 /*    be activated. The bulk endpoints enumerated(1 IN, 1 OUT).           */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    storage                               Pointer to storage class      */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    Completion Status                                                   */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _ux_host_stack_configuration_interface_get    Get configuration     */
60 /*    _ux_host_stack_device_configuration_get       Get device config     */
61 /*    _ux_host_stack_device_configuration_select    Select configuration  */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    Storage Class                                                       */
66 /*                                                                        */
67 /*  RELEASE HISTORY                                                       */
68 /*                                                                        */
69 /*    DATE              NAME                      DESCRIPTION             */
70 /*                                                                        */
71 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
72 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
73 /*                                            optimized based on compile  */
74 /*                                            definitions,                */
75 /*                                            resulting in version 6.1    */
76 /*                                                                        */
77 /**************************************************************************/
_ux_host_class_storage_configure(UX_HOST_CLASS_STORAGE * storage)78 UINT  _ux_host_class_storage_configure(UX_HOST_CLASS_STORAGE *storage)
79 {
80 
81 UINT                    status;
82 UX_CONFIGURATION        *configuration;
83 #if UX_MAX_DEVICES > 1
84 UX_DEVICE               *parent_device;
85 #endif
86 
87 
88     /* If the device has been configured already, we don't need to do it
89        again.  */
90     if (storage -> ux_host_class_storage_device -> ux_device_state == UX_DEVICE_CONFIGURED)
91         return(UX_SUCCESS);
92 
93     /* A storage device normally has one configuration. So retrieve the 1st configuration
94        only.  */
95     status =  _ux_host_stack_device_configuration_get(storage -> ux_host_class_storage_device, 0, &configuration);
96 
97     /* Check completion status.  */
98     if (status != UX_SUCCESS)
99     {
100 
101         /* Error trap. */
102         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN);
103 
104         /* If trace is enabled, insert this event into the trace buffer.  */
105         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, storage -> ux_host_class_storage_device, 0, 0, UX_TRACE_ERRORS, 0, 0)
106 
107         return(UX_CONFIGURATION_HANDLE_UNKNOWN);
108     }
109 
110 #if UX_MAX_DEVICES > 1
111     /* Check the storage device power source and check the parent power source for
112        incompatible connections.  */
113     if (storage -> ux_host_class_storage_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)
114     {
115 
116         /* Pickup pointer to parent device.  */
117         parent_device =  storage -> ux_host_class_storage_device -> ux_device_parent;
118 
119         /* If the device is NULL, the parent is the root hub and we don't have to worry
120            if the parent is not the root hub, check for its power source.  */
121         if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED))
122         {
123 
124             /* Error trap. */
125             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONNECTION_INCOMPATIBLE);
126 
127             /* If trace is enabled, insert this event into the trace buffer.  */
128             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, storage, 0, 0, UX_TRACE_ERRORS, 0, 0)
129 
130             return(UX_CONNECTION_INCOMPATIBLE);
131         }
132     }
133 #endif
134 
135     /* We have the valid configuration. Ask the USBX stack to set this configuration.  */
136     status =  _ux_host_stack_device_configuration_select(configuration);
137     if (status != UX_SUCCESS)
138         return(status);
139 
140     /* If the operation went well, the storage device default alternate setting
141        for the storage device interface is active and the interrupt endpoint is now enabled.
142        We have to memorize the first interface since the interrupt endpoint is hooked to it.  */
143     status =  _ux_host_stack_configuration_interface_get(configuration, 0, 0, &storage -> ux_host_class_storage_interface);
144 
145     /* Check completion status.  */
146     if (status != UX_SUCCESS)
147     {
148         /* Store the instance in the interface container, this is for the USBX stack
149            when it needs to invoke the class.  */
150         storage -> ux_host_class_storage_interface -> ux_interface_class_instance =  (VOID *) storage;
151     }
152 
153     /* Return completion status.  */
154     return(status);
155 }
156 
157