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 /**   HUB Class                                                           */
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_class_hub.h"
29 #include "ux_host_stack.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_host_class_hub_configure                        PORTABLE C      */
37 /*                                                           6.1.11       */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function calls the USBX stack to do a SET_CONFIGURATION to the */
45 /*    HUB. Once the HUB is configured, its interface will be activated    */
46 /*    and all the endpoints enumerated (1 interrupt endpoint in the case  */
47 /*    of the HUB).                                                        */
48 /*                                                                        */
49 /*  INPUT                                                                 */
50 /*                                                                        */
51 /*    hub                                   Pointer to HUB                */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    Completion Status                                                   */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _ux_host_stack_device_configuration_get Get device configuration    */
60 /*    _ux_host_stack_device_configuration_select                          */
61 /*                                          Select device configuration   */
62 /*    _ux_host_stack_configuration_interface_get                          */
63 /*                                          Get interface                 */
64 /*    _ux_host_stack_transfer_request       Process transfer request      */
65 /*    _ux_utility_memory_allocate           Allocate memory block         */
66 /*    _ux_utility_memory_free               Release memory block          */
67 /*                                                                        */
68 /*  CALLED BY                                                             */
69 /*                                                                        */
70 /*    HUB 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 /*                                            optimized based on compile  */
79 /*                                            definitions,                */
80 /*                                            resulting in version 6.1    */
81 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
82 /*                                            internal clean up,          */
83 /*                                            resulting in version 6.1.11 */
84 /*                                                                        */
85 /**************************************************************************/
_ux_host_class_hub_configure(UX_HOST_CLASS_HUB * hub)86 UINT  _ux_host_class_hub_configure(UX_HOST_CLASS_HUB *hub)
87 {
88 
89 UINT                    status;
90 UX_CONFIGURATION        *configuration;
91 UX_DEVICE               *device;
92 UX_ENDPOINT             *control_endpoint;
93 UCHAR                   *device_status_data;
94 UX_TRANSFER             *transfer_request;
95 #if UX_MAX_DEVICES > 1
96 UX_DEVICE               *parent_device;
97 #endif
98 
99 
100     /* A HUB normally has one configuration. So retrieve the 1st configuration
101        only.  */
102     _ux_host_stack_device_configuration_get(hub -> ux_host_class_hub_device, 0, &configuration);
103 
104     /* Get the device container for this configuration.  */
105     device =  configuration -> ux_configuration_device;
106 
107     /* To find the true source of the HUB power source, we need to do a GET_STATUS of
108        the device.  */
109     control_endpoint =  &device -> ux_device_control_endpoint;
110     transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
111 
112     /* Allocate a buffer for the device status: 2 bytes.  */
113     device_status_data =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 2);
114     if (device_status_data == UX_NULL)
115         return(UX_MEMORY_INSUFFICIENT);
116 
117     /* Create a transfer_request for the GET_STATUS request, 2 bytes are returned.  */
118     transfer_request -> ux_transfer_request_requested_length =  2;
119     transfer_request -> ux_transfer_request_data_pointer =      device_status_data;
120     transfer_request -> ux_transfer_request_function =          UX_GET_STATUS;
121     transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE;
122     transfer_request -> ux_transfer_request_value =             0;
123     transfer_request -> ux_transfer_request_index =             0;
124 
125     /* Send request to HCD layer.  */
126     status =  _ux_host_stack_transfer_request(transfer_request);
127 
128     /* Check the status and the length of the data returned.  */
129     if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 2))
130     {
131 
132         /* The data returned is good, now analyze power source.  */
133         if (*device_status_data & UX_STATUS_DEVICE_SELF_POWERED)
134             device -> ux_device_power_source =  UX_DEVICE_SELF_POWERED;
135         else
136             device -> ux_device_power_source =  UX_DEVICE_BUS_POWERED;
137 
138         /* Free the buffer resource now.  */
139         _ux_utility_memory_free(device_status_data);
140     }
141     else
142     {
143 
144         /* Free the buffer resource now.  */
145         _ux_utility_memory_free(device_status_data);
146 
147         /* Error trap. */
148         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_CONNECTION_INCOMPATIBLE);
149 
150         /* If trace is enabled, insert this event into the trace buffer.  */
151         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, hub, 0, 0, UX_TRACE_ERRORS, 0, 0)
152 
153         /* Return an error.  */
154         return(UX_CONNECTION_INCOMPATIBLE);
155     }
156 
157 #if UX_MAX_DEVICES > 1
158     /* Check the HUB power source and check the parent power source for
159        incompatible connections.  */
160     if (hub -> ux_host_class_hub_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)
161     {
162 
163         /* Get the parent container for this device.  */
164         parent_device =  device -> ux_device_parent;
165 
166         /* If the device is NULL, the parent is the root HUB and we don't have to worry
167            if the parent is not the root HUB, check for its power source.  */
168         if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED))
169         {
170 
171             /* Error trap. */
172             _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_CONNECTION_INCOMPATIBLE);
173 
174             /* If trace is enabled, insert this event into the trace buffer.  */
175             UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, hub, 0, 0, UX_TRACE_ERRORS, 0, 0)
176 
177             return(UX_CONNECTION_INCOMPATIBLE);
178         }
179     }
180 #endif
181 
182     /* We have the valid configuration. Ask the USBX stack to set this configuration.  */
183     _ux_host_stack_device_configuration_select(configuration);
184 
185     /* If the operation went well, the HUB default alternate setting for the HUB interface is
186        active and the interrupt endpoint is now enabled. We have to memorize the first interface
187        since the interrupt endpoint is hooked to it. */
188     status =  _ux_host_stack_configuration_interface_get(configuration, 0, 0, &hub -> ux_host_class_hub_interface);
189 
190     /* Return completion status.  */
191     return(status);
192 }
193 
194