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 /**************************************************************************/
14 /**                                                                       */
15 /** USBX Component                                                        */
16 /**                                                                       */
17 /**   Printer Class                                                       */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 
23 /* Include necessary system files.  */
24 
25 #define UX_SOURCE_CODE
26 
27 #include "ux_api.h"
28 #include "ux_host_class_printer.h"
29 #include "ux_host_stack.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_host_class_printer_status_get                   PORTABLE C      */
37 /*                                                           6.1.12       */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function obtains the printer status. The printer status is     */
45 /*    similar to the LPT status (1284 standard).                          */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*    printer                               Pointer to printer class      */
50 /*    printer_status                        Pointer to return status      */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    Completion Status                                                   */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    _ux_host_stack_class_instance_verify  Verify the class instance     */
59 /*    _ux_host_stack_transfer_request       Process transfer request      */
60 /*    _ux_utility_long_get                  Get 32-bit long word          */
61 /*    _ux_utility_memory_allocate           Allocate memory block         */
62 /*    _ux_utility_memory_free               Free memory block             */
63 /*    _ux_host_semaphore_get                Get protection semaphore      */
64 /*    _ux_host_semaphore_put                Release protection semaphore  */
65 /*                                                                        */
66 /*  CALLED BY                                                             */
67 /*                                                                        */
68 /*    Application                                                         */
69 /*                                                                        */
70 /*  RELEASE HISTORY                                                       */
71 /*                                                                        */
72 /*    DATE              NAME                      DESCRIPTION             */
73 /*                                                                        */
74 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
75 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
76 /*                                            resulting in version 6.1    */
77 /*  02-02-2021     Chaoqiong Xiao           Modified comment(s),          */
78 /*                                            supported interface other   */
79 /*                                            than number zero,           */
80 /*                                            resulting in version 6.1.4  */
81 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
82 /*                                            added standalone support,   */
83 /*                                            resulting in version 6.1.10 */
84 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
85 /*                                            fixed parameter/variable    */
86 /*                                            names conflict C++ keyword, */
87 /*                                            resulting in version 6.1.12 */
88 /*                                                                        */
89 /**************************************************************************/
_ux_host_class_printer_status_get(UX_HOST_CLASS_PRINTER * printer,ULONG * printer_status)90 UINT  _ux_host_class_printer_status_get(UX_HOST_CLASS_PRINTER *printer, ULONG *printer_status)
91 {
92 #if defined(UX_HOST_STANDALONE)
93 UX_INTERRUPT_SAVE_AREA
94 #endif
95 UX_INTERFACE    *interface_ptr;
96 UX_ENDPOINT     *control_endpoint;
97 UX_TRANSFER     *transfer_request;
98 UINT            status;
99 UCHAR *         printer_status_buffer;
100 
101     /* Ensure the instance is valid.  */
102     if (printer -> ux_host_class_printer_state !=  UX_HOST_CLASS_INSTANCE_LIVE)
103     {
104 
105         /* If trace is enabled, insert this event into the trace buffer.  */
106         UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, printer, 0, 0, UX_TRACE_ERRORS, 0, 0)
107 
108         return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
109     }
110 
111 #if defined(UX_HOST_STANDALONE)
112     UX_DISABLE
113     if ((printer -> ux_host_class_printer_flags & UX_HOST_CLASS_PRINTER_FLAG_LOCK) ||
114         (printer -> ux_host_class_printer_device -> ux_device_flags & UX_DEVICE_FLAG_LOCK))
115     {
116         UX_RESTORE
117         return(UX_BUSY);
118     }
119     printer -> ux_host_class_printer_flags |= UX_HOST_CLASS_PRINTER_FLAG_LOCK;
120     printer -> ux_host_class_printer_device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK;
121     UX_RESTORE
122 #else
123 
124     /* Protect thread reentry to this instance.  */
125     status =  _ux_host_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER);
126     if (status != UX_SUCCESS)
127 
128         /* Return error.  */
129         return(status);
130 
131     /* Protect the control endpoint semaphore here.  It will be unprotected in the
132        transfer request function.  */
133     status =  _ux_utility_semaphore_get(&printer -> ux_host_class_printer_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER);
134 
135     /* Check for status.  */
136     if (status != UX_SUCCESS)
137     {
138         _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore);
139         return(status);
140     }
141 #endif
142 
143     /* We need to get the default control endpoint transfer_request pointer.  */
144     control_endpoint =  &printer -> ux_host_class_printer_device -> ux_device_control_endpoint;
145     transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
146 
147     /* Need to allocate memory for the descriptor.  */
148     printer_status_buffer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PRINTER_STATUS_LENGTH);
149     if (printer_status_buffer == UX_NULL)
150     {
151 
152         /* Unprotect thread reentry to this instance */
153         _ux_host_class_printer_unlock(printer);
154         return(UX_MEMORY_INSUFFICIENT);
155     }
156 
157     /* Need interface for wIndex.  */
158     interface_ptr = printer -> ux_host_class_printer_interface;
159 
160     /* Create a transfer_request for the GET_STATUS request.  */
161     transfer_request -> ux_transfer_request_data_pointer =      printer_status_buffer;
162     transfer_request -> ux_transfer_request_requested_length =  UX_HOST_CLASS_PRINTER_STATUS_LENGTH;
163     transfer_request -> ux_transfer_request_function =          UX_HOST_CLASS_PRINTER_GET_STATUS;
164     transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
165     transfer_request -> ux_transfer_request_value =             0;
166     transfer_request -> ux_transfer_request_index =             interface_ptr -> ux_interface_descriptor.bInterfaceNumber;
167 
168 #if defined(UX_HOST_STANDALONE)
169 
170     /* Enable auto unlock device.  */
171     transfer_request -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK;
172 #endif
173 
174     /* Send request to HCD layer.  */
175     status =  _ux_host_stack_transfer_request(transfer_request);
176 
177     /* Check for correct transfer and entire descriptor returned.  */
178     if ((status == UX_SUCCESS) &&
179         (transfer_request -> ux_transfer_request_actual_length > 0) &&
180         (transfer_request -> ux_transfer_request_actual_length <= UX_HOST_CLASS_PRINTER_STATUS_LENGTH))
181     {
182 
183         /* Retrieve the printer status and translate it locally for endianness.  */
184         *printer_status = printer_status_buffer[0];
185         if (transfer_request -> ux_transfer_request_actual_length > 1)
186             *printer_status |= (ULONG)(printer_status_buffer[1] << 8);
187         if (transfer_request -> ux_transfer_request_actual_length > 2)
188             *printer_status |= (ULONG)(printer_status_buffer[2] << 16);
189         if (transfer_request -> ux_transfer_request_actual_length > 3)
190             *printer_status |= (ULONG)(printer_status_buffer[3] << 24);
191 
192         /* If trace is enabled, insert this event into the trace buffer.  */
193         UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_STATUS_GET, printer, *printer_status, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
194     }
195     else
196     {
197 
198         /* Error trap. */
199         _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status);
200     }
201 
202     /* Free all used resources.  */
203     _ux_utility_memory_free(printer_status_buffer);
204 
205     /* Unprotect thread reentry to this instance.  */
206     _ux_host_class_printer_unlock(printer);
207 
208     /* Return completion status.  */
209     return(status);
210 }
211 
212 /**************************************************************************/
213 /*                                                                        */
214 /*  FUNCTION                                               RELEASE        */
215 /*                                                                        */
216 /*    _uxe_host_class_printer_status_get                  PORTABLE C      */
217 /*                                                           6.3.0        */
218 /*  AUTHOR                                                                */
219 /*                                                                        */
220 /*    Yajun Xia, Microsoft Corporation                                    */
221 /*                                                                        */
222 /*  DESCRIPTION                                                           */
223 /*                                                                        */
224 /*    This function checks errors in printer statis get function call.    */
225 /*                                                                        */
226 /*  INPUT                                                                 */
227 /*                                                                        */
228 /*    printer                               Pointer to printer class      */
229 /*    printer_status                        Pointer to return status      */
230 /*                                                                        */
231 /*  OUTPUT                                                                */
232 /*                                                                        */
233 /*    Completion Status                                                   */
234 /*                                                                        */
235 /*  CALLS                                                                 */
236 /*                                                                        */
237 /*    _ux_host_class_printer_status_get     Obtains the printer status    */
238 /*                                                                        */
239 /*  CALLED BY                                                             */
240 /*                                                                        */
241 /*    Application                                                         */
242 /*                                                                        */
243 /*  RELEASE HISTORY                                                       */
244 /*                                                                        */
245 /*    DATE              NAME                      DESCRIPTION             */
246 /*                                                                        */
247 /*  10-31-2023        Yajun xia             Initial Version 6.3.0         */
248 /*                                                                        */
249 /**************************************************************************/
_uxe_host_class_printer_status_get(UX_HOST_CLASS_PRINTER * printer,ULONG * printer_status)250 UINT  _uxe_host_class_printer_status_get(UX_HOST_CLASS_PRINTER *printer, ULONG *printer_status)
251 {
252 
253     /* Sanity checks.  */
254     if ((printer == UX_NULL) || (printer_status == UX_NULL))
255         return(UX_INVALID_PARAMETER);
256 
257     /* Call the actual printer status get function.  */
258     return(_ux_host_class_printer_status_get(printer, printer_status));
259 }
260