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