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 #include "ux_host_class_hid_remote_control.h"
12 
13 
14 static UCHAR hid_keyboard_report[] = {
15 
16     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
17     0x09, 0x06,                    // USAGE (Keyboard)
18     0xa1, 0x01,                    // COLLECTION (Application)
19     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
20     0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
21     0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
22     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
23     0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
24     0x75, 0x01,                    //   REPORT_SIZE (1)
25     0x95, 0x08,                    //   REPORT_COUNT (8)
26     0x81, 0x02,                    //   INPUT (Data,Var,Abs)
27     0x95, 0x01,                    //   REPORT_COUNT (1)
28     0x75, 0x08,                    //   REPORT_SIZE (8)
29     0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)
30     0x95, 0x05,                    //   REPORT_COUNT (5)
31     0x75, 0x01,                    //   REPORT_SIZE (1)
32     0x05, 0x08,                    //   USAGE_PAGE (LEDs)
33     0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
34     0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
35     0x91, 0x02,                    //   OUTPUT (Data,Var,Abs)
36     0x95, 0x01,                    //   REPORT_COUNT (1)
37     0x75, 0x03,                    //   REPORT_SIZE (3)
38     0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs)
39     0x95, 0x06,                    //   REPORT_COUNT (6)
40     0x75, 0x08,                    //   REPORT_SIZE (8)
41     0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
42     0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
43     0x05, 0x07,                    //   USAGE_PAGE (Keyboard)
44     0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
45     0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)
46     0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
47     0xc0,                          // END_COLLECTION
48 
49     0xa1, 0x01,                    // COLLECTION (Application)
50     0x19, 0x01,                    //   USAGE_MINIMUM (1)
51     0x29, 0x04,                    //   USAGE_MAXIMUM (4)
52     0x75, 0x04,                    //   REPORT_SIZE (4)
53     0x95, 0x04,                    //   REPORT_COUNT (4)
54     0xb1, 0x02,                    //   FEATURE (Data,Var,Abs)
55     0x85, 0x02,                    //   REPORT_ID (2)
56     0x19, 0x05,                    //   USAGE_MINIMUM (5)
57     0x29, 0x07,                    //   USAGE_MAXIMUM (7)
58     0x75, 0x08,                    //   REPORT_SIZE (8)
59     0x95, 0x03,                    //   REPORT_COUNT (3)
60     0xb1, 0x02,                    //   FEATURE (Data,Var,Abs)
61     0x85, 0x04,                    //   REPORT_ID (4)
62     0x09, 0x08,                    //   USAGE (8)
63     0x75, 0x10,                    //   REPORT_SIZE (16)
64     0x95, 0x01,                    //   REPORT_COUNT (1)
65     0xb1, 0x02,                    //   FEATURE (Data,Var,Abs)
66     0xc0,                          // END_COLLECTION
67 };
68 #define HID_KEYBOARD_REPORT_LENGTH sizeof(hid_keyboard_report)/sizeof(hid_keyboard_report[0])
69 
70 
71 static UCHAR hid_mouse_report[] = {
72 
73     0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
74     0x09, 0x02,                    // USAGE (Mouse)
75     0xa1, 0x01,                    // COLLECTION (Application)
76     0x09, 0x01,                    //   USAGE (Pointer)
77     0xa1, 0x00,                    //   COLLECTION (Physical)
78     0x05, 0x09,                    //     USAGE_PAGE (Button)
79     0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
80     0x29, 0x03,                    //     USAGE_MAXIMUM (Button 3)
81     0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
82     0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
83     0x95, 0x03,                    //     REPORT_COUNT (3)
84     0x75, 0x01,                    //     REPORT_SIZE (1)
85     0x81, 0x02,                    //     INPUT (Data,Var,Abs)
86     0x95, 0x01,                    //     REPORT_COUNT (1)
87     0x75, 0x05,                    //     REPORT_SIZE (5)
88     0x81, 0x03,                    //     INPUT (Cnst,Var,Abs)
89     0x05, 0x01,                    //     USAGE_PAGE (Generic Desktop)
90     0x09, 0x30,                    //     USAGE (X)
91     0x09, 0x31,                    //     USAGE (Y)
92     0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
93     0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
94     0x75, 0x08,                    //     REPORT_SIZE (8)
95     0x95, 0x02,                    //     REPORT_COUNT (2)
96     0x81, 0x06,                    //     INPUT (Data,Var,Rel)
97     0x09, 0x38,                    //     USAGE (Mouse Wheel)
98     0x15, 0x81,                    //     LOGICAL_MINIMUM (-127)
99     0x25, 0x7f,                    //     LOGICAL_MAXIMUM (127)
100     0x75, 0x08,                    //     REPORT_SIZE (8)
101     0x95, 0x01,                    //     REPORT_COUNT (1)
102     0x81, 0x06,                    //     INPUT (Data,Var,Rel)
103     0xc0,                          //   END_COLLECTION
104     0xc0,                          // END_COLLECTION
105 };
106 #define HID_MOUSE_REPORT_LENGTH (sizeof(hid_mouse_report)/sizeof(hid_mouse_report[0]))
107 
108 static UCHAR hid_remote_control_report[] = {
109 
110     0x05, 0x0c,                    // USAGE_PAGE (Consumer Devices)
111     0x09, 0x01,                    // USAGE (Consumer Control)
112     0xa1, 0x01,                    // COLLECTION (Application)
113     0x09, 0x02,                    //   USAGE (Numeric Key Pad)
114     0xa1, 0x02,                    //   COLLECTION (Logical)
115     0x05, 0x09,                    //     USAGE_PAGE (Button)
116     0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
117     0x29, 0x0a,                    //     USAGE_MAXIMUM (Button 10)
118     0x15, 0x01,                    //     LOGICAL_MINIMUM (1)
119     0x25, 0x0a,                    //     LOGICAL_MAXIMUM (10)
120     0x75, 0x04,                    //     REPORT_SIZE (4)
121     0x95, 0x01,                    //     REPORT_COUNT (1)
122     0x81, 0x00,                    //     INPUT (Data,Ary,Abs)
123     0xc0,                          //   END_COLLECTION
124     0x05, 0x0c,                    //   USAGE_PAGE (Consumer Devices)
125     0x09, 0x86,                    //   USAGE (Channel)
126     0x09, 0xe0,                    //   USAGE (Volume)
127     0x15, 0xff,                    //   LOGICAL_MINIMUM (-1)
128     0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
129     0x75, 0x02,                    //   REPORT_SIZE (2)
130     0x95, 0x02,                    //   REPORT_COUNT (2)
131     0x81, 0x46,                    //   INPUT (Data,Var,Rel,Null)
132     0xc0                           // END_COLLECTION
133 };
134 #define HID_REMOTE_CONTROL_REPORT_LENGTH (sizeof(hid_remote_control_report)/sizeof(hid_remote_control_report[0]))
135 
136 /* Configuration descriptor 9 bytes */
137 #define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
138     /* Configuration 1 descriptor 9 bytes */\
139     0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
140     (bNumInterfaces), (bConfigurationValue), 0x00,\
141     0x40, 0x00,
142 #define CFG_DESC_LEN (9)
143 
144 
145 /* HID Mouse/Keyboard interface descriptors 9+9+7=25 bytes */
146 #define HID_IFC_DESC_ALL(ifc, report_len, interrupt_epa) \
147     /* Interface descriptor */\
148     0x09, 0x04, (ifc), 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,\
149     /* HID descriptor */\
150     0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(report_len),\
151         MSB(report_len),\
152     /* Endpoint descriptor (Interrupt) */\
153     0x07, 0x05, (interrupt_epa), 0x03, 0x08, 0x00, 0x08,
154 #define HID_IFC_DESC_ALL_LEN (9+9+7)
155 
156 
157 static UCHAR device_framework_full_speed[] = {
158 
159     /* Device descriptor */
160     0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
161     0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
162     0x00, 0x01,
163 
164     CFG_DESC(CFG_DESC_LEN+3*HID_IFC_DESC_ALL_LEN, 2, 1)
165     /* Keyboard */
166     HID_IFC_DESC_ALL(0, HID_KEYBOARD_REPORT_LENGTH, 0x82)
167     /* Mouse */
168     HID_IFC_DESC_ALL(1, HID_MOUSE_REPORT_LENGTH, 0x81)
169     /* Remote control */
170     HID_IFC_DESC_ALL(2, HID_REMOTE_CONTROL_REPORT_LENGTH, 0x83)
171 };
172 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
173 
174 
175 static UCHAR device_framework_high_speed[] = {
176 
177     /* Device descriptor */
178     0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
179     0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
180     0x03, 0x01,
181 
182     /* Device qualifier descriptor */
183     0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
184     0x01, 0x00,
185 
186     CFG_DESC(CFG_DESC_LEN+3*HID_IFC_DESC_ALL_LEN, 2, 1)
187     /* Keyboard */
188     HID_IFC_DESC_ALL(0, HID_KEYBOARD_REPORT_LENGTH, 0x82)
189     /* Mouse */
190     HID_IFC_DESC_ALL(1, HID_MOUSE_REPORT_LENGTH, 0x81)
191     /* Remote control */
192     HID_IFC_DESC_ALL(2, HID_REMOTE_CONTROL_REPORT_LENGTH, 0x83)
193 };
194 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
195 
196 
197 /* String Device Framework :
198     Byte 0 and 1 : Word containing the language ID : 0x0904 for US
199     Byte 2       : Byte containing the index of the descriptor
200     Byte 3       : Byte containing the length of the descriptor string
201 */
202 static UCHAR string_framework[] = {
203 
204     /* Manufacturer string descriptor : Index 1 */
205     0x09, 0x04, 0x01, 0x0c,
206     0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
207     0x6f, 0x67, 0x69, 0x63,
208 
209     /* Product string descriptor : Index 2 */
210     0x09, 0x04, 0x02, 0x0c,
211     0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
212     0x6f, 0x61, 0x72, 0x64,
213 
214     /* Serial Number string descriptor : Index 3 */
215     0x09, 0x04, 0x03, 0x04,
216     0x30, 0x30, 0x30, 0x31
217 };
218 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
219 
220 
221 /* Multiple languages are supported on the device, to add
222     a language besides english, the unicode language code must
223     be appended to the language_id_framework array and the length
224     adjusted accordingly. */
225 static UCHAR language_id_framework[] = {
226 
227     /* English. */
228     0x09, 0x04
229 };
230 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
231 
232 static UX_HOST_CLASS_HID                   *hid = UX_NULL;
233 static UX_HOST_CLASS_HID_MOUSE             *hid_mouse = UX_NULL;
234 static UX_HOST_CLASS_HID_KEYBOARD          *hid_keyboard = UX_NULL;
235 static UX_HOST_CLASS_HID_REMOTE_CONTROL    *hid_remote_control = UX_NULL;
236 
237 static UX_SLAVE_CLASS_HID                  *hid_mouse_slave = UX_NULL;
238 static UX_SLAVE_CLASS_HID                  *hid_keyboard_slave = UX_NULL;
239 static UX_SLAVE_CLASS_HID                  *hid_remote_control_slave = UX_NULL;
240 
241 static UX_SLAVE_CLASS_HID_PARAMETER         hid_mouse_parameter;
242 static UX_SLAVE_CLASS_HID_PARAMETER         hid_keyboard_parameter;
243 static UX_SLAVE_CLASS_HID_PARAMETER         hid_remote_control_parameter;
244 
245 static ULONG                               rsc_mem_alloc_cnt_on_set_cfg;
246 static ULONG                               rsc_enum_mem_alloc_count;
247 static ULONG                               rsc_hid_mem_alloc_count;
248 
249 static ULONG                               error_callback_counter;
250 static UCHAR                               error_callback_ignore;
251 
252 static ULONG                               error_counter = 0;
253 
ux_system_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)254 static UINT ux_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
255 {
256 
257 UX_HOST_CLASS_HID_CLIENT *client = (UX_HOST_CLASS_HID_CLIENT *)inst;
258 UINT                      is_mouse = (UX_SUCCESS == _ux_utility_memory_compare(client->ux_host_class_hid_client_name,
259                                                                 _ux_system_host_class_hid_client_mouse_name,
260                                                                 _ux_utility_string_length_get(_ux_system_host_class_hid_client_mouse_name)));
261 UINT                      is_keyboard = (UX_SUCCESS == _ux_utility_memory_compare(client->ux_host_class_hid_client_name,
262                                                                 _ux_system_host_class_hid_client_keyboard_name,
263                                                                 _ux_utility_string_length_get(_ux_system_host_class_hid_client_keyboard_name)));
264 
265     // if(event >= UX_HID_CLIENT_INSERTION) printf("hChg: ev %lx, cls %p, inst %p, %s\n", event, cls, inst, is_mouse ? "Mouse" : "Keyboard");
266     switch(event)
267     {
268 
269         case UX_HID_CLIENT_INSERTION:
270             if (is_mouse)
271                 hid_mouse = (UX_HOST_CLASS_HID_MOUSE *)client->ux_host_class_hid_client_local_instance;
272             else
273             {
274                 if (is_keyboard)
275                     hid_keyboard = (UX_HOST_CLASS_HID_KEYBOARD *)client->ux_host_class_hid_client_local_instance;
276                 else
277                     hid_remote_control = (UX_HOST_CLASS_HID_REMOTE_CONTROL *)client->ux_host_class_hid_client_local_instance;
278             }
279         break;
280 
281         case UX_HID_CLIENT_REMOVAL:
282             if (is_mouse)
283                 hid_mouse = UX_NULL;
284             else
285             {
286                 if (is_keyboard)
287                     hid_keyboard = UX_NULL;
288                 else
289                     hid_remote_control = UX_NULL;
290             }
291         break;
292 
293         default:
294         break;
295     }
296     return 0;
297 }
298 
mouse_instance_activate_callback(VOID * parameter)299 static VOID mouse_instance_activate_callback(VOID *parameter)
300 {
301     // printf("dMouse: %p\n", parameter);
302     hid_mouse_slave = (UX_SLAVE_CLASS_HID *)parameter;
303 }
304 
keyboard_instance_activate_callback(VOID * parameter)305 static VOID keyboard_instance_activate_callback(VOID *parameter)
306 {
307     // printf("dKeyboard: %p\n", parameter);
308     hid_keyboard_slave = (UX_SLAVE_CLASS_HID *)parameter;
309 }
310 
remote_control_instance_activate_callback(VOID * parameter)311 static VOID remote_control_instance_activate_callback(VOID *parameter)
312 {
313     // printf("dKeyboard: %p\n", parameter);
314     hid_remote_control_slave = (UX_SLAVE_CLASS_HID *)parameter;
315 }
316 
instance_deactivate_callback(VOID * parameter)317 static VOID instance_deactivate_callback(VOID *parameter)
318 {
319     // printf("dRm: %p\n", parameter);
320     if ((VOID *)hid_mouse_slave == parameter)
321         hid_mouse_slave = UX_NULL;
322 
323     if ((VOID *)hid_keyboard_slave == parameter)
324         hid_keyboard_slave = UX_NULL;
325 
326     if ((VOID *)hid_remote_control_slave == parameter)
327         hid_remote_control_slave = UX_NULL;
328 }
329 
error_callback(UINT system_level,UINT system_context,UINT error_code)330 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
331 {
332     if (error_code == UX_MEMORY_INSUFFICIENT)
333         error_callback_counter ++;
334     // printf("ERROR #%d: 0x%x, 0x%x, 0x%x\n", __LINE__, system_level, system_context, error_code);
335 }
336 
break_on_all_activated(VOID)337 static UINT break_on_all_activated(VOID)
338 {
339 
340     if (hid_mouse_slave == UX_NULL)
341         return 0;
342     if (hid_keyboard_slave == UX_NULL)
343         return 0;
344     if (hid_remote_control_slave == UX_NULL)
345         return 0;
346     if (hid_mouse == UX_NULL)
347         return 0;
348     if (hid_keyboard == UX_NULL)
349         return 0;
350     if (hid_remote_control == UX_NULL)
351         return 0;
352 
353     return 1;
354 }
355 
356 
break_on_all_removed(VOID)357 static UINT break_on_all_removed(VOID)
358 {
359     if (hid_mouse_slave || hid_keyboard_slave || hid_remote_control_slave)
360         return 0;
361     if (hid_mouse || hid_keyboard || hid_remote_control)
362         return 0;
363 
364     return 1;
365 }
366 
367 
sleep_break_on_error(VOID)368 static UINT  sleep_break_on_error(VOID)
369 {
370 
371     if (error_callback_counter >= 3)
372         return error_callback_counter;
373 
374     return UX_SUCCESS;
375 }
376 
377 
ux_test_hcd_entry_set_cfg(UX_TEST_ACTION * action,VOID * _params)378 static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *_params)
379 {
380     rsc_mem_alloc_cnt_on_set_cfg = ux_test_utility_sim_mem_alloc_count();
381 }
382 
383 static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
384 
385 static UX_TEST_HCD_SIM_ACTION log_on_SetCfg[] = {
386 /* function, request to match,
387    port action, port status,
388    request action, request EP, request data, request actual length, request status,
389    status, additional callback,
390    no_return */
391 {   UX_HCD_TRANSFER_REQUEST, &_SetConfigure,
392         UX_FALSE, UX_TEST_PORT_STATUS_DISC,
393         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
394         UX_SUCCESS, ux_test_hcd_entry_set_cfg,
395         UX_TRUE}, /* Invoke callback & continue */
396 {   0   }
397 };
398 
399 /* Define what the initial system looks like.  */
400 
401 #ifdef CTEST
test_application_define(void * first_unused_memory)402 void test_application_define(void *first_unused_memory)
403 #else
404 void    usbx_ux_device_class_hid_receiver_memory_test_application_define(void *first_unused_memory)
405 #endif
406 {
407 
408 UINT                                                status;
409 CHAR                                               *stack_pointer;
410 CHAR                                               *memory_pointer;
411 ULONG                                               mem_free;
412 ULONG                                               alloc_count;
413 ULONG                                               test_n;
414 
415     /* Inform user.  */
416     printf("Running ux_device_class_hid Receiver Memory test ................... ");
417     stepinfo("\n");
418 
419     /* Initialize memory logger. */
420     ux_test_utility_sim_mem_alloc_log_enable(UX_TRUE);
421     ux_test_utility_sim_mem_alloc_count_reset();
422 
423     /* Initialize the free memory pointer */
424     stack_pointer = (CHAR *) usbx_memory;
425     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
426 
427     /* Initialize USBX. Memory */
428     status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
429 
430     /* Check for error.  */
431     if (status != UX_SUCCESS)
432     {
433 
434         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
435         test_control_return(1);
436     }
437 
438     /* Register the error callback. */
439     _ux_utility_error_callback_register(error_callback);
440 
441     /* The code below is required for installing the host portion of USBX */
442     status =  ux_host_stack_initialize(ux_system_host_change_function);
443     if (status != UX_SUCCESS)
444     {
445 
446         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
447         test_control_return(1);
448     }
449 
450     status =  ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
451     if (status != UX_SUCCESS)
452     {
453 
454         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
455         test_control_return(1);
456     }
457 
458     /* Register the HID client(s).  */
459     status |= ux_host_class_hid_client_register(_ux_system_host_class_hid_client_mouse_name, ux_host_class_hid_mouse_entry);
460     status |= ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
461     status |= ux_host_class_hid_client_register(_ux_system_host_class_hid_client_remote_control_name, ux_host_class_hid_remote_control_entry);
462 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
463     if (status != UX_SUCCESS)
464     {
465 
466         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
467         test_control_return(1);
468     }
469 #endif
470 
471     /* The code below is required for installing the device portion of USBX. No call back for
472        device status change in this example. */
473     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
474                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
475                                        string_framework, STRING_FRAMEWORK_LENGTH,
476                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
477     if(status!=UX_SUCCESS)
478     {
479 
480         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
481         test_control_return(1);
482     }
483 
484     /* Initialize the hid class parameters for mouse and keyboard.  */
485     hid_mouse_parameter.ux_device_class_hid_parameter_report_address          = hid_mouse_report;
486     hid_mouse_parameter.ux_device_class_hid_parameter_report_length           = HID_MOUSE_REPORT_LENGTH;
487     hid_mouse_parameter.ux_device_class_hid_parameter_callback                = demo_thread_hid_callback;
488     hid_mouse_parameter.ux_slave_class_hid_instance_activate                  = mouse_instance_activate_callback;
489     hid_mouse_parameter.ux_slave_class_hid_instance_deactivate                = instance_deactivate_callback;
490 
491     hid_keyboard_parameter.ux_device_class_hid_parameter_report_address       = hid_keyboard_report;
492     hid_keyboard_parameter.ux_device_class_hid_parameter_report_length        = HID_KEYBOARD_REPORT_LENGTH;
493     hid_keyboard_parameter.ux_device_class_hid_parameter_callback             = demo_thread_hid_callback;
494     hid_keyboard_parameter.ux_slave_class_hid_instance_activate               = keyboard_instance_activate_callback;
495     hid_keyboard_parameter.ux_slave_class_hid_instance_deactivate             = instance_deactivate_callback;
496 
497     hid_remote_control_parameter.ux_device_class_hid_parameter_report_address = hid_remote_control_report;
498     hid_remote_control_parameter.ux_device_class_hid_parameter_report_length  = HID_REMOTE_CONTROL_REPORT_LENGTH;
499     hid_remote_control_parameter.ux_device_class_hid_parameter_callback       = demo_thread_hid_callback;
500     hid_remote_control_parameter.ux_slave_class_hid_instance_activate         = remote_control_instance_activate_callback;
501     hid_remote_control_parameter.ux_slave_class_hid_instance_deactivate       = instance_deactivate_callback;
502 
503 #if defined(UX_DEVICE_CLASS_HID_INTERRUPT_OUT_SUPPORT)
504     hid_mouse_parameter.ux_device_class_hid_parameter_receiver_initialize                = ux_device_class_hid_receiver_initialize;
505     hid_mouse_parameter.ux_device_class_hid_parameter_receiver_event_max_number          = 8;
506     hid_mouse_parameter.ux_device_class_hid_parameter_receiver_event_max_length          = 32;
507 
508     hid_keyboard_parameter.ux_device_class_hid_parameter_receiver_initialize             = ux_device_class_hid_receiver_initialize;
509     hid_keyboard_parameter.ux_device_class_hid_parameter_receiver_event_max_number       = 8;
510     hid_keyboard_parameter.ux_device_class_hid_parameter_receiver_event_max_length       = 32;
511 
512     hid_remote_control_parameter.ux_device_class_hid_parameter_receiver_initialize       = ux_device_class_hid_receiver_initialize;
513     hid_remote_control_parameter.ux_device_class_hid_parameter_receiver_event_max_number = 8;
514     hid_remote_control_parameter.ux_device_class_hid_parameter_receiver_event_max_length = 32;
515 #endif
516 
517     stepinfo(">>>>>>>>>> Test HID Class Initialize/deinitialize memory\n");
518 
519     stepinfo(">>>>>>>>>> - Reset counts\n");
520     ux_test_utility_sim_mem_alloc_count_reset();
521     mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
522 
523     stepinfo(">>>>>>>>>> - _class_register\n");
524 
525     /* Initilize the device hid class. */
526     status  = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
527                                              1,1, (VOID *)&hid_mouse_parameter);
528     status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
529                                              1,0, (VOID *)&hid_keyboard_parameter);
530     status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
531                                              1,2, (VOID *)&hid_remote_control_parameter);
532 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
533     if(status!=UX_SUCCESS)
534     {
535 
536         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
537         test_control_return(1);
538     }
539 #endif
540 #if 1
541     /* Log create counts when instances active for further tests. */
542     alloc_count = ux_test_utility_sim_mem_alloc_count();
543 
544     /* Lock log base for tests. */
545     ux_test_utility_sim_mem_alloc_log_lock();
546 
547     stepinfo("init & uninit alloc : %ld\n", alloc_count);
548     stepinfo("mem free            : %ld, %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available);
549 
550     if (alloc_count) stepinfo(">>>>>>>>>> - Init/deinit memory errors test\n");
551     mem_free = (~0);
552     for (test_n = 0; test_n < alloc_count; test_n ++)
553     {
554 
555         stepinfo("%4ld / %4ld\n", test_n, alloc_count - 1);
556 
557         /* Unregister. */
558         ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
559         ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
560         ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
561 
562         /* Update memory free level (disconnect) */
563         if (mem_free == (~0))
564             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
565         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
566         {
567 
568             printf("ERROR #%d.%ld: Memory level different after re-enumerations %ld <> %ld\n", __LINE__, test_n, mem_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
569             error_counter ++;
570             test_control_return(1);
571         }
572 
573         /* Set memory error generation */
574         ux_test_utility_sim_mem_alloc_error_generation_start(test_n);
575 
576         /* Register. */
577         status  = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
578                                                 1,1, (VOID *)&hid_mouse_parameter);
579         status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
580                                                 1,0, (VOID *)&hid_keyboard_parameter);
581         status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
582                                                 1,2, (VOID *)&hid_remote_control_parameter);
583 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
584         /* Check error */
585         if (status == UX_SUCCESS)
586         {
587 
588             printf("ERROR #%d.%ld: registered when there is memory error\n", __LINE__, test_n);
589             error_counter ++;
590         }
591 #endif
592 
593         stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
594     }
595     ux_test_utility_sim_mem_alloc_error_generation_stop();
596     if (alloc_count) stepinfo("\n");
597 
598     /* Unregister. */
599     ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
600     ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
601     ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
602 
603     /* Register. */
604     status  = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
605                                             1,1, (VOID *)&hid_mouse_parameter);
606     status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
607                                             1,0, (VOID *)&hid_keyboard_parameter);
608     status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
609                                             1,2, (VOID *)&hid_remote_control_parameter);
610 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
611     if(status!=UX_SUCCESS)
612     {
613 
614         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
615         test_control_return(1);
616     }
617 #endif
618 #endif
619     /* Initialize the simulated device controller.  */
620     status =  _ux_dcd_sim_slave_initialize();
621 
622     /* Check for error.  */
623     if (status != UX_SUCCESS)
624     {
625 
626         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
627         test_control_return(1);
628     }
629 
630     /* Register all the USB host controllers available in this system */
631     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
632 
633     /* Check for error.  */
634     if (status != UX_SUCCESS)
635     {
636 
637         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
638         test_control_return(1);
639     }
640 
641     /* Create the main host simulation thread.  */
642     status =  tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
643             stack_pointer, UX_DEMO_STACK_SIZE,
644             20, 20, 1, TX_AUTO_START);
645 
646     /* Check for error.  */
647     if (status != TX_SUCCESS)
648     {
649 
650         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
651         test_control_return(1);
652     }
653 
654     /* Create the main device simulation thread.  */
655     stack_pointer += UX_DEMO_STACK_SIZE;
656     status =  tx_thread_create(&tx_demo_thread_device_simulation, "tx demo device simulation", tx_demo_thread_device_simulation_entry, 0,
657             stack_pointer, UX_DEMO_STACK_SIZE,
658             20, 20, 1, TX_AUTO_START);
659 
660     /* Check for error.  */
661     if (status != TX_SUCCESS)
662     {
663 
664         printf("ERROR $%d, error code: 0x%x\n", __LINE__, status);
665         test_control_return(1);
666     }
667 }
668 
tx_demo_thread_host_simulation_entry(ULONG arg)669 static void  tx_demo_thread_host_simulation_entry(ULONG arg)
670 {
671 
672 UINT                                                status;
673 UX_DEVICE                                           *device;
674 ULONG                                               mem_free;
675 ULONG                                               alloc_count;
676 ULONG                                               test_n;
677 UX_HCD                                              *hcd;
678 
679 
680     stepinfo(">>>>>>>>>> Thread start\n");
681 
682     hcd = &_ux_system_host->ux_system_host_hcd_array[0];
683 
684     ux_test_breakable_sleep(500, break_on_all_activated);
685 
686     /* Get device instance. */
687     status = ux_host_stack_device_get(0, &device);
688 
689     if (status != UX_SUCCESS)
690     {
691         printf("ERROR #%d: get_device fail, 0x%x\n", __LINE__, status);
692         test_control_return(1);
693     }
694 
695     stepinfo(">>>>>>>>>> Disconnect\n");
696 
697     ux_test_dcd_sim_slave_disconnect();
698     ux_test_hcd_sim_host_disconnect();
699 
700     if (hid_keyboard || hid_mouse)
701     {
702         printf("ERROR #%d\n", __LINE__);
703         test_control_return(1);
704     }
705 
706     stepinfo(">>>>>>>>>> Reset counts\n");
707 
708     ux_test_utility_sim_mem_alloc_count_reset();
709     mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
710 
711     rsc_mem_alloc_cnt_on_set_cfg = 0;
712     ux_test_hcd_sim_host_set_actions(log_on_SetCfg);
713 
714     stepinfo(">>>>>>>>>> Connect\n");
715 
716     ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
717     ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
718     ux_test_breakable_sleep(500, break_on_all_activated);
719 
720     /* Log create counts for further tests. */
721     rsc_enum_mem_alloc_count = rsc_mem_alloc_cnt_on_set_cfg;
722 
723     /* Log create counts when instances active for further tests. */
724     alloc_count = ux_test_utility_sim_mem_alloc_count();
725 
726     /* Lock log base for tests. */
727     ux_test_utility_sim_mem_alloc_log_lock();
728 
729     rsc_hid_mem_alloc_count = alloc_count - rsc_enum_mem_alloc_count;
730 
731     stepinfo("enum mem: %ld\n", rsc_enum_mem_alloc_count);
732     stepinfo("hid mem : %ld\n", rsc_hid_mem_alloc_count);
733     stepinfo("mem free: %ld, %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_CACHE_SAFE] -> ux_byte_pool_available);
734 
735     if (hid_mouse == UX_NULL
736 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
737         || hid_keyboard == UX_NULL
738 #endif
739         )
740     {
741         printf("ERROR #%d: %p %p\n", __LINE__, hid_keyboard, hid_mouse);
742         test_control_return(1);
743     }
744 
745     /* Simulate detach and attach for FS enumeration,
746        and test possible memory allocation error handlings.
747      */
748     if (rsc_hid_mem_alloc_count) stepinfo(">>>>>>>>>> Memory errors enumeration test\n");
749     mem_free = (~0);
750     for (test_n = 0; test_n < rsc_hid_mem_alloc_count; test_n ++)
751     {
752 
753         stepinfo("%4ld / %4ld\n", test_n, rsc_hid_mem_alloc_count - 1);
754 
755         /* Disconnect. */
756         ux_test_dcd_sim_slave_disconnect();
757         ux_test_hcd_sim_host_disconnect();
758 
759         /* Check number of devices.  */
760         if (hcd->ux_hcd_nb_devices != 0)
761         {
762             printf("ERROR #%d.%ld: number of devices (%d) must be 0\n", __LINE__, test_n, hcd->ux_hcd_nb_devices);
763             error_counter ++;
764         }
765 
766         /* Update memory free level (disconnect) */
767         if (mem_free == (~0))
768             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
769         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
770         {
771 
772             printf("ERROR #%d.%ld: Memory level different after re-enumerations %ld <> %ld\n", __LINE__, test_n, mem_free, _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
773             error_counter ++;
774             test_control_return(1);
775         }
776 
777         /* Set memory error generation */
778         ux_test_utility_sim_mem_alloc_error_generation_start(test_n + rsc_enum_mem_alloc_count);
779 
780         /* Connect. */
781         error_callback_counter = 0;
782         ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
783 #if 1 /* @nick */
784         ux_test_hcd_sim_host_connect_no_wait(UX_FULL_SPEED_DEVICE);
785 
786         /* Wait for enum thread to complete. */
787         ux_test_wait_for_enum_thread_completion();
788 #else
789         ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
790 
791         /* Wait and break on errors. */
792         ux_test_breakable_sleep(400, sleep_break_on_error);
793 #endif
794 
795         /* Check error */
796         if (hid_mouse && hid_keyboard && hid_mouse_slave && hid_keyboard_slave && hid_remote_control && hid_remote_control_slave)
797         {
798 
799             printf("ERROR #%d.%ld: device detected when there is memory error\n", __LINE__, test_n);
800             error_counter ++;
801         }
802         stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
803         ux_test_utility_sim_mem_alloc_error_generation_stop();
804     }
805     if (alloc_count) stepinfo("\n");
806 
807     stepinfo(">>>>>>>>>> Test done\n");
808 
809     /* Now disconnect the device.  */
810     _ux_device_stack_disconnect();
811 
812     /* And deinitialize the class.  */
813     status =  ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
814 
815     /* Deinitialize the device side of usbx.  */
816     _ux_device_stack_uninitialize();
817 
818     /* And finally the usbx system resources.  */
819     _ux_system_uninitialize();
820 
821     if (error_counter)
822     {
823         printf("FAIL %ld errors!\n", error_counter);
824         test_control_return(1);
825     }
826 
827     /* Successful test.  */
828     printf("SUCCESS!\n");
829     test_control_return(0);
830 }
831 
tx_demo_thread_device_simulation_entry(ULONG arg)832 static void  tx_demo_thread_device_simulation_entry(ULONG arg)
833 {
834 
835     while(1)
836     {
837 #if defined(UX_DEVICE_STANDALONE)
838         ux_system_tasks_run();
839 #else
840         /* Nothing to do.  */
841         tx_thread_sleep(1000);
842 #endif
843     }
844 }
845 
demo_thread_hid_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)846 static UINT    demo_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
847 {
848     return(UX_SUCCESS);
849 }
850