1 /* This test is designed to test simple usage of the mouse class.  */
2 
3 #include "usbx_test_common_hid.h"
4 
5 #include "ux_host_class_hid_keyboard.h"
6 #include "ux_host_class_hid_mouse.h"
7 
8 #include "ux_test_utility_sim.h"
9 #include "ux_test_hcd_sim_host.h"
10 
11 static UX_HOST_CLASS_HID_MOUSE *mouse;
12 static UCHAR has_host_received;
13 
14 
15 static UCHAR hid_mouse_report[] = {
16 
17     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
18     0x09, 0x02,                    // USAGE (Mouse)
19     0xa1, 0x01,                    // COLLECTION (Application)
20     0x09, 0x01,                    //   USAGE (Pointer)
21     0xa1, 0x00,                    //   COLLECTION (Physical)
22     0x05, 0x09,                    //     USAGE_PAGE (Button)
23     0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
24     0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
25     0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
26     0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
27     0x95, 0x03,                    //     REPORT_COUNT (3)
28     0x75, 0x01,                    //     REPORT_SIZE (1)
29     0x81, 0x02,                    //     INPUT (Data,Var,Abs)
30     0x95, 0x01,                    //     REPORT_COUNT (1)
31     0x75, 0x05,                    //     REPORT_SIZE (5)
32     0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
33     0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
34     0x09, 0x30,                    //     USAGE (X)
35     0x09, 0x31,                    //     USAGE (Y)
36     0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
37     0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
38     0x75, 0x08,                    //     REPORT_SIZE (8)
39     0x95, 0x02,                    //     REPORT_COUNT (2)
40     0x81, 0x06,                    //     INPUT (Data,Var,Rel)
41     0x09, 0x38,                    //     USAGE (Mouse Wheel)
42     0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
43     0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
44     0x75, 0x08,                    //     REPORT_SIZE (8)
45     0x95, 0x01,                    //     REPORT_COUNT (1)
46     0x81, 0x06,                    //     INPUT (Data,Var,Rel)
47     0xc0,                          //   END_COLLECTION
48     0xc0                           // END_COLLECTION
49 };
50 #define HID_MOUSE_REPORT_LENGTH (sizeof(hid_mouse_report)/sizeof(hid_mouse_report[0]))
51 
52 
53 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 52
54 static UCHAR device_framework_full_speed[] = {
55 
56     /* Device descriptor */
57         0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
58         0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
59         0x00, 0x01,
60 
61     /* Configuration descriptor */
62         0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
63         0x32,
64 
65     /* Interface descriptor */
66         0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
67         0x00,
68 
69     /* HID descriptor */
70         0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_MOUSE_REPORT_LENGTH),
71         MSB(HID_MOUSE_REPORT_LENGTH),
72 
73     /* Endpoint descriptor (Interrupt) */
74         0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
75 
76     };
77 
78 
79 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 62
80 static UCHAR device_framework_high_speed[] = {
81 
82     /* Device descriptor */
83         0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
84         0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
85         0x03, 0x01,
86 
87     /* Device qualifier descriptor */
88         0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
89         0x01, 0x00,
90 
91     /* Configuration descriptor */
92         0x09, 0x02, 0x22, 0x00, 0x01, 0x01, 0x00, 0xc0,
93         0x32,
94 
95     /* Interface descriptor */
96         0x09, 0x04, 0x02, 0x00, 0x01, 0x03, 0x00, 0x00,
97         0x00,
98 
99     /* HID descriptor */
100         0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_MOUSE_REPORT_LENGTH),
101         MSB(HID_MOUSE_REPORT_LENGTH),
102 
103     /* Endpoint descriptor (Interrupt) */
104         0x07, 0x05, 0x82, 0x03, 0x08, 0x00, 0x08
105 
106     };
107 
108 
109     /* String Device Framework :
110      Byte 0 and 1 : Word containing the language ID : 0x0904 for US
111      Byte 2       : Byte containing the index of the descriptor
112      Byte 3       : Byte containing the length of the descriptor string
113     */
114 
115 #define STRING_FRAMEWORK_LENGTH 40
116 static UCHAR string_framework[] = {
117 
118     /* Manufacturer string descriptor : Index 1 */
119         0x09, 0x04, 0x01, 0x0c,
120         0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
121         0x6f, 0x67, 0x69, 0x63,
122 
123     /* Product string descriptor : Index 2 */
124         0x09, 0x04, 0x02, 0x0c,
125         0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
126         0x6f, 0x61, 0x72, 0x64,
127 
128     /* Serial Number string descriptor : Index 3 */
129         0x09, 0x04, 0x03, 0x04,
130         0x30, 0x30, 0x30, 0x31
131     };
132 
133 
134     /* Multiple languages are supported on the device, to add
135        a language besides english, the unicode language code must
136        be appended to the language_id_framework array and the length
137        adjusted accordingly. */
138 #define LANGUAGE_ID_FRAMEWORK_LENGTH 2
139 static UCHAR language_id_framework[] = {
140 
141     /* English. */
142         0x09, 0x04
143     };
144 
145 
error_callback(UINT system_level,UINT system_context,UINT error_code)146 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
147 {
148 
149     /* Failed test.  */
150     printf("Error on line %d, system_level: %d, system_context: %d, error code: %d\n", __LINE__, system_level, system_context, error_code);
151     test_control_return(1);
152 }
153 
154 /* Define what the initial system looks like.  */
155 
156 #ifdef CTEST
test_application_define(void * first_unused_memory)157 void test_application_define(void *first_unused_memory)
158 #else
159 void    usbx_hid_mouse_basic_test_application_define(void *first_unused_memory)
160 #endif
161 {
162 
163 UINT status;
164 CHAR *stack_pointer;
165 CHAR *memory_pointer;
166 
167     /* Inform user.  */
168     printf("Running HID Mouse Basic Functionality Test.......................... ");
169 
170     /* Initialize the free memory pointer */
171     stack_pointer = (CHAR *) usbx_memory;
172     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
173 
174     /* Initialize USBX. Memory */
175     status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
176 
177     /* Check for error.  */
178     if (status != UX_SUCCESS)
179     {
180 
181         printf("Error on line %d\n", __LINE__);
182         test_control_return(1);
183     }
184 
185     /* Register the error callback. */
186     _ux_utility_error_callback_register(error_callback);
187 
188     /* The code below is required for installing the host portion of USBX */
189     status =  ux_host_stack_initialize(UX_NULL);
190     if (status != UX_SUCCESS)
191     {
192 
193         printf("Error on line %d\n", __LINE__);
194         test_control_return(1);
195     }
196 
197     status =  ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
198     if (status != UX_SUCCESS)
199     {
200 
201         printf("Error on line %d\n", __LINE__);
202         test_control_return(1);
203     }
204 
205     /* Register the HID client(s).  */
206     status =  ux_host_class_hid_client_register(_ux_system_host_class_hid_client_mouse_name, ux_host_class_hid_mouse_entry);
207     if (status != UX_SUCCESS)
208     {
209 
210         printf("Error on line %d\n", __LINE__);
211         test_control_return(1);
212     }
213 
214     /* The code below is required for installing the device portion of USBX. No call back for
215        device status change in this example. */
216     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
217                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
218                                        string_framework, STRING_FRAMEWORK_LENGTH,
219                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
220     if(status!=UX_SUCCESS)
221     {
222 
223         printf("Error on line %d\n", __LINE__);
224         test_control_return(1);
225     }
226 
227     /* Initialize the hid class parameters for a mouse.  */
228     hid_parameter.ux_device_class_hid_parameter_report_address = hid_mouse_report;
229     hid_parameter.ux_device_class_hid_parameter_report_length  = HID_MOUSE_REPORT_LENGTH;
230     hid_parameter.ux_device_class_hid_parameter_callback       = demo_thread_hid_callback;
231 
232     /* Initilize the device hid class. The class is connected with interface 2 */
233     status =  ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
234                                                 1,2, (VOID *)&hid_parameter);
235     if(status!=UX_SUCCESS)
236     {
237 
238         printf("Error on line %d\n", __LINE__);
239         test_control_return(1);
240     }
241 
242 
243     /* Initialize the simulated device controller.  */
244     status =  _ux_dcd_sim_slave_initialize();
245 
246     /* Check for error.  */
247     if (status != UX_SUCCESS)
248     {
249 
250         printf("Error on line %d\n", __LINE__);
251         test_control_return(1);
252     }
253 
254     /* Register all the USB host controllers available in this system */
255     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0);
256 
257     /* Check for error.  */
258     if (status != UX_SUCCESS)
259     {
260 
261         printf("Error on line %d\n", __LINE__);
262         test_control_return(1);
263     }
264 
265     /* Create the main host simulation thread.  */
266     status =  tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
267             stack_pointer, UX_DEMO_STACK_SIZE,
268             20, 20, 1, TX_AUTO_START);
269 
270     /* Check for error.  */
271     if (status != TX_SUCCESS)
272     {
273 
274         printf("Error on line %d\n", __LINE__);
275         test_control_return(1);
276     }
277 
278     /* Create the main demo thread.  */
279     status =  tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0,
280             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
281             20, 20, 1, TX_AUTO_START);
282 
283     /* Check for error.  */
284     if (status != TX_SUCCESS)
285     {
286 
287         printf("Error on line %d\n", __LINE__);
288         test_control_return(1);
289     }
290 
291 }
292 
293 
sleep_break_on_removed(VOID)294 static UINT  sleep_break_on_removed(VOID)
295 {
296 
297 UINT            status;
298 UX_HOST_CLASS   *class;
299 
300     /* Find the main HID container. */
301     status =  ux_host_stack_class_get(_ux_system_host_class_hid_name, &class);
302     if (status == UX_SUCCESS)
303     {
304 
305         /* Find the instance. */
306         status =  ux_host_stack_class_instance_get(class, 0, (void **) &hid);
307         if (status != UX_SUCCESS)
308             return UX_TRUE;
309     }
310 
311     return UX_FALSE;
312 }
313 
314 
tx_demo_thread_host_simulation_entry(ULONG arg)315 static void  tx_demo_thread_host_simulation_entry(ULONG arg)
316 {
317 
318 UINT    status;
319 UINT    max_num_loops;
320 UINT    num_loops;
321 ULONG   num_attempts;
322 ULONG   max_attempts;
323 SLONG   cur_mouse_wheel_movement;
324 SLONG   next_mouse_wheel_movement;
325 SLONG   cur_mouse_x_position;
326 SLONG   cur_mouse_y_position;
327 SLONG   next_mouse_x_position;
328 SLONG   next_mouse_y_position;
329 ULONG   cur_mouse_buttons;
330 UCHAR   next_mouse_buttons;
331 
332     /* Initilize max loop value.  */
333     max_num_loops = 16;
334 
335     /* Find the HID class */
336     status =  demo_class_hid_get();
337     if (status != UX_SUCCESS)
338     {
339 
340         printf("Error on line %d\n", __LINE__);
341         test_control_return(1);
342     }
343 
344     /* Get the HID client */
345     hid_client = hid -> ux_host_class_hid_client;
346 
347     /* Check if the instance of the keyboard is live */
348     while (hid_client -> ux_host_class_hid_client_local_instance == UX_NULL)
349         tx_thread_sleep(10);
350 
351     /* Get the mouse instance */
352     mouse =  (UX_HOST_CLASS_HID_MOUSE *)hid_client -> ux_host_class_hid_client_local_instance;
353 
354     /* Set number of successful loops to execute. */
355     num_loops = 0;
356     max_num_loops = 16;
357 
358     /* Set number of fails. */
359     num_attempts = 0;
360     max_attempts = 3*max_num_loops;
361 
362     /* Set initial mouse button values. */
363     next_mouse_buttons = 0x01;
364 
365     /* Set initial mouse position values. */
366     next_mouse_x_position = -8;
367     next_mouse_y_position = -8;
368 
369     /* Set initial mouse wheel value. */
370     next_mouse_wheel_movement = -8;
371 
372     while (num_loops++ != max_num_loops)
373     {
374 
375         /* Once one works, the others should work as well. */
376         while (1)
377         {
378             ux_host_class_hid_mouse_buttons_get(mouse, &cur_mouse_buttons);
379             if (cur_mouse_buttons == next_mouse_buttons)
380                 break;
381             tx_thread_sleep(10);
382         }
383         ux_host_class_hid_mouse_position_get(mouse, &cur_mouse_x_position, &cur_mouse_y_position);
384         ux_host_class_hid_mouse_wheel_get(mouse, &cur_mouse_wheel_movement);
385 
386         /* Are these the expected values? */
387         UX_TEST_ASSERT(cur_mouse_buttons == next_mouse_buttons &&
388                        cur_mouse_x_position == next_mouse_x_position &&
389                        cur_mouse_y_position == next_mouse_y_position &&
390                        cur_mouse_wheel_movement == next_mouse_wheel_movement);
391 
392         /* Signal to device to continue.  */
393         has_host_received = 1;
394 
395         /* Increment values. */
396         next_mouse_buttons = 0x07 & (next_mouse_buttons + 1);
397         next_mouse_x_position++;
398         next_mouse_y_position++;
399         next_mouse_wheel_movement++;
400     }
401 
402     /* Simulate detach. */
403     ux_test_hcd_sim_host_disconnect();
404     ux_test_breakable_sleep(50, sleep_break_on_removed);
405 
406     /* Now disconnect the device.  */
407     _ux_device_stack_disconnect();
408 
409     /* And deinitialize the class.  */
410     status =  ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
411 
412     /* Deinitialize the device side of usbx.  */
413     _ux_device_stack_uninitialize();
414 
415     /* And finally the usbx system resources.  */
416     _ux_system_uninitialize();
417 
418     /* Successful test.  */
419     printf("SUCCESS!\n");
420     test_control_return(0);
421 }
422 
demo_thread_hid_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)423 static UINT    demo_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
424 {
425     return(UX_SUCCESS);
426 }
427 
tx_demo_thread_slave_simulation_entry(ULONG arg)428 static void  tx_demo_thread_slave_simulation_entry(ULONG arg)
429 {
430 
431 UX_SLAVE_DEVICE                 *device;
432 UX_SLAVE_INTERFACE              *interface;
433 UX_SLAVE_CLASS_HID              *hid;
434 UX_SLAVE_CLASS_HID_EVENT        hid_event;
435 
436     /* Get the pointer to the device.  */
437     device =  &_ux_system_slave -> ux_system_slave_device;
438 
439     /* reset the HID event structure.  */
440     ux_utility_memory_set(&hid_event, 0, sizeof(UX_SLAVE_CLASS_HID_EVENT));
441 
442     /* Set length of event.  */
443     hid_event.ux_device_class_hid_event_length = 4;
444 
445     /* Set initial value for buttons. The first three bits are for buttons, the rest are padding. */
446     hid_event.ux_device_class_hid_event_buffer[0] = 1;
447 
448     /* Set initial value for x and y positions. */
449     hid_event.ux_device_class_hid_event_buffer[1] = -8;
450     hid_event.ux_device_class_hid_event_buffer[2] = -8;
451 
452     /* Set initial value for mouse wheel. */
453     hid_event.ux_device_class_hid_event_buffer[3] = -8;
454 
455     while (1)
456     {
457 
458         /* Is the device configured ? */
459         while (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED)
460         {
461 #if defined(UX_DEVICE_STANDALONE)
462             ux_system_tasks_run();
463             tx_thread_relinquish();
464 #else
465             /* Then wait.  */
466             tx_thread_sleep(10);
467 #endif
468         }
469 
470 
471         /* Until the device stays configured.  */
472         while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED)
473         {
474 #if defined(UX_DEVICE_STANDALONE)
475             ux_system_tasks_run();
476             tx_thread_relinquish();
477 #endif
478 
479             /* Get the interface.  We use the first interface, this is a simple device.  */
480             interface =  device -> ux_slave_device_first_interface;
481 
482             /* From that interface, derive the HID owner.  */
483             hid = interface -> ux_slave_interface_class_instance;
484 
485             /* Set the mouse event.  */
486             ux_device_class_hid_event_set(hid, &hid_event);
487 
488             /* Wait for host to receive.  */
489             while (!has_host_received)
490             {
491 #if defined(UX_DEVICE_STANDALONE)
492                 ux_system_tasks_run();
493                 tx_thread_relinquish();
494 #else
495                 tx_thread_sleep(10);
496 #endif
497             }
498             has_host_received = 0;
499 
500             /* Change the buttons.  */
501             hid_event.ux_device_class_hid_event_buffer[0] = (0x7 & hid_event.ux_device_class_hid_event_buffer[0] + 1);
502 
503             /* Change the x, y, and wheel positions. These are relative values.  */
504             hid_event.ux_device_class_hid_event_buffer[1] = 1;
505             hid_event.ux_device_class_hid_event_buffer[2] = 1;
506             hid_event.ux_device_class_hid_event_buffer[3] = 1;
507         }
508     }
509 }
510 
511