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