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