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 static inline
35 #else
36 VOID _ux_host_class_printer_name_parse(UX_HOST_CLASS_PRINTER *printer, UCHAR *descriptor_buffer, ULONG descriptor_length);
37 #endif
_ux_host_class_printer_name_parse(UX_HOST_CLASS_PRINTER * printer,UCHAR * descriptor_buffer,ULONG descriptor_length)38 VOID _ux_host_class_printer_name_parse(UX_HOST_CLASS_PRINTER *printer, UCHAR *descriptor_buffer, ULONG descriptor_length)
39 {
40 ULONG           length;
41 UCHAR *         printer_name_buffer;
42 UCHAR *         printer_name;
43 UINT            printer_name_length;
44 
45     /* Cannot use descriptor buffer, so copy it to 1284 buffer.  */
46     printer_name_buffer =  descriptor_buffer;
47 
48     /* Retrieve the printer name which is a USHORT at the beginning of the returned buffer.  */
49     length =  (USHORT)_ux_utility_short_get_big_endian(printer_name_buffer);
50     if (length < descriptor_length)
51         descriptor_length = length;
52 
53     /* Point the name buffer after the length.  */
54     printer_name_buffer +=  2;
55 
56     /* Parse the name for a tag which is in the form DES: or DESCRIPTOR:  */
57     while (descriptor_length != 0)
58     {
59 
60         if (descriptor_length > 12)
61         {
62 
63             /* Compare the current pointer position with the DESCRIPTOR: tag.  */
64             if (_ux_utility_memory_compare(printer_name_buffer, UX_HOST_CLASS_PRINTER_TAG_DESCRIPTION, 12) == UX_SUCCESS)
65             {
66 
67                 printer_name_buffer +=  12;
68                 descriptor_length =  (USHORT)(descriptor_length - 12);
69                 break;
70             }
71         }
72 
73         if (descriptor_length > 4)
74         {
75 
76             /* Compare the current pointer position with the DES: tag.  */
77             if (_ux_utility_memory_compare(printer_name_buffer, UX_HOST_CLASS_PRINTER_TAG_DES, 4) == UX_SUCCESS)
78             {
79 
80                 printer_name_buffer +=  4;
81                 descriptor_length = (USHORT)(descriptor_length - 4);
82                 break;
83             }
84         }
85 
86         /* And reduce the remaining length by 1.  */
87         descriptor_length--;
88 
89         /* Increment the descriptor pointer.  */
90         printer_name_buffer++;
91     }
92 
93     /* If the length remaining is 0, we have not found the descriptor tag we wanted.  */
94     if (descriptor_length == 0)
95     {
96 
97         /* Use the generic USB printer name.  */
98         _ux_utility_memory_copy(printer -> ux_host_class_printer_name, UX_HOST_CLASS_PRINTER_GENERIC_NAME, 11); /* Use case of memcpy is verified. */
99     }
100     else
101     {
102 
103         /* We have found a tag and the name is right after delimited by ; or a 0.  */
104         printer_name =  printer -> ux_host_class_printer_name;
105         printer_name_length =  UX_HOST_CLASS_PRINTER_NAME_LENGTH;
106 
107         /* Parse the name and only copy the name until the max length is reached
108             or the delimiter is reached.  */
109         while ((descriptor_length--) && (printer_name_length--))
110         {
111 
112             /* Check for the delimiter.  */
113             if((*printer_name_buffer == 0) || (*printer_name_buffer == ';'))
114                 break;
115             else
116                 /* Copy the name of the printer to the printer instance character
117                     by character.  */
118                 *printer_name++ =  *printer_name_buffer++;
119         }
120     }
121 }
122 
123 /**************************************************************************/
124 /*                                                                        */
125 /*  FUNCTION                                               RELEASE        */
126 /*                                                                        */
127 /*    _ux_host_class_printer_name_get                     PORTABLE C      */
128 /*                                                           6.1.12       */
129 /*  AUTHOR                                                                */
130 /*                                                                        */
131 /*    Chaoqiong Xiao, Microsoft Corporation                               */
132 /*                                                                        */
133 /*  DESCRIPTION                                                           */
134 /*                                                                        */
135 /*    This function obtains the printer name. The name is used by the     */
136 /*    application layer to identify the printer and loads its handler.    */
137 /*                                                                        */
138 /*  INPUT                                                                 */
139 /*                                                                        */
140 /*    printer                               Pointer to printer class      */
141 /*                                                                        */
142 /*  OUTPUT                                                                */
143 /*                                                                        */
144 /*    Completion Status                                                   */
145 /*                                                                        */
146 /*  CALLS                                                                 */
147 /*                                                                        */
148 /*    _ux_host_stack_transfer_request       Process transfer request      */
149 /*    _ux_utility_memory_allocate           Allocate memory block         */
150 /*    _ux_utility_memory_compare            Compare memory block          */
151 /*    _ux_utility_memory_copy               Copy memory block             */
152 /*    _ux_utility_memory_free               Free memory block             */
153 /*    _ux_utility_short_get_big_endian      Get 16-bit value              */
154 /*                                                                        */
155 /*  CALLED BY                                                             */
156 /*                                                                        */
157 /*    Printer Class                                                       */
158 /*                                                                        */
159 /*  RELEASE HISTORY                                                       */
160 /*                                                                        */
161 /*    DATE              NAME                      DESCRIPTION             */
162 /*                                                                        */
163 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
164 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
165 /*                                            verified memset and memcpy  */
166 /*                                            cases,                      */
167 /*                                            resulting in version 6.1    */
168 /*  02-02-2021     Chaoqiong Xiao           Modified comment(s),          */
169 /*                                            supported interface other   */
170 /*                                            than number zero,           */
171 /*                                            resulting in version 6.1.4  */
172 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
173 /*                                            added standalone support,   */
174 /*                                            resulting in version 6.1.10 */
175 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
176 /*                                            fixed parameter/variable    */
177 /*                                            names conflict C++ keyword, */
178 /*                                            resulting in version 6.1.12 */
179 /*                                                                        */
180 /**************************************************************************/
_ux_host_class_printer_name_get(UX_HOST_CLASS_PRINTER * printer)181 UINT  _ux_host_class_printer_name_get(UX_HOST_CLASS_PRINTER *printer)
182 {
183 
184 UCHAR *         descriptor_buffer;
185 UX_INTERFACE    *interface_ptr;
186 UX_ENDPOINT     *control_endpoint;
187 UX_TRANSFER     *transfer_request;
188 #if !defined(UX_HOST_STANDALONE)
189 UINT            status;
190 #endif
191 
192     /* If trace is enabled, insert this event into the trace buffer.  */
193     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_NAME_GET, printer, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
194 
195     /* We need to get the default control endpoint transfer request pointer.  */
196     control_endpoint =  &printer -> ux_host_class_printer_device -> ux_device_control_endpoint;
197     transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
198 
199     /* Need to allocate memory for the 1284 descriptor.  */
200     descriptor_buffer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PRINTER_DESCRIPTOR_LENGTH);
201     if(descriptor_buffer == UX_NULL)
202         return(UX_MEMORY_INSUFFICIENT);
203 
204     /* Need interface for wIndex.  */
205     interface_ptr = printer -> ux_host_class_printer_interface;
206 
207     /* Create a transfer request for the GET_DEVICE_ID request.  */
208     transfer_request -> ux_transfer_request_data_pointer =      descriptor_buffer;
209     transfer_request -> ux_transfer_request_requested_length =  UX_HOST_CLASS_PRINTER_DESCRIPTOR_LENGTH;
210     transfer_request -> ux_transfer_request_function =          UX_HOST_CLASS_PRINTER_GET_DEVICE_ID;
211     transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
212     transfer_request -> ux_transfer_request_value =             0; /* Do not support multiple configuration for now.  */
213     transfer_request -> ux_transfer_request_index =             (interface_ptr -> ux_interface_descriptor.bInterfaceNumber  << 8) |
214                                                                 (interface_ptr -> ux_interface_descriptor.bAlternateSetting     );
215 
216 #if defined(UX_HOST_STANDALONE)
217     printer -> ux_host_class_printer_allocated = descriptor_buffer;
218     UX_TRANSFER_STATE_RESET(transfer_request);
219     return(UX_SUCCESS);
220 #else
221 
222     /* Send request to HCD layer.  */
223     status =  _ux_host_stack_transfer_request(transfer_request);
224 
225     /* Check for correct transfer. We do not check for entire length as it may vary.  */
226     if(status == UX_SUCCESS)
227     {
228 
229         _ux_host_class_printer_name_parse(printer, descriptor_buffer,
230                                     UX_HOST_CLASS_PRINTER_DESCRIPTOR_LENGTH);
231     }
232 
233     /* Free all used resources.  */
234     _ux_utility_memory_free(descriptor_buffer);
235 
236     /* Return completion status.  */
237     return(status);
238 
239 #endif
240 }
241 
242