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