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