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 Printer 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_printer.h"
28 #include "ux_device_stack.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _ux_device_class_printer_read PORTABLE C */
36 /* 6.1.11 */
37 /* AUTHOR */
38 /* */
39 /* Chaoqiong Xiao, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function reads from the Printer class. */
44 /* */
45 /* INPUT */
46 /* */
47 /* printer Address of printer class */
48 /* instance */
49 /* buffer Pointer to buffer to save */
50 /* received data */
51 /* requested_length Length of bytes to read */
52 /* actual_length Pointer to save number of */
53 /* bytes read */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* None */
58 /* */
59 /* CALLS */
60 /* */
61 /* _ux_device_stack_transfer_request Transfer request */
62 /* _ux_utility_memory_copy Copy memory */
63 /* _ux_device_mutex_off Release mutex */
64 /* */
65 /* CALLED BY */
66 /* */
67 /* Application */
68 /* */
69 /* RELEASE HISTORY */
70 /* */
71 /* DATE NAME DESCRIPTION */
72 /* */
73 /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */
74 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
75 /* fixed standalone compile, */
76 /* resulting in version 6.1.11 */
77 /* */
78 /**************************************************************************/
_ux_device_class_printer_read(UX_DEVICE_CLASS_PRINTER * printer,UCHAR * buffer,ULONG requested_length,ULONG * actual_length)79 UINT _ux_device_class_printer_read(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buffer,
80 ULONG requested_length, ULONG *actual_length)
81 {
82
83 UX_SLAVE_ENDPOINT *endpoint;
84 UX_SLAVE_DEVICE *device;
85 UX_SLAVE_TRANSFER *transfer_request;
86 UINT status= UX_SUCCESS;
87 ULONG local_requested_length;
88
89 /* If trace is enabled, insert this event into the trace buffer. */
90 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PRINTER_READ, printer, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
91
92 /* Get the pointer to the device. */
93 device = &_ux_system_slave -> ux_system_slave_device;
94
95 /* As long as the device is in the CONFIGURED state. */
96 if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
97 {
98
99 /* Error trap. */
100 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN);
101
102 /* If trace is enabled, insert this event into the trace buffer. */
103 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0)
104
105 /* Cannot proceed with command, the interface is down. */
106 return(UX_CONFIGURATION_HANDLE_UNKNOWN);
107 }
108
109 /* Locate the endpoint. */
110 endpoint = printer -> ux_device_class_printer_endpoint_out;
111
112 /* Protect this thread. */
113 _ux_device_mutex_on(&printer -> ux_device_class_printer_endpoint_out_mutex);
114
115 /* All Printer reading are on the endpoint OUT, from the host. */
116 transfer_request = &endpoint -> ux_slave_endpoint_transfer_request;
117
118 #if (UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1) && defined(UX_DEVICE_CLASS_PRINTER_ZERO_COPY)
119
120 /* Check if device is configured. */
121 if (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
122 {
123
124 /* Issue the transfer request. */
125 local_requested_length = requested_length;
126 transfer_request -> ux_slave_transfer_request_data_pointer = buffer;
127 status = _ux_device_stack_transfer_request(transfer_request,
128 local_requested_length, local_requested_length);
129 *actual_length = transfer_request -> ux_slave_transfer_request_actual_length;
130 }
131 #else
132
133 /* Reset the actual length. */
134 *actual_length = 0;
135
136 /* Check if we need more transactions. */
137 while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED && requested_length != 0)
138 {
139
140 /* Check if we have enough in the local buffer. */
141 if (requested_length > endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize)
142
143 /* We have too much to transfer. */
144 local_requested_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize;
145
146 else
147
148 /* We can proceed with the demanded length. */
149 local_requested_length = requested_length;
150
151 /* Send the request to the device controller. */
152 status = _ux_device_stack_transfer_request(transfer_request,
153 local_requested_length, local_requested_length);
154
155 /* Check the status */
156 if (status == UX_SUCCESS)
157 {
158
159 /* We need to copy the buffer locally. */
160 _ux_utility_memory_copy(buffer,
161 transfer_request -> ux_slave_transfer_request_data_pointer,
162 transfer_request -> ux_slave_transfer_request_actual_length); /* Use case of memcpy is verified. */
163
164 /* Next buffer address. */
165 buffer += transfer_request -> ux_slave_transfer_request_actual_length;
166
167 /* Set the length actually received. */
168 *actual_length += transfer_request -> ux_slave_transfer_request_actual_length;
169
170 /* Decrement what left has to be done. */
171 requested_length -= transfer_request -> ux_slave_transfer_request_actual_length;
172
173 /* Is this a short packet or a ZLP indicating we are done with this transfer ? */
174 if (transfer_request -> ux_slave_transfer_request_actual_length <
175 endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize)
176 {
177
178 /* We are done. */
179 /* Free Mutex resource. */
180 _ux_device_mutex_off(&printer -> ux_device_class_printer_endpoint_out_mutex);
181
182 /* Return with success. */
183 return(UX_SUCCESS);
184 }
185 }
186 else
187 {
188
189 /* Free Mutex resource. */
190 _ux_device_mutex_off(&printer -> ux_device_class_printer_endpoint_out_mutex);
191
192 /* We got an error. */
193 return(status);
194 }
195 }
196 #endif
197
198 /* Free Mutex resource. */
199 _ux_device_mutex_off(&printer -> ux_device_class_printer_endpoint_out_mutex);
200
201 /* Check why we got here, either completion or device was extracted. */
202 if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
203 {
204
205 /* Error trap. */
206 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER);
207
208 /* If trace is enabled, insert this event into the trace buffer. */
209 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0)
210
211 /* Device must have been extracted. */
212 return (UX_TRANSFER_NO_ANSWER);
213 }
214 else
215
216 /* Simply return the last transaction result. */
217 return(status);
218 }
219
220 /**************************************************************************/
221 /* */
222 /* FUNCTION RELEASE */
223 /* */
224 /* _uxe_device_class_printer_read PORTABLE C */
225 /* 6.3.0 */
226 /* AUTHOR */
227 /* */
228 /* Yajun Xia, Microsoft Corporation */
229 /* */
230 /* DESCRIPTION */
231 /* */
232 /* This function checks errors in printer class read function */
233 /* */
234 /* INPUT */
235 /* */
236 /* printer Address of printer class */
237 /* instance */
238 /* buffer Pointer to buffer to save */
239 /* received data */
240 /* requested_length Length of bytes to read */
241 /* actual_length Pointer to save number of */
242 /* bytes read */
243 /* */
244 /* OUTPUT */
245 /* */
246 /* None */
247 /* */
248 /* CALLS */
249 /* */
250 /* _ux_device_class_printer_read Printer class read function */
251 /* */
252 /* CALLED BY */
253 /* */
254 /* Application */
255 /* */
256 /* RELEASE HISTORY */
257 /* */
258 /* DATE NAME DESCRIPTION */
259 /* */
260 /* 03-08-2023 Yajun Xia Initial Version 6.2.1 */
261 /* 10-31-2023 Yajun Xia Modified comment(s), */
262 /* fixed error checking issue, */
263 /* resulting in version 6.3.0 */
264 /* */
265 /**************************************************************************/
_uxe_device_class_printer_read(UX_DEVICE_CLASS_PRINTER * printer,UCHAR * buffer,ULONG requested_length,ULONG * actual_length)266 UINT _uxe_device_class_printer_read(UX_DEVICE_CLASS_PRINTER *printer, UCHAR *buffer,
267 ULONG requested_length, ULONG *actual_length)
268 {
269
270 /* Sanity checks. */
271 if ((printer == UX_NULL) || ((buffer == UX_NULL) && (requested_length > 0)) || (actual_length == UX_NULL))
272 {
273 return (UX_INVALID_PARAMETER);
274 }
275
276 return (_ux_device_class_printer_read(printer, buffer, requested_length, actual_length));
277 }