1 /* This test concentrates on the report compress api. */
2 
3 #include "usbx_test_common_hid.h"
4 #include "ux_host_class_hid_keyboard.h"
5 #include "ux_test.h"
6 
7 
8 static UCHAR                               input_report_buffer_compressed[1024];
9 static SLONG                               input_report_buffer_decompressed_original[1024];
10 
11 static UCHAR hid_report_descriptor[] = {
12 
13     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
14     0x09, 0x06,                    // USAGE (Keyboard)
15     0xa1, 0x01,                    // COLLECTION (Application)
16                                         /* Keys. */
17     0x95, 0x06,                    //   REPORT_COUNT (6)
18     0x75, 0x08,                    //   REPORT_SIZE (8)
19     0x15, 0x01,                    //   LOGICAL_MINIMUM (0)
20     0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
21     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
22     0x19, 0x01,                    //   USAGE_MINIMUM (Reserved (no event indicated))
23     0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
24     0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
25     0xc0,                          // END_COLLECTION
26 };
27 #define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
28 
29 
30 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
31 static UCHAR device_framework_full_speed[DEVICE_FRAMEWORK_LENGTH_FULL_SPEED] = {
32 
33     /* Device descriptor */
34         0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
35         0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
36         0x00, 0x01,
37 
38     /* Configuration descriptor */
39         0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
40         0x32,
41 
42     /* Interface descriptor */
43         0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
44         0x00,
45 
46     /* HID descriptor */
47         0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
48         MSB(HID_REPORT_LENGTH),
49 
50     /* Endpoint descriptor (Interrupt) */
51         0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
52 
53     };
54 
55 
56 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
57 static UCHAR device_framework_high_speed[DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED] = {
58 
59     /* Device descriptor */
60         0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
61         0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
62         0x03, 0x01,
63 
64     /* Device qualifier descriptor */
65         0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
66         0x01, 0x00,
67 
68     /* Configuration descriptor */
69         0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
70         0x32,
71 
72     /* Interface descriptor */
73         0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
74         0x00,
75 
76     /* HID descriptor */
77         0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),
78         MSB(HID_REPORT_LENGTH),
79 
80     /* Endpoint descriptor (Interrupt) */
81         0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
82 
83     };
84 
85 
86     /* String Device Framework :
87      Byte 0 and 1 : Word containing the language ID : 0x0904 for US
88      Byte 2       : Byte containing the index of the descriptor
89      Byte 3       : Byte containing the length of the descriptor string
90     */
91 
92 #define STRING_FRAMEWORK_LENGTH 40
93 static UCHAR string_framework[] = {
94 
95     /* Manufacturer string descriptor : Index 1 */
96         0x09, 0x04, 0x01, 0x0c,
97         0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
98         0x6f, 0x67, 0x69, 0x63,
99 
100     /* Product string descriptor : Index 2 */
101         0x09, 0x04, 0x02, 0x0c,
102         0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
103         0x6f, 0x61, 0x72, 0x64,
104 
105     /* Serial Number string descriptor : Index 3 */
106         0x09, 0x04, 0x03, 0x04,
107         0x30, 0x30, 0x30, 0x31
108     };
109 
110 
111     /* Multiple languages are supported on the device, to add
112        a language besides english, the unicode language code must
113        be appended to the language_id_framework array and the length
114        adjusted accordingly. */
115 #define LANGUAGE_ID_FRAMEWORK_LENGTH 2
116 static UCHAR language_id_framework[] = {
117 
118     /* English. */
119         0x09, 0x04
120     };
121 
122 
123 static UCHAR ignore_errors;
error_callback(UINT system_level,UINT system_context,UINT error_code)124 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
125 {
126 
127     if (!ignore_errors)
128     {
129 
130         /* Failed test.  */
131         printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
132         test_control_return(1);
133     }
134 }
135 
136 /* Define what the initial system looks like.  */
137 
138 #ifdef CTEST
test_application_define(void * first_unused_memory)139 void test_application_define(void *first_unused_memory)
140 #else
141 void    usbx_hid_report_descriptor_compress_array_test_application_define(void *first_unused_memory)
142 #endif
143 {
144 
145 UINT                            status;
146 CHAR *                          stack_pointer;
147 CHAR *                          memory_pointer;
148 UINT                            descriptor_size = HID_REPORT_LENGTH;
149 
150     /* Inform user.  */
151     printf("Running HID Report Descriptor Decompress Test....................... ");
152 
153     /* Initialize the free memory pointer */
154     stack_pointer = (CHAR *) usbx_memory;
155     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
156 
157     /* Initialize USBX. Memory */
158     status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
159 
160     /* Check for error.  */
161     if (status != UX_SUCCESS)
162     {
163 
164         printf("Error on line %d\n", __LINE__);
165         test_control_return(1);
166     }
167 
168     /* Register the error callback. */
169     _ux_utility_error_callback_register(error_callback);
170 
171     /* The code below is required for installing the host portion of USBX */
172     status =  ux_host_stack_initialize(UX_NULL);
173     if (status != UX_SUCCESS)
174     {
175 
176         printf("Error on line %d\n", __LINE__);
177         test_control_return(1);
178     }
179 
180     status =  ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
181     if (status != UX_SUCCESS)
182     {
183 
184         printf("Error on line %d\n", __LINE__);
185         test_control_return(1);
186     }
187 
188     /* Register the HID client(s).  */
189     status =  ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
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     /* The code below is required for installing the device portion of USBX. No call back for
198        device status change in this example. */
199     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
200                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
201                                        string_framework, STRING_FRAMEWORK_LENGTH,
202                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
203     if(status!=UX_SUCCESS)
204     {
205 
206         printf("Error on line %d\n", __LINE__);
207         test_control_return(1);
208     }
209 
210     /* Initialize the hid class parameters.  */
211     hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
212     hid_parameter.ux_device_class_hid_parameter_report_length  = HID_REPORT_LENGTH;
213     hid_parameter.ux_device_class_hid_parameter_callback       = demo_thread_hid_callback;
214 
215     /* Initilize the device hid class. The class is connected with interface 2 */
216     status =  ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
217                                                 1,2, (VOID *)&hid_parameter);
218     if(status!=UX_SUCCESS)
219     {
220 
221         printf("Error on line %d\n", __LINE__);
222         test_control_return(1);
223     }
224 
225 
226     /* Initialize the simulated device controller.  */
227     status =  _ux_dcd_sim_slave_initialize();
228 
229     /* Check for error.  */
230     if (status != UX_SUCCESS)
231     {
232 
233         printf("Error on line %d\n", __LINE__);
234         test_control_return(1);
235     }
236 
237     /* Register all the USB host controllers available in this system */
238     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
239 
240     /* Check for error.  */
241     if (status != UX_SUCCESS)
242     {
243 
244         printf("Error on line %d\n", __LINE__);
245         test_control_return(1);
246     }
247 
248     /* Create the main host simulation thread.  */
249     status =  tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
250             stack_pointer, UX_DEMO_STACK_SIZE,
251             20, 20, 1, TX_AUTO_START);
252 
253     /* Check for error.  */
254     if (status != TX_SUCCESS)
255     {
256 
257         printf("Error on line %d\n", __LINE__);
258         test_control_return(1);
259     }
260 }
261 
262 
tx_demo_thread_host_simulation_entry(ULONG arg)263 static void  tx_demo_thread_host_simulation_entry(ULONG arg)
264 {
265 
266 UINT                                status;
267 UX_HOST_CLASS_HID_REPORT_GET_ID     report_id;
268 UX_HOST_CLASS_HID_CLIENT_REPORT     client_report;
269 UX_HOST_CLASS_HID_REPORT            *input_report_descriptor;
270 SLONG                               report_buffer_decompressed[1024];
271 UCHAR                               report_buffer_compressed[1024] = {0};
272 
273 
274     /* Find the HID class */
275     status = demo_class_hid_get();
276     if (status != UX_SUCCESS)
277     {
278 
279         printf("Error on line %d\n", __LINE__);
280         test_control_return(1);
281     }
282 
283     /** Do basic test.  **/
284 
285     /* Get the first input report descriptor. */
286     report_id.ux_host_class_hid_report_get_report = UX_NULL;
287     report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
288     UX_TEST_CHECK_SUCCESS(ux_host_class_hid_report_id_get(hid, &report_id));
289     input_report_descriptor = report_id.ux_host_class_hid_report_get_report;
290 
291     /* 1 */
292     report_buffer_decompressed[0] = 0x00070001;
293     report_buffer_decompressed[1] = 0x1;
294 
295     /* 2 */
296     report_buffer_decompressed[2] = 0x00070002;
297     report_buffer_decompressed[3] = 0x2;
298 
299     /* 3 */
300     report_buffer_decompressed[4] = 0x00070003;
301     report_buffer_decompressed[5] = 0x3;
302 
303     /* 4 */
304     report_buffer_decompressed[6] = 0x00070004;
305     report_buffer_decompressed[7] = 0x4;
306 
307     /* 5 */
308     report_buffer_decompressed[8] = 0x00070005;
309     report_buffer_decompressed[9] = 0x5;
310 
311     /* 6 */
312     report_buffer_decompressed[10] = 0x00070006;
313     report_buffer_decompressed[11] = 0x6;
314 
315     /* Fill out the request for the compress api. */
316     client_report.ux_host_class_hid_client_report = input_report_descriptor;
317     client_report.ux_host_class_hid_client_report_buffer = report_buffer_decompressed;
318     client_report.ux_host_class_hid_client_report_actual_length = 0;
319 
320     /* Request compression. */
321     UX_TEST_CHECK_SUCCESS(_ux_host_class_hid_report_compress(hid, &client_report, report_buffer_compressed, sizeof(report_buffer_compressed)));
322 
323     /* Check it. */
324     UX_TEST_ASSERT(report_buffer_compressed[0] == 0x1);
325     UX_TEST_ASSERT(report_buffer_compressed[1] == 0x2);
326     UX_TEST_ASSERT(report_buffer_compressed[2] == 0x3);
327     UX_TEST_ASSERT(report_buffer_compressed[3] == 0x4);
328     UX_TEST_ASSERT(report_buffer_compressed[4] == 0x5);
329     UX_TEST_ASSERT(report_buffer_compressed[5] == 0x6);
330 
331     /** Test invalid usage page. **/
332 
333     /* Get the first input report descriptor. */
334     report_id.ux_host_class_hid_report_get_report = UX_NULL;
335     report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
336     UX_TEST_CHECK_SUCCESS(ux_host_class_hid_report_id_get(hid, &report_id));
337     input_report_descriptor = report_id.ux_host_class_hid_report_get_report;
338 
339     /* Add invalid usage page. */
340     report_buffer_decompressed[0] = 0x00000000;
341     report_buffer_decompressed[1] = 0x00;
342 
343     /* Fill out the request for the compress api. */
344     client_report.ux_host_class_hid_client_report = input_report_descriptor;
345     client_report.ux_host_class_hid_client_report_buffer = report_buffer_decompressed;
346     client_report.ux_host_class_hid_client_report_actual_length = 0;
347 
348     ignore_errors = 1;
349 
350     /* Request compression. This should fail. */
351     UX_TEST_CHECK_NOT_SUCCESS(_ux_host_class_hid_report_compress(hid, &client_report, report_buffer_compressed, sizeof(report_buffer_compressed)));
352 
353     ignore_errors = 0;
354 
355     /** Test usage too large. **/
356 
357     /* Get the first input report descriptor. */
358     report_id.ux_host_class_hid_report_get_report = UX_NULL;
359     report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
360     UX_TEST_CHECK_SUCCESS(ux_host_class_hid_report_id_get(hid, &report_id));
361     input_report_descriptor = report_id.ux_host_class_hid_report_get_report;
362 
363     /* Add unknown usage. */
364     report_buffer_decompressed[0] = 0x00070066;
365     report_buffer_decompressed[1] = 0x66;
366 
367     /* Fill out the request for the compress api. */
368     client_report.ux_host_class_hid_client_report = input_report_descriptor;
369     client_report.ux_host_class_hid_client_report_buffer = report_buffer_decompressed;
370     client_report.ux_host_class_hid_client_report_actual_length = 0;
371 
372     ignore_errors = 1;
373 
374     /* Request compression. This should fail. */
375     UX_TEST_CHECK_NOT_SUCCESS(_ux_host_class_hid_report_compress(hid, &client_report, report_buffer_compressed, sizeof(report_buffer_compressed)));
376 
377     ignore_errors = 0;
378 
379     /** Test usage too small. **/
380 
381     /* Get the first input report descriptor. */
382     report_id.ux_host_class_hid_report_get_report = UX_NULL;
383     report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
384     UX_TEST_CHECK_SUCCESS(ux_host_class_hid_report_id_get(hid, &report_id));
385     input_report_descriptor = report_id.ux_host_class_hid_report_get_report;
386 
387     /* Add unknown usage. */
388     report_buffer_decompressed[0] = 0x00070000;
389     report_buffer_decompressed[1] = 0x0;
390 
391     /* Fill out the request for the compress api. */
392     client_report.ux_host_class_hid_client_report = input_report_descriptor;
393     client_report.ux_host_class_hid_client_report_buffer = report_buffer_decompressed;
394     client_report.ux_host_class_hid_client_report_actual_length = 0;
395 
396     ignore_errors = 1;
397 
398     /* Request compression. This should fail. */
399     UX_TEST_CHECK_NOT_SUCCESS(_ux_host_class_hid_report_compress(hid, &client_report, report_buffer_compressed, sizeof(report_buffer_compressed)));
400 
401     ignore_errors = 0;
402 
403     /* Now disconnect the device.  */
404     _ux_device_stack_disconnect();
405 
406     /* And deinitialize the class.  */
407     status =  ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
408 
409     /* Deinitialize the device side of usbx.  */
410     _ux_device_stack_uninitialize();
411 
412     /* And finally the usbx system resources.  */
413     _ux_system_uninitialize();
414 
415     /* Successful test.  */
416     printf("SUCCESS!\n");
417     test_control_return(0);
418 }
419 
demo_thread_hid_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)420 static UINT    demo_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
421 {
422     return(UX_SUCCESS);
423 }
424