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_control_request PORTABLE C */
37 /* 6.1.12 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function manages the requests sent by the host on the control */
45 /* endpoint with a CLASS or VENDOR SPECIFIC type. */
46 /* */
47 /* INPUT */
48 /* */
49 /* command Pointer to class command */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* None */
54 /* */
55 /* CALLS */
56 /* */
57 /* (ux_device_class_printer_soft_reset) Notify a software reset */
58 /* _ux_device_class_printer_soft_reset Performs software reset */
59 /* _ux_device_stack_transfer_request Transfer request */
60 /* _ux_utility_short_get Get short value from buffer */
61 /* _ux_utility_short_get_big_endian Get big endian short value */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* Device Printer Class */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */
72 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
73 /* fixed parameter/variable */
74 /* names conflict C++ keyword, */
75 /* resulting in version 6.1.12 */
76 /* */
77 /**************************************************************************/
_ux_device_class_printer_control_request(UX_SLAVE_CLASS_COMMAND * command)78 UINT _ux_device_class_printer_control_request(UX_SLAVE_CLASS_COMMAND *command)
79 {
80 UX_DEVICE_CLASS_PRINTER *printer;
81 UX_SLAVE_CLASS *printer_class;
82 UX_SLAVE_INTERFACE *printer_interface;
83 UX_SLAVE_TRANSFER *transfer_request;
84 UX_SLAVE_DEVICE *device;
85 ULONG request;
86 ULONG value;
87 ULONG request_length;
88 ULONG length;
89 UCHAR *buffer;
90 UCHAR index_low;
91 UCHAR *descriptor;
92 ULONG descriptor_length;
93 ULONG index;
94 UCHAR found;
95
96 /* Get the class container. */
97 printer_class = command -> ux_slave_class_command_class_ptr;
98
99 /* Get the class instance in the container. */
100 printer = (UX_DEVICE_CLASS_PRINTER *) printer_class -> ux_slave_class_instance;
101
102 /* Get the interface. */
103 printer_interface = printer_class -> ux_slave_class_interface;
104
105 /* Get the pointer to the device. */
106 device = &_ux_system_slave -> ux_system_slave_device;
107
108 /* Get the pointer to the transfer request associated with the control endpoint. */
109 transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request;
110
111 /* Extract all necessary fields of the request. */
112 request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST);
113
114 /* Extract all necessary fields of the value. */
115 value = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE);
116 index_low = transfer_request -> ux_slave_transfer_request_setup[UX_SETUP_INDEX];
117
118 /* Pickup the request length. */
119 request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH);
120
121 /* Get buffer to fill. */
122 buffer = transfer_request -> ux_slave_transfer_request_data_pointer;
123
124 /* Here we proceed only the standard request we know of at the device level. */
125 switch (request)
126 {
127 case UX_DEVICE_CLASS_PRINTER_GET_DEVICE_ID:
128
129 /* Sanity check
130 - wValue == config index
131 - wIndex_high == interface (already checked before entry, index of
132 interface should equal to interface number)
133 - wIndex_low == alternate */
134 if (index_low != (UCHAR)printer_interface -> ux_slave_interface_descriptor.bAlternateSetting)
135 return(UX_ERROR);
136
137 /* Check config index. */
138 descriptor = _ux_system_slave -> ux_system_slave_device_framework;
139 length = _ux_system_slave->ux_system_slave_device_framework_length;
140 index = 0;
141 found = 0;
142 while(length)
143 {
144
145 /* By default use bLength @ 0. */
146 descriptor_length = descriptor[0];
147
148 /* Check bDescriptorType @ 1. */
149 switch(descriptor[1])
150 {
151 case UX_CONFIGURATION_DESCRIPTOR_ITEM:
152
153 /* It's configuration requested? */
154 if (index == value)
155 {
156
157 /* Check if bConfigurationValue @ 5 is as expected. */
158 if ((UCHAR)printer_class -> ux_slave_class_configuration_number != descriptor[5])
159 return(UX_ERROR);
160
161 /* Find the configuration. */
162 found = 1;
163 break;
164 }
165
166 /* Target to next configuration index. */
167 index ++;
168
169 /* Use wTotalLength @ 2. */
170 descriptor_length = _ux_utility_short_get(descriptor + 2);
171 break;
172
173 default:
174 break;
175 }
176
177 /* Break if found. */
178 if (found)
179 break;
180
181 /* Descriptor broken check. */
182 if (descriptor_length < 2 ||
183 descriptor_length > length)
184 {
185
186 /* Error trap! */
187 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED);
188 return(UX_DESCRIPTOR_CORRUPTED);
189 }
190
191 /* Next descriptor. */
192 descriptor += descriptor_length;
193 length -= descriptor_length;
194 }
195
196 /* Request parameter not expected if not found. */
197 if (!found)
198 return(UX_ERROR);
199
200 /* Length of data (first two bytes in big endian). */
201 length = _ux_utility_short_get_big_endian(printer ->
202 ux_device_class_printer_parameter.ux_device_class_printer_device_id);
203
204 /* Prepare device ID to send. */
205 if (length)
206 {
207
208 /* Sanity check. */
209 if (length > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH)
210 {
211
212 /* Error trap! */
213 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW);
214 return(UX_BUFFER_OVERFLOW);
215 }
216
217 /* Copy data. */
218 _ux_utility_memory_copy(buffer, printer ->
219 ux_device_class_printer_parameter.ux_device_class_printer_device_id,
220 length); /* Use case of memcpy is verified. */
221 }
222
223 /* Set the phase of the transfer to data out. */
224 transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT;
225
226 /* Transfer. */
227 _ux_device_stack_transfer_request(transfer_request, length, request_length);
228 break ;
229
230 case UX_DEVICE_CLASS_PRINTER_GET_PORT_STATUS:
231
232 /* Sanity check. */
233 if (request_length < 1)
234 return(UX_ERROR);
235
236 /* Fill status byte. */
237 *buffer = (UCHAR)printer -> ux_device_class_printer_port_status;
238
239 /* Set the phase of the transfer to data out. */
240 transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT;
241
242 /* Perform the data transfer. */
243 _ux_device_stack_transfer_request(transfer_request, 1, request_length);
244 break;
245
246 case UX_DEVICE_CLASS_PRINTER_SOFT_RESET:
247 _ux_device_class_printer_soft_reset(printer);
248
249 /* If there is a soft reset function call it. */
250 if (printer -> ux_device_class_printer_parameter.
251 ux_device_class_printer_soft_reset != UX_NULL)
252 {
253
254 /* Invoke the application callback. */
255 printer -> ux_device_class_printer_parameter.
256 ux_device_class_printer_soft_reset(printer);
257 }
258 break;
259
260 default:
261
262 /* Unknown function. It's not handled. */
263 return(UX_ERROR);
264 }
265
266 /* It's handled. */
267 return(UX_SUCCESS);
268 }
269