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_interface_setting_select             PORTABLE C      */
37 /*                                                           6.1.12       */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function selects a specific alternate setting for a given      */
45 /*    interface belonging to the selected configuration.                  */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    interface                             Pointer to interface          */
50 /*                                                                        */
51 /*  OUTPUT                                                                */
52 /*                                                                        */
53 /*    Completion Status                                                   */
54 /*                                                                        */
55 /*  CALLS                                                                 */
56 /*                                                                        */
57 /*    _ux_host_stack_interface_instance_create  Create interface instance */
58 /*    _ux_host_stack_interface_instance_delete  Delete interface instance */
59 /*    _ux_host_stack_interface_set              Set interface instance    */
60 /*    _ux_host_semaphore_get                    Get semaphore             */
61 /*    _ux_host_semaphore_put                    Put semaphore             */
62 /*                                                                        */
63 /*  CALLED BY                                                             */
64 /*                                                                        */
65 /*    Application                                                         */
66 /*    USBX Components                                                     */
67 /*                                                                        */
68 /*  RELEASE HISTORY                                                       */
69 /*                                                                        */
70 /*    DATE              NAME                      DESCRIPTION             */
71 /*                                                                        */
72 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
73 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
74 /*                                            resulting in version 6.1    */
75 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
76 /*                                            protected control request,  */
77 /*                                            resulting in version 6.1.12 */
78 /*                                                                        */
79 /**************************************************************************/
_ux_host_stack_interface_setting_select(UX_INTERFACE * interface_ptr)80 UINT  _ux_host_stack_interface_setting_select(UX_INTERFACE *interface_ptr)
81 {
82 
83 UX_CONFIGURATION    *configuration;
84 UX_INTERFACE        *current_interface;
85 UX_INTERFACE        *previous_interface;
86 UX_INTERFACE        *main_interface;
87 UINT                current_interface_number;
88 UINT                current_alternate_setting;
89 UINT                status;
90 
91     /* If trace is enabled, insert this event into the trace buffer.  */
92     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_INTERFACE_SETTING_SELECT, interface_ptr, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0)
93 
94     /* Check this alternate setting container. It must be valid before
95        we continue.  */
96     if (interface_ptr -> ux_interface_handle != (ULONG) (ALIGN_TYPE) interface_ptr)
97     {
98         /* If trace is enabled, insert this event into the trace buffer.  */
99         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_INTERFACE_HANDLE_UNKNOWN, interface_ptr, 0, 0, UX_TRACE_ERRORS, 0, 0)
100 
101         return(UX_INTERFACE_HANDLE_UNKNOWN);
102     }
103 
104     /* From the interface, get the configuration container and the first
105        interface hooked to this configuration.  */
106     configuration =             interface_ptr -> ux_interface_configuration;
107     current_interface_number =  interface_ptr -> ux_interface_descriptor.bInterfaceNumber;
108     current_interface =         configuration -> ux_configuration_first_interface;
109 
110     /* Remember the main interface to store the next alternate setting.  We set the main interface
111        to the first interface to keep the compiler happy. */
112     main_interface =  current_interface;
113 
114     /* In order to keep the compiler happy, we reset the alternate setting.  */
115     current_alternate_setting =  0;
116     previous_interface = UX_NULL;
117 
118     /* Search for the current alternate setting for this interface.
119        All its endpoints will need to be destroyed.
120        Since interfaces in the parent configuration should be linked together
121        in correct way, just find it in while loop.
122      */
123     while (1)
124     {
125 
126         /* Try to locate the first interface container in the interface chain which
127            has the same interface number as the one supplied by the caller.  */
128         if (current_interface -> ux_interface_descriptor.bInterfaceNumber == current_interface_number)
129         {
130 
131             /* The alternate setting 0 of this interface has the current selected
132                alternate setting.  */
133             if (current_interface -> ux_interface_descriptor.bAlternateSetting == 0)
134             {
135 
136                 /* Set the alternate setting.  */
137                 current_alternate_setting =  current_interface -> ux_interface_current_alternate_setting;
138 
139                 /* Remember the main interface to store the next alternate setting.  */
140                 main_interface =  current_interface;
141 
142             }
143 
144             /* See if the current alternate setting matches that of the interface alternate setting.  */
145             if (current_alternate_setting == current_interface -> ux_interface_descriptor.bAlternateSetting)
146             {
147 
148                 /* Yes, save the current alternate setting.  */
149                 previous_interface = current_interface;
150 
151                 /* Then delete the current interface.  */
152                 _ux_host_stack_interface_instance_delete(current_interface);
153 
154                 /* We are done in this loop.  */
155                 break;
156 
157             }
158         }
159 
160         /* Move to the next interface. */
161         current_interface =  current_interface -> ux_interface_next_interface;
162     }
163 
164     /* Remember the new alternate setting.  */
165     main_interface -> ux_interface_current_alternate_setting =  interface_ptr -> ux_interface_descriptor.bAlternateSetting;
166 
167     /* Now, the interface must be created with the new alternate setting.  */
168     status =  _ux_host_stack_interface_instance_create(interface_ptr);
169 
170     /* If we could not create it, we return to the default one.  */
171     if (status != UX_SUCCESS)
172     {
173 
174         /* Then delete the failed interface.  */
175         _ux_host_stack_interface_instance_delete(interface_ptr);
176 
177         /* Error, reset the main interface alternate setting to the default.  */
178         main_interface -> ux_interface_current_alternate_setting =  current_alternate_setting;
179 
180         /* Re-create the previous interface with the old alternate setting.  */
181         _ux_host_stack_interface_instance_create(previous_interface);
182 
183         /* Return error status.  */
184         return(status);
185     }
186 
187     /* Protect the control endpoint semaphore here.  It will be unprotected in the
188        transfer request function.  */
189     status =  _ux_host_semaphore_get(&configuration -> ux_configuration_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER);
190     if (status != UX_SUCCESS)
191         return(status);
192 
193     /* Issue a SET_INTERFACE command to the target device.  */
194     status =  _ux_host_stack_interface_set(interface_ptr);
195 
196     /* Check completion status.  */
197     if (status != UX_SUCCESS)
198     {
199 
200         /* Error, reset the main interface alternate setting to the default.  */
201         main_interface -> ux_interface_current_alternate_setting =  current_alternate_setting;
202 
203         /* Delete the current interface.  */
204         _ux_host_stack_interface_instance_delete(interface_ptr);
205 
206         /* Re-create the previous interface with the old alternate setting.  */
207         _ux_host_stack_interface_instance_create(previous_interface);
208 
209         /* Return error status.  */
210         _ux_host_semaphore_put(&configuration -> ux_configuration_device -> ux_device_protection_semaphore);
211         return(status);
212     }
213 
214     /* Return to caller.  */
215     return(status);
216 }
217 
218