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