1 /* This test simulator is designed to simulate ux_hcd_ APIs for test. */
2
3 #include "tx_api.h"
4 #include "tx_thread.h"
5
6 #include "ux_api.h"
7 #include "ux_hcd_sim_host.h"
8
9 #include "ux_test_utility_sim.h"
10 #include "ux_test_hcd_sim_host.h"
11
12 void test_control_return(UINT status);
13
14 ULONG ux_test_port_status = UX_PS_CCS | UX_PS_DS_FS;
15
16 /* We have a no wait version because in a real world scenario, there is no waiting. */
ux_test_hcd_sim_host_disconnect_no_wait(VOID)17 VOID ux_test_hcd_sim_host_disconnect_no_wait(VOID)
18 {
19
20 UINT status;
21 UX_HCD *hcd = &_ux_system_host -> ux_system_host_hcd_array[0];
22 UX_HCD_SIM_HOST *hcd_sim_host = hcd -> ux_hcd_controller_hardware;
23
24
25 /* Port is disconnected. */
26 ux_test_port_status = 0;
27 if (hcd_sim_host != UX_NULL)
28 {
29 #if !defined(UX_HOST_STANDALONE)
30 /* Don't let the timer function run, or else the HCD thread will perform transfer requests. */
31 status = tx_timer_deactivate(&hcd_sim_host -> ux_hcd_sim_host_timer);
32 if (status != TX_SUCCESS)
33 {
34
35 printf("test_hcd_sim_host #%d, error: %d\n", __LINE__, status);
36 test_control_return(1);
37 }
38 #endif
39 }
40 /* Signal change on the port (HCD0.RH.PORT0). */
41 hcd -> ux_hcd_root_hub_signal[0] = 1;
42 /* Signal detach to host enum thread. */
43 _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
44 }
45
ux_test_hcd_sim_host_disconnect(VOID)46 VOID ux_test_hcd_sim_host_disconnect(VOID)
47 {
48
49 ux_test_hcd_sim_host_disconnect_no_wait();
50
51 #if defined(UX_HOST_STANDALONE)
52 {
53 UX_HCD *hcd = &_ux_system_host -> ux_system_host_hcd_array[0];
54 ULONG n_device = hcd -> ux_hcd_nb_devices;
55 for (unsigned i = 0; i < 20000; i ++)
56 {
57 ux_system_tasks_run();
58 if (hcd -> ux_hcd_nb_devices == 0 ||
59 hcd -> ux_hcd_nb_devices < n_device)
60 break;
61 }
62 }
63 #else
64
65 /* Sleep current thread for enum thread to run. */
66 tx_thread_sleep(100);
67 #endif
68 }
69
ux_test_hcd_sim_host_connect_no_wait(ULONG speed)70 VOID ux_test_hcd_sim_host_connect_no_wait(ULONG speed)
71 {
72
73 UINT status;
74 UX_HCD *hcd = &_ux_system_host -> ux_system_host_hcd_array[0];
75 UX_HCD_SIM_HOST *hcd_sim_host = hcd -> ux_hcd_controller_hardware;
76
77
78 /* Connect with specific speed. */
79 switch(speed)
80 {
81 case UX_LOW_SPEED_DEVICE:
82
83 ux_test_port_status = UX_PS_CCS | UX_PS_DS_LS;
84 break;
85
86 case UX_FULL_SPEED_DEVICE:
87
88 ux_test_port_status = UX_PS_CCS | UX_PS_DS_FS;
89 break;
90
91 case UX_HIGH_SPEED_DEVICE:
92
93 ux_test_port_status = UX_PS_CCS | UX_PS_DS_HS;
94 break;
95
96 default:
97 break;
98 }
99
100 #if !defined(UX_HOST_STANDALONE)
101 /* Allow the timer function to run, or else the HCD thread won't perform transfer requests. */
102 status = tx_timer_activate(&hcd_sim_host -> ux_hcd_sim_host_timer);
103 if (status != TX_SUCCESS &&
104 /* Was the timer already active? */
105 status != TX_ACTIVATE_ERROR)
106 {
107
108 printf("test_hcd_sim_host #%d, error code: %d\n", __LINE__, status);
109 test_control_return(1);
110 }
111 #endif
112
113 /* Signal change on the port (HCD0.RH.PORT0). */
114 _ux_system_host -> ux_system_host_hcd_array -> ux_hcd_root_hub_signal[0] = 1;
115 /* Signal detach to host enum thread. */
116 _ux_host_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore);
117 }
118
ux_test_hcd_sim_host_connect(ULONG speed)119 VOID ux_test_hcd_sim_host_connect(ULONG speed)
120 {
121
122 ux_test_hcd_sim_host_connect_no_wait(speed);
123
124 /* Sleep current thread for enum thread to run. */
125 tx_thread_sleep(100);
126 }
127
128 /* Fork and modify _ux_hcd_sim_host_port_status_get. */
129
_ux_hcd_sim_host_port_status_get(UX_HCD_SIM_HOST * hcd_sim_host,ULONG port_index)130 ULONG _ux_hcd_sim_host_port_status_get(UX_HCD_SIM_HOST *hcd_sim_host, ULONG port_index)
131 {
132
133 /* Check to see if this port is valid on this controller. */
134 if (hcd_sim_host -> ux_hcd_sim_host_nb_root_hubs < port_index)
135 {
136
137 /* Error trap. */
138 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_PORT_INDEX_UNKNOWN);
139
140 /* If trace is enabled, insert this event into the trace buffer. */
141 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_INDEX_UNKNOWN, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0)
142
143 return(UX_PORT_INDEX_UNKNOWN);
144 }
145
146 /* Return port status. */
147 return(ux_test_port_status);
148 }
149
150 static UINT last_function = 0;
151 static char *_func_name[] = {
152 "",
153 "DISABLE_CONTROLLER",
154 "GET_PORT_STATUS",
155 "ENABLE_PORT",
156 "DISABLE_PORT",
157 "POWER_ON_PORT",
158 "POWER_DOWN_PORT",
159 "SUSPEND_PORT",
160 "RESUME_PORT",
161 "RESET_PORT",
162 "GET_FRAME_NUMBER",
163 "SET_FRAME_NUMBER",
164 "TRANSFER_REQUEST",
165 "TRANSFER_ABORT",
166 "CREATE_ENDPOINT",
167 "DESTROY_ENDPOINT",
168 "RESET_ENDPOINT",
169 "PROCESS_DONE_QUEUE"
170 };
171
172 #if 0 /* Not sure what the purpose of this is. -Nick */
173 UINT _ux_test_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter)
174 {
175
176 UINT status;
177 UCHAR act = 0;
178 UX_TRANSFER *req;
179 UX_ENDPOINT *ep;
180 TX_THREAD *this_thread;
181 UINT i;
182 UCHAR action_matched;
183
184
185 #if 0 /* TODO: Enable/disable HCD entry call display */
186 if (function != last_function)
187 {
188 last_function = function;
189 printf("\n_H %2d(%s) ", function, _func_name[function]);
190 }
191 else
192 printf(".");
193 #endif
194
195 status = ux_test_cd_handle_action(action, hcd, UX_TEST_CD_TYPE_HCD, function, parameter, &action_matched);
196 if (action_matched)
197 {
198 /* Proceed to next action */
199 action++;
200 if (action->function == 0)
201 action = UX_NULL;
202 }
203
204 return status;
205 }
206 #endif
207
_ux_test_hcd_sim_host_dummy_entry(UX_HCD * hcd,UINT function,VOID * parameter)208 UINT _ux_test_hcd_sim_host_dummy_entry(UX_HCD *hcd, UINT function, VOID *parameter)
209 {
210 if (function == UX_HCD_GET_PORT_STATUS)
211 /* Never connected. */
212 return 0;
213
214 return _ux_hcd_sim_host_entry(hcd, function, parameter);
215 }
216
_ux_test_hcd_sim_host_entry(UX_HCD * hcd,UINT function,VOID * parameter)217 UINT _ux_test_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter)
218 {
219
220 UINT status;
221 UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY_PARAMS params = { hcd, function, parameter };
222 UX_TEST_ACTION action;
223 ULONG action_taken;
224
225 /* Perform hooked callbacks. */
226 action_taken = ux_test_do_hooks_before(UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY, ¶ms);
227 if (action_taken & 0x80000000u) /* The hook breaks normal process. */
228 return(action.status);
229
230 action = ux_test_action_handler(UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY, ¶ms);
231 ux_test_do_action_before(&action, ¶ms);
232
233 if (ux_test_is_expedient_on())
234 {
235 if (action.matched && !action.do_after)
236 {
237 if (!action.no_return)
238 {
239 return action.status;
240 }
241 }
242 }
243
244 status = _ux_hcd_sim_host_entry(hcd, function, parameter);
245
246 ux_test_do_action_after(&action, ¶ms);
247
248 if (ux_test_is_expedient_on())
249 {
250 if (action.matched && action.do_after)
251 {
252 if (!action.no_return)
253 {
254 return action.status;
255 }
256 }
257 }
258
259 /* Perform hooked callbacks. */
260 ux_test_do_hooks_after(UX_TEST_OVERRIDE_UX_HCD_SIM_HOST_ENTRY, ¶ms);
261
262 /* Return completion status. */
263 return(status);
264 }
265
_ux_test_hcd_sim_host_initialize(UX_HCD * hcd)266 UINT _ux_test_hcd_sim_host_initialize(UX_HCD *hcd)
267 {
268 UINT status;
269
270 if (ux_utility_name_match((UCHAR*)"dummy", hcd->ux_hcd_name, 5))
271 {
272 /* Use dummy halted */
273 hcd -> ux_hcd_status = UX_HCD_STATUS_DEAD; /* Must not be UX_UNUSED == UX_HCD_STATUS_HALTED */
274 hcd -> ux_hcd_entry_function = _ux_test_hcd_sim_host_dummy_entry;
275 return UX_SUCCESS;
276 }
277
278 /* Use hcd sim host */
279 status = _ux_hcd_sim_host_initialize(hcd);
280
281 /* Redirect the entry function */
282 hcd -> ux_hcd_entry_function = _ux_test_hcd_sim_host_entry;
283
284 return status;
285 }
286
ux_test_hcd_sim_host_cleanup(VOID)287 VOID ux_test_hcd_sim_host_cleanup(VOID)
288 {
289
290 ux_test_port_status = UX_PS_CCS | UX_PS_DS_FS;
291 }
292