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 /**   Device Data Pump Class                                              */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define UX_SOURCE_CODE
23 
24 
25 /* Include necessary system files.  */
26 
27 #include "ux_api.h"
28 #include "ux_device_class_dpump.h"
29 #include "ux_device_stack.h"
30 
31 /* Remove compiling warning. */
32 VOID  _ux_device_class_dpump_thread(ULONG dpump_class);
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _ux_device_class_dpump_thread                       PORTABLE C      */
39 /*                                                           6.1.12       */
40 /*  AUTHOR                                                                */
41 /*                                                                        */
42 /*    Chaoqiong Xiao, Microsoft Corporation                               */
43 /*                                                                        */
44 /*  DESCRIPTION                                                           */
45 /*                                                                        */
46 /*    This function is the thread of the dpump class.                     */
47 /*                                                                        */
48 /*    It's for RTOS mode.                                                 */
49 /*                                                                        */
50 /*  INPUT                                                                 */
51 /*                                                                        */
52 /*    class                                   Address of dpump class      */
53 /*                                            container                   */
54 /*                                                                        */
55 /*  OUTPUT                                                                */
56 /*                                                                        */
57 /*    None                                                                */
58 /*                                                                        */
59 /*  CALLS                                                                 */
60 /*                                                                        */
61 /*    _ux_device_stack_transfer_request     Request transfer              */
62 /*    _ux_utility_memory_copy               Copy memory                   */
63 /*    _ux_utility_thread_suspend            Suspend thread                */
64 /*                                                                        */
65 /*  CALLED BY                                                             */
66 /*                                                                        */
67 /*    ThreadX                                                             */
68 /*                                                                        */
69 /*  RELEASE HISTORY                                                       */
70 /*                                                                        */
71 /*    DATE              NAME                      DESCRIPTION             */
72 /*                                                                        */
73 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
74 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
75 /*                                            verified memset and memcpy  */
76 /*                                            cases,                      */
77 /*                                            resulting in version 6.1    */
78 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
79 /*                                            refined macros names,       */
80 /*                                            resulting in version 6.1.10 */
81 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
82 /*                                            fixed parameter/variable    */
83 /*                                            names conflict C++ keyword, */
84 /*                                            resulting in version 6.1.12 */
85 /*                                                                        */
86 /**************************************************************************/
_ux_device_class_dpump_thread(ULONG dpump_class)87 VOID  _ux_device_class_dpump_thread(ULONG dpump_class)
88 {
89 
90 UX_SLAVE_CLASS              *class_ptr;
91 UX_SLAVE_INTERFACE          *interface_ptr;
92 UX_SLAVE_CLASS_DPUMP        *dpump;
93 UX_SLAVE_TRANSFER           *transfer_request;
94 UX_SLAVE_DEVICE             *device;
95 UX_SLAVE_ENDPOINT           *endpoint_in;
96 UX_SLAVE_ENDPOINT           *endpoint_out;
97 UINT                        status;
98 ULONG                       length;
99 
100     /* This thread runs forever but can be suspended or resumed.  */
101     while(1)
102     {
103 
104         /* Cast properly the dpump instance.  */
105         UX_THREAD_EXTENSION_PTR_GET(class_ptr, UX_SLAVE_CLASS, dpump_class)
106 
107         /* Get the dpump instance from this class container.  */
108         dpump =  (UX_SLAVE_CLASS_DPUMP *) class_ptr -> ux_slave_class_instance;
109 
110         /* Get the pointer to the device.  */
111         device =  &_ux_system_slave -> ux_system_slave_device;
112 
113         /* This is the first time we are activated. We need the interface to the class.  */
114         interface_ptr =  dpump -> ux_slave_class_dpump_interface;
115 
116         /* Locate the endpoints.  */
117         endpoint_in =  interface_ptr -> ux_slave_interface_first_endpoint;
118 
119         /* Check the endpoint direction, if IN we have the correct endpoint.  */
120         if ((endpoint_in -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN)
121         {
122 
123             /* Wrong direction, we found the OUT endpoint first.  */
124             endpoint_out =  endpoint_in;
125 
126             /* So the next endpoint has to be the IN endpoint.  */
127             endpoint_in =  endpoint_out -> ux_slave_endpoint_next_endpoint;
128         }
129         else
130         {
131 
132             /* We found the endpoint IN first, so next endpoint is OUT.  */
133             endpoint_out =  endpoint_in -> ux_slave_endpoint_next_endpoint;
134         }
135 
136         /* As long as the device is in the CONFIGURED state.  */
137         while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
138         {
139 
140             /* We prepare to receive from the host on the OUT endpoint.  */
141             transfer_request =  &endpoint_out -> ux_slave_endpoint_transfer_request;
142 
143             /* Send the request to the device controller.  */
144             status =  _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_DPUMP_PACKET_SIZE, UX_DEVICE_CLASS_DPUMP_PACKET_SIZE);
145 
146             /* Check the status */
147             if (status == UX_SUCCESS)
148             {
149 
150                 /* Obtain the length of the transaction.  */
151                 length =  transfer_request -> ux_slave_transfer_request_actual_length;
152 
153                 /* Copy the buffer to the target in endpoint.  */
154                 _ux_utility_memory_copy(endpoint_in -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer,
155                                         endpoint_out -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer,
156                                         length); /* Use case of memcpy is verified. */
157 
158                 /* Now we send the packet back to the host. On the endpoint In.  */
159                 transfer_request =  &endpoint_in -> ux_slave_endpoint_transfer_request;
160 
161                 /* Sends the data payload back to the caller.  */
162                 status =  _ux_device_stack_transfer_request(transfer_request, length, length);
163 
164                 /* Check error code. */
165                 if (status != UX_SUCCESS)
166 
167                     /* Error trap. */
168                     _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status);
169             }
170         }
171 
172         /* We need to suspend ourselves. We will be resumed by the
173            device enumeration module.  */
174         _ux_device_thread_suspend(&class_ptr -> ux_slave_class_thread);
175     }
176 }
177 
178