1 /* This is a small demo of the USBX */
2
3 #include "ux_api.h"
4 #include "ux_system.h"
5 #include "ux_utility.h"
6 #include "ux_host_class_dpump.h"
7 #include "ux_device_class_dpump.h"
8
9
10 /* Define USBX demo constants. */
11
12 #define UX_DEMO_STACK_SIZE 4096
13 #define UX_DEMO_MEMORY_SIZE (28*1024)
14
15
16 /* Define the counters used in the demo application... */
17
18 ULONG thread_0_counter;
19 ULONG thread_1_counter;
20 ULONG error_counter;
21
22
23 /* Define USBX demo global variables. */
24
25 ULONG ux_demo_memory_buffer[(UX_DEMO_MEMORY_SIZE + UX_DEMO_STACK_SIZE * 2) / sizeof(ULONG)];
26
27 unsigned char host_out_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
28 unsigned char host_in_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
29 unsigned char device_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE];
30
31 UX_HOST_CLASS *class_driver;
32 UX_HOST_CLASS_DPUMP *dpump;
33 UX_SLAVE_CLASS_DPUMP *dpump_device;
34
35
36 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 50
37 UCHAR device_framework_full_speed[] = {
38
39 /* Device descriptor */
40 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
41 0xec, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
42 0x00, 0x01,
43
44 /* Configuration descriptor */
45 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
46 0x32,
47
48 /* Interface descriptor */
49 0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
50 0x00,
51
52 /* Endpoint descriptor (Bulk Out) */
53 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00,
54
55 /* Endpoint descriptor (Bulk In) */
56 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00
57 };
58
59
60 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 60
61 UCHAR device_framework_high_speed[] = {
62
63 /* Device descriptor */
64 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
65 0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
66 0x03, 0x01,
67
68 /* Device qualifier descriptor */
69 0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
70 0x01, 0x00,
71
72 /* Configuration descriptor */
73 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0,
74 0x32,
75
76 /* Interface descriptor */
77 0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99,
78 0x00,
79
80 /* Endpoint descriptor (Bulk Out) */
81 0x07, 0x05, 0x01, 0x02, 0x00, 0x02, 0x00,
82
83 /* Endpoint descriptor (Bulk In) */
84 0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00
85 };
86
87 /* String Device Framework :
88 Byte 0 and 1 : Word containing the language ID : 0x0904 for US
89 Byte 2 : Byte containing the index of the descriptor
90 Byte 3 : Byte containing the length of the descriptor string
91 */
92
93 #define STRING_FRAMEWORK_LENGTH 38
94 UCHAR string_framework[] = {
95
96 /* Manufacturer string descriptor : Index 1 */
97 0x09, 0x04, 0x01, 0x0c,
98 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
99 0x6f, 0x67, 0x69, 0x63,
100
101 /* Product string descriptor : Index 2 */
102 0x09, 0x04, 0x02, 0x0c,
103 0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70,
104 0x44, 0x65, 0x6d, 0x6f,
105
106 /* Serial Number string descriptor : Index 3 */
107 0x09, 0x04, 0x03, 0x04,
108 0x30, 0x30, 0x30, 0x31
109 };
110
111
112 /* Multiple languages are supported on the device, to add
113 a language besides English, the unicode language code must
114 be appended to the language_id_framework array and the length
115 adjusted accordingly. */
116 #define LANGUAGE_ID_FRAMEWORK_LENGTH 2
117 UCHAR language_id_framework[] = {
118
119 /* English. */
120 0x09, 0x04
121 };
122
123
124 /* Define prototypes for external Host Controller's (HCDs), classes and clients. */
125
126 VOID tx_demo_instance_activate(VOID *dpump_instance);
127 VOID tx_demo_instance_deactivate(VOID *dpump_instance);
128
129 UINT _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command);
130 UINT ux_hcd_sim_initialize(UX_HCD *hcd);
131 UINT _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer,
132 ULONG requested_length, ULONG *actual_length);
133 UINT _ux_host_class_dpump_read (UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer,
134 ULONG requested_length, ULONG *actual_length);
135
136 TX_THREAD tx_demo_thread_host_simulation;
137 TX_THREAD tx_demo_thread_device_simulation;
138 void tx_demo_thread_host_simulation_entry(ULONG);
139 void tx_demo_thread_device_simulation_entry(ULONG);
140 VOID error_handler(void);
141
142
143 /* Define the entry point. */
144
main()145 int main()
146 {
147
148 /* Enter the ThreadX kernel. */
149 tx_kernel_enter();
150
151 return(0);
152 }
153
154
155 /* Define what the initial system looks like. */
156
tx_application_define(void * first_unused_memory)157 void tx_application_define(void *first_unused_memory)
158 {
159
160 CHAR *stack_pointer;
161 CHAR *memory_pointer;
162 UINT status;
163 UX_SLAVE_CLASS_DPUMP_PARAMETER parameter;
164
165
166 UX_PARAMETER_NOT_USED(first_unused_memory);
167
168 /* Initialize the free memory pointer. */
169 stack_pointer = (CHAR *) ux_demo_memory_buffer;
170 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
171
172 /* Initialize USBX Memory. */
173 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0);
174
175 /* Check for error. */
176 if (status != UX_SUCCESS)
177 error_handler();
178
179 /* The code below is required for installing the host portion of USBX. */
180 status = ux_host_stack_initialize(UX_NULL);
181
182 /* Check for error. */
183 if (status != UX_SUCCESS)
184 error_handler();
185
186 /* Register all the host class drivers for this USBX implementation. */
187 status = ux_host_stack_class_register(_ux_system_host_class_dpump_name, ux_host_class_dpump_entry);
188
189 /* Check for error. */
190 if (status != UX_SUCCESS)
191 error_handler();
192
193 /* Register all the USB host controllers available in this system */
194 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
195
196 /* Check for error. */
197 if (status != UX_SUCCESS)
198 error_handler();
199
200 /* The code below is required for installing the device portion of USBX */
201 status = _ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
202 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
203 string_framework, STRING_FRAMEWORK_LENGTH,
204 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL);
205
206 /* Check for error. */
207 if (status != UX_SUCCESS)
208 error_handler();
209
210 /* Set the parameters for callback when insertion/extraction of a Data Pump device. */
211 parameter.ux_slave_class_dpump_instance_activate = tx_demo_instance_activate;
212 parameter.ux_slave_class_dpump_instance_deactivate = tx_demo_instance_deactivate;
213
214 /* Initialize the device dpump class. The class is connected with interface 0 */
215 status = _ux_device_stack_class_register(_ux_system_slave_class_dpump_name, _ux_device_class_dpump_entry,
216 1, 0, ¶meter);
217
218 /* Check for error. */
219 if (status != UX_SUCCESS)
220 error_handler();
221
222 /* Initialize the simulated device controller. */
223 status = _ux_dcd_sim_slave_initialize();
224
225 /* Check for error. */
226 if (status != UX_SUCCESS)
227 error_handler();
228
229 /* Create the main host simulation thread. */
230 status = tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
231 stack_pointer, UX_DEMO_STACK_SIZE,
232 20, 20, 1, TX_AUTO_START);
233
234 /* Check for error. */
235 if (status != TX_SUCCESS)
236 error_handler();
237
238 /* Create the main demo thread. */
239 status = tx_thread_create(&tx_demo_thread_device_simulation, "tx demo slave simulation", tx_demo_thread_device_simulation_entry, 0,
240 stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
241 20, 20, 1, TX_AUTO_START);
242
243 /* Check for error. */
244 if (status != TX_SUCCESS)
245 error_handler();
246 }
247
248
tx_demo_thread_host_simulation_entry(ULONG arg)249 void tx_demo_thread_host_simulation_entry(ULONG arg)
250 {
251
252 UINT status;
253 ULONG actual_length;
254 UCHAR current_char;
255 UX_HOST_CLASS *class;
256
257
258 UX_PARAMETER_NOT_USED(arg);
259
260 /* Find the main data pump container. */
261 status = ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class);
262
263 /* Check for error. */
264 if (status != UX_SUCCESS)
265 error_handler();
266
267 /* We get the first instance of the data pump device. */
268 do
269 {
270
271 status = ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump);
272 tx_thread_relinquish();
273 } while (status != UX_SUCCESS);
274
275 /* We still need to wait for the data pump status to be live. */
276 while (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE)
277 {
278
279 tx_thread_relinquish();
280 }
281
282 /* At this point, the data pump class has been found. Now use the
283 data pump to send and receive data between the host and device. */
284
285 /* We start with a 'A' in buffer. */
286 current_char = 'A';
287
288 while(1)
289 {
290
291 /* Increment thread counter. */
292 thread_0_counter++;
293
294 /* Initialize the write buffer. */
295 _ux_utility_memory_set(host_out_buffer, current_char, UX_HOST_CLASS_DPUMP_PACKET_SIZE); /* Use case of memset is verified. */
296
297 /* Increment the character in buffer. */
298 current_char++;
299
300 /* Check for upper alphabet limit. */
301 if (current_char > 'Z')
302 current_char = 'A';
303
304 /* Write to the host Data Pump Bulk out endpoint. */
305 status = _ux_host_class_dpump_write (dpump, host_out_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length);
306
307 /* Check for error. */
308 if (status != UX_SUCCESS)
309 error_handler();
310
311 /* Verify that the status and the amount of data is correct. */
312 if ((status != UX_SUCCESS) || actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE)
313 return;
314
315 /* Read to the Data Pump Bulk out endpoint. */
316 status = _ux_host_class_dpump_read (dpump, host_in_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length);
317
318 /* Verify that the status and the amount of data is correct. */
319 if ((status != UX_SUCCESS) || actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE)
320 error_handler();
321
322 /* Relinquish to other thread. */
323 tx_thread_relinquish();
324 }
325 }
326
327
tx_demo_thread_device_simulation_entry(ULONG arg)328 void tx_demo_thread_device_simulation_entry(ULONG arg)
329 {
330
331 UINT status;
332 ULONG actual_length;
333
334
335 UX_PARAMETER_NOT_USED(arg);
336
337 while(1)
338 {
339
340 /* Ensure the dpump class on the device is still alive. */
341 while (dpump_device != UX_NULL)
342 {
343
344 /* Increment thread counter. */
345 thread_1_counter++;
346
347 /* Read from the device data pump. */
348 status = _ux_device_class_dpump_read(dpump_device, device_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length);
349
350 /* Verify that the status and the amount of data is correct. */
351 if ((status != UX_SUCCESS) || actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE)
352 error_handler();
353
354 /* Now write to the device data pump. */
355 status = _ux_device_class_dpump_write(dpump_device, device_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length);
356
357 /* Verify that the status and the amount of data is correct. */
358 if ((status != UX_SUCCESS) || actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE)
359 error_handler();
360 }
361
362 /* Relinquish to other thread. */
363 tx_thread_relinquish();
364 }
365 }
366
tx_demo_instance_activate(VOID * dpump_instance)367 VOID tx_demo_instance_activate(VOID *dpump_instance)
368 {
369
370 /* Save the DPUMP instance. */
371 dpump_device = (UX_SLAVE_CLASS_DPUMP *) dpump_instance;
372 }
373
tx_demo_instance_deactivate(VOID * dpump_instance)374 VOID tx_demo_instance_deactivate(VOID *dpump_instance)
375 {
376
377 UX_PARAMETER_NOT_USED(dpump_instance);
378
379 /* Reset the DPUMP instance. */
380 dpump_device = UX_NULL;
381 }
382
383
error_handler(void)384 VOID error_handler(void)
385 {
386
387 /* Increment error counter. */
388 error_counter++;
389
390 while(1)
391 {
392
393 /* Error - just spin here! Look at call tree in debugger
394 to see where the error occurred. */
395 }
396 }
397
398