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