1 #include "usbx_test_common_hid.h"
2 #include "ux_host_class_hid_keyboard.h"
3 
4 #include "ux_test_utility_sim.h"
5 
6 #define DUMMY_USBX_MEMORY_SIZE (64*1024)
7 static UCHAR dummy_usbx_memory[DUMMY_USBX_MEMORY_SIZE];
8 
9 static UCHAR hid_report_descriptor[] = {
10 
11     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
12     0x09, 0x06,                    // USAGE (Keyboard)
13     0xa1, 0x01,                    // COLLECTION (Application)
14     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
15     0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
16     0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
17     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
18     0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
19     0x75, 0x01,                    //   REPORT_SIZE (1)
20     0x95, 0x08,                    //   REPORT_COUNT (8)
21     0x81, 0x02,                    //   INPUT (Data,Var,Abs)
22     0x95, 0x01,                    //   REPORT_COUNT (1)
23     0x75, 0x08,                    //   REPORT_SIZE (8)
24     0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
25     0x95, 0x05,                    //   REPORT_COUNT (5)
26     0x75, 0x01,                    //   REPORT_SIZE (1)
27     0x05, 0x08,                    //   USAGE_PAGE (LEDs)
28     0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
29     0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
30     0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
31     0x95, 0x01,                    //   REPORT_COUNT (1)
32     0x75, 0x03,                    //   REPORT_SIZE (3)
33     0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)
34     0x95, 0x06,                    //   REPORT_COUNT (6)
35     0x75, 0x08,                    //   REPORT_SIZE (8)
36     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
37     0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
38     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
39     0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
40     0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
41     0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
42     0xc0                           // END_COLLECTION
43 };
44 #define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
45 
46 
47 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
48 static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
49 
50     /* Device descriptor */
51         0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
52         0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
53         0x00, 0x01,
54 
55     /* Configuration descriptor */
56         0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
57         0x32,
58 
59     /* Interface descriptor */
60         0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
61         0x00,
62 
63     /* HID descriptor */
64         0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
65         MSB(HID_REPORT_LENGTH),
66 
67     /* Endpoint descriptor (Interrupt) */
68         0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
69 
70     };
71 
72 
73 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
74 static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
75 
76     /* Device descriptor */
77         0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
78         0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
79         0x03, 0x01,
80 
81     /* Device qualifier descriptor */
82         0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
83         0x01, 0x00,
84 
85     /* Configuration descriptor */
86         0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
87         0x32,
88 
89     /* Interface descriptor */
90         0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
91         0x00,
92 
93     /* HID descriptor */
94         0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
95         MSB(HID_REPORT_LENGTH),
96 
97     /* Endpoint descriptor (Interrupt) */
98         0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
99 
100     };
101 
102 
103     /* String Device Framework :
104      Byte 0 and 1 : Word containing the language ID : 0x0904 for US
105      Byte 2       : Byte containing the index of the descriptor
106      Byte 3       : Byte containing the length of the descriptor string
107     */
108 
109 #define STRING_FRAMEWORK_LENGTH 40
110 static UCHAR string_framework[] = {
111 
112     /* Manufacturer string descriptor : Index 1 */
113         0x09, 0x04, 0x01, 0x0c,
114         0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
115         0x6f, 0x67, 0x69, 0x63,
116 
117     /* Product string descriptor : Index 2 */
118         0x09, 0x04, 0x02, 0x0c,
119         0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
120         0x6f, 0x61, 0x72, 0x64,
121 
122     /* Serial Number string descriptor : Index 3 */
123         0x09, 0x04, 0x03, 0x04,
124         0x30, 0x30, 0x30, 0x31
125     };
126 
127 
128     /* Multiple languages are supported on the device, to add
129        a language besides english, the unicode language code must
130        be appended to the language_id_framework array and the length
131        adjusted accordingly. */
132 #define LANGUAGE_ID_FRAMEWORK_LENGTH 2
133 static UCHAR language_id_framework[] = {
134 
135     /* English. */
136         0x09, 0x04
137     };
138 
139 
140 UINT  _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
141 
142 
ux_system_host_change_function(ULONG a,UX_HOST_CLASS * b,VOID * c)143 static UINT ux_system_host_change_function(ULONG a, UX_HOST_CLASS *b, VOID *c)
144 {
145     return 0;
146 }
147 
148 
149 static UINT error_counts = 0;
150 static UINT last_error = UX_SUCCESS;
error_callback(UINT system_level,UINT system_context,UINT error_code)151 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
152 {
153     error_counts ++;
154     last_error = error_code;
155     if (error_code != UX_MEMORY_INSUFFICIENT &&
156         error_code != UX_TRANSFER_NOT_READY)
157     {
158 
159         /* Failed test.  */
160         printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
161         test_control_return(1);
162     }
163 }
164 
165 /* Define what the initial system looks like.  */
166 
167 #ifdef CTEST
test_application_define(void * first_unused_memory)168 void test_application_define(void *first_unused_memory)
169 #else
170 void    usbx_ux_host_class_hid_transfer_request_completed_test_application_define(void *first_unused_memory)
171 #endif
172 {
173 
174 UINT                            status;
175 CHAR *                          stack_pointer;
176 CHAR *                          memory_pointer;
177 
178 
179     /* Inform user.  */
180     printf("Running ux_host_class_hid_transfer_request_completed Test........... ");
181 
182     /* Initialize the free memory pointer */
183     stack_pointer = (CHAR *) usbx_memory;
184     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
185 
186     /* Initialize USBX. Memory */
187     status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
188 
189     /* Check for error.  */
190     if (status != UX_SUCCESS)
191     {
192 
193         printf("Error on line %d, error code: %d\n", __LINE__, status);
194         test_control_return(1);
195     }
196 
197     /* Register the error callback. */
198     _ux_utility_error_callback_register(error_callback);
199 
200     /* The code below is required for installing the host portion of USBX */
201     status =  ux_host_stack_initialize(ux_system_host_change_function);
202     if (status != UX_SUCCESS)
203     {
204 
205         printf("Error on line %d, error code: %d\n", __LINE__, status);
206         test_control_return(1);
207     }
208 
209     status =  ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
210     if (status != UX_SUCCESS)
211     {
212 
213         printf("Error on line %d, error code: %d\n", __LINE__, status);
214         test_control_return(1);
215     }
216 
217     /* Register the HID client(s).  */
218     status =  ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
219     if (status != UX_SUCCESS)
220     {
221 
222         printf("Error on line %d, error code: %d\n", __LINE__, status);
223         test_control_return(1);
224     }
225 
226     /* The code below is required for installing the device portion of USBX. No call back for
227        device status change in this example. */
228     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
229                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
230                                        string_framework, STRING_FRAMEWORK_LENGTH,
231                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
232     if(status!=UX_SUCCESS)
233     {
234 
235         printf("Error on line %d, error code: %d\n", __LINE__, status);
236         test_control_return(1);
237     }
238 
239     /* Initialize the hid class parameters.  */
240     hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
241     hid_parameter.ux_device_class_hid_parameter_report_length  = HID_REPORT_LENGTH;
242     hid_parameter.ux_device_class_hid_parameter_callback       = demo_thread_hid_callback;
243 
244     /* Initilize the device hid class. The class is connected with interface 2 */
245     status =  ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
246                                                 1,2, (VOID *)&hid_parameter);
247     if(status!=UX_SUCCESS)
248     {
249 
250         printf("Error on line %d, error code: %d\n", __LINE__, status);
251         test_control_return(1);
252     }
253 
254     /* Initialize the simulated device controller.  */
255     status =  _ux_dcd_sim_slave_initialize();
256 
257     /* Check for error.  */
258     if (status != UX_SUCCESS)
259     {
260 
261         printf("Error on line %d, error code: %d\n", __LINE__, status);
262         test_control_return(1);
263     }
264 
265     /* Register all the USB host controllers available in this system */
266     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
267 
268     /* Check for error.  */
269     if (status != UX_SUCCESS)
270     {
271 
272         printf("Error on line %d, error code: %d\n", __LINE__, status);
273         test_control_return(1);
274     }
275 
276     /* Create the main host simulation thread.  */
277     status =  tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
278             stack_pointer, UX_DEMO_STACK_SIZE,
279             20, 20, 1, TX_AUTO_START);
280 
281     /* Check for error.  */
282     if (status != TX_SUCCESS)
283     {
284 
285         printf("Error on line %d, error code: %d\n", __LINE__, status);
286         test_control_return(1);
287     }
288 
289     /* Create the main demo thread.  */
290     status =  tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
291             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
292             20, 20, 1, TX_AUTO_START);
293 
294     /* Check for error.  */
295     if (status != TX_SUCCESS)
296     {
297 
298         printf("Error on line %d, error code: %d\n", __LINE__, status);
299         test_control_return(1);
300     }
301 }
302 
tx_demo_thread_host_simulation_entry(ULONG arg)303 static void  tx_demo_thread_host_simulation_entry(ULONG arg)
304 {
305 
306 UINT                            status;
307 ALIGN_TYPE                      tmp;
308 UX_TRANSFER                     transfer_request;
309 UX_DEVICE                       device;
310 UX_ENDPOINT                     endpoint;
311 UX_HOST_CLASS_HID_KEYBOARD     *keyboard;
312 
313     /* Find the HID class */
314     status = demo_class_hid_get();
315     if (status != UX_SUCCESS)
316     {
317 
318         printf("Error on line %d, error code: %d\n", __LINE__, status);
319         test_control_return(1);
320     }
321 
322     /* Get the HID client */
323     hid_client = hid -> ux_host_class_hid_client;
324 
325     /* Check if the instance of the keyboard is live */
326     while (hid_client -> ux_host_class_hid_client_local_instance == UX_NULL)
327         tx_thread_sleep(10);
328 
329     /* Get the keyboard instance */
330     keyboard =  (UX_HOST_CLASS_HID_KEYBOARD *)hid_client -> ux_host_class_hid_client_local_instance;
331 
332     /**************************************************/
333     /** Test case: Template for making ux_utility_memory_allocate() fail **/
334     /**************************************************/
335 
336     device.ux_device_state = UX_DEVICE_RESET;
337     endpoint.ux_endpoint_device = &device;
338     transfer_request.ux_transfer_request_endpoint = &endpoint;
339     transfer_request.ux_transfer_request_class_instance = hid;
340     transfer_request.ux_transfer_request_completion_code = UX_SUCCESS;
341 
342     ux_test_utility_sim_mem_alloc_fail_all_start();
343 
344     _ux_host_class_hid_transfer_request_completed(&transfer_request);
345 
346     /* Restore state for next test. */
347     ux_test_utility_sim_mem_alloc_fail_all_stop();
348 
349     /**************************************************/
350     /** Test case: if (hid_report -> ux_host_class_hid_report_callback_function != UX_NULL) fails **/
351     /**************************************************/
352 
353     tmp = (ALIGN_TYPE)hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_input_report -> ux_host_class_hid_report_callback_function;
354     hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_input_report -> ux_host_class_hid_report_callback_function = UX_NULL;
355 
356     /* Wait for transfer_completed() to run. */
357     tx_thread_sleep(50);
358 
359     /* Restore state for next test. */
360     hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_input_report -> ux_host_class_hid_report_callback_function = (VOID (*) (struct UX_HOST_CLASS_HID_REPORT_CALLBACK_STRUCT *))tmp;
361 
362     /**************************************************/
363     /** Test case: (hid_report->ux_host_class_hid_report_number_item * 8) overflow **/
364     /**************************************************/
365 
366     tmp = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_input_report -> ux_host_class_hid_report_number_item;
367 
368     last_error = UX_SUCCESS;
369     hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_input_report -> ux_host_class_hid_report_number_item = 0xFFFFFFFF;
370 
371     /* Wait for transfer_completed() to run. */
372     tx_thread_sleep(50);
373 
374     if (last_error != UX_MEMORY_INSUFFICIENT)
375     {
376         printf("Error on line %d, expect error code: %d\n", __LINE__, last_error);
377         test_control_return(1);
378     }
379 
380     /* Restore state for next test. */
381     hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_input_report -> ux_host_class_hid_report_number_item = (ULONG)tmp;
382 
383     /* Now disconnect the device.  */
384     _ux_device_stack_disconnect();
385 
386     /* And deinitialize the class.  */
387     status =  ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
388 
389     /* Deinitialize the device side of usbx.  */
390     _ux_device_stack_uninitialize();
391 
392     /* And finally the usbx system resources.  */
393     _ux_system_uninitialize();
394 
395     /* Successful test.  */
396     printf("SUCCESS!\n");
397     test_control_return(0);
398 }
399 
tx_demo_thread_slave_simulation_entry(ULONG arg)400 static void  tx_demo_thread_slave_simulation_entry(ULONG arg)
401 {
402 
403 UX_SLAVE_DEVICE                 *device;
404 UX_SLAVE_INTERFACE              *interface;
405 UX_SLAVE_CLASS_HID              *hid;
406 UX_SLAVE_CLASS_HID_EVENT        hid_event;
407 UCHAR                           key;
408 
409     /* Get the pointer to the device.  */
410     device =  &_ux_system_slave -> ux_system_slave_device;
411 
412     /* Set the first key to 'a' which is 04.  */
413     key = 0x04;
414 
415     /* reset the HID event structure.  */
416     ux_utility_memory_set(&hid_event, 0, sizeof(UX_SLAVE_CLASS_HID_EVENT));
417 
418     while(1)
419     {
420 
421         /* Is the device configured ? */
422         while (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
423 
424             /* Then wait.  */
425             tx_thread_sleep(10);
426 
427         /* Until the device stays configured.  */
428         while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
429         {
430 
431             /* Get the interface.  We use the first interface, this is a simple device.  */
432             interface =  device -> ux_slave_device_first_interface;
433 
434             /* Form that interface, derive the HID owner.  */
435             hid = interface -> ux_slave_interface_class_instance;
436 
437             /* Wait for 2 seconds. */
438             ux_utility_thread_sleep(20);
439 
440             /* Then insert a key into the keyboard event.  Length is fixed to 8.  */
441             hid_event.ux_device_class_hid_event_length = 8;
442 
443             /* First byte is a modifier byte.  */
444             hid_event.ux_device_class_hid_event_buffer[0] = 0;
445 
446             /* Second byte is reserved. */
447             hid_event.ux_device_class_hid_event_buffer[1] = 0;
448 
449             /* The 6 next bytes are keys. We only have one key here.  */
450             hid_event.ux_device_class_hid_event_buffer[2] = key;
451 
452             /* Set the keyboard event.  */
453             ux_device_class_hid_event_set(hid, &hid_event);
454 
455             /* Next event has the key depressed.  */
456             hid_event.ux_device_class_hid_event_buffer[2] = 0;
457 
458             /* Length is fixed to 8.  */
459             hid_event.ux_device_class_hid_event_length = 8;
460 
461             /* Set the keyboard event.  */
462             ux_device_class_hid_event_set(hid, &hid_event);
463 
464             /* Are we at the end of alphabet ?  */
465             if (key != (0x04 + 26))
466 
467                 /* Next key.  */
468                 key++;
469 
470             else
471 
472                 /* Start over again.  */
473                 key = 0x04;
474 
475         }
476     }
477 }
478 
479 
demo_thread_hid_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)480 static UINT    demo_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
481 {
482     return(UX_SUCCESS);
483 }
484