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