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