1 /* This file tests the ux_device_class_hid API. */
2
3 #include "usbx_test_common_hid.h"
4
5 #include "ux_test_dcd_sim_slave.h"
6 #include "ux_test_hcd_sim_host.h"
7 #include "ux_test_utility_sim.h"
8
9 #include "ux_host_class_hid_mouse.h"
10 #include "ux_host_class_hid_keyboard.h"
11
12
13 static UCHAR hid_keyboard_report[] = {
14
15 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
16 0x09, 0x06, // USAGE (Keyboard)
17 0xa1, 0x01, // COLLECTION (Application)
18 0x05, 0x07, // USAGE_PAGE (Keyboard)
19 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
20 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
21 0x15, 0x00, // LOGICAL_MINIMUM (0)
22 0x25, 0x01, // LOGICAL_MAXIMUM (1)
23 0x75, 0x01, // REPORT_SIZE (1)
24 0x95, 0x08, // REPORT_COUNT (8)
25 0x81, 0x02, // INPUT (Data,Var,Abs)
26 0x95, 0x01, // REPORT_COUNT (1)
27 0x75, 0x08, // REPORT_SIZE (8)
28 0x81, 0x03, // INPUT (Cnst,Var,Abs)
29 0x95, 0x05, // REPORT_COUNT (5)
30 0x75, 0x01, // REPORT_SIZE (1)
31 0x05, 0x08, // USAGE_PAGE (LEDs)
32 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
33 0x29, 0x05, // USAGE_MAXIMUM (Kana)
34 0x91, 0x02, // OUTPUT (Data,Var,Abs)
35 0x95, 0x01, // REPORT_COUNT (1)
36 0x75, 0x03, // REPORT_SIZE (3)
37 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
38 0x95, 0x06, // REPORT_COUNT (6)
39 0x75, 0x08, // REPORT_SIZE (8)
40 0x15, 0x00, // LOGICAL_MINIMUM (0)
41 0x25, 0x65, // LOGICAL_MAXIMUM (101)
42 0x05, 0x07, // USAGE_PAGE (Keyboard)
43 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
44 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
45 0x81, 0x00, // INPUT (Data,Ary,Abs)
46 0xc0 // END_COLLECTION
47 };
48 #define HID_KEYBOARD_REPORT_LENGTH sizeof(hid_keyboard_report)/sizeof(hid_keyboard_report[0])
49
50
51 static UCHAR hid_mouse_report[] = {
52
53 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
54 0x09, 0x02, // USAGE (Mouse)
55 0xa1, 0x01, // COLLECTION (Application)
56 0x85, 0x01, // REPORT_ID (1)
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
90 /* Configuration descriptor 9 bytes */
91 #define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
92 /* Configuration 1 descriptor 9 bytes */\
93 0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
94 (bNumInterfaces), (bConfigurationValue), 0x00,\
95 0x40, 0x00,
96 #define CFG_DESC_LEN (9)
97
98
99 /* HID Mouse/Keyboard interface descriptors 9+9+7=25 bytes */
100 #define HID_IFC_DESC_ALL(ifc, report_len, interrupt_epa) \
101 /* Interface descriptor */\
102 0x09, 0x04, (ifc), 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,\
103 /* HID descriptor */\
104 0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(report_len),\
105 MSB(report_len),\
106 /* Endpoint descriptor (Interrupt) */\
107 0x07, 0x05, (interrupt_epa), 0x03, 0x08, 0x00, 0x08,
108 #define HID_IFC_DESC_ALL_LEN (9+9+7)
109
110
111 static UCHAR device_framework_full_speed[] = {
112
113 /* Device descriptor */
114 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
115 0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x01,
117
118 CFG_DESC(CFG_DESC_LEN+2*HID_IFC_DESC_ALL_LEN, 2, 1)
119 /* Mouse */
120 HID_IFC_DESC_ALL(0, HID_MOUSE_REPORT_LENGTH, 0x81)
121 /* Keyboard */
122 HID_IFC_DESC_ALL(1, HID_KEYBOARD_REPORT_LENGTH, 0x82)
123 };
124 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
125
126
127 static UCHAR device_framework_high_speed[] = {
128
129 /* Device descriptor */
130 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
131 0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
132 0x03, 0x01,
133
134 /* Device qualifier descriptor */
135 0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
136 0x01, 0x00,
137
138 CFG_DESC(CFG_DESC_LEN+2*HID_IFC_DESC_ALL_LEN, 2, 1)
139 /* Mouse */
140 HID_IFC_DESC_ALL(0, HID_MOUSE_REPORT_LENGTH, 0x81)
141 /* Keyboard */
142 HID_IFC_DESC_ALL(1, HID_KEYBOARD_REPORT_LENGTH, 0x82)
143 };
144 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
145
146
147 /* String Device Framework :
148 Byte 0 and 1 : Word containing the language ID : 0x0904 for US
149 Byte 2 : Byte containing the index of the descriptor
150 Byte 3 : Byte containing the length of the descriptor string
151 */
152 static UCHAR string_framework[] = {
153
154 /* Manufacturer string descriptor : Index 1 */
155 0x09, 0x04, 0x01, 0x0c,
156 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
157 0x6f, 0x67, 0x69, 0x63,
158
159 /* Product string descriptor : Index 2 */
160 0x09, 0x04, 0x02, 0x0c,
161 0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
162 0x6f, 0x61, 0x72, 0x64,
163
164 /* Serial Number string descriptor : Index 3 */
165 0x09, 0x04, 0x03, 0x04,
166 0x30, 0x30, 0x30, 0x31
167 };
168 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
169
170
171 /* Multiple languages are supported on the device, to add
172 a language besides english, the unicode language code must
173 be appended to the language_id_framework array and the length
174 adjusted accordingly. */
175 static UCHAR language_id_framework[] = {
176
177 /* English. */
178 0x09, 0x04
179 };
180 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
181
182 static UCHAR buffer[4*UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH];
183
184 static UX_HOST_CLASS_HID *hid = UX_NULL;
185 static UX_HOST_CLASS_HID_MOUSE *hid_mouse = UX_NULL;
186 static UX_HOST_CLASS_HID_KEYBOARD *hid_keyboard = UX_NULL;
187
188 static UX_SLAVE_CLASS_HID *hid_mouse_slave = UX_NULL;
189 static UX_SLAVE_CLASS_HID *hid_keyboard_slave = UX_NULL;
190
191 static UX_SLAVE_CLASS_HID_PARAMETER hid_mouse_parameter;
192 static UX_SLAVE_CLASS_HID_PARAMETER hid_keyboard_parameter;
193
194 static ULONG rsc_mem_alloc_cnt_on_set_cfg;
195 static ULONG rsc_enum_mem_alloc_count;
196 static ULONG rsc_hid_mem_alloc_count;
197
198 static ULONG error_callback_counter;
199 static UCHAR error_callback_ignore;
200
201 static ULONG error_counter = 0;
202
203 static UCHAR event_callback_length_error = 0;
204
ux_system_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)205 static UINT ux_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
206 {
207
208 UX_HOST_CLASS_HID_CLIENT *client = (UX_HOST_CLASS_HID_CLIENT *)inst;
209 UINT is_mouse = (UX_SUCCESS == _ux_utility_memory_compare(client->ux_host_class_hid_client_name,
210 _ux_system_host_class_hid_client_mouse_name,
211 _ux_utility_string_length_get(_ux_system_host_class_hid_client_mouse_name)));
212
213 // printf("hChg: %lx, %p, %p\n", event, cls, inst);
214 switch(event)
215 {
216
217 case UX_HID_CLIENT_INSERTION:
218 if (is_mouse)
219 hid_mouse = (UX_HOST_CLASS_HID_MOUSE *)client->ux_host_class_hid_client_local_instance;
220 else
221 hid_keyboard = (UX_HOST_CLASS_HID_KEYBOARD *)client->ux_host_class_hid_client_local_instance;
222 break;
223
224 case UX_HID_CLIENT_REMOVAL:
225 if (is_mouse)
226 hid_mouse = UX_NULL;
227 else
228 hid_keyboard = UX_NULL;
229 break;
230
231 default:
232 break;
233 }
234 return 0;
235 }
236
mouse_instance_activate_callback(VOID * parameter)237 static VOID mouse_instance_activate_callback(VOID *parameter)
238 {
239 // printf("dMouse: %p\n", parameter);
240 hid_mouse_slave = (UX_SLAVE_CLASS_HID *)parameter;
241 }
242
keyboard_instance_activate_callback(VOID * parameter)243 static VOID keyboard_instance_activate_callback(VOID *parameter)
244 {
245 // printf("dKeyboard: %p\n", parameter);
246 hid_keyboard_slave = (UX_SLAVE_CLASS_HID *)parameter;
247 }
248
instance_deactivate_callback(VOID * parameter)249 static VOID instance_deactivate_callback(VOID *parameter)
250 {
251 // printf("dRm: %p\n", parameter);
252 if ((VOID *)hid_mouse_slave == parameter)
253 hid_mouse_slave = UX_NULL;
254
255 if ((VOID *)hid_keyboard_slave == parameter)
256 hid_keyboard_slave = UX_NULL;
257 }
258
error_callback(UINT system_level,UINT system_context,UINT error_code)259 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
260 {
261 if (error_code == UX_MEMORY_INSUFFICIENT)
262 error_callback_counter ++;
263 // printf("ERROR #%d: 0x%x, 0x%x, 0x%x\n", __LINE__, system_level, system_context, error_code);
264 }
265
break_on_all_activated(VOID)266 static UINT break_on_all_activated(VOID)
267 {
268
269 if (hid_mouse_slave == UX_NULL)
270 return 0;
271 if (hid_keyboard_slave == UX_NULL)
272 return 0;
273 if (hid_mouse == UX_NULL)
274 return 0;
275 if (hid_keyboard == UX_NULL)
276 return 0;
277
278 return 1;
279 }
280
281
break_on_all_removed(VOID)282 static UINT break_on_all_removed(VOID)
283 {
284 if (hid_mouse_slave || hid_keyboard_slave)
285 return 0;
286 if (hid_mouse || hid_keyboard)
287 return 0;
288
289 return 1;
290 }
291
292
sleep_break_on_error(VOID)293 static UINT sleep_break_on_error(VOID)
294 {
295
296 if (error_callback_counter >= 3)
297 return error_callback_counter;
298
299 return UX_SUCCESS;
300 }
301
302 /* Define what the initial system looks like. */
303
304 #ifdef CTEST
test_application_define(void * first_unused_memory)305 void test_application_define(void *first_unused_memory)
306 #else
307 void usbx_ux_device_class_hid_report_test_application_define(void *first_unused_memory)
308 #endif
309 {
310
311 UINT status;
312 CHAR *stack_pointer;
313 CHAR *memory_pointer;
314
315
316 /* Inform user. */
317 printf("Running ux_device_class_hid_report_... test ......,,................ ");
318 stepinfo("\n");
319
320 /* Initialize the free memory pointer */
321 stack_pointer = (CHAR *) usbx_memory;
322 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
323
324 /* Initialize USBX. Memory */
325 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
326
327 /* Check for error. */
328 if (status != UX_SUCCESS)
329 {
330
331 printf("ERROR #%d, code 0x%x\n", __LINE__, status);
332 test_control_return(1);
333 }
334
335 /* Register the error callback. */
336 _ux_utility_error_callback_register(error_callback);
337
338 /* The code below is required for installing the host portion of USBX */
339 status = ux_host_stack_initialize(ux_system_host_change_function);
340 if (status != UX_SUCCESS)
341 {
342
343 printf("ERROR #%d, code 0x%x\n", __LINE__, status);
344 test_control_return(1);
345 }
346
347 status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
348 if (status != UX_SUCCESS)
349 {
350
351 printf("ERROR #%d, code 0x%x\n", __LINE__, status);
352 test_control_return(1);
353 }
354
355 /* Register the HID client(s). */
356 status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_mouse_name, ux_host_class_hid_mouse_entry);
357 status |= ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
358 if (status != UX_SUCCESS)
359 {
360
361 printf("ERROR #%d, code 0x%x\n", __LINE__, status);
362 test_control_return(1);
363 }
364
365 /* The code below is required for installing the device portion of USBX. No call back for
366 device status change in this example. */
367 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
368 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
369 string_framework, STRING_FRAMEWORK_LENGTH,
370 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
371 if(status!=UX_SUCCESS)
372 {
373
374 printf("ERROR #%d, code 0x%x\n", __LINE__, status);
375 test_control_return(1);
376 }
377
378 /* Initialize the hid class parameters for mouse and keyboard. */
379 hid_mouse_parameter.ux_device_class_hid_parameter_report_address = hid_mouse_report;
380 hid_mouse_parameter.ux_device_class_hid_parameter_report_length = HID_MOUSE_REPORT_LENGTH;
381 hid_mouse_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
382 hid_mouse_parameter.ux_device_class_hid_parameter_get_callback = demo_thread_hid_get_callback;
383 hid_mouse_parameter.ux_slave_class_hid_instance_activate = mouse_instance_activate_callback;
384 hid_mouse_parameter.ux_slave_class_hid_instance_deactivate = instance_deactivate_callback;
385 hid_mouse_parameter.ux_device_class_hid_parameter_report_id = UX_TRUE;
386
387 hid_keyboard_parameter.ux_device_class_hid_parameter_report_address = hid_keyboard_report;
388 hid_keyboard_parameter.ux_device_class_hid_parameter_report_length = HID_KEYBOARD_REPORT_LENGTH;
389 hid_keyboard_parameter.ux_device_class_hid_parameter_callback = UX_NULL;
390 hid_keyboard_parameter.ux_device_class_hid_parameter_get_callback = UX_NULL;
391 hid_keyboard_parameter.ux_slave_class_hid_instance_activate = keyboard_instance_activate_callback;
392
393 /* Initilize the device hid class. */
394 status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
395 1,0, (VOID *)&hid_mouse_parameter);
396 status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
397 1,1, (VOID *)&hid_keyboard_parameter);
398 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
399 if(status!=UX_SUCCESS)
400 {
401
402 printf("ERROR #%d, code 0x%x\n", __LINE__, status);
403 test_control_return(1);
404 }
405 #endif
406
407 /* Initialize the simulated device controller. */
408 status = _ux_dcd_sim_slave_initialize();
409
410 /* Check for error. */
411 if (status != UX_SUCCESS)
412 {
413
414 printf("ERROR #%d, code 0x%x\n", __LINE__, status);
415 test_control_return(1);
416 }
417
418 /* Register all the USB host controllers available in this system */
419 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
420
421 /* Check for error. */
422 if (status != UX_SUCCESS)
423 {
424
425 printf("ERROR #%d, code 0x%x\n", __LINE__, status);
426 test_control_return(1);
427 }
428
429 /* Create the main host simulation thread. */
430 status = tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
431 stack_pointer, UX_DEMO_STACK_SIZE,
432 20, 20, 1, TX_AUTO_START);
433
434 /* Check for error. */
435 if (status != TX_SUCCESS)
436 {
437
438 printf("ERROR #%d, code 0x%x\n", __LINE__, status);
439 test_control_return(1);
440 }
441 }
442
tx_demo_thread_host_simulation_entry(ULONG arg)443 static void tx_demo_thread_host_simulation_entry(ULONG arg)
444 {
445
446 UINT status;
447 UX_DEVICE *device;
448 UX_ENDPOINT *endpoint;
449 UX_TRANSFER *transfer_request;
450
451 stepinfo(">>>>>>>>>> Thread start\n");
452
453 ux_test_breakable_sleep(200, break_on_all_activated);
454
455 /* Get device instance. */
456 status = ux_host_stack_device_get(0, &device);
457
458 if (status != UX_SUCCESS)
459 {
460 printf("ERROR #%d: get_device fail, 0x%x\n", __LINE__, status);
461 test_control_return(1);
462 }
463
464 /* Get control endpoint and control transfer request. */
465 endpoint = &device->ux_device_control_endpoint;
466 transfer_request = &endpoint->ux_endpoint_transfer_request;
467
468 /* Create a transfer request for the SET_REPORT request. */
469 transfer_request -> ux_transfer_request_data_pointer = buffer;
470 transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_SET_REPORT;
471 transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
472
473 if (hid_keyboard)
474 {
475
476 stepinfo(">>>>>>>>>> SetReport(noID, %d)\n", UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH + 1);
477
478 transfer_request -> ux_transfer_request_requested_length = UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH + 1;
479 transfer_request -> ux_transfer_request_value = (UINT)((USHORT) 0 | (USHORT) UX_HOST_CLASS_HID_REPORT_TYPE_OUTPUT << 8);
480 transfer_request -> ux_transfer_request_index = hid_keyboard->ux_host_class_hid_keyboard_hid->ux_host_class_hid_interface->ux_interface_descriptor.bInterfaceNumber;
481
482 status = ux_host_stack_transfer_request(transfer_request);
483 if (status != UX_SUCCESS)
484 {
485 printf("ERROR #%d: code 0x%x\n", __LINE__, status);
486 error_counter ++;
487 }
488 }
489
490 stepinfo(">>>>>>>>>> SetReport(1, %d)\n", UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH + 1);
491
492 /* Create a transfer request for the SET_REPORT request. */
493 transfer_request -> ux_transfer_request_requested_length = UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH;
494 transfer_request -> ux_transfer_request_value = (UINT)((USHORT) 1 | (USHORT) UX_HOST_CLASS_HID_REPORT_TYPE_OUTPUT << 8);
495 transfer_request -> ux_transfer_request_index = hid_mouse->ux_host_class_hid_mouse_hid->ux_host_class_hid_interface->ux_interface_descriptor.bInterfaceNumber;
496
497 status = ux_host_stack_transfer_request(transfer_request);
498 if (status != UX_SUCCESS)
499 {
500 printf("ERROR #%d: code 0x%x\n", __LINE__, status);
501 error_counter ++;
502 }
503
504 if (hid_keyboard)
505 {
506
507 /* Create a transfer request for the GET_REPORT request. */
508 transfer_request -> ux_transfer_request_data_pointer = buffer;
509 transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_GET_REPORT;
510 transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
511
512 stepinfo(">>>>>>>>>> GetReport(noID, %d)\n", UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH + 1);
513
514 transfer_request -> ux_transfer_request_requested_length = UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH + 1;
515 transfer_request -> ux_transfer_request_value = (UINT)((USHORT) 0 | (USHORT) UX_HOST_CLASS_HID_REPORT_TYPE_INPUT << 8);
516 transfer_request -> ux_transfer_request_index = hid_keyboard->ux_host_class_hid_keyboard_hid->ux_host_class_hid_interface->ux_interface_descriptor.bInterfaceNumber;
517
518 status = ux_host_stack_transfer_request(transfer_request);
519 if (status != UX_SUCCESS)
520 {
521 printf("ERROR #%d: code 0x%x\n", __LINE__, status);
522 error_counter ++;
523 }
524 }
525
526 /* Create a transfer request for the GET_REPORT request. */
527 transfer_request -> ux_transfer_request_data_pointer = buffer;
528 transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_GET_REPORT;
529 transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
530
531 if (hid_keyboard)
532 {
533
534 /* Request a size that is smaller than the event buffer. */
535 stepinfo(">>>>>>>>>> GetReport(noID, %d)\n", UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH - 1);
536
537 /* Suspend the background keyboard interrupt thread so that it doesn't get our report. */
538 tx_thread_suspend(&hid_keyboard_slave->ux_slave_class_hid_interface->ux_slave_interface_class->ux_slave_class_thread);
539
540 /* Add an event so the device will try to send one back to the host. */
541 UX_SLAVE_CLASS_HID_EVENT hid_event = { 0 };
542 hid_event.ux_device_class_hid_event_length = UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH;
543 hid_event.ux_device_class_hid_event_report_id = 0;
544 hid_event.ux_device_class_hid_event_report_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT;
545 status = _ux_device_class_hid_event_set(hid_keyboard_slave, &hid_event);
546 if (status != UX_SUCCESS)
547 {
548 printf("ERROR #%d: code 0x%x\n", __LINE__, status);
549 error_counter ++;
550 }
551
552 transfer_request -> ux_transfer_request_data_pointer = buffer;
553 transfer_request -> ux_transfer_request_requested_length = UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH - 1;
554 transfer_request -> ux_transfer_request_value = (UINT)((USHORT) 0 | (USHORT) UX_HOST_CLASS_HID_REPORT_TYPE_INPUT << 8);
555 transfer_request -> ux_transfer_request_index = hid_keyboard->ux_host_class_hid_keyboard_hid->ux_host_class_hid_interface->ux_interface_descriptor.bInterfaceNumber;
556
557 status = ux_host_stack_transfer_request(transfer_request);
558 if (status != UX_SUCCESS)
559 {
560 printf("ERROR #%d: code 0x%x\n", __LINE__, status);
561 error_counter ++;
562 }
563
564 /* Resume the keyboard interrupt thread. */
565 tx_thread_suspend(&hid_keyboard_slave->ux_slave_class_hid_interface->ux_slave_interface_class->ux_slave_class_thread);
566
567 /* Request a size that is larger than the max control transfer, and when there are no events. */
568 stepinfo(">>>>>>>>>> SetReport(noID, %d)\n", UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH + 1);
569
570 transfer_request -> ux_transfer_request_data_pointer = buffer;
571 transfer_request -> ux_transfer_request_requested_length = UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH + 1;
572 transfer_request -> ux_transfer_request_value = (UINT)((USHORT) 0 | (USHORT) UX_HOST_CLASS_HID_REPORT_TYPE_INPUT << 8);
573 transfer_request -> ux_transfer_request_index = hid_keyboard->ux_host_class_hid_keyboard_hid->ux_host_class_hid_interface->ux_interface_descriptor.bInterfaceNumber;
574
575 status = ux_host_stack_transfer_request(transfer_request);
576 if (status != UX_SUCCESS)
577 {
578 printf("ERROR #%d: code 0x%x\n", __LINE__, status);
579 error_counter ++;
580 }
581 }
582
583 stepinfo(">>>>>>>>>> SetReport(1, %d)\n", UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH + 1);
584
585 /* Create a transfer request for the SET_REPORT request. */
586 transfer_request -> ux_transfer_request_requested_length = UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH + 1;
587 transfer_request -> ux_transfer_request_value = (UINT)((USHORT) 1 | (USHORT) UX_HOST_CLASS_HID_REPORT_TYPE_INPUT << 8);
588 transfer_request -> ux_transfer_request_index = hid_mouse->ux_host_class_hid_mouse_hid->ux_host_class_hid_interface->ux_interface_descriptor.bInterfaceNumber;
589
590 status = ux_host_stack_transfer_request(transfer_request);
591 if (status != UX_SUCCESS)
592 {
593 printf("ERROR #%d: code 0x%x\n", __LINE__, status);
594 error_counter ++;
595 }
596
597 stepinfo(">>>>>>>>>> SetReport(FEATURE, 1, %d)\n", 2);
598
599 /* Create a transfer request for the SET_REPORT request. */
600 transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_SET_REPORT;
601 transfer_request -> ux_transfer_request_type = UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
602 transfer_request -> ux_transfer_request_requested_length = 2;
603 transfer_request -> ux_transfer_request_value = (UINT)((USHORT) 1 | (USHORT) UX_HOST_CLASS_HID_REPORT_TYPE_FEATURE << 8);
604 transfer_request -> ux_transfer_request_index = hid_mouse->ux_host_class_hid_mouse_hid->ux_host_class_hid_interface->ux_interface_descriptor.bInterfaceNumber;
605 buffer[0] = 1;
606 buffer[1] = 0x5A;
607
608 status = ux_host_stack_transfer_request(transfer_request);
609 if (status != UX_SUCCESS)
610 {
611 printf("ERROR #%d: code 0x%x\n", __LINE__, status);
612 error_counter ++;
613 }
614
615 stepinfo(">>>>>>>>>> GetReport(FEATURE, 1, %d)\n", 2);
616
617 /* Create a transfer request for the GET_REPORT request. */
618 transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_GET_REPORT;
619 transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
620 transfer_request -> ux_transfer_request_requested_length = 2;
621 transfer_request -> ux_transfer_request_value = (UINT)((USHORT) 1 | (USHORT) UX_HOST_CLASS_HID_REPORT_TYPE_FEATURE << 8);
622 transfer_request -> ux_transfer_request_index = hid_mouse->ux_host_class_hid_mouse_hid->ux_host_class_hid_interface->ux_interface_descriptor.bInterfaceNumber;
623 buffer[0] = 0;
624 buffer[1] = 0;
625
626 status = ux_host_stack_transfer_request(transfer_request);
627 if (status != UX_SUCCESS)
628 {
629 printf("ERROR #%d: code 0x%x\n", __LINE__, status);
630 error_counter ++;
631 }
632 if (buffer[0] != 1)
633 {
634 printf("ERROR #%d: buffer[0] %x\n", __LINE__, buffer[0]);
635 error_counter ++;
636 }
637 if (buffer[1] != 0x5A)
638 {
639 printf("ERROR #%d: buffer[1] %x\n", __LINE__, buffer[1]);
640 error_counter ++;
641 }
642
643 stepinfo(">>>>>>>>>> GetReport(FEATURE, 1, %d)\n", UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH + 2);
644
645 /* Create a transfer request for the SET_REPORT request. */
646 transfer_request -> ux_transfer_request_requested_length = UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH + 2;
647 transfer_request -> ux_transfer_request_value = (UINT)((USHORT) 1 | (USHORT) UX_HOST_CLASS_HID_REPORT_TYPE_FEATURE << 8);
648 transfer_request -> ux_transfer_request_index = hid_mouse->ux_host_class_hid_mouse_hid->ux_host_class_hid_interface->ux_interface_descriptor.bInterfaceNumber;
649 event_callback_length_error = UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH + 3;
650
651 status = ux_host_stack_transfer_request(transfer_request);
652 if (status != UX_SUCCESS)
653 {
654 printf("ERROR #%d: code 0x%x\n", __LINE__, status);
655 error_counter ++;
656 }
657
658 if (hid_keyboard)
659 {
660
661 stepinfo(">>>>>>>>>> GetReport(keyboard, FEATURE, 1, %d)\n", 1);
662
663 /* Create a transfer request for the SET_REPORT request. */
664 transfer_request -> ux_transfer_request_requested_length = 1;
665 transfer_request -> ux_transfer_request_value = (UINT)((USHORT) 1 | (USHORT) UX_HOST_CLASS_HID_REPORT_TYPE_FEATURE << 8);
666 transfer_request -> ux_transfer_request_index = hid_keyboard->ux_host_class_hid_keyboard_hid->ux_host_class_hid_interface->ux_interface_descriptor.bInterfaceNumber;
667
668 status = ux_host_stack_transfer_request(transfer_request);
669 if (status != UX_SUCCESS)
670 {
671 printf("ERROR #%d: code 0x%x\n", __LINE__, status);
672 error_counter ++;
673 }
674 }
675
676 stepinfo(">>>>>>>>>> Test done\n");
677
678 /* Now disconnect the device. */
679 _ux_device_stack_disconnect();
680
681 /* And deinitialize the class. */
682 status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
683
684 /* Deinitialize the device side of usbx. */
685 _ux_device_stack_uninitialize();
686
687 /* And finally the usbx system resources. */
688 _ux_system_uninitialize();
689
690 if (error_counter)
691 {
692 printf("FAIL %ld errors!\n", error_counter);
693 test_control_return(1);
694 }
695
696 /* Successful test. */
697 printf("SUCCESS!\n");
698 test_control_return(0);
699 }
700
701 static UX_SLAVE_CLASS_HID_EVENT hid_mouse_slave_event;
702 static UX_SLAVE_CLASS_HID_EVENT hid_keyboard_slave_event;
demo_thread_hid_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)703 static UINT demo_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
704 {
705 /* Event buffer contains no report ID. */
706 if (class == hid_mouse_slave)
707 _ux_utility_memory_copy(&hid_mouse_slave_event, event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
708 if (class == hid_keyboard_slave)
709 _ux_utility_memory_copy(&hid_keyboard_slave_event, event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
710 return(UX_SUCCESS);
711 }
712
demo_thread_hid_get_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)713 static UINT demo_thread_hid_get_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
714 {
715 UX_SLAVE_CLASS_HID_EVENT *class_event;
716 if (class == hid_mouse_slave)
717 class_event = &hid_mouse_slave_event;
718 else if (class == hid_keyboard_slave)
719 class_event = &hid_keyboard_slave_event;
720 else
721 return(UX_ERROR);
722 if (class -> ux_device_class_hid_report_id)
723 {
724 /* First byte in buffer should be report ID, if report ID is required.
725 * See HID spec. for more details.
726 */
727 event->ux_device_class_hid_event_report_id = class_event->ux_device_class_hid_event_report_id;
728 event->ux_device_class_hid_event_report_type = class_event->ux_device_class_hid_event_report_type;
729 if (class_event->ux_device_class_hid_event_length < UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH - 1)
730 class_event->ux_device_class_hid_event_length += 1;
731 event->ux_device_class_hid_event_length = class_event->ux_device_class_hid_event_length;
732 *(event->ux_device_class_hid_event_buffer) = (UCHAR)event->ux_device_class_hid_event_report_id;
733 _ux_utility_memory_copy(event->ux_device_class_hid_event_buffer + 1,
734 class_event->ux_device_class_hid_event_buffer,
735 event->ux_device_class_hid_event_length - 1);
736 }
737 else
738 _ux_utility_memory_copy(event, class_event, sizeof(UX_SLAVE_CLASS_HID_EVENT));
739 if (event_callback_length_error)
740 {
741 event->ux_device_class_hid_event_length = event_callback_length_error;
742 event_callback_length_error = 0;
743 }
744 return(UX_SUCCESS);
745 }