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 /**************************************************************************/
33 /* */
34 /* FUNCTION RELEASE */
35 /* */
36 /* _ux_device_class_dpump_write PORTABLE C */
37 /* 6.1 */
38 /* AUTHOR */
39 /* */
40 /* Chaoqiong Xiao, Microsoft Corporation */
41 /* */
42 /* DESCRIPTION */
43 /* */
44 /* This function writes to the DPUMP class. */
45 /* */
46 /* INPUT */
47 /* */
48 /* dpump Address of dpump class */
49 /* instance */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* None */
54 /* */
55 /* CALLS */
56 /* */
57 /* _ux_utility_memory_copy */
58 /* _ux_device_stack_transfer_request */
59 /* */
60 /* CALLED BY */
61 /* */
62 /* ThreadX */
63 /* */
64 /* RELEASE HISTORY */
65 /* */
66 /* DATE NAME DESCRIPTION */
67 /* */
68 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
69 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
70 /* verified memset and memcpy */
71 /* cases, */
72 /* resulting in version 6.1 */
73 /* */
74 /**************************************************************************/
_ux_device_class_dpump_write(UX_SLAVE_CLASS_DPUMP * dpump,UCHAR * buffer,ULONG requested_length,ULONG * actual_length)75 UINT _ux_device_class_dpump_write(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer,
76 ULONG requested_length, ULONG *actual_length)
77 {
78
79 UX_SLAVE_ENDPOINT *endpoint;
80 UX_SLAVE_DEVICE *device;
81 UX_SLAVE_TRANSFER *transfer_request;
82 ULONG local_requested_length;
83 UINT status;
84
85 /* If trace is enabled, insert this event into the trace buffer. */
86 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DPUMP_WRITE, dpump, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
87
88 /* Get the pointer to the device. */
89 device = &_ux_system_slave -> ux_system_slave_device;
90
91 /* As long as the device is in the CONFIGURED state. */
92 if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
93 {
94
95 /* Error trap. */
96 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN);
97
98 /* If trace is enabled, insert this event into the trace buffer. */
99 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0)
100
101 /* Cannot proceed with command, the interface is down. */
102 return(UX_CONFIGURATION_HANDLE_UNKNOWN);
103 }
104
105 /* Locate the IN endpoint. */
106 endpoint = dpump -> ux_slave_class_dpump_bulkin_endpoint;
107
108 /* Check endpoint. If NULL, we have not yet received the proper SET_INTERFACE command. */
109 if (endpoint == UX_NULL)
110 {
111
112 /* Error trap. */
113 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN);
114
115 return(UX_ENDPOINT_HANDLE_UNKNOWN);
116 }
117
118 /* We are writing to the IN endpoint. */
119 transfer_request = &endpoint -> ux_slave_endpoint_transfer_request;
120
121 /* Reset the actual length. */
122 *actual_length = 0;
123
124 /* Set return status to SUCCESS to make certain compilers happy. */
125 status = UX_SUCCESS;
126
127 /* Check if we need more transactions. */
128 while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED && requested_length != 0)
129 {
130
131 /* Check if we have enough in the local buffer. */
132 if (requested_length > UX_SLAVE_REQUEST_DATA_MAX_LENGTH)
133
134 /* We have too much to transfer. */
135 local_requested_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH;
136
137 else
138
139 /* We can proceed with the demanded length. */
140 local_requested_length = requested_length;
141
142 /* On a out, we copy the buffer to the caller. Not very efficient but it makes the API
143 easier. */
144 _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer,
145 buffer, local_requested_length); /* Use case of memcpy is verified. */
146
147 /* Send the request to the device controller. */
148 status = _ux_device_stack_transfer_request(transfer_request, local_requested_length, local_requested_length);
149
150 /* Check the status */
151 if (status == UX_SUCCESS)
152 {
153
154 /* Next buffer address. */
155 buffer += transfer_request -> ux_slave_transfer_request_actual_length;
156
157 /* Set the length actually received. */
158 *actual_length += transfer_request -> ux_slave_transfer_request_actual_length;
159
160 /* Decrement what left has to be done. */
161 requested_length -= transfer_request -> ux_slave_transfer_request_actual_length;
162
163 }
164
165 else
166
167 /* We had an error, abort. */
168 return(status);
169 }
170
171 /* Check why we got here, either completion or device was extracted. */
172 if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
173 {
174
175 /* Error trap. */
176 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER);
177
178 /* If trace is enabled, insert this event into the trace buffer. */
179 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0)
180
181 /* Device must have been extracted. */
182 return (UX_TRANSFER_NO_ANSWER);
183 }
184 else
185
186 /* Simply return the last transaction result. */
187 return(status);
188
189 }
190
191