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 #if defined(UX_DEVICE_STANDALONE)
33 
34 
35 /**************************************************************************/
36 /*                                                                        */
37 /*  FUNCTION                                               RELEASE        */
38 /*                                                                        */
39 /*    _ux_device_class_printer_read_run                   PORTABLE C      */
40 /*                                                           6.2.0        */
41 /*  AUTHOR                                                                */
42 /*                                                                        */
43 /*    Yajun Xia, Microsoft Corporation                                    */
44 /*                                                                        */
45 /*  DESCRIPTION                                                           */
46 /*                                                                        */
47 /*    This function reads from the Printer class.                         */
48 /*                                                                        */
49 /*    It's for standalone mode.                                           */
50 /*                                                                        */
51 /*  INPUT                                                                 */
52 /*                                                                        */
53 /*    printer                               Address of printer class      */
54 /*                                            instance                    */
55 /*    buffer                                Pointer to buffer to save     */
56 /*                                            received data               */
57 /*    requested_length                      Length of bytes to read       */
58 /*    actual_length                         Pointer to save number of     */
59 /*                                            bytes read                  */
60 /*                                                                        */
61 /*  OUTPUT                                                                */
62 /*                                                                        */
63 /*    State machine Status to check                                       */
64 /*    UX_STATE_NEXT                         Transfer done, to next state  */
65 /*    UX_STATE_EXIT                         Abnormal, to reset state      */
66 /*    (others)                              Keep running, waiting         */
67 /*                                                                        */
68 /*  CALLS                                                                 */
69 /*                                                                        */
70 /*    _ux_device_stack_transfer_run         Transfer request              */
71 /*    _ux_utility_memory_copy               Copy memory                   */
72 /*                                                                        */
73 /*  CALLED BY                                                             */
74 /*                                                                        */
75 /*    Application                                                         */
76 /*                                                                        */
77 /*  RELEASE HISTORY                                                       */
78 /*                                                                        */
79 /*    DATE              NAME                      DESCRIPTION             */
80 /*                                                                        */
81 /*  10-31-2022        Yajun xia             Initial Version 6.2.0         */
82 /*                                                                        */
83 /**************************************************************************/
_ux_device_class_printer_read_run(UX_DEVICE_CLASS_PRINTER * printer,UCHAR * buffer,ULONG requested_length,ULONG * actual_length)84 UINT _ux_device_class_printer_read_run(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                       max_transfer_length;
92 UINT                        status = UX_SUCCESS;
93 
94     /* If trace is enabled, insert this event into the trace buffer.  */
95     UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PRINTER_READ, printer, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
96 
97     /* Get the pointer to the device.  */
98     device =  &_ux_system_slave -> ux_system_slave_device;
99 
100     /* As long as the device is in the CONFIGURED state.  */
101     if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
102     {
103 
104         /* Error trap. */
105         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN);
106 
107         /* If trace is enabled, insert this event into the trace buffer.  */
108         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0)
109 
110         /* Cannot proceed with command, the interface is down.  */
111         printer -> ux_device_class_printer_read_state = UX_STATE_RESET;
112         printer -> ux_device_class_printer_read_status = UX_CONFIGURATION_HANDLE_UNKNOWN;
113 
114         return(UX_STATE_EXIT);
115     }
116 
117     /* Locate the endpoint.  */
118     endpoint = printer -> ux_device_class_printer_endpoint_out;
119 
120     /* All Printer reading  are on the endpoint OUT, from the host.  */
121     transfer_request =  &endpoint -> ux_slave_endpoint_transfer_request;
122 
123     /* Handle state cases.  */
124     switch(printer -> ux_device_class_printer_read_state)
125     {
126     case UX_STATE_RESET:
127 
128         /* If trace is enabled, insert this event into the trace buffer.  */
129         UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PRINTER_READ, printer, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
130 
131         printer -> ux_device_class_printer_read_state = UX_DEVICE_CLASS_PRINTER_READ_START;
132         printer -> ux_device_class_printer_read_status = UX_TRANSFER_NO_ANSWER;
133         printer -> ux_device_class_printer_read_buffer = buffer;
134         printer -> ux_device_class_printer_read_requested_length = requested_length;
135         printer -> ux_device_class_printer_read_actual_length = 0;
136 
137         /* Fall through. */
138     case UX_DEVICE_CLASS_PRINTER_READ_START:
139 
140         /* Get remaining transfer length.  */
141         requested_length = printer -> ux_device_class_printer_read_requested_length -
142                         printer -> ux_device_class_printer_read_actual_length;
143 
144         /* There is nothing remaining, it's done.  */
145         if (requested_length == 0)
146         {
147             *actual_length = printer -> ux_device_class_printer_read_actual_length;
148             printer -> ux_device_class_printer_read_state = UX_STATE_RESET;
149             printer -> ux_device_class_printer_read_status = UX_SUCCESS;
150             return(UX_STATE_NEXT);
151         }
152 
153         printer -> ux_device_class_printer_read_transfer_length = requested_length;
154 
155         /* Next state.  */
156         printer -> ux_device_class_printer_read_state = UX_DEVICE_CLASS_PRINTER_READ_WAIT;
157         UX_SLAVE_TRANSFER_STATE_RESET(transfer_request);
158 
159         /* Fall through.  */
160     case UX_DEVICE_CLASS_PRINTER_READ_WAIT:
161 
162         /* Get a full packet each time */
163         max_transfer_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize;
164 
165         /* Run the transfer state machine.  */
166         status = _ux_device_stack_transfer_run(transfer_request,
167                                                 max_transfer_length,
168                                                 max_transfer_length);
169 
170         /* Error case.  */
171         if (status < UX_STATE_NEXT)
172         {
173             printer -> ux_device_class_printer_read_state = UX_STATE_RESET;
174             printer -> ux_device_class_printer_read_status =
175                 transfer_request -> ux_slave_transfer_request_completion_code;
176             return(UX_STATE_ERROR);
177         }
178 
179         /* Success case.  */
180         if (status == UX_STATE_NEXT)
181         {
182             /* Check overflow */
183             if (printer -> ux_device_class_printer_read_transfer_length <
184                 transfer_request -> ux_slave_transfer_request_actual_length)
185             {
186                 printer -> ux_device_class_printer_read_state = UX_STATE_ERROR;
187                 printer -> ux_device_class_printer_read_status = UX_TRANSFER_BUFFER_OVERFLOW;
188                 return(UX_STATE_ERROR);
189             }
190 
191             /* We need to copy the buffer locally.  */
192             _ux_utility_memory_copy(printer -> ux_device_class_printer_read_buffer,
193                     transfer_request -> ux_slave_transfer_request_data_pointer,
194                     transfer_request -> ux_slave_transfer_request_actual_length); /* Use case of memcpy is verified. */
195 
196             /* Next buffer address.  */
197             printer -> ux_device_class_printer_read_buffer +=
198                     transfer_request -> ux_slave_transfer_request_actual_length;
199 
200             /* Set the length actually received. */
201             printer -> ux_device_class_printer_read_actual_length +=
202                     transfer_request -> ux_slave_transfer_request_actual_length;
203 
204             /* Last transfer status.  */
205             printer -> ux_device_class_printer_read_status =
206                 transfer_request -> ux_slave_transfer_request_completion_code;
207 
208             /* Update actual length.  */
209             *actual_length = printer -> ux_device_class_printer_read_actual_length;
210 
211             /* Check short packet.  */
212             if (transfer_request -> ux_slave_transfer_request_actual_length <
213                 transfer_request -> ux_slave_transfer_request_requested_length)
214             {
215 
216                 /* It's done.  */
217                 printer -> ux_device_class_printer_read_state = UX_STATE_RESET;
218                 return(UX_STATE_NEXT);
219             }
220 
221             /* Next state.  */
222             printer -> ux_device_class_printer_read_state = UX_DEVICE_CLASS_PRINTER_READ_START;
223         }
224 
225         /* Keep waiting.  */
226         return(UX_STATE_WAIT);
227 
228     default: /* Error.  */
229         printer -> ux_device_class_printer_read_state = UX_STATE_RESET;
230         printer -> ux_device_class_printer_read_status = UX_INVALID_STATE;
231         break;
232     }
233 
234     /* Error cases.  */
235     return(UX_STATE_EXIT);
236 }
237 
238 #endif
239