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