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, &params);
201 
202     action = ux_test_action_handler(UX_TEST_OVERRIDE_UX_DCD_SIM_SLAVE_FUNCTION, &params);
203     ux_test_do_action_before(&action, &params);
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, &params);
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, &params);
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