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_device_remove                        PORTABLE C      */
37 /*                                                           6.1.12       */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function will remove a USB device from the bus.                */
45 /*                                                                        */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    HCD                                   Pointer to the HCD            */
49 /*    parent                                The parent device address     */
50 /*    port_index                            Index of the port on which the*/
51 /*                                            change of status occurred   */
52 /*                                                                        */
53 /*  OUTPUT                                                                */
54 /*                                                                        */
55 /*    Completion Status                                                   */
56 /*                                                                        */
57 /*  CALLS                                                                 */
58 /*                                                                        */
59 /*    _ux_host_stack_device_resources_free  Free all device resources     */
60 /*                                                                        */
61 /*  CALLED BY                                                             */
62 /*                                                                        */
63 /*    USBX Components                                                     */
64 /*                                                                        */
65 /*  RELEASE HISTORY                                                       */
66 /*                                                                        */
67 /*    DATE              NAME                      DESCRIPTION             */
68 /*                                                                        */
69 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
70 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
71 /*                                            optimized based on compile  */
72 /*                                            definitions,                */
73 /*                                            resulting in version 6.1    */
74 /*  02-02-2021     Chaoqiong Xiao           Modified comment(s),          */
75 /*                                            used pointer for current    */
76 /*                                            selected configuration,     */
77 /*                                            added notification for      */
78 /*                                            device disconnection,       */
79 /*                                            resulting in version 6.1.4  */
80 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
81 /*                                            added standalone support,   */
82 /*                                            resulting in version 6.1.10 */
83 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
84 /*                                            fixed parameter/variable    */
85 /*                                            names conflict C++ keyword, */
86 /*                                            resulting in version 6.1.12 */
87 /*                                                                        */
88 /**************************************************************************/
_ux_host_stack_device_remove(UX_HCD * hcd,UX_DEVICE * parent,UINT port_index)89 UINT  _ux_host_stack_device_remove(UX_HCD *hcd, UX_DEVICE *parent, UINT port_index)
90 {
91 
92 #if UX_MAX_DEVICES > 1
93 ULONG                       container_index;
94 #endif
95 UX_DEVICE                   *device;
96 UX_CONFIGURATION            *configuration;
97 UX_INTERFACE                *interface_ptr;
98 UX_HOST_CLASS_COMMAND       command;
99 
100     /* We need to find the device descriptor for the removed device. We can find it
101        with the parent device and the port it was attached to. Start with the first device.  */
102     device =  _ux_system_host -> ux_system_host_device_array;
103 
104 #if UX_MAX_DEVICES > 1
105     /* Start at the beginning of the list.  */
106     container_index =  0;
107 
108     /* Search the list until the end.  */
109     while (container_index++ < _ux_system_host -> ux_system_host_max_devices)
110     {
111 
112         /* Until we have found a used entry.  */
113         if (device -> ux_device_handle != UX_UNUSED)
114         {
115 
116             /* Check for the parent device and the port location and the controller.  */
117             if( UX_DEVICE_PARENT_MATCH(device, parent) &&
118                 UX_DEVICE_PORT_LOCATION_MATCH(device, port_index) &&
119                 UX_DEVICE_HCD_MATCH(device, hcd))
120                 break;
121         }
122 
123         /* Move to the next device entry.  */
124         device++;
125     }
126 
127     /* Device not found.  */
128     if (container_index > _ux_system_host -> ux_system_host_max_devices)
129 #else
130     UX_PARAMETER_NOT_USED(parent);
131     UX_PARAMETER_NOT_USED(port_index);
132 
133     /* Device is available and HCD is expected.  */
134     if (device -> ux_device_handle == UX_UNUSED ||
135         !UX_DEVICE_HCD_MATCH(device, hcd))
136 #endif
137     {
138 
139         /* Error trap. */
140         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DEVICE_HANDLE_UNKNOWN);
141 
142         /* If trace is enabled, insert this event into the trace buffer.  */
143         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0)
144 
145         /* We get here when we could not find the device.  */
146         return(UX_DEVICE_HANDLE_UNKNOWN);
147     }
148 
149     /* If trace is enabled, insert this event into the trace buffer.  */
150     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_REMOVE, hcd, parent, port_index, device, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
151 
152     /* If trace is enabled, unregister this object.  */
153     UX_TRACE_OBJECT_UNREGISTER(device);
154 
155     /* We have found the device to be removed. */
156     device -> ux_device_state = UX_DEVICE_REMOVED;
157 
158     /* We have found the device to be removed. Initialize the class
159         command with the generic parameters.  */
160     command.ux_host_class_command_request =  UX_HOST_CLASS_COMMAND_DEACTIVATE;
161 
162     /* The device may have a class associated with the device container or its interfaces.  */
163     if (device -> ux_device_class_instance != UX_NULL)
164     {
165 
166         /* We need to stop the class instance for the device.  */
167         command.ux_host_class_command_instance =  device -> ux_device_class_instance;
168 
169         /* Call the class.  */
170         device -> ux_device_class -> ux_host_class_entry_function(&command);
171     }
172     else
173     {
174 
175         /* Search for the active configuration.  */
176         configuration =  device -> ux_device_current_configuration;
177 
178         /* If configuration is activated.  */
179         if (configuration != UX_NULL)
180         {
181 
182             /* We have the correct configuration, search the interface(s).  */
183             interface_ptr =  configuration -> ux_configuration_first_interface;
184 
185             /* Loop to perform the search.  */
186             while (interface_ptr != UX_NULL)
187             {
188 
189                 /* Check if an instance of the interface is present.  */
190                 if (interface_ptr -> ux_interface_class_instance != UX_NULL)
191                 {
192 
193                     /* We need to stop the class instance for the device.  */
194                     command.ux_host_class_command_instance =  interface_ptr -> ux_interface_class_instance;
195 
196                     /* Call the class.  */
197                     interface_ptr -> ux_interface_class -> ux_host_class_entry_function(&command);
198                 }
199 
200                 /* Move to next interface.  */
201                 interface_ptr =  interface_ptr -> ux_interface_next_interface;
202             }
203         }
204     }
205 
206     /* Notify application for disconnection of existing physical device.  */
207     if (_ux_system_host -> ux_system_host_change_function)
208     {
209         _ux_system_host -> ux_system_host_change_function(UX_DEVICE_DISCONNECTION, UX_NULL, (VOID*)device);
210     }
211 
212     /* Now all the resources for this device must be free.  */
213     _ux_host_stack_device_resources_free(device);
214 
215     /* Decrement the number of devices on this bus.  */
216     hcd -> ux_hcd_nb_devices--;
217 
218     /* We are done with this device removal.  */
219     return(UX_SUCCESS);
220 }
221