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