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