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 }