1 /* This test concentrates on the ux_host_class_hid_report_set API. */
2 
3 #include "usbx_test_common_hid.h"
4 #include "ux_host_class_hid_keyboard.h"
5 
6 #include "ux_test_hcd_sim_host.h"
7 
8 UCHAR           buffer[64];
9 UINT            test_number;
10 UCHAR           buffer_device[64];
11 TX_SEMAPHORE    test_semaphore;
12 
13 #define DUMMY_USBX_MEMORY_SIZE (64*1024)
14 static UCHAR dummy_usbx_memory[DUMMY_USBX_MEMORY_SIZE];
15 
16 #define NUM_TESTS 5
17 UCHAR test_buffers[NUM_TESTS][5] = {
18     {0xab, 0xcd, 0xef, 0x01, 0x23},
19     {0x23, 0xab, 0xcd, 0xef, 0x01},
20     {0x01, 0x23, 0xab, 0xcd, 0xef},
21     {0xef, 0x01, 0x23, 0xab, 0xcd},
22     {0xcd, 0xef, 0x01, 0x23, 0xab},
23 };
24 
25 static UCHAR hid_report_descriptor[] = {
26 
27     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
28     0x09, 0x06,                    // USAGE (Keyboard)
29     0xa1, 0x01,                    // COLLECTION (Application)
30     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
31     0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
32     0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
33     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
34     0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
35     0x75, 0x01,                    //   REPORT_SIZE (1)
36     0x95, 0x08,                    //   REPORT_COUNT (8)
37     0x81, 0x02,                    //   INPUT (Data,Var,Abs)
38     0x95, 0x01,                    //   REPORT_COUNT (1)
39     0x75, 0x08,                    //   REPORT_SIZE (8)
40     0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
41     0x95, 0x05,                    //   REPORT_COUNT (5)
42     0x75, 0x01,                    //   REPORT_SIZE (1)
43     0x05, 0x08,                    //   USAGE_PAGE (LEDs)
44     0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
45     0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
46     0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
47     0x95, 0x01,                    //   REPORT_COUNT (1)
48     0x75, 0x03,                    //   REPORT_SIZE (3)
49     0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)
50     0x95, 0x06,                    //   REPORT_COUNT (6)
51     0x75, 0x08,                    //   REPORT_SIZE (8)
52     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
53     0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
54     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
55     0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
56     0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
57     0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
58 
59     0x85, 0x01,                    //   REPORT_ID (1)
60     0x95, 0x05,                    //   REPORT_COUNT (5)
61     0x75, 0x08,                    //   REPORT_SIZE (8)
62     0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)
63 
64     0xc0                           // END_COLLECTION
65 };
66 #define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
67 
68 
69 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
70 static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
71 
72     /* Device descriptor */
73         0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
74         0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
75         0x00, 0x01,
76 
77     /* Configuration descriptor */
78         0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
79         0x32,
80 
81     /* Interface descriptor */
82         0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
83         0x00,
84 
85     /* HID descriptor */
86         0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
87         MSB(HID_REPORT_LENGTH),
88 
89     /* Endpoint descriptor (Interrupt) */
90         0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
91 
92     };
93 
94 
95 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
96 static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
97 
98     /* Device descriptor */
99         0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
100         0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
101         0x03, 0x01,
102 
103     /* Device qualifier descriptor */
104         0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
105         0x01, 0x00,
106 
107     /* Configuration descriptor */
108         0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
109         0x32,
110 
111     /* Interface descriptor */
112         0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
113         0x00,
114 
115     /* HID descriptor */
116         0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
117         MSB(HID_REPORT_LENGTH),
118 
119     /* Endpoint descriptor (Interrupt) */
120         0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
121 
122     };
123 
124 
125     /* String Device Framework :
126      Byte 0 and 1 : Word containing the language ID : 0x0904 for US
127      Byte 2       : Byte containing the index of the descriptor
128      Byte 3       : Byte containing the length of the descriptor string
129     */
130 
131 #define STRING_FRAMEWORK_LENGTH 40
132 static UCHAR string_framework[] = {
133 
134     /* Manufacturer string descriptor : Index 1 */
135         0x09, 0x04, 0x01, 0x0c,
136         0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
137         0x6f, 0x67, 0x69, 0x63,
138 
139     /* Product string descriptor : Index 2 */
140         0x09, 0x04, 0x02, 0x0c,
141         0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
142         0x6f, 0x61, 0x72, 0x64,
143 
144     /* Serial Number string descriptor : Index 3 */
145         0x09, 0x04, 0x03, 0x04,
146         0x30, 0x30, 0x30, 0x31
147     };
148 
149 
150     /* Multiple languages are supported on the device, to add
151        a language besides english, the unicode language code must
152        be appended to the language_id_framework array and the length
153        adjusted accordingly. */
154 #define LANGUAGE_ID_FRAMEWORK_LENGTH 2
155 static UCHAR language_id_framework[] = {
156 
157     /* English. */
158         0x09, 0x04
159     };
160 
161 static UX_TEST_HCD_SIM_ACTION error_on_transfer_0[] = {
162 /* function, request to match,
163    port action, port status,
164    request action, request EP, request data, request actual length, request status,
165    status, additional callback,
166    no_return */
167 {   UX_HCD_TRANSFER_REQUEST, UX_NULL,
168         UX_FALSE, 0,
169         UX_TEST_SIM_REQ_ANSWER, 0, UX_NULL, 0, UX_ERROR,
170         UX_ERROR},
171 {   0   }
172 };
173 
174 static UX_TEST_HCD_SIM_ACTION zlp_on_transfer_0[] = {
175 /* function, request to match,
176    port action, port status,
177    request action, request EP, request data, request actual length, request status,
178    status, additional callback,
179    no_return */
180 {   UX_HCD_TRANSFER_REQUEST, UX_NULL,
181         UX_FALSE, 0,
182         UX_TEST_SIM_REQ_ANSWER, 0, UX_NULL, 0, UX_SUCCESS,
183         UX_SUCCESS},
184 {   0   }
185 };
186 
187 UINT  _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
188 
error_callback(UINT system_level,UINT system_context,UINT error_code)189 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
190 {
191 }
192 
193 /* Define what the initial system looks like.  */
194 
195 #ifdef CTEST
test_application_define(void * first_unused_memory)196 void test_application_define(void *first_unused_memory)
197 #else
198 void    usbx_ux_host_class_hid_report_set_test_application_define(void *first_unused_memory)
199 #endif
200 {
201 
202 UINT status;
203 CHAR *                          stack_pointer;
204 CHAR *                          memory_pointer;
205 UINT                            descriptor_size = HID_REPORT_LENGTH;
206 
207 
208     /* Inform user.  */
209     printf("Running ux_host_class_hid_report_set Test........................... ");
210 
211     /* Initialize the free memory pointer */
212     stack_pointer = (CHAR *) usbx_memory;
213     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
214 
215     /* Initialize USBX. Memory */
216     status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
217 
218     /* Check for error.  */
219     if (status != UX_SUCCESS)
220     {
221 
222         printf("Error on line %d\n", __LINE__);
223         test_control_return(1);
224     }
225 
226     /* Register the error callback. */
227     _ux_utility_error_callback_register(error_callback);
228 
229     /* The code below is required for installing the host portion of USBX */
230     status =  ux_host_stack_initialize(UX_NULL);
231     if (status != UX_SUCCESS)
232     {
233 
234         printf("Error on line %d\n", __LINE__);
235         test_control_return(1);
236     }
237 
238     status =  ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
239     if (status != UX_SUCCESS)
240     {
241 
242         printf("Error on line %d\n", __LINE__);
243         test_control_return(1);
244     }
245 
246     /* Register the HID client(s).  */
247     status =  ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
248     if (status != UX_SUCCESS)
249     {
250 
251         printf("Error on line %d, error code: %d\n", __LINE__, status);
252         test_control_return(1);
253     }
254 
255     /* The code below is required for installing the device portion of USBX. No call back for
256        device status change in this example. */
257     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
258                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
259                                        string_framework, STRING_FRAMEWORK_LENGTH,
260                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
261     if(status!=UX_SUCCESS)
262     {
263 
264         printf("Error on line %d\n", __LINE__);
265         test_control_return(1);
266     }
267 
268     /* Initialize the hid class parameters.  */
269     hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
270     hid_parameter.ux_device_class_hid_parameter_report_length  = HID_REPORT_LENGTH;
271     hid_parameter.ux_device_class_hid_parameter_callback       = demo_thread_hid_callback;
272 
273     /* Initilize the device hid class. The class is connected with interface 2 */
274     status =  ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
275                                                 1,2, (VOID *)&hid_parameter);
276     if(status!=UX_SUCCESS)
277     {
278 
279         printf("Error on line %d\n", __LINE__);
280         test_control_return(1);
281     }
282 
283 
284     /* Initialize the simulated device controller.  */
285     status =  _ux_dcd_sim_slave_initialize();
286 
287     /* Check for error.  */
288     if (status != UX_SUCCESS)
289     {
290 
291         printf("Error on line %d\n", __LINE__);
292         test_control_return(1);
293     }
294 
295     /* Register all the USB host controllers available in this system */
296     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
297 
298     /* Check for error.  */
299     if (status != UX_SUCCESS)
300     {
301 
302         printf("Error on line %d\n", __LINE__);
303         test_control_return(1);
304     }
305 
306     /* Create the main host simulation thread.  */
307     status =  tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
308             stack_pointer, UX_DEMO_STACK_SIZE,
309             20, 20, 1, TX_AUTO_START);
310 
311     /* Check for error.  */
312     if (status != TX_SUCCESS)
313     {
314 
315         printf("Error on line %d\n", __LINE__);
316         test_control_return(1);
317     }
318 }
319 
demo_thread_hid_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)320 static UINT demo_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
321 {
322 
323     if (event -> ux_device_class_hid_event_report_type == UX_DEVICE_CLASS_HID_REPORT_TYPE_OUTPUT)
324     {
325 
326         if (test_number > 0)
327         {
328 
329             /* Ensure report id is correct. */
330             if (event -> ux_device_class_hid_event_buffer[0] != 0x01)
331             {
332 
333                 printf("Error on line %d: test number %d, report id %d\n", __LINE__, test_number, event -> ux_device_class_hid_event_buffer[0]);
334                 test_control_return(1);
335             }
336 
337             if (ux_utility_memory_compare(test_buffers[test_number - 1], event->ux_device_class_hid_event_buffer + 1, 5) != UX_SUCCESS)
338             {
339 
340                 printf("Error on line %d: test number %d\n -", __LINE__, test_number);
341                 for (int i = 0; i < 5; i ++)
342                     printf(" %2x", test_buffers[test_number - 1][i]);
343                 printf(" <>\n -");
344                 for (int i = 0; i < 5; i ++)
345                     printf(" %2x", event->ux_device_class_hid_event_buffer[i + 1]);
346                 printf("\n");
347                 test_control_return(1);
348             }
349 
350             ux_utility_semaphore_put(&test_semaphore);
351         }
352     }
353 
354     return(UX_SUCCESS);
355 }
356 
tx_demo_thread_host_simulation_entry(ULONG arg)357 static void  tx_demo_thread_host_simulation_entry(ULONG arg)
358 {
359 
360 UINT                            status;
361 UX_HOST_CLASS_HID_CLIENT_REPORT client_report;
362 UX_HOST_CLASS_HID_REPORT        hid_report;
363 UX_HOST_CLASS_HID_REPORT       *hid_report_ptr;
364 ULONG                           tmp;
365 UX_MEMORY_BLOCK                *dummy_memory_block_first = (UX_MEMORY_BLOCK *)dummy_usbx_memory;
366 UX_MEMORY_BLOCK                *original_regular_memory_block = (UX_MEMORY_BLOCK *)_ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_start;
367 UX_MEMORY_BLOCK                *original_cache_safe_memory_block = (UX_MEMORY_BLOCK *)_ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_start;
368 UCHAR                           buffer[256];
369 
370 
371     status =  ux_utility_semaphore_create(&test_semaphore, "test_semaphore", 0);
372     if (status != UX_SUCCESS)
373     {
374 
375         printf("Error on line %d\n", __LINE__);
376         test_control_return(1);
377     }
378 
379     /* Find the HID class */
380     status = demo_class_hid_get();
381     if (status != UX_SUCCESS)
382     {
383 
384         printf("Error on line %d\n", __LINE__);
385         test_control_return(1);
386     }
387 
388     /**************************************************/
389     /** Test case: status =  _ux_utility_semaphore_get(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); fails **/
390     /**************************************************/
391 
392     client_report.ux_host_class_hid_client_report = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_output_report -> ux_host_class_hid_report_next_report;
393     client_report.ux_host_class_hid_client_report_flags = UX_HOST_CLASS_HID_REPORT_RAW;
394     client_report.ux_host_class_hid_client_report_length = 5;
395     client_report.ux_host_class_hid_client_report_buffer = (ULONG *)buffer;
396 
397     /* Make sure it fails. */
398     hid -> ux_host_class_hid_device -> ux_device_protection_semaphore.tx_semaphore_id++;
399 
400     status = _ux_host_class_hid_report_set(hid, &client_report);
401     if(status != TX_SEMAPHORE_ERROR)
402     {
403 
404         printf("Error on line %d, error code: %d\n", __LINE__, status);
405         test_control_return(1);
406     }
407 
408     /* Restore state. */
409     hid -> ux_host_class_hid_device -> ux_device_protection_semaphore.tx_semaphore_id--;
410 
411     /* The function did a get() on the hid semaphore and never put() it since we error'd out, so we must do it! */
412     status = ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore);
413     if (status != UX_SUCCESS)
414     {
415 
416         printf("Error on line %d, error code: %d\n", __LINE__, status);
417         test_control_return(1);
418     }
419 
420     /**************************************************/
421     /** Test case: status =  _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); fails **/
422     /**************************************************/
423 
424     client_report.ux_host_class_hid_client_report = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_output_report -> ux_host_class_hid_report_next_report;
425     client_report.ux_host_class_hid_client_report_flags = UX_HOST_CLASS_HID_REPORT_RAW;
426     client_report.ux_host_class_hid_client_report_length = 5;
427 
428     /* Make sure it fails. */
429     hid -> ux_host_class_hid_semaphore.tx_semaphore_id++;
430 
431     status = _ux_host_class_hid_report_set(hid, &client_report);
432     if(status != TX_SEMAPHORE_ERROR)
433     {
434 
435         printf("Error on line %d, error code: %d\n", __LINE__, status);
436         test_control_return(1);
437     }
438 
439     /* Restore state. */
440     hid -> ux_host_class_hid_semaphore.tx_semaphore_id--;
441 
442     /**************************************************/
443     /** Test case: Template for making ux_utility_memory_allocate() fail **/
444     /**************************************************/
445 
446     hid_report.ux_host_class_hid_report_type = UX_HOST_CLASS_HID_REPORT_TYPE_OUTPUT;
447     client_report.ux_host_class_hid_client_report = &hid_report;
448 
449     /* Set up the dummy memory block. */
450     dummy_memory_block_first -> ux_memory_block_next = UX_NULL;
451     dummy_memory_block_first -> ux_memory_byte_pool = UX_NULL;
452     // dummy_memory_block_first -> ux_memory_block_previous = UX_NULL;
453     // dummy_memory_block_first -> ux_memory_block_status = UX_MEMORY_UNUSED;
454     // dummy_memory_block_first -> ux_memory_block_size = 0;
455     _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_start = (UCHAR*)dummy_memory_block_first;
456     _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_start = (UCHAR*)dummy_memory_block_first;
457 
458     status = _ux_host_class_hid_report_set(hid, &client_report);
459     if (status != UX_MEMORY_INSUFFICIENT)
460     {
461 
462         printf("Error on line %d, error code: %d\n", __LINE__, status);
463         test_control_return(1);
464     }
465 
466     /* Restore state for next test. */
467     _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_start = (UCHAR*)original_regular_memory_block;
468     _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_start = (UCHAR*)original_cache_safe_memory_block;
469 
470     /**************************************************/
471     /** Test case: _ux_host_stack_class_instance_verify() fails. **/
472     /**************************************************/
473 
474     /* Make sure verify() doesn't find any classes. */
475     // tmp = _ux_system_host -> ux_system_host_max_class;
476     // _ux_system_host -> ux_system_host_max_class = 0;
477     tmp = _ux_system_host->ux_system_host_class_array->ux_host_class_status;
478     _ux_system_host->ux_system_host_class_array->ux_host_class_status = UX_UNUSED;
479 
480     if (_ux_host_class_hid_report_set(hid, UX_NULL) != UX_HOST_CLASS_INSTANCE_UNKNOWN)
481     {
482 
483         printf("Error on line %d\n", __LINE__);
484         test_control_return(1);
485     }
486 
487     /* Restore state for next test. */
488     // _ux_system_host -> ux_system_host_max_class = tmp;
489     _ux_system_host->ux_system_host_class_array->ux_host_class_status = (UINT)tmp;
490 
491     /**************************************************/
492     /** Test case: if (hid_report -> ux_host_class_hid_report_type == UX_HOST_CLASS_HID_REPORT_TYPE_INPUT) **/
493     /**************************************************/
494 
495     /* Set to an input report. */
496     hid_report.ux_host_class_hid_report_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
497 
498     client_report.ux_host_class_hid_client_report = &hid_report;
499 
500     if (_ux_host_class_hid_report_set(hid, &client_report) != UX_HOST_CLASS_HID_REPORT_ERROR)
501     {
502 
503         printf("Error on line %d\n", __LINE__);
504         test_control_return(1);
505     }
506 
507     /**************************************************/
508     /** Test case: if (hid_report -> ux_host_class_hid_report_byte_length < client_report -> ux_host_class_hid_client_report_length) **/
509     /**************************************************/
510 
511     /* Set client report length to less than hid report length. */
512     hid_report.ux_host_class_hid_report_type = UX_HOST_CLASS_HID_REPORT_TYPE_FEATURE;
513     hid_report.ux_host_class_hid_report_byte_length = 1;
514     client_report.ux_host_class_hid_client_report_length = hid_report.ux_host_class_hid_report_byte_length + 1;
515 
516     client_report.ux_host_class_hid_client_report = &hid_report;
517     client_report.ux_host_class_hid_client_report_flags = UX_HOST_CLASS_HID_REPORT_RAW;
518 
519     if (_ux_host_class_hid_report_set(hid, &client_report) != UX_HOST_CLASS_HID_REPORT_OVERFLOW)
520     {
521 
522         printf("Error on line %d\n", __LINE__);
523         test_control_return(1);
524     }
525 
526     /**************************************************/
527     /** Test case: call _ux_host_class_hid_report_compress(). **/
528     /**************************************************/
529 
530     hid_report_ptr = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_output_report;
531 
532     client_report.ux_host_class_hid_client_report = hid_report_ptr;
533     client_report.ux_host_class_hid_client_report_length = hid_report_ptr -> ux_host_class_hid_report_byte_length;
534     client_report.ux_host_class_hid_client_report_buffer = (ULONG *)buffer;
535     client_report.ux_host_class_hid_client_report_flags = UX_HOST_CLASS_HID_REPORT_DECOMPRESSED;
536 
537     if (_ux_host_class_hid_report_set(hid, &client_report) != UX_SUCCESS)
538     {
539 
540         printf("Error on line %d\n", __LINE__);
541         test_control_return(1);
542     }
543 
544     /**************************************************/
545     /** Test case: ux_host_stack_transfer_request() fails. **/
546     /**************************************************/
547 
548     ux_test_hcd_sim_host_set_actions(error_on_transfer_0);
549 
550     if (_ux_host_class_hid_report_set(hid, &client_report) != UX_HOST_CLASS_HID_REPORT_ERROR)
551     {
552 
553         printf("Error on line %d\n", __LINE__);
554         test_control_return(1);
555     }
556 
557     /** Restore state for next test. **/
558 
559     /* ux_host_stack_transfer_request() doesn't release the device protection semaphore when it fails, so do it manually. */
560     ux_utility_semaphore_put(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore);
561 
562     /**************************************************/
563     /** Test case: ux_host_stack_transfer_request() length error. **/
564     /**************************************************/
565 
566     ux_test_hcd_sim_host_set_actions(zlp_on_transfer_0);
567 
568     if (_ux_host_class_hid_report_set(hid, &client_report) != UX_HOST_CLASS_HID_REPORT_ERROR)
569     {
570 
571         printf("Error on line %d\n", __LINE__);
572         test_control_return(1);
573     }
574 
575     /** Restore state for next test. **/
576 
577     /* ux_host_stack_transfer_request() doesn't release the device protection semaphore when it fails, so do it manually. */
578     ux_utility_semaphore_put(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore);
579 
580 #if 0 /* TODO: USBX-246, USBX-247 */
581     /**************************************************/
582     /** Test case: functionality test. **/
583     /**************************************************/
584 
585     client_report.ux_host_class_hid_client_report = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_output_report -> ux_host_class_hid_report_next_report;
586     client_report.ux_host_class_hid_client_report_flags = UX_HOST_CLASS_HID_REPORT_RAW;
587     client_report.ux_host_class_hid_client_report_length = 5;
588 
589     /* Perform tests. */
590     for (test_number = 1; test_number <= NUM_TESTS; test_number++)
591     {
592         client_report.ux_host_class_hid_client_report_buffer = (ULONG *)test_buffers[test_number - 1];
593 
594         if (_ux_host_class_hid_report_set(hid, &client_report) != UX_SUCCESS)
595         {
596 
597             printf("Error on line %d\n", __LINE__);
598             test_control_return(1);
599         }
600 
601         /* Wait for device to receive our request. */
602         if (ux_utility_semaphore_get(&test_semaphore, 10) != UX_SUCCESS)
603         {
604 
605             printf("Error on line %d\n", __LINE__);
606             test_control_return(1);
607         }
608     }
609 #endif
610     /* Now disconnect the device.  */
611     _ux_device_stack_disconnect();
612 
613     /* And deinitialize the class.  */
614     status =  ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
615 
616     /* Deinitialize the device side of usbx.  */
617     _ux_device_stack_uninitialize();
618 
619     /* And finally the usbx system resources.  */
620     _ux_system_uninitialize();
621 
622     /* Successful test.  */
623     printf("SUCCESS!\n");
624     test_control_return(0);
625 }
626