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