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 /** */
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_write PORTABLE C */
36 /* 6.3.0 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function writes to the DPUMP class. */
44 /* */
45 /* INPUT */
46 /* */
47 /* dpump Address of dpump class */
48 /* instance */
49 /* */
50 /* OUTPUT */
51 /* */
52 /* None */
53 /* */
54 /* CALLS */
55 /* */
56 /* _ux_utility_memory_copy */
57 /* _ux_device_stack_transfer_request */
58 /* */
59 /* CALLED BY */
60 /* */
61 /* ThreadX */
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 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), */
73 /* added a new mode to manage */
74 /* endpoint buffer in classes, */
75 /* resulting in version 6.3.0 */
76 /* */
77 /**************************************************************************/
_ux_device_class_dpump_write(UX_SLAVE_CLASS_DPUMP * dpump,UCHAR * buffer,ULONG requested_length,ULONG * actual_length)78 UINT _ux_device_class_dpump_write(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer,
79 ULONG requested_length, ULONG *actual_length)
80 {
81
82 UX_SLAVE_ENDPOINT *endpoint;
83 UX_SLAVE_DEVICE *device;
84 UX_SLAVE_TRANSFER *transfer_request;
85 ULONG local_requested_length;
86 UINT status;
87
88 /* If trace is enabled, insert this event into the trace buffer. */
89 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DPUMP_WRITE, dpump, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
90
91 /* Get the pointer to the device. */
92 device = &_ux_system_slave -> ux_system_slave_device;
93
94 /* As long as the device is in the CONFIGURED state. */
95 if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
96 {
97
98 /* Error trap. */
99 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN);
100
101 /* If trace is enabled, insert this event into the trace buffer. */
102 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0)
103
104 /* Cannot proceed with command, the interface is down. */
105 return(UX_CONFIGURATION_HANDLE_UNKNOWN);
106 }
107
108 /* Locate the IN endpoint. */
109 endpoint = dpump -> ux_slave_class_dpump_bulkin_endpoint;
110
111 /* Check endpoint. If NULL, we have not yet received the proper SET_INTERFACE command. */
112 if (endpoint == UX_NULL)
113 {
114
115 /* Error trap. */
116 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN);
117
118 return(UX_ENDPOINT_HANDLE_UNKNOWN);
119 }
120
121 /* We are writing to the IN endpoint. */
122 transfer_request = &endpoint -> ux_slave_endpoint_transfer_request;
123
124 /* Reset the actual length. */
125 *actual_length = 0;
126
127 /* Set return status to SUCCESS to make certain compilers happy. */
128 status = UX_SUCCESS;
129
130 /* Check if we need more transactions. */
131 while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED && requested_length != 0)
132 {
133
134 /* Check if we have enough in the local buffer. */
135 if (requested_length > UX_DEVICE_CLASS_DPUMP_WRITE_BUFFER_SIZE)
136
137 /* We have too much to transfer. */
138 local_requested_length = UX_DEVICE_CLASS_DPUMP_WRITE_BUFFER_SIZE;
139
140 else
141
142 /* We can proceed with the demanded length. */
143 local_requested_length = requested_length;
144
145 /* On a out, we copy the buffer to the caller. Not very efficient but it makes the API
146 easier. */
147 _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer,
148 buffer, local_requested_length); /* Use case of memcpy is verified. */
149
150 /* Send the request to the device controller. */
151 status = _ux_device_stack_transfer_request(transfer_request, local_requested_length, local_requested_length);
152
153 /* Check the status */
154 if (status == UX_SUCCESS)
155 {
156
157 /* Next buffer address. */
158 buffer += transfer_request -> ux_slave_transfer_request_actual_length;
159
160 /* Set the length actually received. */
161 *actual_length += transfer_request -> ux_slave_transfer_request_actual_length;
162
163 /* Decrement what left has to be done. */
164 requested_length -= transfer_request -> ux_slave_transfer_request_actual_length;
165
166 }
167
168 else
169
170 /* We had an error, abort. */
171 return(status);
172 }
173
174 /* Check why we got here, either completion or device was extracted. */
175 if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
176 {
177
178 /* Error trap. */
179 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER);
180
181 /* If trace is enabled, insert this event into the trace buffer. */
182 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0)
183
184 /* Device must have been extracted. */
185 return (UX_TRANSFER_NO_ANSWER);
186 }
187 else
188
189 /* Simply return the last transaction result. */
190 return(status);
191
192 }
193
194