1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 /**************************************************************************/
12 /**                                                                       */
13 /** USBX Component                                                        */
14 /**                                                                       */
15 /**   Device Printer Class                                                */
16 /**                                                                       */
17 /**************************************************************************/
18 /**************************************************************************/
19 
20 #define UX_SOURCE_CODE
21 
22 
23 /* Include necessary system files.  */
24 
25 #include "ux_api.h"
26 #include "ux_device_class_printer.h"
27 #include "ux_device_stack.h"
28 
29 
30 /**************************************************************************/
31 /*                                                                        */
32 /*  FUNCTION                                               RELEASE        */
33 /*                                                                        */
34 /*    _ux_device_class_printer_initialize                 PORTABLE C      */
35 /*                                                           6.3.0        */
36 /*  AUTHOR                                                                */
37 /*                                                                        */
38 /*    Chaoqiong Xiao, Microsoft Corporation                               */
39 /*                                                                        */
40 /*  DESCRIPTION                                                           */
41 /*                                                                        */
42 /*    This function initializes the USB Printer device.                   */
43 /*                                                                        */
44 /*  INPUT                                                                 */
45 /*                                                                        */
46 /*    command                               Pointer to printer command    */
47 /*                                                                        */
48 /*  OUTPUT                                                                */
49 /*                                                                        */
50 /*    Completion Status                                                   */
51 /*                                                                        */
52 /*  CALLS                                                                 */
53 /*                                                                        */
54 /*    _ux_utility_memory_allocate           Allocate memory               */
55 /*    _ux_utility_memory_free               Free memory                   */
56 /*    _ux_utility_mutex_create              Create mutex                  */
57 /*    _ux_device_mutex_delete               Delete mutex                  */
58 /*                                                                        */
59 /*  CALLED BY                                                             */
60 /*                                                                        */
61 /*    Device Stack                                                        */
62 /*                                                                        */
63 /*  RELEASE HISTORY                                                       */
64 /*                                                                        */
65 /*    DATE              NAME                      DESCRIPTION             */
66 /*                                                                        */
67 /*  01-31-2022     Chaoqiong Xiao           Initial Version 6.1.10        */
68 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
69 /*                                            fixed standalone compile,   */
70 /*                                            resulting in version 6.1.11 */
71 /*  10-31-2022     Yajun Xia                Modified comment(s),          */
72 /*                                            added standalone support,   */
73 /*                                            resulting in version 6.2.0  */
74 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
75 /*                                            added a new mode to manage  */
76 /*                                            endpoint buffer in classes, */
77 /*                                            resulting in version 6.3.0  */
78 /*                                                                        */
79 /**************************************************************************/
_ux_device_class_printer_initialize(UX_SLAVE_CLASS_COMMAND * command)80 UINT  _ux_device_class_printer_initialize(UX_SLAVE_CLASS_COMMAND *command)
81 {
82 
83 UX_DEVICE_CLASS_PRINTER                 *printer;
84 UX_DEVICE_CLASS_PRINTER_PARAMETER       *printer_parameter;
85 UX_SLAVE_CLASS                          *printer_class;
86 #if !defined(UX_DEVICE_STANDALONE)
87 UINT                                    status;
88 #endif
89 
90     /* Get the class container.  */
91     printer_class =  command -> ux_slave_class_command_class_ptr;
92 
93     /* Create an instance of the device printer class.  */
94     printer =  _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_DEVICE_CLASS_PRINTER));
95 
96     /* Check for successful allocation.  */
97     if (printer == UX_NULL)
98         return(UX_MEMORY_INSUFFICIENT);
99 
100     /* Save the address of the Printer instance inside the Printer container.  */
101     printer_class -> ux_slave_class_instance = (VOID *) printer;
102 
103     /* Get the pointer to the application parameters for the printer class.  */
104     printer_parameter =  command -> ux_slave_class_command_parameter;
105 
106     /* Store the start and stop signals if needed by the application.  */
107     printer -> ux_device_class_printer_parameter.ux_device_class_printer_device_id           = printer_parameter -> ux_device_class_printer_device_id;
108     printer -> ux_device_class_printer_parameter.ux_device_class_printer_instance_activate   = printer_parameter -> ux_device_class_printer_instance_activate;
109     printer -> ux_device_class_printer_parameter.ux_device_class_printer_instance_deactivate = printer_parameter -> ux_device_class_printer_instance_deactivate;
110     printer -> ux_device_class_printer_parameter.ux_device_class_printer_soft_reset          = printer_parameter -> ux_device_class_printer_soft_reset;
111 
112 #if defined(UX_DEVICE_CLASS_PRINTER_OWN_ENDPOINT_BUFFER)
113 
114     /* Allocate endpoint buffer.  */
115     UX_ASSERT(!UX_DEVICE_CLASS_PRINTER_ENDPOINT_BUFFER_SIZE_CALC_OVERFLOW);
116     printer -> ux_device_class_printer_endpoint_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN,
117             UX_CACHE_SAFE_MEMORY, UX_DEVICE_CLASS_PRINTER_ENDPOINT_BUFFER_SIZE);
118     if (printer -> ux_device_class_printer_endpoint_buffer == UX_NULL)
119     {
120         _ux_utility_memory_free(printer);
121         return(UX_MEMORY_INSUFFICIENT);
122     }
123 #endif
124 
125 #if !defined(UX_DEVICE_STANDALONE)
126     /* Create the Mutex for each endpoint as multiple threads cannot access each pipe at the same time.  */
127     status =  _ux_utility_mutex_create(&printer -> ux_device_class_printer_endpoint_in_mutex, "ux_device_class_printer_in_mutex");
128 
129     /* Check Mutex creation error.  */
130     if(status != UX_SUCCESS)
131     {
132 
133         /* Free the resources.  */
134 #if defined(UX_DEVICE_CLASS_PRINTER_OWN_ENDPOINT_BUFFER)
135         _ux_utility_memory_free(printer -> ux_device_class_printer_endpoint_buffer);
136 #endif
137         _ux_utility_memory_free(printer);
138 
139         /* Return fatal error.  */
140         return(UX_MUTEX_ERROR);
141     }
142 
143     /* Out Mutex. */
144     status =  _ux_utility_mutex_create(&printer -> ux_device_class_printer_endpoint_out_mutex, "ux_device_class_printer_out_mutex");
145 
146     /* Check Mutex creation error.  */
147     if(status != UX_SUCCESS)
148     {
149 
150         /* Delete the endpoint IN mutex.  */
151         _ux_device_mutex_delete(&printer -> ux_device_class_printer_endpoint_in_mutex);
152 
153         /* Free the resources.  */
154 #if defined(UX_DEVICE_CLASS_PRINTER_OWN_ENDPOINT_BUFFER)
155         _ux_utility_memory_free(printer -> ux_device_class_printer_endpoint_buffer);
156 #endif
157         _ux_utility_memory_free(printer);
158 
159         /* Return fatal error.  */
160         return(UX_MUTEX_ERROR);
161     }
162 #else
163     printer -> ux_device_class_printer_write_state = UX_STATE_RESET;
164     printer -> ux_device_class_printer_read_state = UX_STATE_RESET;
165 #endif
166 
167     /* Reset port status.  */
168     printer -> ux_device_class_printer_port_status = 0;
169 
170     /* Return completion status.  */
171     return(UX_SUCCESS);
172 }
173 
174 /**************************************************************************/
175 /*                                                                        */
176 /*  FUNCTION                                               RELEASE        */
177 /*                                                                        */
178 /*    _uxe_device_class_printer_initialize                  PORTABLE C    */
179 /*                                                           6.2.1        */
180 /*  AUTHOR                                                                */
181 /*                                                                        */
182 /*    Yajun Xia, Microsoft Corporation                                    */
183 /*                                                                        */
184 /*  DESCRIPTION                                                           */
185 /*                                                                        */
186 /*    This function checks errors in printer initialization function call.*/
187 /*                                                                        */
188 /*  INPUT                                                                 */
189 /*                                                                        */
190 /*    command                               Pointer to printer command    */
191 /*                                                                        */
192 /*  OUTPUT                                                                */
193 /*                                                                        */
194 /*    Completion Status                                                   */
195 /*                                                                        */
196 /*  CALLS                                                                 */
197 /*                                                                        */
198 /*    _ux_device_class_printer_initialize   Initialize printer instance   */
199 /*                                                                        */
200 /*  CALLED BY                                                             */
201 /*                                                                        */
202 /*    Device Stack                                                        */
203 /*                                                                        */
204 /*  RELEASE HISTORY                                                       */
205 /*                                                                        */
206 /*    DATE              NAME                      DESCRIPTION             */
207 /*                                                                        */
208 /*  03-08-2023     Yajun Xia                Initial Version 6.2.1         */
209 /*                                                                        */
210 /**************************************************************************/
_uxe_device_class_printer_initialize(UX_SLAVE_CLASS_COMMAND * command)211 UINT  _uxe_device_class_printer_initialize(UX_SLAVE_CLASS_COMMAND *command)
212 {
213 UX_DEVICE_CLASS_PRINTER_PARAMETER       *printer_parameter;
214 ULONG length;
215 
216     /* Get the pointer to the application parameters for the printer class.  */
217     printer_parameter =  command -> ux_slave_class_command_parameter;
218 
219     /* Sanity checks.  */
220 
221     /* Length of data (first two bytes in big endian).  */
222     length = _ux_utility_short_get_big_endian(printer_parameter -> ux_device_class_printer_device_id);
223 
224     if (length > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH)
225     {
226         return(UX_INVALID_PARAMETER);
227     }
228 
229     return (_ux_device_class_printer_initialize(command));
230 }
231