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 /** */
16 /** USBX Component */
17 /** */
18 /** Printer Class */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23
24 /* Include necessary system files. */
25
26 #define UX_SOURCE_CODE
27
28 #include "ux_api.h"
29 #include "ux_host_class_printer.h"
30 #include "ux_host_stack.h"
31
32
33 #if defined(UX_HOST_STANDALONE)
34 #define UX_HOST_CLASS_PRINTER_ENUM_START (UX_STATE_WAIT)
35 #define UX_HOST_CLASS_PRINTER_ENUM_IDLE (UX_STATE_IDLE)
36
37 #define UX_HOST_CLASS_PRINTER_ENUM_NAME_GET (UX_STATE_STACK_STEP + 0)
38 #define UX_HOST_CLASS_PRINTER_ENUM_NAME_PARSE (UX_STATE_STACK_STEP + 1)
39 #define UX_HOST_CLASS_PRINTER_ENUM_TRANSFER (UX_STATE_STACK_STEP + 2)
40 #define UX_HOST_CLASS_PRINTER_ENUM_DONE (UX_STATE_STACK_STEP + 3)
41
42 extern VOID _ux_host_class_printer_name_parse(UX_HOST_CLASS_PRINTER *printer,
43 UCHAR *descriptor_buffer, ULONG descriptor_length);
44
45 static inline UINT _ux_host_class_printer_activate_wait(UX_HOST_CLASS_COMMAND *command);
46 #endif
47
48 /**************************************************************************/
49 /* */
50 /* FUNCTION RELEASE */
51 /* */
52 /* _ux_host_class_printer_entry PORTABLE C */
53 /* 6.1.12 */
54 /* AUTHOR */
55 /* */
56 /* Chaoqiong Xiao, Microsoft Corporation */
57 /* */
58 /* DESCRIPTION */
59 /* */
60 /* This function is the entry point of the printer class. It will be */
61 /* called by the USBX stack enumeration module when there is a new */
62 /* printer on the bus or when the USB printer is removed. */
63 /* */
64 /* INPUT */
65 /* */
66 /* command Printer class command */
67 /* */
68 /* OUTPUT */
69 /* */
70 /* Completion Status */
71 /* */
72 /* CALLS */
73 /* */
74 /* _ux_host_class_printer_activate Activate printer class */
75 /* _ux_host_class_printer_deactivate Deactivate printer class */
76 /* */
77 /* CALLED BY */
78 /* */
79 /* Printer Class */
80 /* */
81 /* RELEASE HISTORY */
82 /* */
83 /* DATE NAME DESCRIPTION */
84 /* */
85 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
86 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
87 /* resulting in version 6.1 */
88 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
89 /* added standalone support, */
90 /* resulting in version 6.1.10 */
91 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
92 /* removed compile warning, */
93 /* fixed parameter/variable */
94 /* names conflict C++ keyword, */
95 /* resulting in version 6.1.12 */
96 /* */
97 /**************************************************************************/
_ux_host_class_printer_entry(UX_HOST_CLASS_COMMAND * command)98 UINT _ux_host_class_printer_entry(UX_HOST_CLASS_COMMAND *command)
99 {
100
101 UINT status;
102
103
104 /* The command request will tell us we need to do here, either a enumeration
105 query, an activation or a deactivation. */
106 switch (command -> ux_host_class_command_request)
107 {
108
109 case UX_HOST_CLASS_COMMAND_QUERY:
110
111 /* The query command is used to let the stack enumeration process know if we want to own
112 this device or not. */
113 if((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) &&
114 (command -> ux_host_class_command_class == UX_HOST_CLASS_PRINTER_CLASS))
115 return(UX_SUCCESS);
116 else
117 return(UX_NO_CLASS_MATCH);
118
119 case UX_HOST_CLASS_COMMAND_ACTIVATE:
120
121 /* The activate command is used when the device inserted has found a parent and
122 is ready to complete the enumeration. */
123 status = _ux_host_class_printer_activate(command);
124 return(status);
125
126 #if defined(UX_HOST_STANDALONE)
127 case UX_HOST_CLASS_COMMAND_ACTIVATE_WAIT:
128 status = _ux_host_class_printer_activate_wait(command);
129 return(status);
130 #endif
131
132 case UX_HOST_CLASS_COMMAND_DEACTIVATE:
133
134 /* The deactivate command is used when the device has been extracted either
135 directly or when its parents has been extracted. */
136 status = _ux_host_class_printer_deactivate(command);
137 return(status);
138
139 default:
140
141 /* If trace is enabled, insert this event into the trace buffer. */
142 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
143
144 return(UX_FUNCTION_NOT_SUPPORTED);
145 }
146 }
147
148 #if defined(UX_HOST_STANDALONE)
_ux_host_class_printer_activate_wait(UX_HOST_CLASS_COMMAND * command)149 static inline UINT _ux_host_class_printer_activate_wait(UX_HOST_CLASS_COMMAND *command)
150 {
151 UX_INTERFACE *interface_ptr;
152 UX_HOST_CLASS_PRINTER *printer;
153 UX_ENDPOINT *control_endpoint;
154 UX_TRANSFER *transfer;
155 UINT status;
156
157 /* Get the instance for this class. */
158 interface_ptr = (UX_INTERFACE *)command -> ux_host_class_command_container;
159
160 /* Sanity check. */
161 if (interface_ptr == UX_NULL)
162 return(UX_STATE_EXIT);
163
164 printer = (UX_HOST_CLASS_PRINTER *) interface_ptr -> ux_interface_class_instance;
165
166 /* Sanity check. */
167 if (printer == UX_NULL)
168 return(UX_STATE_EXIT);
169
170 switch(printer -> ux_host_class_printer_enum_state)
171 {
172 case UX_HOST_CLASS_PRINTER_ENUM_START:
173 status = _ux_host_class_printer_endpoints_get(printer);
174 if (status != UX_SUCCESS)
175 {
176 printer -> ux_host_class_printer_status = status;
177 printer -> ux_host_class_printer_enum_state =
178 UX_HOST_CLASS_PRINTER_ENUM_DONE;
179 return(UX_STATE_WAIT);
180 }
181
182 /* Fall through. */
183 case UX_HOST_CLASS_PRINTER_ENUM_NAME_GET:
184 status = _ux_host_class_printer_name_get(printer);
185 if (status != UX_SUCCESS)
186 {
187 printer -> ux_host_class_printer_status = status;
188 printer -> ux_host_class_printer_enum_state =
189 UX_HOST_CLASS_PRINTER_ENUM_DONE;
190 return(UX_STATE_WAIT);
191 }
192
193 /* Next: transfer -> parse name. */
194 printer -> ux_host_class_printer_enum_state =
195 UX_HOST_CLASS_PRINTER_ENUM_TRANSFER;
196 printer -> ux_host_class_printer_next_state =
197 UX_HOST_CLASS_PRINTER_ENUM_NAME_PARSE;
198
199 /* Fall through. */
200 case UX_HOST_CLASS_PRINTER_ENUM_TRANSFER:
201
202 /* We need to get the default control endpoint transfer request pointer. */
203 control_endpoint = &printer -> ux_host_class_printer_device -> ux_device_control_endpoint;
204 transfer = &control_endpoint -> ux_endpoint_transfer_request;
205
206 status = _ux_host_stack_transfer_run(transfer);
207
208 /* Transfer finished any way. */
209 if (status < UX_STATE_WAIT)
210 {
211
212 /* Error. */
213 if (transfer -> ux_transfer_request_completion_code != UX_SUCCESS)
214 {
215 printer -> ux_host_class_printer_status = status;
216 printer -> ux_host_class_printer_enum_state =
217 UX_HOST_CLASS_PRINTER_ENUM_DONE;
218 return(UX_STATE_WAIT);
219 }
220
221 /* Next state. */
222 printer -> ux_host_class_printer_enum_state =
223 printer -> ux_host_class_printer_next_state;
224
225 return(UX_STATE_WAIT);
226 }
227
228 /* Wait transfer. */
229 return(UX_STATE_WAIT);
230
231 case UX_HOST_CLASS_PRINTER_ENUM_NAME_PARSE:
232
233 /* We need to get the default control endpoint transfer request pointer. */
234 control_endpoint = &printer -> ux_host_class_printer_device -> ux_device_control_endpoint;
235 transfer = &control_endpoint -> ux_endpoint_transfer_request;
236
237 _ux_host_class_printer_name_parse(printer,
238 transfer -> ux_transfer_request_data_pointer,
239 transfer -> ux_transfer_request_actual_length);
240
241 /* Fall through. */
242 case UX_HOST_CLASS_PRINTER_ENUM_DONE:
243
244 /* Free allocated resources. */
245 if (printer -> ux_host_class_printer_allocated)
246 {
247 _ux_utility_memory_free(printer -> ux_host_class_printer_allocated);
248 printer -> ux_host_class_printer_allocated = UX_NULL;
249 }
250
251 /* Check status. */
252 if (printer -> ux_host_class_printer_status != UX_SUCCESS)
253 {
254
255 /* On error, free resources. */
256 _ux_host_stack_class_instance_destroy(
257 printer -> ux_host_class_printer_class, (VOID *) printer);
258 interface_ptr -> ux_interface_class_instance = UX_NULL;
259 _ux_utility_memory_free(printer);
260 return(UX_STATE_ERROR);
261 }
262
263 /* Success. */
264
265 /* Mark the printer as live now. */
266 printer -> ux_host_class_printer_state = UX_HOST_CLASS_INSTANCE_LIVE;
267
268 /* If all is fine and the device is mounted, we may need to inform the application
269 if a function has been programmed in the system structure. */
270 if (_ux_system_host -> ux_system_host_change_function != UX_NULL)
271 {
272
273 /* Call system change function. */
274 _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, printer -> ux_host_class_printer_class, (VOID *) printer);
275 }
276
277 /* If trace is enabled, insert this event into the trace buffer. */
278 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_ACTIVATE, printer, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
279
280 /* If trace is enabled, register this object. */
281 UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, printer, 0, 0, 0)
282
283 /* Return success. */
284 printer -> ux_host_class_printer_enum_state = UX_STATE_IDLE;
285 return(UX_STATE_NEXT);
286
287 default: /* reset, idle, error ... */
288 break;
289 }
290
291 /* Just next phase. */
292 return(UX_STATE_NEXT);
293 }
294 #endif
295