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