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_hcd_unregister                       PORTABLE C      */
36 /*                                                           6.1.2        */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Chaoqiong Xiao, Microsoft Corporation                               */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function unregisters a USB host controller driver (HCD) with   */
44 /*    the USBX stack, removes all devices rooted from that controller and */
45 /*    disable/stop the controller.                                        */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    hcd_name                              Name of HCD to unregister     */
50 /*    hcd_param1                            Parameter 1 of HCD            */
51 /*    hcd_param2                            Parameter 2 of HCD            */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    Completion Status                                                   */
56 /*    UX_SUCCESS                            HCD unregistered, related     */
57 /*                                          devices removed and hardware  */
58 /*                                          disabled/stopped success      */
59 /*    UX_ERROR                              HCD not found                 */
60 /*                                                                        */
61 /*  CALLS                                                                 */
62 /*                                                                        */
63 /*    _ux_utility_string_length_check       Check and return C string     */
64 /*                                          length if no error            */
65 /*    _ux_utility_memory_compare            Memory compare                */
66 /*    (ux_hcd_entry_function)               HCD dispatch entry function   */
67 /*                                                                        */
68 /*  CALLED BY                                                             */
69 /*                                                                        */
70 /*    Application                                                         */
71 /*                                                                        */
72 /*  RELEASE HISTORY                                                       */
73 /*                                                                        */
74 /*    DATE              NAME                      DESCRIPTION             */
75 /*                                                                        */
76 /*  09-30-2020     Chaoqiong Xiao           Initial Version 6.1           */
77 /*  11-09-2020     Chaoqiong Xiao           Modified comment(s),          */
78 /*                                            fixed HCD devices scan,     */
79 /*                                            used HCD uninit command,    */
80 /*                                            fixed HCD status scan,      */
81 /*                                            resulting in version 6.1.2  */
82 /*                                                                        */
83 /**************************************************************************/
_ux_host_stack_hcd_unregister(UCHAR * hcd_name,ULONG hcd_param1,ULONG hcd_param2)84 UINT  _ux_host_stack_hcd_unregister(UCHAR *hcd_name,
85                                     ULONG hcd_param1, ULONG hcd_param2)
86 {
87 
88 UINT        status;
89 UX_DEVICE   *device;
90 UX_HCD      *hcd;
91 #if UX_MAX_CLASS_DRIVER > 1 || UX_MAX_DEVICES > 1
92 ULONG       scan_index;
93 #endif
94 #if !defined(UX_NAME_REFERENCED_BY_POINTER)
95 UINT        hcd_name_length =  0;
96 #endif
97 
98 
99     /* If trace is enabled, insert this event into the trace buffer.  */
100     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_HCD_UNREGISTER, hcd_name, hcd_param1, hcd_param2, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
101 
102 #if !defined(UX_NAME_REFERENCED_BY_POINTER)
103     /* Get the length of the class name (exclude null-terminator).  */
104     status =  _ux_utility_string_length_check(hcd_name,
105                                     &hcd_name_length, UX_MAX_HCD_NAME_LENGTH);
106     if (status)
107         return(status);
108 #endif
109 
110     /* Get first HCD.  */
111     hcd =  _ux_system_host -> ux_system_host_hcd_array;
112 
113     /* Default to not found status.  */
114     status = UX_FALSE;
115 
116 #if UX_MAX_CLASS_DRIVER > 1
117     /* We need to parse the controller driver table to find an empty spot.  */
118     for (scan_index = 0;
119          scan_index < UX_SYSTEM_HOST_MAX_HCD_GET();
120          scan_index++)
121     {
122 #endif
123 
124         /* Is this slot available and saved hcd_parameters match?  */
125         if (hcd -> ux_hcd_status != UX_UNUSED &&
126             hcd -> ux_hcd_io == hcd_param1 &&
127             hcd -> ux_hcd_irq == hcd_param2)
128         {
129 
130 
131             /* Yes, compare the name (with null terminator).  */
132             status = ux_utility_name_match(hcd -> ux_hcd_name,
133                                             hcd_name, hcd_name_length + 1);
134 #if UX_MAX_CLASS_DRIVER > 1
135 
136             /* Break if name match (found HCD).  */
137             if (status == UX_TRUE)
138                 break;
139 #endif
140             }
141 
142 #if UX_MAX_CLASS_DRIVER > 1
143         /* Try the next HCD structure */
144         hcd ++;
145     }
146 #endif
147 
148     /* No valid HCD found.  */
149     if (status != UX_TRUE)
150         return(UX_ERROR);
151 
152     /* Now disable controller.  */
153     hcd -> ux_hcd_entry_function(hcd, UX_HCD_UNINITIALIZE, UX_NULL);
154 
155     /* Get first device.  */
156     device = _ux_system_host -> ux_system_host_device_array;
157 
158 #if UX_MAX_DEVICES > 1
159     /* Remove all devices connected to the controller.  */
160     for (scan_index = 0;
161          scan_index < _ux_system_host -> ux_system_host_max_devices;
162          scan_index ++)
163     {
164 #else
165 
166         /* No device.  */
167         if (device -> ux_device_handle == UX_UNUSED)
168             return(UX_SUCCESS);
169 #endif
170 
171         /* Is this device on the HCD root hub?  */
172         if (UX_DEVICE_HCD_MATCH(device, hcd) &&
173             UX_DEVICE_PARENT_IS_ROOTHUB(device))
174         {
175 
176             /* Remove the device (and downstream things connected to it).  */
177             _ux_host_stack_device_remove(hcd, UX_DEVICE_PARENT_GET(device),
178                                          UX_DEVICE_PORT_LOCATION_GET(device));
179 
180             /* The device has been removed, so the port is free again.  */
181             hcd -> ux_hcd_rh_device_connection &= (ULONG)
182                                     ~(1 << device -> ux_device_port_location);
183         }
184 
185 #if UX_MAX_DEVICES > 1
186 
187         /* Try the next device.  */
188         device ++;
189     }
190 #endif
191 
192     /* And we have one new controller unregistered.  */
193     _ux_system_host -> ux_system_host_registered_hcd --;
194 
195     return(UX_SUCCESS);
196 }
197 
198 
199 /**************************************************************************/
200 /*                                                                        */
201 /*  FUNCTION                                               RELEASE        */
202 /*                                                                        */
203 /*    _uxe_host_stack_hcd_unregister                      PORTABLE C      */
204 /*                                                           6.3.0        */
205 /*  AUTHOR                                                                */
206 /*                                                                        */
207 /*    Chaoqiong Xiao, Microsoft Corporation                               */
208 /*                                                                        */
209 /*  DESCRIPTION                                                           */
210 /*                                                                        */
211 /*    This function checks errors in host stack HCD unregister function   */
212 /*    call.                                                               */
213 /*                                                                        */
214 /*  INPUT                                                                 */
215 /*                                                                        */
216 /*    hcd_name                              Name of HCD to unregister     */
217 /*    hcd_param1                            Parameter 1 of HCD            */
218 /*    hcd_param2                            Parameter 2 of HCD            */
219 /*                                                                        */
220 /*  OUTPUT                                                                */
221 /*                                                                        */
222 /*    None                                                                */
223 /*                                                                        */
224 /*  CALLS                                                                 */
225 /*                                                                        */
226 /*    _ux_host_stack_hcd_unregister         HCD unregister                */
227 /*                                                                        */
228 /*  CALLED BY                                                             */
229 /*                                                                        */
230 /*    Application                                                         */
231 /*                                                                        */
232 /*  RELEASE HISTORY                                                       */
233 /*                                                                        */
234 /*    DATE              NAME                      DESCRIPTION             */
235 /*                                                                        */
236 /*  10-31-2023     Chaoqiong Xiao           Initial Version 6.3.0         */
237 /*                                                                        */
238 /**************************************************************************/
_uxe_host_stack_hcd_unregister(UCHAR * hcd_name,ULONG hcd_param1,ULONG hcd_param2)239 UINT  _uxe_host_stack_hcd_unregister(UCHAR *hcd_name,
240                                     ULONG hcd_param1, ULONG hcd_param2)
241 {
242 
243     /* Sanity check.  */
244     if (hcd_name == UX_NULL)
245         return(UX_INVALID_PARAMETER);
246 
247     /* Invoke HCD unregister function.  */
248     return(_ux_host_stack_hcd_unregister(hcd_name, hcd_param1, hcd_param2));
249 }
250