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 /**   Prolific 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_prolific.h"
29 #include "ux_host_stack.h"
30 
31 
32 /**************************************************************************/
33 /*                                                                        */
34 /*  FUNCTION                                               RELEASE        */
35 /*                                                                        */
36 /*    _ux_host_class_prolific_setup                       PORTABLE C      */
37 /*                                                           6.1.11       */
38 /*  AUTHOR                                                                */
39 /*                                                                        */
40 /*    Chaoqiong Xiao, Microsoft Corporation                               */
41 /*                                                                        */
42 /*  DESCRIPTION                                                           */
43 /*                                                                        */
44 /*    This function obtains the entire prolific configuration descriptors.*/
45 /*    This is needed because the prolific class needs to know if commands */
46 /*    are routed through the comm interface or the data class.            */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    prolific                                 Pointer to prolific class  */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    Completion Status                                                   */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*    _ux_host_stack_transfer_request       Process transfer request      */
59 /*    _ux_utility_memory_allocate           Allocate memory block         */
60 /*    _ux_utility_memory_free               Release memory block          */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    _ux_host_class_prolific_activate                                    */
65 /*                                                                        */
66 /*  RELEASE HISTORY                                                       */
67 /*                                                                        */
68 /*    DATE              NAME                      DESCRIPTION             */
69 /*                                                                        */
70 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
71 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
72 /*                                            resulting in version 6.1    */
73 /*  04-25-2022     Chaoqiong Xiao           Modified comment(s),          */
74 /*                                            internal clean up,          */
75 /*                                            resulting in version 6.1.11 */
76 /*                                                                        */
77 /**************************************************************************/
_ux_host_class_prolific_setup(UX_HOST_CLASS_PROLIFIC * prolific)78 UINT  _ux_host_class_prolific_setup(UX_HOST_CLASS_PROLIFIC *prolific)
79 {
80 
81 UCHAR                       *setup_buffer;
82 UX_ENDPOINT                 *control_endpoint;
83 UX_TRANSFER                 *transfer_request;
84 UINT                        status;
85 
86     /* We need to get the default control endpoint transfer request pointer.  */
87     control_endpoint =  &prolific -> ux_host_class_prolific_device -> ux_device_control_endpoint;
88     transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
89 
90     /* Need to allocate memory for the buffer.  */
91     setup_buffer =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PROLIFIC_SETUP_BUFFER_SIZE);
92     if (setup_buffer == UX_NULL)
93         return(UX_MEMORY_INSUFFICIENT);
94 
95     /* Set the device type. Can be either 0, 1 or HX.  */
96     if (prolific -> ux_host_class_prolific_device -> ux_device_descriptor.bDeviceClass == 0x02)
97 
98         /* Device is of type 0. */
99         prolific -> ux_host_class_prolific_device_type = UX_HOST_CLASS_PROLIFIC_DEVICE_TYPE_0;
100 
101     else
102     {
103 
104         /* Check packet size. If 64, we are dealing with HX type device.  */
105         if (prolific -> ux_host_class_prolific_device -> ux_device_descriptor.bMaxPacketSize0 == 64)
106 
107             /* Device is of type HX. */
108             prolific -> ux_host_class_prolific_device_type = UX_HOST_CLASS_PROLIFIC_DEVICE_TYPE_HX;
109 
110         else
111 
112             /* Default case : type 1.  */
113             prolific -> ux_host_class_prolific_device_type = UX_HOST_CLASS_PROLIFIC_DEVICE_TYPE_1;
114 
115     }
116 
117     /* Create a transfer request for the prolific setup request # 1.  */
118     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
119     transfer_request -> ux_transfer_request_requested_length    =  1;
120     transfer_request -> ux_transfer_request_function            =  1;
121     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
122     transfer_request -> ux_transfer_request_value               =  UX_HOST_CLASS_PROLIFIC_COMMAND_EEPROM_READ;
123     transfer_request -> ux_transfer_request_index               =  0;
124 
125     /* Send request to HCD layer.  */
126     status =  _ux_host_stack_transfer_request(transfer_request);
127 
128     /* Check status, if error, do not proceed.  */
129     if (status != UX_SUCCESS)
130     {
131 
132         /* Free all used resources.  */
133         _ux_utility_memory_free(setup_buffer);
134 
135         /* Return completion status.  */
136         return(status);
137 
138     }
139 
140     /* Create a transfer request for the prolific setup request # 2.  */
141     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
142     transfer_request -> ux_transfer_request_requested_length    =  0;
143     transfer_request -> ux_transfer_request_function            =  1;
144     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
145     transfer_request -> ux_transfer_request_value               =  0x0404;
146     transfer_request -> ux_transfer_request_index               =  0;
147 
148     /* Send request to HCD layer.  */
149     status =  _ux_host_stack_transfer_request(transfer_request);
150 
151     /* Check status, if error, do not proceed.  */
152     if (status != UX_SUCCESS)
153     {
154 
155         /* Free all used resources.  */
156         _ux_utility_memory_free(setup_buffer);
157 
158         /* Return completion status.  */
159         return(status);
160 
161     }
162 
163     /* Create a transfer request for the prolific setup request # 3.  */
164     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
165     transfer_request -> ux_transfer_request_requested_length    =  1;
166     transfer_request -> ux_transfer_request_function            =  1;
167     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
168     transfer_request -> ux_transfer_request_value               =  UX_HOST_CLASS_PROLIFIC_COMMAND_EEPROM_READ;
169     transfer_request -> ux_transfer_request_index               =  0;
170 
171     /* Send request to HCD layer.  */
172     status =  _ux_host_stack_transfer_request(transfer_request);
173 
174     /* Check status, if error, do not proceed.  */
175     if (status != UX_SUCCESS)
176     {
177 
178         /* Free all used resources.  */
179         _ux_utility_memory_free(setup_buffer);
180 
181         /* Return completion status.  */
182         return(status);
183 
184     }
185 
186     /* Create a transfer request for the prolific setup request # 4.  */
187     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
188     transfer_request -> ux_transfer_request_requested_length    =  1;
189     transfer_request -> ux_transfer_request_function            =  1;
190     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
191     transfer_request -> ux_transfer_request_value               =  0x8383;
192     transfer_request -> ux_transfer_request_index               =  0;
193 
194     /* Send request to HCD layer.  */
195     status =  _ux_host_stack_transfer_request(transfer_request);
196 
197     /* Check status, if error, do not proceed.  */
198     if (status != UX_SUCCESS)
199     {
200 
201         /* Free all used resources.  */
202         _ux_utility_memory_free(setup_buffer);
203 
204         /* Return completion status.  */
205         return(status);
206 
207     }
208 
209     /* Create a transfer request for the prolific setup request # 5.  */
210     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
211     transfer_request -> ux_transfer_request_requested_length    =  1;
212     transfer_request -> ux_transfer_request_function            =  1;
213     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
214     transfer_request -> ux_transfer_request_value               =  UX_HOST_CLASS_PROLIFIC_COMMAND_EEPROM_READ;
215     transfer_request -> ux_transfer_request_index               =  0;
216 
217     /* Send request to HCD layer.  */
218     status =  _ux_host_stack_transfer_request(transfer_request);
219 
220     /* Check status, if error, do not proceed.  */
221     if (status != UX_SUCCESS)
222     {
223 
224         /* Free all used resources.  */
225         _ux_utility_memory_free(setup_buffer);
226 
227         /* Return completion status.  */
228         return(status);
229 
230     }
231 
232     /* Create a transfer request for the prolific setup request # 6.  */
233     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
234     transfer_request -> ux_transfer_request_requested_length    =  0;
235     transfer_request -> ux_transfer_request_function            =  1;
236     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
237     transfer_request -> ux_transfer_request_value               =  0x0404;
238     transfer_request -> ux_transfer_request_index               =  1;
239 
240     /* Send request to HCD layer.  */
241     status =  _ux_host_stack_transfer_request(transfer_request);
242 
243     /* Check status, if error, do not proceed.  */
244     if (status != UX_SUCCESS)
245     {
246 
247         /* Free all used resources.  */
248         _ux_utility_memory_free(setup_buffer);
249 
250         /* Return completion status.  */
251         return(status);
252 
253     }
254 
255     /* Create a transfer request for the prolific setup request # 7.  */
256     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
257     transfer_request -> ux_transfer_request_requested_length    =  1;
258     transfer_request -> ux_transfer_request_function            =  1;
259     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
260     transfer_request -> ux_transfer_request_value               =  UX_HOST_CLASS_PROLIFIC_COMMAND_EEPROM_READ;
261     transfer_request -> ux_transfer_request_index               =  0;
262 
263     /* Send request to HCD layer.  */
264     status =  _ux_host_stack_transfer_request(transfer_request);
265 
266     /* Check status, if error, do not proceed.  */
267     if (status != UX_SUCCESS)
268     {
269 
270         /* Free all used resources.  */
271         _ux_utility_memory_free(setup_buffer);
272 
273         /* Return completion status.  */
274         return(status);
275 
276     }
277 
278     /* Create a transfer request for the prolific setup request # 8.  */
279     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
280     transfer_request -> ux_transfer_request_requested_length    =  1;
281     transfer_request -> ux_transfer_request_function            =  1;
282     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
283     transfer_request -> ux_transfer_request_value               =  0x8383;
284     transfer_request -> ux_transfer_request_index               =  0;
285 
286     /* Send request to HCD layer.  */
287     status =  _ux_host_stack_transfer_request(transfer_request);
288 
289     /* Check status, if error, do not proceed.  */
290     if (status != UX_SUCCESS)
291     {
292 
293         /* Free all used resources.  */
294         _ux_utility_memory_free(setup_buffer);
295 
296         /* Return completion status.  */
297         return(status);
298 
299     }
300 
301     /* Create a transfer request for the prolific setup request # 9.  */
302     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
303     transfer_request -> ux_transfer_request_requested_length    =  0;
304     transfer_request -> ux_transfer_request_function            =  1;
305     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
306     transfer_request -> ux_transfer_request_value               =  0;
307     transfer_request -> ux_transfer_request_index               =  1;
308 
309     /* Send request to HCD layer.  */
310     status =  _ux_host_stack_transfer_request(transfer_request);
311 
312     /* Check status, if error, do not proceed.  */
313     if (status != UX_SUCCESS)
314     {
315 
316         /* Free all used resources.  */
317         _ux_utility_memory_free(setup_buffer);
318 
319         /* Return completion status.  */
320         return(status);
321 
322     }
323 
324     /* Create a transfer request for the prolific setup request # 9.  */
325     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
326     transfer_request -> ux_transfer_request_requested_length    =  0;
327     transfer_request -> ux_transfer_request_function            =  1;
328     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
329     transfer_request -> ux_transfer_request_value               =  1;
330     transfer_request -> ux_transfer_request_index               =  0;
331 
332     /* Send request to HCD layer.  */
333     status =  _ux_host_stack_transfer_request(transfer_request);
334 
335     /* Check status, if error, do not proceed.  */
336     if (status != UX_SUCCESS)
337     {
338 
339         /* Free all used resources.  */
340         _ux_utility_memory_free(setup_buffer);
341 
342         /* Return completion status.  */
343         return(status);
344 
345     }
346 
347     /* Create a transfer request for the prolific setup request # 10.  */
348     if (prolific -> ux_host_class_prolific_device_type == UX_HOST_CLASS_PROLIFIC_DEVICE_TYPE_HX)
349 
350         /* Chip is HX.  */
351         transfer_request -> ux_transfer_request_index           =  0x44;
352 
353     else
354 
355         /* Chip is not HX.  */
356         transfer_request -> ux_transfer_request_index           =  0x24;
357 
358     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
359     transfer_request -> ux_transfer_request_requested_length    =  0;
360     transfer_request -> ux_transfer_request_function            =  1;
361     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
362     transfer_request -> ux_transfer_request_value               =  UX_HOST_CLASS_PROLIFIC_COMMAND_REG_CONFIGURE;
363 
364     /* Send request to HCD layer.  */
365     _ux_host_stack_transfer_request(transfer_request);
366 
367 
368     /* Reset upstream data pipes part 1.  */
369     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
370     transfer_request -> ux_transfer_request_requested_length    =  0;
371     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_PROLIFIC_VENDOR_WRITE_REQUEST;
372     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
373     transfer_request -> ux_transfer_request_value               =  UX_HOST_CLASS_PROLIFIC_COMMAND_PIPE1_RESET;
374     transfer_request -> ux_transfer_request_index               =  0;
375 
376     /* Send request to HCD layer.  */
377     status =  _ux_host_stack_transfer_request(transfer_request);
378 
379     /* Check status, if error, do not proceed.  */
380     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
381     {
382 
383         /* Free all used resources.  */
384         _ux_utility_memory_free(setup_buffer);
385 
386         /* Return completion status.  */
387         return(UX_TRANSFER_ERROR);
388 
389     }
390 
391     /* Reset upstream data pipes part 2.  */
392     transfer_request -> ux_transfer_request_data_pointer        =  setup_buffer;
393     transfer_request -> ux_transfer_request_requested_length    =  0;
394     transfer_request -> ux_transfer_request_function            =  UX_HOST_CLASS_PROLIFIC_VENDOR_WRITE_REQUEST;
395     transfer_request -> ux_transfer_request_type                =  UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
396     transfer_request -> ux_transfer_request_value               =  UX_HOST_CLASS_PROLIFIC_COMMAND_PIPE2_RESET;
397     transfer_request -> ux_transfer_request_index               =  0;
398 
399     /* Send request to HCD layer.  */
400     status =  _ux_host_stack_transfer_request(transfer_request);
401 
402     /* Check status, if error, do not proceed.  */
403     if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS)
404     {
405 
406         /* Free all used resources.  */
407         _ux_utility_memory_free(setup_buffer);
408 
409         /* Return completion status.  */
410         return(UX_TRANSFER_ERROR);
411 
412     }
413 
414     /* Free all used resources.  */
415     _ux_utility_memory_free(setup_buffer);
416 
417     /* Return completion status.  */
418     return(status);
419 }
420 
421