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 /** USBX Component */
15 /** */
16 /** Device DPUMP Class */
17 /** */
18 /**************************************************************************/
19 /**************************************************************************/
20
21 #define UX_SOURCE_CODE
22
23
24 /* Include necessary system files. */
25
26 #include "ux_api.h"
27 #include "ux_device_class_dpump.h"
28 #include "ux_device_stack.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_device_class_dpump_change PORTABLE C */
36 /* 6.3.0 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function changes the interface of the DPUMP device */
44 /* */
45 /* INPUT */
46 /* */
47 /* command Pointer to dpump command */
48 /* */
49 /* OUTPUT */
50 /* */
51 /* Completion Status */
52 /* */
53 /* CALLS */
54 /* */
55 /* _ux_utility_memory_set Set memory */
56 /* _ux_device_stack_transfer_all_request_abort */
57 /* Abort request */
58 /* */
59 /* CALLED BY */
60 /* */
61 /* USBX Source Code */
62 /* */
63 /* RELEASE HISTORY */
64 /* */
65 /* DATE NAME DESCRIPTION */
66 /* */
67 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
68 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
69 /* verified memset and memcpy */
70 /* cases, */
71 /* resulting in version 6.1 */
72 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
73 /* added standalone support, */
74 /* resulting in version 6.1.10 */
75 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
76 /* fixed parameter/variable */
77 /* names conflict C++ keyword, */
78 /* resulting in version 6.1.12 */
79 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), */
80 /* added a new mode to manage */
81 /* endpoint buffer in classes, */
82 /* resulting in version 6.3.0 */
83 /* */
84 /**************************************************************************/
_ux_device_class_dpump_change(UX_SLAVE_CLASS_COMMAND * command)85 UINT _ux_device_class_dpump_change(UX_SLAVE_CLASS_COMMAND *command)
86 {
87
88 UX_SLAVE_INTERFACE *interface_ptr;
89 UX_SLAVE_CLASS *class_ptr;
90 UX_SLAVE_CLASS_DPUMP *dpump;
91 UX_SLAVE_ENDPOINT *endpoint;
92
93 /* Get the class container. */
94 class_ptr = command -> ux_slave_class_command_class_ptr;
95
96 /* Get the class instance in the container. */
97 dpump = (UX_SLAVE_CLASS_DPUMP *) class_ptr -> ux_slave_class_instance;
98
99 /* Get the interface that owns this instance. */
100 interface_ptr = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface;
101
102 /* Locate the endpoints. Control and Bulk in/out for data. */
103 endpoint = interface_ptr -> ux_slave_interface_first_endpoint;
104
105 /* Keep the alternate setting in the dpump structure. */
106 dpump -> ux_slave_class_dpump_alternate_setting = interface_ptr -> ux_slave_interface_descriptor.bAlternateSetting;
107
108 /* If the interface to mount has a non zero alternate setting, the class is really active with
109 the endpoints active. If the interface reverts to alternate setting 0, it needs to have
110 the pending transactions terminated. */
111 if (interface_ptr -> ux_slave_interface_descriptor.bAlternateSetting != 0)
112 {
113
114 /* Parse all endpoints. */
115 while (endpoint != UX_NULL)
116 {
117
118 /* Check the endpoint direction, and type. */
119 if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN)
120 {
121
122 /* Look at type. */
123 if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)
124
125 /* We have found the bulk in endpoint, save it. */
126 dpump -> ux_slave_class_dpump_bulkin_endpoint = endpoint;
127 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
128 endpoint -> ux_slave_endpoint_transfer_request.
129 ux_slave_transfer_request_data_pointer =
130 UX_DEVICE_CLASS_DPUMP_WRITE_BUFFER(dpump);
131 #endif
132 }
133 else
134 {
135 /* Look at type for out endpoint. */
136 if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)
137
138 /* We have found the bulk out endpoint, save it. */
139 dpump -> ux_slave_class_dpump_bulkout_endpoint = endpoint;
140 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
141 endpoint -> ux_slave_endpoint_transfer_request.
142 ux_slave_transfer_request_data_pointer =
143 UX_DEVICE_CLASS_DPUMP_READ_BUFFER(dpump);
144 #endif
145 }
146
147 /* Next endpoint. */
148 endpoint = endpoint -> ux_slave_endpoint_next_endpoint;
149 }
150
151
152 /* Now check if all endpoints have been found. */
153 if (dpump -> ux_slave_class_dpump_bulkout_endpoint == UX_NULL || dpump -> ux_slave_class_dpump_bulkin_endpoint == UX_NULL)
154
155 /* Not all endpoints have been found. Major error, do not proceed. */
156 return(UX_ERROR);
157
158 /* Reset the endpoint buffers. */
159 _ux_utility_memory_set(dpump -> ux_slave_class_dpump_bulkout_endpoint -> ux_slave_endpoint_transfer_request.
160 ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */
161 _ux_utility_memory_set(dpump -> ux_slave_class_dpump_bulkin_endpoint -> ux_slave_endpoint_transfer_request.
162 ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); /* Use case of memset is verified. */
163
164 /* Keep the alternate setting in the dpump structure. */
165 dpump -> ux_slave_class_dpump_alternate_setting = interface_ptr -> ux_slave_interface_descriptor.bAlternateSetting;
166
167 #if defined(UX_DEVICE_STANDALONE)
168
169 /* Reset read/write states. */
170 dpump -> ux_device_class_dpump_read_state = 0;
171 dpump -> ux_device_class_dpump_write_state = 0;
172 #endif
173
174 /* If there is an activate function call it. */
175 if (dpump -> ux_slave_class_dpump_parameter.ux_slave_class_dpump_instance_activate != UX_NULL)
176
177 /* Invoke the application. */
178 dpump -> ux_slave_class_dpump_parameter.ux_slave_class_dpump_instance_activate(dpump);
179 }
180 else
181 {
182
183 /* In this case, we are reverting to the Alternate Setting 0. We need to terminate the pending transactions. */
184 /* Terminate the transactions pending on the endpoints (bulk in, bulk out). */
185 _ux_device_stack_transfer_all_request_abort(dpump -> ux_slave_class_dpump_bulkin_endpoint, UX_TRANSFER_APPLICATION_RESET);
186 _ux_device_stack_transfer_all_request_abort(dpump -> ux_slave_class_dpump_bulkout_endpoint, UX_TRANSFER_APPLICATION_RESET);
187
188 }
189
190 /* If trace is enabled, insert this event into the trace buffer. */
191 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DPUMP_CHANGE, dpump, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
192
193 /* If trace is enabled, register this object. */
194 UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, dpump, 0, 0, 0)
195
196 /* Return completion status. */
197 return(UX_SUCCESS);
198 }
199
200