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