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 /** Host Stack */
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_stack.h"
30
31
32 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_host_stack_configuration_set PORTABLE C */
37 /* 6.1.10 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function performs a setting of a device configuration. */
45 /* */
46 /* In RTOS mode, this function is blocking. */
47 /* If the host is OTG capable and the device has an OTG descriptor */
48 /* that supports HNP we perform a SET_FEATURE with b_hnp_support. */
49 /* */
50 /* In standalone mode, when device enumeration is in progress, this */
51 /* function is non-blocking, it prepares transfer for enum step of */
52 /* SET_CONFIGURE request. Otherwise it blocks until transfer request */
53 /* done. */
54 /* */
55 /* INPUT */
56 /* */
57 /* configuration Pointer to configuration */
58 /* */
59 /* OUTPUT */
60 /* */
61 /* Completion Status */
62 /* */
63 /* CALLS */
64 /* */
65 /* _ux_host_stack_transfer_request Process transfer request */
66 /* */
67 /* CALLED BY */
68 /* */
69 /* USBX Components */
70 /* */
71 /* RELEASE HISTORY */
72 /* */
73 /* DATE NAME DESCRIPTION */
74 /* */
75 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
76 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
77 /* optimized based on compile */
78 /* definitions, */
79 /* resulting in version 6.1 */
80 /* 02-02-2021 Chaoqiong Xiao Modified comment(s), */
81 /* used pointer for current */
82 /* selected configuration, */
83 /* resulting in version 6.1.4 */
84 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
85 /* added standalone support, */
86 /* set device power source, */
87 /* resulting in version 6.1.10 */
88 /* */
89 /**************************************************************************/
_ux_host_stack_configuration_set(UX_CONFIGURATION * configuration)90 UINT _ux_host_stack_configuration_set(UX_CONFIGURATION *configuration)
91 {
92
93 UX_DEVICE *device;
94 UX_TRANSFER *transfer_request;
95 UINT status;
96 UX_ENDPOINT *control_endpoint;
97 #ifdef UX_OTG_SUPPORT
98 UX_HCD *hcd;
99 #endif
100
101
102 /* A configuration is selected. Retrieve the pointer to the control endpoint
103 and its transfer request. */
104 device = configuration -> ux_configuration_device;
105 control_endpoint = &device -> ux_device_control_endpoint;
106 transfer_request = &control_endpoint -> ux_endpoint_transfer_request;
107
108 #ifdef UX_OTG_SUPPORT
109 /* Check if the configuration has an OTG device with HNP feature. */
110 if (configuration -> ux_configuration_otg_capabilities & UX_OTG_HNP_SUPPORT)
111 {
112
113 /* For HNP to work the device has to be connected directly to the Root Hub and not
114 a down stream hub. If the parent is NULL, the device is on the root hub. */
115 if (UX_DEVICE_PARENT_IS_ROOTHUB(device))
116 {
117
118 /* With the device we have the pointer to the HCD. */
119 hcd = UX_DEVICE_HCD_GET(device);
120
121 /* Check the HCD to ensure we have an OTG host controller. */
122 if (hcd -> ux_hcd_otg_capabilities & UX_HCD_OTG_CAPABLE)
123 {
124
125 /* The Host controller is OTG aware. Perform a SET_FEATURE with b_hnp_support. */
126 transfer_request -> ux_transfer_request_data_pointer = UX_NULL;
127 transfer_request -> ux_transfer_request_requested_length = 0;
128 transfer_request -> ux_transfer_request_function = UX_SET_FEATURE;
129 transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT| UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
130 transfer_request -> ux_transfer_request_value = UX_OTG_FEATURE_A_HNP_SUPPORT;
131 transfer_request -> ux_transfer_request_index = 0;
132
133 /* Send request to HCD layer. */
134 status = _ux_host_stack_transfer_request(transfer_request);
135
136 /* If the device fails this command we turn off its OTG capabilities. */
137 if (status != UX_SUCCESS)
138
139 /* Reset the OTG capabilities of the device. */
140 configuration -> ux_configuration_otg_capabilities = 0;
141
142 }
143 }
144 }
145 #endif
146
147 /* If trace is enabled, insert this event into the trace buffer. */
148 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_CONFIGURATION_SET, configuration, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
149
150 /* Create a transfer_request for the SET_CONFIGURATION request. No data for this request. */
151 transfer_request -> ux_transfer_request_requested_length = 0;
152 transfer_request -> ux_transfer_request_function = UX_SET_CONFIGURATION;
153 transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
154 transfer_request -> ux_transfer_request_value = (USHORT) configuration -> ux_configuration_descriptor.bConfigurationValue;
155 transfer_request -> ux_transfer_request_index = 0;
156
157 #if defined(UX_HOST_STANDALONE)
158 if (device -> ux_device_flags &= UX_DEVICE_FLAG_ENUM)
159 {
160
161 /* Special case for enumeration process, non-blocking. */
162 device -> ux_device_enum_trans = transfer_request;
163 status = UX_SUCCESS;
164 return(status);
165 }
166
167 /* Tend to be blocking after enumeration done. */
168 #endif
169
170 /* Send request to HCD layer. */
171 status = _ux_host_stack_transfer_request(transfer_request);
172
173 /* Check completion status. */
174 if(status == UX_SUCCESS)
175 {
176
177 /* Change the device state to configured. */
178 device -> ux_device_state = UX_DEVICE_CONFIGURED;
179
180 /* Store the new configuration value in the device container. */
181 device -> ux_device_current_configuration = configuration;
182
183 /* Save current device power source. */
184 device -> ux_device_power_source = (configuration ->
185 ux_configuration_descriptor.bmAttributes &
186 UX_CONFIGURATION_DEVICE_SELF_POWERED) ?
187 UX_DEVICE_SELF_POWERED : UX_DEVICE_BUS_POWERED;
188 }
189
190 /* Return status to caller. */
191 return(status);
192 }
193