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 /** USBX Component */
16 /** */
17 /** Device DPUMP 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
32 #if defined(UX_DEVICE_STANDALONE)
33
34 #define UX_DEVICE_CLASS_DPUMP_READ_START (UX_STATE_STEP + 1)
35 #define UX_DEVICE_CLASS_DPUMP_READ_WAIT (UX_STATE_STEP + 2)
36
37 /**************************************************************************/
38 /* */
39 /* FUNCTION RELEASE */
40 /* */
41 /* _ux_device_class_dpump_read_run PORTABLE C */
42 /* 6.1.10 */
43 /* AUTHOR */
44 /* */
45 /* Chaoqiong Xiao, Microsoft Corporation */
46 /* */
47 /* DESCRIPTION */
48 /* */
49 /* This function reads from the DPUMP class. */
50 /* */
51 /* It's for standalone mode. */
52 /* */
53 /* INPUT */
54 /* */
55 /* dpump DPUMP class instance */
56 /* buffer Buffer to hold data read */
57 /* requested_length Bytes to read */
58 /* actual_length Bytes read */
59 /* */
60 /* OUTPUT */
61 /* */
62 /* State machine Status to check */
63 /* UX_STATE_NEXT Transfer done, to next state */
64 /* UX_STATE_EXIT Abnormal, to reset state */
65 /* (others) Keep running, waiting */
66 /* */
67 /* CALLS */
68 /* */
69 /* _ux_device_stack_transfer_request Request transfer */
70 /* _ux_utility_memory_copy Copy memory */
71 /* */
72 /* CALLED BY */
73 /* */
74 /* Application */
75 /* */
76 /* RELEASE HISTORY */
77 /* */
78 /* DATE NAME DESCRIPTION */
79 /* */
80 /* 01-31-2022 Chaoqiong Xiao Initial Version 6.1.10 */
81 /* */
82 /**************************************************************************/
_ux_device_class_dpump_read_run(UX_SLAVE_CLASS_DPUMP * dpump,UCHAR * buffer,ULONG requested_length,ULONG * actual_length)83 UINT _ux_device_class_dpump_read_run(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer,
84 ULONG requested_length, ULONG *actual_length)
85 {
86
87 UX_SLAVE_ENDPOINT *endpoint;
88 UX_SLAVE_DEVICE *device;
89 UX_SLAVE_TRANSFER *transfer_request;
90 UINT status;
91 UINT read_state;
92
93
94 /* If trace is enabled, insert this event into the trace buffer. */
95 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DPUMP_READ, dpump, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
96
97 /* Get the pointer to the device. */
98 device = &_ux_system_slave -> ux_system_slave_device;
99
100 /* As long as the device is in the CONFIGURED state. */
101 if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
102 {
103
104 /* Error trap. */
105 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN);
106
107 /* If trace is enabled, insert this event into the trace buffer. */
108 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0)
109
110 /* Cannot proceed with command, the interface is down. */
111 dpump -> ux_device_class_dpump_read_state = UX_STATE_RESET;
112 dpump -> ux_device_class_dpump_read_status = UX_CONFIGURATION_HANDLE_UNKNOWN;
113 return(UX_STATE_EXIT);
114 }
115
116 /* Locate the OUT endpoint. */
117 endpoint = dpump -> ux_slave_class_dpump_bulkout_endpoint;
118
119 /* Check endpoint. If NULL, we have not yet received the proper SET_INTERFACE command. */
120 if (endpoint == UX_NULL)
121 {
122 /* Error trap. */
123 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN);
124
125 dpump -> ux_device_class_dpump_read_state = UX_STATE_RESET;
126 dpump -> ux_device_class_dpump_read_status = UX_ENDPOINT_HANDLE_UNKNOWN;
127 return(UX_STATE_EXIT);
128 }
129
130 /* All DPUMP reading are on the endpoint OUT, from the host. */
131 transfer_request = &endpoint -> ux_slave_endpoint_transfer_request;
132
133 /* Handle state cases. */
134 read_state = dpump -> ux_device_class_dpump_read_state;
135 switch(read_state)
136 {
137 case UX_STATE_RESET:
138 dpump -> ux_device_class_dpump_read_state = UX_DEVICE_CLASS_DPUMP_READ_START;
139 dpump -> ux_device_class_dpump_read_status = UX_TRANSFER_NO_ANSWER;
140 dpump -> ux_device_class_dpump_read_buffer = buffer;
141 dpump -> ux_device_class_dpump_read_requested_length = requested_length;
142 dpump -> ux_device_class_dpump_read_actual_length = 0;
143
144 /* Fall through. */
145 case UX_DEVICE_CLASS_DPUMP_READ_START:
146
147 /* Get remaining requested length. */
148 requested_length = dpump -> ux_device_class_dpump_read_requested_length -
149 dpump -> ux_device_class_dpump_read_actual_length;
150
151 /* There is no remaining, we are done. */
152 if (requested_length == 0)
153 {
154 *actual_length = dpump -> ux_device_class_dpump_read_actual_length;
155 dpump -> ux_device_class_dpump_read_state = UX_STATE_RESET;
156 dpump -> ux_device_class_dpump_read_status = UX_SUCCESS;
157 return(UX_STATE_NEXT);
158 }
159
160 /* Check if we have enough in the local buffer. */
161 if (requested_length > UX_SLAVE_REQUEST_DATA_MAX_LENGTH)
162
163 /* We have too much to transfer. */
164 dpump -> ux_device_class_dpump_read_transfer_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH;
165
166 else
167
168 /* We can proceed with the demanded length. */
169 dpump -> ux_device_class_dpump_read_transfer_length = requested_length;
170
171 /* Next state. */
172 dpump -> ux_device_class_dpump_read_state = UX_DEVICE_CLASS_DPUMP_READ_WAIT;
173 UX_SLAVE_TRANSFER_STATE_RESET(transfer_request);
174
175 /* Fall through. */
176 case UX_DEVICE_CLASS_DPUMP_READ_WAIT:
177
178 /* Send the request to the device controller. */
179 status = _ux_device_stack_transfer_run(transfer_request,
180 dpump -> ux_device_class_dpump_read_transfer_length,
181 dpump -> ux_device_class_dpump_read_transfer_length);
182
183 /* Error case. */
184 if (status < UX_STATE_NEXT)
185 {
186
187 dpump -> ux_device_class_dpump_read_state = UX_STATE_RESET;
188 dpump -> ux_device_class_dpump_read_status =
189 transfer_request -> ux_slave_transfer_request_completion_code;
190 return(UX_STATE_EXIT);
191 }
192
193 /* Success case. */
194 if (status == UX_STATE_NEXT)
195 {
196
197 /* We need to copy the buffer locally. */
198 _ux_utility_memory_copy(dpump -> ux_device_class_dpump_read_buffer,
199 transfer_request -> ux_slave_transfer_request_data_pointer,
200 dpump -> ux_device_class_dpump_read_transfer_length); /* Use case of memcpy is verified. */
201
202 /* Next buffer address. */
203 dpump -> ux_device_class_dpump_read_buffer +=
204 transfer_request -> ux_slave_transfer_request_actual_length;
205
206 /* Set the length actually received. */
207 dpump -> ux_device_class_dpump_read_actual_length +=
208 transfer_request -> ux_slave_transfer_request_actual_length;
209
210 /* Last transfer status. */
211 dpump -> ux_device_class_dpump_read_status =
212 transfer_request -> ux_slave_transfer_request_completion_code;
213
214 /* Update actual length. */
215 *actual_length = dpump -> ux_device_class_dpump_read_actual_length;
216
217 /* Check short packet. */
218 if (transfer_request -> ux_slave_transfer_request_actual_length <
219 transfer_request -> ux_slave_transfer_request_requested_length)
220 {
221
222 /* It's done. */
223 dpump -> ux_device_class_dpump_read_state = UX_STATE_RESET;
224 return(UX_STATE_NEXT);
225 }
226
227 /* Next state. */
228 dpump -> ux_device_class_dpump_read_state = UX_DEVICE_CLASS_DPUMP_READ_START;
229 }
230
231 /* Keep waiting. */
232 return(UX_STATE_WAIT);
233
234 default: /* Error. */
235 dpump -> ux_device_class_dpump_read_state = UX_STATE_RESET;
236 break;
237 }
238
239 /* Error case. */
240 return(UX_STATE_EXIT);
241 }
242 #endif
243