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 }