1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
|
/***************************************************************************/
/* Copyright (c) 2024 Microsoft Corporation */
/* Copyright (c) 2026 Eclipse ThreadX contributors */
/* */
/* This program and the accompanying materials are made available under */
/* the terms of the MIT License which is available at */
/* https://opensource.org/licenses/MIT. */
/* */
/* SPDX-License-Identifier: MIT */
/***************************************************************************/
/* This test simulator is designed to redirect simulate ux_hcd_sim_slave_ APIs for test. */
#include "tx_api.h"
#include "tx_thread.h"
#include "ux_api.h"
#include "ux_dcd_sim_slave.h"
#include "ux_test_dcd_sim_slave.h"
#include "ux_test_utility_sim.h"
static ULONG _ux_dcd_sim_slave_speed = UX_FULL_SPEED_DEVICE;
static UCHAR *_ux_dcd_sim_framework = UX_NULL;
static ULONG _ux_dcd_sim_framework_length = 0;
static UX_TEST_DCD_SIM_ACTION *ux_test_actions = UX_NULL;
static UX_TEST_DCD_SIM_ACTION *ux_test_main_action_list;
VOID ux_test_dcd_sim_slave_cleanup(VOID)
{
_ux_dcd_sim_slave_speed = UX_FULL_SPEED_DEVICE;
_ux_dcd_sim_framework = UX_NULL;
_ux_dcd_sim_framework_length = 0;
ux_test_actions = UX_NULL;
ux_test_main_action_list = UX_NULL;
}
VOID ux_test_dcd_sim_slave_disconnect(VOID)
{
#if 1
UINT old_threshold;
#else
TX_INTERRUPT_SAVE_AREA
#endif
#if 1
/* Disconnection is usually handled in an ISR, which cannot be preempted. Copy behavior.
Note that the regular TX_DISABLE doesn't work on Windows. Might not work for Linux
either. */
tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold);
#else
TX_DISABLE
#endif
ux_device_stack_disconnect();
#if 1
tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold);
#else
TX_RESTORE
#endif
}
VOID ux_test_dcd_sim_slave_connect(ULONG speed)
{
_ux_dcd_sim_slave_speed = speed;
//_ux_dcd_sim_slave_initialize_complete();
}
VOID ux_test_dcd_sim_slave_connect_framework(UCHAR * framework, ULONG framework_length)
{
_ux_dcd_sim_framework = framework;
_ux_dcd_sim_framework_length = framework_length;
//_ux_dcd_sim_slave_initialize_complete();
}
/* Fork and modified to replace _ux_dcd_sim_slave_initialize_complete in lib for testing control. */
UINT _ux_dcd_sim_slave_initialize_complete(VOID)
{
UX_SLAVE_DCD *dcd;
UX_SLAVE_DEVICE *device;
UCHAR * device_framework;
UX_SLAVE_TRANSFER *transfer_request;
/* Get the pointer to the DCD. */
dcd = &_ux_system_slave -> ux_system_slave_dcd;
/* Get the pointer to the device. */
device = &_ux_system_slave -> ux_system_slave_device;
if (_ux_dcd_sim_framework != UX_NULL && _ux_dcd_sim_framework_length != 0)
{
/* Initialize customized framework. */
_ux_system_slave -> ux_system_slave_device_framework = _ux_dcd_sim_framework;
_ux_system_slave -> ux_system_slave_device_framework_length = _ux_dcd_sim_framework_length;
}
else
{
/* Slave simulator is a Full/high speed controller. */
if (_ux_dcd_sim_slave_speed == UX_HIGH_SPEED_DEVICE)
{
_ux_system_slave -> ux_system_slave_device_framework = _ux_system_slave -> ux_system_slave_device_framework_high_speed;
_ux_system_slave -> ux_system_slave_device_framework_length = _ux_system_slave -> ux_system_slave_device_framework_length_high_speed;
}
else
{
_ux_system_slave -> ux_system_slave_device_framework = _ux_system_slave -> ux_system_slave_device_framework_full_speed;
_ux_system_slave -> ux_system_slave_device_framework_length = _ux_system_slave -> ux_system_slave_device_framework_length_full_speed;
}
/* Save device speed. */
_ux_system_slave->ux_system_slave_speed = _ux_dcd_sim_slave_speed;
}
/* Get the device framework pointer. */
device_framework = _ux_system_slave -> ux_system_slave_device_framework;
/* And create the decompressed device descriptor structure. */
_ux_utility_descriptor_parse(device_framework,
_ux_system_device_descriptor_structure,
UX_DEVICE_DESCRIPTOR_ENTRIES,
(UCHAR *) &device -> ux_slave_device_descriptor);
/* Now we create a transfer request to accept the first SETUP packet
and get the ball running. First get the address of the endpoint
transfer request container. */
transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request;
/* Set the timeout to be for Control Endpoint. */
transfer_request -> ux_slave_transfer_request_timeout = MS_TO_TICK(UX_CONTROL_TRANSFER_TIMEOUT);
/* Adjust the current data pointer as well. */
transfer_request -> ux_slave_transfer_request_current_data_pointer =
transfer_request -> ux_slave_transfer_request_data_pointer;
/* Update the transfer request endpoint pointer with the default endpoint. */
transfer_request -> ux_slave_transfer_request_endpoint = &device -> ux_slave_device_control_endpoint;
/* The control endpoint max packet size needs to be filled manually in its descriptor. */
transfer_request -> ux_slave_transfer_request_endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize =
device -> ux_slave_device_descriptor.bMaxPacketSize0;
/* On the control endpoint, always expect the maximum. */
transfer_request -> ux_slave_transfer_request_requested_length =
device -> ux_slave_device_descriptor.bMaxPacketSize0;
/* Attach the control endpoint to the transfer request. */
transfer_request -> ux_slave_transfer_request_endpoint = &device -> ux_slave_device_control_endpoint;
/* Create the default control endpoint attached to the device.
Once this endpoint is enabled, the host can then send a setup packet
The device controller will receive it and will call the setup function
module. */
dcd -> ux_slave_dcd_function(dcd, UX_DCD_CREATE_ENDPOINT,
(VOID *) &device -> ux_slave_device_control_endpoint);
/* Ensure the control endpoint is properly reset. */
device -> ux_slave_device_control_endpoint.ux_slave_endpoint_state = UX_ENDPOINT_RESET;
/* A SETUP packet is a DATA IN operation. */
transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_IN;
/* We are now ready for the USB device to accept the first packet when connected. */
return(UX_SUCCESS);
}
static UINT last_function = 0;
static char *_func_name[] = {
"",
"DISABLE_CONTROLLER",
"GET_PORT_STATUS",
"ENABLE_PORT",
"DISABLE_PORT",
"POWER_ON_PORT",
"POWER_DOWN_PORT",
"SUSPEND_PORT",
"RESUME_PORT",
"RESET_PORT",
"GET_FRAME_NUMBER",
"SET_FRAME_NUMBER",
"TRANSFER_REQUEST",
"TRANSFER_ABORT",
"CREATE_ENDPOINT",
"DESTROY_ENDPOINT",
"RESET_ENDPOINT",
"SET_DEVICE_ADDRESS",
"ISR_PENDING",
"CHANGE_STATE",
"STALL_ENDPOINT",
"ENDPOINT_STATUS"
};
UINT _ux_test_dcd_sim_slave_function(UX_SLAVE_DCD *dcd, UINT function, VOID *parameter)
{
UINT status;
UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION_PARAMS params = { dcd, function, parameter };
UX_TEST_ACTION action;
/* Perform hooked callbacks. */
ux_test_do_hooks_before(UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION, ¶ms);
action = ux_test_action_handler(UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION, ¶ms);
ux_test_do_action_before(&action, ¶ms);
/* NOTE: This shouldn't be used anymore. */
if (ux_test_is_expedient_on())
{
if (action.matched && !action.do_after)
{
if (!action.no_return)
{
return action.status;
}
}
}
status = _ux_dcd_sim_slave_function(dcd, function, parameter);
ux_test_do_action_after(&action, ¶ms);
/* NOTE: This shouldn't be used anymore. */
if (ux_test_is_expedient_on())
{
if (action.matched && action.do_after)
{
if (!action.no_return)
{
return action.status;
}
}
}
/* Perform hooked callbacks. */
ux_test_do_hooks_after(UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION, ¶ms);
/* Return completion status. */
return(status);
}
UINT _ux_test_dcd_sim_slave_initialize(VOID)
{
UINT status;
UX_SLAVE_DEVICE *device;
UX_SLAVE_DCD *dcd;
status = _ux_dcd_sim_slave_initialize();
/* Redirect the entry function */
device = &_ux_system_slave -> ux_system_slave_device;
dcd = &_ux_system_slave -> ux_system_slave_dcd;
dcd -> ux_slave_dcd_function = _ux_test_dcd_sim_slave_function;
return status;
}
VOID ux_test_dcd_sim_slave_transfer_done(UX_SLAVE_TRANSFER *transfer, UINT code)
{
UX_SLAVE_ENDPOINT *endpoint = transfer -> ux_slave_transfer_request_endpoint;
UX_DCD_SIM_SLAVE_ED *slave_ed = (UX_DCD_SIM_SLAVE_ED *)endpoint -> ux_slave_endpoint_ed;
transfer -> ux_slave_transfer_request_completion_code = code;
transfer -> ux_slave_transfer_request_status = UX_TRANSFER_STATUS_COMPLETED;
slave_ed -> ux_sim_slave_ed_status |= UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER;
slave_ed -> ux_sim_slave_ed_status |= UX_DCD_SIM_SLAVE_ED_STATUS_DONE;
_ux_device_semaphore_put(&transfer -> ux_slave_transfer_request_semaphore);
}
|