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 }