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