1 /* This test is designed to test the simple dpump host/device class operation. */
2
3 #include <stdio.h>
4 #include "tx_api.h"
5 #include "ux_api.h"
6 #include "ux_system.h"
7 #include "ux_utility.h"
8 #include "ux_host_class_hid.h"
9 #include "ux_host_class_hid_keyboard.h"
10 #include "ux_device_class_hid.h"
11 #include "ux_device_stack.h"
12 #include "ux_test_utility_sim.h"
13 #include "ux_test_hcd_sim_host.h"
14
15 /* Define constants. */
16 #define UX_DEMO_DEBUG_SIZE (4096*8)
17 #define UX_DEMO_STACK_SIZE 1024
18 #define UX_DEMO_BUFFER_SIZE 2048
19 #define UX_DEMO_RECEPTION_BUFFER_SIZE 512
20 #define UX_DEMO_XMIT_BUFFER_SIZE 512
21 #define UX_DEMO_RECEPTION_BLOCK_SIZE 64
22 #define UX_DEMO_MEMORY_SIZE (64*1024)
23
24 /* Define local/extern function prototypes. */
25 static void demo_thread_entry(ULONG);
26 static UINT demo_thread_hid_callback(UX_SLAVE_CLASS_HID *, UX_SLAVE_CLASS_HID_EVENT *);
27 static TX_THREAD tx_demo_thread_host_simulation;
28 static TX_THREAD tx_demo_thread_slave_simulation;
29 static void tx_demo_thread_host_simulation_entry(ULONG);
30 static void tx_demo_thread_slave_simulation_entry(ULONG);
31
32
33 /* Define global data structures. */
34 static UCHAR usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
35 static ULONG error_counter;
36 static TX_THREAD demo_thread;
37 static UX_HOST_CLASS *class_driver;
38 static ULONG class_driver_index;
39 static UX_HOST_CLASS_HID *hid;
40 static UX_HOST_CLASS_HID_CLIENT *hid_client;
41 static UX_HOST_CLASS_HID_KEYBOARD *keyboard;
42 static UINT status;
43 static UINT transfer_completed;
44 static ULONG requested_length;
45 static TX_SEMAPHORE demo_semaphore;
46
47 static ULONG keyboard_char;
48 static ULONG keyboard_state;
49 static UCHAR keyboard_queue[1024];
50 static ULONG keyboard_queue_index;
51
52 static UX_SLAVE_CLASS_HID_PARAMETER hid_parameter;
53
54 static UCHAR hid_keyboard_report[] = {
55
56 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
57 0x09, 0x06, // USAGE (Keyboard)
58 0xa1, 0x01, // COLLECTION (Application)
59 /* Modifier keys. */
60 0x05, 0x07, // USAGE_PAGE (Keyboard)
61 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
62 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
63 0x15, 0x00, // LOGICAL_MINIMUM (0)
64 0x25, 0x01, // LOGICAL_MAXIMUM (1)
65 0x75, 0x01, // REPORT_SIZE (1)
66 0x95, 0x08, // REPORT_COUNT (8)
67 0x81, 0x02, // INPUT (Data,Var,Abs)
68 /* Padding. */
69 0x95, 0x01, // REPORT_COUNT (1)
70 0x75, 0x08, // REPORT_SIZE (8)
71 0x81, 0x03, // INPUT (Cnst,Var,Abs)
72 /* LEDs. */
73 0x95, 0x05, // REPORT_COUNT (5)
74 0x75, 0x01, // REPORT_SIZE (1)
75 0x05, 0x08, // USAGE_PAGE (LEDs)
76 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
77 0x29, 0x05, // USAGE_MAXIMUM (Kana)
78 0x91, 0x02, // OUTPUT (Data,Var,Abs)
79 /* Padding. */
80 0x95, 0x01, // REPORT_COUNT (1)
81 0x75, 0x03, // REPORT_SIZE (3)
82 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
83 /* Keys. */
84 0x95, 0x06, // REPORT_COUNT (6)
85 0x75, 0x08, // REPORT_SIZE (8)
86 0x15, 0x00, // LOGICAL_MINIMUM (0)
87 0x25, 0x65, // LOGICAL_MAXIMUM (101)
88 0x05, 0x07, // USAGE_PAGE (Keyboard)
89 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
90 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
91 0x81, 0x00, // INPUT (Data,Ary,Abs)
92 0xc0, // END_COLLECTION
93
94 0xa1, 0x01, // COLLECTION (Application)
95 0x19, 0x01, // USAGE_MINIMUM (1)
96 0x29, 0x04, // USAGE_MAXIMUM (4)
97 0x75, 0x04, // REPORT_SIZE (4)
98 0x95, 0x04, // REPORT_COUNT (4)
99 0xb1, 0x02, // FEATURE (Data,Var,Abs)
100 0x85, 0x02, // REPORT_ID (2)
101 0x19, 0x05, // USAGE_MINIMUM (5)
102 0x29, 0x07, // USAGE_MAXIMUM (7)
103 0x75, 0x08, // REPORT_SIZE (8)
104 0x95, 0x03, // REPORT_COUNT (3)
105 0xb1, 0x02, // FEATURE (Data,Var,Abs)
106 0x85, 0x04, // REPORT_ID (4)
107 0x09, 0x08, // USAGE (8)
108 0x75, 0x10, // REPORT_SIZE (16)
109 0x95, 0x01, // REPORT_COUNT (1)
110 0xb1, 0x02, // FEATURE (Data,Var,Abs)
111 0xc0, // END_COLLECTION
112
113 };
114 #define HID_KEYBOARD_REPORT_LENGTH (sizeof(hid_keyboard_report)/sizeof(hid_keyboard_report[0]))
115
116
117 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
118 static UCHAR device_framework_full_speed[] = {
119
120 /* Device descriptor */
121 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
122 0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x01,
124
125 /* Configuration descriptor */
126 0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
127 0x32,
128
129 /* Interface descriptor */
130 0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
131 0x00,
132
133 /* HID descriptor */
134 0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, HID_KEYBOARD_REPORT_LENGTH,
135 0x00,
136
137 /* Endpoint descriptor (Interrupt) */
138 0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
139
140 };
141
142
143 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
144 static UCHAR device_framework_high_speed[] = {
145
146 /* Device descriptor */
147 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
148 0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
149 0x03, 0x01,
150
151 /* Device qualifier descriptor */
152 0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
153 0x01, 0x00,
154
155 /* Configuration descriptor */
156 0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
157 0x32,
158
159 /* Interface descriptor */
160 0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
161 0x00,
162
163 /* HID descriptor */
164 0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, HID_KEYBOARD_REPORT_LENGTH,
165 0x00,
166
167 /* Endpoint descriptor (Interrupt) */
168 0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
169
170 };
171
172
173 /* String Device Framework :
174 Byte 0 and 1 : Word containing the language ID : 0x0904 for US
175 Byte 2 : Byte containing the index of the descriptor
176 Byte 3 : Byte containing the length of the descriptor string
177 */
178
179 #define STRING_FRAMEWORK_LENGTH 40
180 static UCHAR string_framework[] = {
181
182 /* Manufacturer string descriptor : Index 1 */
183 0x09, 0x04, 0x01, 0x0c,
184 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
185 0x6f, 0x67, 0x69, 0x63,
186
187 /* Product string descriptor : Index 2 */
188 0x09, 0x04, 0x02, 0x0c,
189 0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
190 0x6f, 0x61, 0x72, 0x64,
191
192 /* Serial Number string descriptor : Index 3 */
193 0x09, 0x04, 0x03, 0x04,
194 0x30, 0x30, 0x30, 0x31
195 };
196
197
198 /* Multiple languages are supported on the device, to add
199 a language besides english, the unicode language code must
200 be appended to the language_id_framework array and the length
201 adjusted accordingly. */
202 #define LANGUAGE_ID_FRAMEWORK_LENGTH 2
203 static UCHAR language_id_framework[] = {
204
205 /* English. */
206 0x09, 0x04
207 };
208
209 /* Define the ISR dispatch. */
210
211 extern VOID (*test_isr_dispatch)(void);
212
213
214 /* Prototype for test control return. */
215
216 void test_control_return(UINT status);
217
218
219 /* Define the ISR dispatch routine. */
220
test_isr(void)221 static void test_isr(void)
222 {
223
224 /* For further expansion of interrupt-level testing. */
225 }
226
227 /* Define what the initial system looks like. */
228
229 #ifdef CTEST
test_application_define(void * first_unused_memory)230 void test_application_define(void *first_unused_memory)
231 #else
232 void usbx_hid_keyboard_basic_test_application_define(void *first_unused_memory)
233 #endif
234 {
235
236 UINT status;
237 CHAR * stack_pointer;
238 CHAR * memory_pointer;
239
240 /* Inform user. */
241 printf("Running HID Keyboard Basic Functionality Test....................... ");
242
243 /* Initialize the free memory pointer */
244 stack_pointer = (CHAR *) usbx_memory;
245 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
246
247 /* Initialize USBX. Memory */
248 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
249
250 /* Check for error. */
251 if (status != UX_SUCCESS)
252 {
253
254 printf("ERROR #1\n");
255 test_control_return(1);
256 }
257
258 /* Register the error callback. */
259 ux_utility_error_callback_register(ux_test_error_callback);
260
261 /* The code below is required for installing the host portion of USBX */
262 status = ux_host_stack_initialize(UX_NULL);
263 if (status != UX_SUCCESS)
264 {
265
266 printf("ERROR #2\n");
267 test_control_return(1);
268 }
269
270 status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
271 if (status != UX_SUCCESS)
272 {
273
274 printf("ERROR #3\n");
275 test_control_return(1);
276 }
277
278 /* Register the HID client(s). */
279 status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
280 if (status != UX_SUCCESS)
281 {
282
283 printf("ERROR #4\n");
284 test_control_return(1);
285 }
286
287 /* The code below is required for installing the device portion of USBX. No call back for
288 device status change in this example. */
289 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
290 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
291 string_framework, STRING_FRAMEWORK_LENGTH,
292 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
293 if(status!=UX_SUCCESS)
294 {
295
296 printf("ERROR #6\n");
297 test_control_return(1);
298 }
299
300 /* Initialize the hid class parameters for a keyboard. */
301 hid_parameter.ux_device_class_hid_parameter_report_address = hid_keyboard_report;
302 hid_parameter.ux_device_class_hid_parameter_report_length = HID_KEYBOARD_REPORT_LENGTH;
303 hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
304
305 /* Initilize the device hid class. The class is connected with interface 2 */
306 status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
307 1,2, (VOID *)&hid_parameter);
308 if(status!=UX_SUCCESS)
309 {
310
311 printf("ERROR #7\n");
312 test_control_return(1);
313 }
314
315
316 /* Initialize the simulated device controller. */
317 status = _ux_dcd_sim_slave_initialize();
318
319 /* Check for error. */
320 if (status != UX_SUCCESS)
321 {
322
323 printf("ERROR #8\n");
324 test_control_return(1);
325 }
326
327 /* Register all the USB host controllers available in this system */
328 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
329
330 /* Check for error. */
331 if (status != UX_SUCCESS)
332 {
333
334 printf("ERROR #5\n");
335 test_control_return(1);
336 }
337
338 /* Create the main host simulation thread. */
339 status = tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
340 stack_pointer, UX_DEMO_STACK_SIZE,
341 20, 20, 1, TX_AUTO_START);
342
343 /* Check for error. */
344 if (status != TX_SUCCESS)
345 {
346
347 printf("ERROR #9\n");
348 test_control_return(1);
349 }
350
351 /* Create the main demo thread. */
352 status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
353 stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
354 20, 20, 1, TX_AUTO_START);
355
356 /* Check for error. */
357 if (status != TX_SUCCESS)
358 {
359
360 printf("ERROR #10\n");
361 test_control_return(1);
362 }
363
364 }
365
demo_class_hid_connect_wait(ULONG nb_loop)366 static UINT demo_class_hid_connect_wait(ULONG nb_loop)
367 {
368
369 UINT status;
370 UX_HOST_CLASS *class;
371
372 /* Find the main HID container */
373 status = ux_host_stack_class_get(_ux_system_host_class_hid_name, &class);
374 if (status != UX_SUCCESS)
375 return(status);
376
377 /* We get the first instance of the hid device */
378 do
379 {
380
381 status = ux_host_stack_class_instance_get(class, 0, (void **) &hid);
382 if (status == UX_SUCCESS && hid -> ux_host_class_hid_state == UX_HOST_CLASS_INSTANCE_LIVE)
383 return(UX_SUCCESS);
384 _ux_utility_delay_ms(10);
385 } while (nb_loop --);
386
387 return(UX_ERROR);
388 }
389
demo_class_hid_disconnect_wait(ULONG nb_loop)390 static UINT demo_class_hid_disconnect_wait(ULONG nb_loop)
391 {
392
393 UINT status;
394 UX_HOST_CLASS *class;
395
396 /* Find the main HID container */
397 status = ux_host_stack_class_get(_ux_system_host_class_hid_name, &class);
398 if (status != UX_SUCCESS)
399 return(status);
400
401 /* We get the first instance of the hid device */
402 do {
403
404 status = ux_host_stack_class_instance_get(class, 0, (void **) &hid);
405 if (status != UX_SUCCESS)
406 return(UX_SUCCESS);
407 _ux_utility_delay_ms(10);
408 } while(nb_loop --);
409
410 return(UX_ERROR);
411 }
412
tx_demo_thread_host_simulation_entry(ULONG arg)413 static void tx_demo_thread_host_simulation_entry(ULONG arg)
414 {
415
416 UINT status;
417 UINT max_hid_loop;
418
419
420 /* Initilize max loop value. */
421 max_hid_loop = 16;
422
423 /* Find the HID class */
424 status = demo_class_hid_connect_wait(50);
425 if (status != UX_SUCCESS)
426 {
427
428 /* HID Keyboard basic test error. */
429 printf("ERROR #11\n");
430 test_control_return(1);
431 }
432
433 /* Get the HID client */
434 hid_client = hid -> ux_host_class_hid_client;
435
436 /* Get the keyboard instance */
437 keyboard = (UX_HOST_CLASS_HID_KEYBOARD *)hid_client -> ux_host_class_hid_client_local_instance;
438
439 /* Init the keyboard queue index. */
440 keyboard_queue_index = 0;
441
442 while (max_hid_loop--)
443 {
444 /* Get a key/state from the keyboard. */
445 status = ux_host_class_hid_keyboard_key_get(keyboard, &keyboard_char, &keyboard_state);
446
447 /* Check if there is something. */
448 if (status == UX_SUCCESS)
449 {
450 /* We have a character in the queue. */
451 keyboard_queue[keyboard_queue_index] = (UCHAR) keyboard_char;
452
453 /* Can we accept more ? */
454 if(keyboard_queue_index < 1024)
455 keyboard_queue_index++;
456
457 }
458
459 tx_thread_sleep(10);
460 }
461
462 /* Simulate disconnect. */
463 ux_test_hcd_sim_host_disconnect();
464 demo_class_hid_disconnect_wait(5);
465
466 /* Now disconnect the device. */
467 _ux_device_stack_disconnect();
468
469 /* And deinitialize the class. */
470 status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
471
472 /* Deinitialize the device side of usbx. */
473 _ux_device_stack_uninitialize();
474
475 /* And finally the usbx system resources. */
476 _ux_system_uninitialize();
477
478 /* Successful test. */
479 printf("SUCCESS!\n");
480 test_control_return(0);
481 }
482
demo_thread_hid_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)483 static UINT demo_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
484 {
485 return(UX_SUCCESS);
486 }
487
tx_demo_thread_slave_simulation_entry(ULONG arg)488 static void tx_demo_thread_slave_simulation_entry(ULONG arg)
489 {
490
491 UX_SLAVE_DEVICE *device;
492 UX_SLAVE_INTERFACE *interface;
493 UX_SLAVE_CLASS_HID *hid;
494 UX_SLAVE_CLASS_HID_EVENT hid_event;
495 UCHAR key;
496
497 /* Get the pointer to the device. */
498 device = &_ux_system_slave -> ux_system_slave_device;
499
500 /* Set the first key to 'a' which is 04. */
501 key = 0x04;
502
503 /* reset the HID event structure. */
504 ux_utility_memory_set(&hid_event, 0, sizeof(UX_SLAVE_CLASS_HID_EVENT));
505
506 while(1)
507 {
508
509 /* Is the device configured ? */
510 while (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
511 {
512 #if defined(UX_DEVICE_STANDALONE)
513 ux_system_tasks_run();
514 tx_thread_relinquish();
515 #else
516 /* Then wait. */
517 tx_thread_sleep(10);
518 #endif
519 }
520
521 /* Until the device stays configured. */
522 while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
523 {
524
525 /* Get the interface. We use the first interface, this is a simple device. */
526 interface = device -> ux_slave_device_first_interface;
527
528 /* Form that interface, derive the HID owner. */
529 hid = interface -> ux_slave_interface_class_instance;
530
531 #if defined(UX_DEVICE_STANDALONE)
532 ULONG tick_to_wait = UX_MS_TO_TICK(2000);
533 ULONG tick_start = _ux_utility_time_get();
534 while(_ux_utility_time_elapsed(tick_start, _ux_utility_time_get()) < tick_to_wait)
535 {
536 ux_system_tasks_run();
537 tx_thread_relinquish();
538 }
539 #else
540 /* Wait for 2 seconds. */
541 ux_utility_thread_sleep(UX_MS_TO_TICK(2000));
542 #endif
543
544 /* Then insert a key into the keyboard event. Length is fixed to 8. */
545 hid_event.ux_device_class_hid_event_length = 8;
546
547 /* First byte is a modifier byte. */
548 hid_event.ux_device_class_hid_event_buffer[0] = 0;
549
550 /* Second byte is reserved. */
551 hid_event.ux_device_class_hid_event_buffer[1] = 0;
552
553 /* The 6 next bytes are keys. We only have one key here. */
554 hid_event.ux_device_class_hid_event_buffer[2] = key;
555
556 /* Set the keyboard event. */
557 ux_device_class_hid_event_set(hid, &hid_event);
558
559 /* Next event has the key depressed. */
560 hid_event.ux_device_class_hid_event_buffer[2] = 0;
561
562 /* Length is fixed to 8. */
563 hid_event.ux_device_class_hid_event_length = 8;
564
565 /* Set the keyboard event. */
566 ux_device_class_hid_event_set(hid, &hid_event);
567
568 /* Are we at the end of alphabet ? */
569 if (key != (0x04 + 26))
570
571 /* Next key. */
572 key++;
573
574 else
575
576 /* Start over again. */
577 key = 0x04;
578
579 }
580 }
581 }
582
583