1 /* This file tests basic HID functionalities. */
2
3 #include "usbx_test_common_hid.h"
4 #include "ux_host_class_hid_keyboard.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_keyboard_report[] = {
10
11 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
12 0x09, 0x06, // USAGE (Keyboard)
13 0xa1, 0x01, // COLLECTION (Application)
14
15 0x05, 0x07, // USAGE_PAGE (Keyboard)
16 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
17 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
18 0x15, 0x00, // LOGICAL_MINIMUM (0)
19 0x25, 0x01, // LOGICAL_MAXIMUM (1)
20 0x75, 0x01, // REPORT_SIZE (1)
21 0x95, 0x08, // REPORT_COUNT (8)
22 0x81, 0x02, // INPUT (Data,Var,Abs)
23
24 0x95, 0x01, // REPORT_COUNT (1)
25 0x75, 0x08, // REPORT_SIZE (8)
26 0x81, 0x03, // INPUT (Cnst,Var,Abs)
27
28 0x95, 0x05, // REPORT_COUNT (5)
29 0x75, 0x01, // REPORT_SIZE (1)
30 0x05, 0x08, // USAGE_PAGE (LEDs)
31 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
32 0x29, 0x05, // USAGE_MAXIMUM (Kana)
33 0x91, 0x02, // OUTPUT (Data,Var,Abs)
34
35 0x95, 0x01, // REPORT_COUNT (1)
36 0x75, 0x03, // REPORT_SIZE (3)
37 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
38
39 0x95, 0x06, // REPORT_COUNT (6)
40 0x75, 0x08, // REPORT_SIZE (8)
41 0x15, 0x00, // LOGICAL_MINIMUM (0)
42 0x25, 0x65, // LOGICAL_MAXIMUM (101)
43 0x05, 0x07, // USAGE_PAGE (Keyboard)
44 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
45 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
46 0x81, 0x00, // INPUT (Data,Ary,Abs)
47
48 0xc0 // END_COLLECTION
49 };
50 #define HID_KEYBOARD_REPORT_LENGTH sizeof(hid_keyboard_report)/sizeof(hid_keyboard_report[0])
51
52 static UCHAR hid_mouse_report[] = {
53
54 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
55 0x09, 0x02, // USAGE (Mouse)
56 0xa1, 0x01, // COLLECTION (Application)
57 0x09, 0x01, // USAGE (Pointer)
58 0xa1, 0x00, // COLLECTION (Physical)
59 0x05, 0x09, // USAGE_PAGE (Button)
60 0x19, 0x01, // USAGE_MINIMUM (Button 1)
61 0x29, 0x03, // USAGE_MAXIMUM (Button 3)
62 0x15, 0x00, // LOGICAL_MINIMUM (0)
63 0x25, 0x01, // LOGICAL_MAXIMUM (1)
64 0x95, 0x03, // REPORT_COUNT (3)
65 0x75, 0x01, // REPORT_SIZE (1)
66 0x81, 0x02, // INPUT (Data,Var,Abs)
67 0x95, 0x01, // REPORT_COUNT (1)
68 0x75, 0x05, // REPORT_SIZE (5)
69 0x81, 0x03, // INPUT (Cnst,Var,Abs)
70 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
71 0x09, 0x30, // USAGE (X)
72 0x09, 0x31, // USAGE (Y)
73 0x15, 0x81, // LOGICAL_MINIMUM (-127)
74 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
75 0x75, 0x08, // REPORT_SIZE (8)
76 0x95, 0x02, // REPORT_COUNT (2)
77 0x81, 0x06, // INPUT (Data,Var,Rel)
78 0x09, 0x38, // USAGE (Mouse Wheel)
79 0x15, 0x81, // LOGICAL_MINIMUM (-127)
80 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
81 0x75, 0x08, // REPORT_SIZE (8)
82 0x95, 0x01, // REPORT_COUNT (1)
83 0x81, 0x06, // INPUT (Data,Var,Rel)
84 0xc0, // END_COLLECTION
85 0xc0 // END_COLLECTION
86 };
87 #define HID_MOUSE_REPORT_LENGTH (sizeof(hid_mouse_report)/sizeof(hid_mouse_report[0]))
88
89 static UCHAR hid_remote_control_report[] = {
90
91 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
92 0x09, 0x01, // USAGE (Consumer Control)
93 0xa1, 0x01, // COLLECTION (Application)
94 0x09, 0x02, // USAGE (Numeric Key Pad)
95 0xa1, 0x02, // COLLECTION (Logical)
96 0x05, 0x09, // USAGE_PAGE (Button)
97 0x19, 0x01, // USAGE_MINIMUM (Button 1)
98 0x29, 0x0a, // USAGE_MAXIMUM (Button 10)
99 0x15, 0x01, // LOGICAL_MINIMUM (1)
100 0x25, 0x0a, // LOGICAL_MAXIMUM (10)
101 0x75, 0x04, // REPORT_SIZE (4)
102 0x95, 0x01, // REPORT_COUNT (1)
103 0x81, 0x00, // INPUT (Data,Ary,Abs)
104 0xc0, // END_COLLECTION
105 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
106 0x09, 0x86, // USAGE (Channel)
107 0x09, 0xe0, // USAGE (Volume)
108 0x15, 0xff, // LOGICAL_MINIMUM (-1)
109 0x25, 0x01, // LOGICAL_MAXIMUM (1)
110 0x75, 0x02, // REPORT_SIZE (2)
111 0x95, 0x02, // REPORT_COUNT (2)
112 0x81, 0x46, // INPUT (Data,Var,Rel,Null)
113 0xc0 // END_COLLECTION
114 };
115 #define HID_REMOTE_CONTROL_REPORT_LENGTH (sizeof(hid_remote_control_report)/sizeof(hid_remote_control_report[0]))
116
117
118 #define hid_report_descriptor hid_remote_control_report
119 #define HID_REPORT_LENGTH HID_REMOTE_CONTROL_REPORT_LENGTH
120
121 /* Configuration descriptor 9 bytes */
122 #define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
123 /* Configuration 1 descriptor 9 bytes */\
124 0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
125 (bNumInterfaces), (bConfigurationValue), 0x00,\
126 0x40, 0x00,
127 #define CFG_DESC_LEN (9)
128
129
130 /* HID Mouse/Keyboard interface descriptors 9+9+7=25 bytes */
131 #define HID_IFC_DESC_ALL(ifc, report_len, interrupt_epa) \
132 /* Interface descriptor */\
133 0x09, 0x04, (ifc), 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,\
134 /* HID descriptor */\
135 0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(report_len),\
136 MSB(report_len),\
137 /* Endpoint descriptor (Interrupt) */\
138 0x07, 0x05, (interrupt_epa), 0x03, 0x08, 0x00, 0x08,
139 #define HID_IFC_DESC_ALL_LEN (9+9+7)
140
141 static UCHAR device_framework_full_speed[] = {
142
143 /* Device descriptor */
144 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
145 0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x01,
147
148 CFG_DESC(CFG_DESC_LEN+1*HID_IFC_DESC_ALL_LEN, 1, 1)
149 /* Keyboard */
150 HID_IFC_DESC_ALL(0, HID_REPORT_LENGTH, 0x81)
151 };
152 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
153
154 static UCHAR device_framework_high_speed[] = {
155
156 /* Device descriptor */
157 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
158 0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
159 0x03, 0x01,
160
161 /* Device qualifier descriptor */
162 0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
163 0x01, 0x00,
164
165 CFG_DESC(CFG_DESC_LEN+1*HID_IFC_DESC_ALL_LEN, 1, 1)
166 /* Keyboard */
167 HID_IFC_DESC_ALL(0, HID_REPORT_LENGTH, 0x81)
168 };
169 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
170
171
172 /* String Device Framework :
173 Byte 0 and 1 : Word containing the language ID : 0x0904 for US
174 Byte 2 : Byte containing the index of the descriptor
175 Byte 3 : Byte containing the length of the descriptor string
176 */
177 static UCHAR string_framework[] = {
178
179 /* Manufacturer string descriptor : Index 1 */
180 0x09, 0x04, 0x01, 0x0c,
181 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
182 0x6f, 0x67, 0x69, 0x63,
183
184 /* Product string descriptor : Index 2 */
185 0x09, 0x04, 0x02, 0x0c,
186 0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
187 0x6f, 0x61, 0x72, 0x64,
188
189 /* Serial Number string descriptor : Index 3 */
190 0x09, 0x04, 0x03, 0x04,
191 0x30, 0x30, 0x30, 0x31
192 };
193 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
194
195
196 /* Multiple languages are supported on the device, to add
197 a language besides english, the unicode language code must
198 be appended to the language_id_framework array and the length
199 adjusted accordingly. */
200 static UCHAR language_id_framework[] = {
201
202 /* English. */
203 0x09, 0x04
204 };
205 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
206
207
208 UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
209
210
ux_system_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)211 static UINT ux_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
212 {
213 switch(event)
214 {
215 case UX_HID_CLIENT_INSERTION:
216 break;
217 case UX_HID_CLIENT_REMOVAL:
218 break;
219 #if defined(UX_HOST_STANDALONE)
220 case UX_STANDALONE_WAIT_BACKGROUND_TASK:
221 /* Let other threads to run. */
222 tx_thread_relinquish();
223 break;
224 #endif
225 default:
226 break;
227 }
228 return 0;
229 }
230
error_callback(UINT system_level,UINT system_context,UINT error_code)231 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
232 {
233 }
234
235 /* Define what the initial system looks like. */
236
237 #ifdef CTEST
test_application_define(void * first_unused_memory)238 void test_application_define(void *first_unused_memory)
239 #else
240 void usbx_class_hid_remote_control_basic_test_application_define(void *first_unused_memory)
241 #endif
242 {
243
244 UINT status;
245 CHAR * stack_pointer;
246 CHAR * memory_pointer;
247
248
249 /* Inform user. */
250 printf("Running HID Class Remote Control Basic Test......................... ");
251
252 /* Initialize the free memory pointer */
253 stack_pointer = (CHAR *) usbx_memory;
254 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
255
256 /* Initialize USBX. Memory */
257 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
258
259 /* Check for error. */
260 if (status != UX_SUCCESS)
261 {
262
263 printf("Error on line %d, error code: %d\n", __LINE__, status);
264 test_control_return(1);
265 }
266
267 /* Register the error callback. */
268 _ux_utility_error_callback_register(error_callback);
269
270 /* The code below is required for installing the host portion of USBX */
271 status = ux_host_stack_initialize(ux_system_host_change_function);
272 if (status != UX_SUCCESS)
273 {
274
275 printf("Error on line %d, error code: %d\n", __LINE__, status);
276 test_control_return(1);
277 }
278
279 status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
280 if (status != UX_SUCCESS)
281 {
282
283 printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
284 test_control_return(1);
285 }
286
287 /* Register the HID client(s). */
288 status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_remote_control_name, ux_host_class_hid_remote_control_entry);
289 if (status != UX_SUCCESS)
290 {
291
292 printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
293 test_control_return(1);
294 }
295
296 /* The code below is required for installing the device portion of USBX. No call back for
297 device status change in this example. */
298 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
299 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
300 string_framework, STRING_FRAMEWORK_LENGTH,
301 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
302 if(status!=UX_SUCCESS)
303 {
304
305 printf("Error on line %d, error code: %d\n", __LINE__, status);
306 test_control_return(1);
307 }
308
309 /* Initialize the hid class parameters. */
310 hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
311 hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
312 hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_set_callback;
313 hid_parameter.ux_device_class_hid_parameter_get_callback = demo_thread_hid_get_callback;
314
315 hid_parameter.ux_slave_class_hid_instance_activate = demo_device_hid_instance_activate;
316 hid_parameter.ux_slave_class_hid_instance_deactivate = demo_device_hid_instance_deactivate;
317
318 /* Initilize the device hid class. The class is connected with interface 2 */
319 status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
320 1, 0, (VOID *)&hid_parameter);
321 if(status!=UX_SUCCESS)
322 {
323
324 printf("Error on line %d, error code: %d\n", __LINE__, status);
325 test_control_return(1);
326 }
327
328 /* Initialize the simulated device controller. */
329 status = _ux_dcd_sim_slave_initialize();
330
331 /* Check for error. */
332 if (status != UX_SUCCESS)
333 {
334
335 printf("Error on line %d, error code: %d\n", __LINE__, status);
336 test_control_return(1);
337 }
338
339 /* Register all the USB host controllers available in this system */
340 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
341
342 /* Check for error. */
343 if (status != UX_SUCCESS)
344 {
345
346 printf("Error on line %d, error code: %d\n", __LINE__, status);
347 test_control_return(1);
348 }
349
350 /* Create the main device simulation thread. */
351 status = tx_thread_create(&tx_demo_thread_device_simulation, "tx demo device simulation", tx_demo_thread_device_simulation_entry, 0,
352 stack_pointer, UX_DEMO_STACK_SIZE,
353 20, 20, 1, TX_AUTO_START);
354
355 /* Check for error. */
356 if (status != TX_SUCCESS)
357 {
358
359 printf("Error on line %d, error code: %d\n", __LINE__, status);
360 test_control_return(1);
361 }
362 stack_pointer += UX_DEMO_STACK_SIZE;
363
364 /* Create the main host simulation thread. */
365 status = tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
366 stack_pointer, UX_DEMO_STACK_SIZE,
367 20, 20, 1, TX_AUTO_START);
368
369 /* Check for error. */
370 if (status != TX_SUCCESS)
371 {
372
373 printf("Error on line %d, error code: %d\n", __LINE__, status);
374 test_control_return(1);
375 }
376 }
377
tx_demo_thread_device_simulation_entry(ULONG arg)378 static void tx_demo_thread_device_simulation_entry(ULONG arg)
379 {
380 while(1)
381 {
382 #if defined(UX_DEVICE_STANDALONE)
383 ux_system_tasks_run();
384 #else
385 tx_thread_suspend(&tx_demo_thread_device_simulation);
386 #endif
387 }
388 }
389
demo_class_hid_wait(ULONG tick)390 static UINT demo_class_hid_wait(ULONG tick)
391 {
392 return(ux_test_sleep_break_on_success(tick, demo_class_hid_remote_control_get));
393 }
394
_wait_remote_control_usage(UX_HOST_CLASS_HID_REMOTE_CONTROL * remote_control,ULONG * usage,ULONG * value)395 static UINT _wait_remote_control_usage(UX_HOST_CLASS_HID_REMOTE_CONTROL *remote_control,
396 ULONG *usage, ULONG *value)
397 {
398 UINT status;
399 UINT i;
400
401 for (i = 0; i < 200; i ++)
402 {
403 #if defined(UX_HOST_STANDALONE)
404 ux_system_tasks_run();
405 #endif
406 status = ux_host_class_hid_remote_control_usage_get(remote_control, usage, value);
407 if (status == UX_SUCCESS)
408 return(UX_SUCCESS);
409 tx_thread_sleep(1);
410 }
411 return(UX_ERROR);
412 }
413
test_hid_remote_control_events(VOID)414 static void test_hid_remote_control_events(VOID)
415 {
416 UINT status;
417 ULONG usage;
418 ULONG value;
419
420 /* Initialize mouse event. */
421 device_hid_event.ux_device_class_hid_event_length = 1;
422 device_hid_event.ux_device_class_hid_event_buffer[0] = 0; /* CH(2)|CH(2)|Bn(4) */
423
424 device_hid_event.ux_device_class_hid_event_buffer[0] = (3 << 6) | (1 << 4) | (10); /* CH(2)|CH(2)|Bn(4) */
425 _ux_device_class_hid_event_set(device_hid, &device_hid_event);
426 status = _wait_remote_control_usage(hid_remote_control, &usage, &value);
427 UX_ASSERT(status == UX_SUCCESS);
428 UX_ASSERT(usage == (0x90000+10));
429 UX_ASSERT(value == 10);
430 status = ux_host_class_hid_remote_control_usage_get(hid_remote_control, &usage, &value);
431 UX_ASSERT(status == UX_SUCCESS);
432 UX_ASSERT(usage == 0xc0086);
433 UX_ASSERT(value == 1);
434 status = ux_host_class_hid_remote_control_usage_get(hid_remote_control, &usage, &value);
435 UX_ASSERT(status == UX_SUCCESS);
436 UX_ASSERT(usage == 0xc00e0);
437 UX_ASSERT(value == 3);
438
439 device_hid_event.ux_device_class_hid_event_buffer[0] = (1 << 6) | (0 << 4) | (5); /* CH(2)|CH(2)|Bn(4) */
440 _ux_device_class_hid_event_set(device_hid, &device_hid_event);
441 status = _wait_remote_control_usage(hid_remote_control, &usage, &value);
442 UX_ASSERT(status == UX_SUCCESS);
443 UX_ASSERT(usage == (0x90000+5));
444 UX_ASSERT(value == 5);
445 status = ux_host_class_hid_remote_control_usage_get(hid_remote_control, &usage, &value);
446 UX_ASSERT(status == UX_SUCCESS);
447 UX_ASSERT(usage == 0xc0086);
448 UX_ASSERT(value == 0);
449 status = ux_host_class_hid_remote_control_usage_get(hid_remote_control, &usage, &value);
450 UX_ASSERT(status == UX_SUCCESS);
451 UX_ASSERT(usage == 0xc00e0);
452 UX_ASSERT(value == 1);
453 }
454
tx_demo_thread_host_simulation_entry(ULONG arg)455 static void tx_demo_thread_host_simulation_entry(ULONG arg)
456 {
457
458 UINT status;
459
460 /* Find the HID class */
461 status = demo_class_hid_wait(100);
462 UX_TEST_ASSERT(status == UX_SUCCESS);
463
464 test_hid_remote_control_events();
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_set_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)483 static UINT demo_thread_hid_set_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
484 {
485 _ux_utility_memory_copy(&device_hid_event, event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
486 return(UX_SUCCESS);
487 }
demo_thread_hid_get_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)488 static UINT demo_thread_hid_get_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
489 {
490 _ux_utility_memory_copy(event, &device_hid_event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
491 return(UX_SUCCESS);
492 }
493
demo_device_hid_instance_activate(VOID * inst)494 static void demo_device_hid_instance_activate(VOID *inst)
495 {
496 if (device_hid == UX_NULL)
497 device_hid = (UX_SLAVE_CLASS_HID *)inst;
498 }
demo_device_hid_instance_deactivate(VOID * inst)499 static void demo_device_hid_instance_deactivate(VOID *inst)
500 {
501 if (inst == (VOID *)device_hid)
502 device_hid = UX_NULL;
503 }
504