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