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_basic_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 Basic 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     stepinfo(">>>>>>>>>> Test HID Class Initialize/deinitialize memory\n");
504 
505     stepinfo(">>>>>>>>>> - Reset counts\n");
506     ux_test_utility_sim_mem_alloc_count_reset();
507     mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
508 
509     stepinfo(">>>>>>>>>> - _class_register\n");
510 
511     /* Initilize the device hid class. */
512     status  = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
513                                              1,1, (VOID *)&hid_mouse_parameter);
514     status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
515                                              1,0, (VOID *)&hid_keyboard_parameter);
516     status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
517                                              1,2, (VOID *)&hid_remote_control_parameter);
518 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
519     if(status!=UX_SUCCESS)
520     {
521 
522         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
523         test_control_return(1);
524     }
525 #endif
526 #if 1
527     /* Log create counts when instances active for further tests. */
528     alloc_count = ux_test_utility_sim_mem_alloc_count();
529 
530     /* Lock log base for tests. */
531     ux_test_utility_sim_mem_alloc_log_lock();
532 
533     stepinfo("init & uninit alloc : %ld\n", alloc_count);
534     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);
535 
536     if (alloc_count) stepinfo(">>>>>>>>>> - Init/deinit memory errors test\n");
537     mem_free = (~0);
538     for (test_n = 0; test_n < alloc_count; test_n ++)
539     {
540 
541         stepinfo("%4ld / %4ld\n", test_n, alloc_count - 1);
542 
543         /* Unregister. */
544         ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
545         ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
546         ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
547 
548         /* Update memory free level (disconnect) */
549         if (mem_free == (~0))
550             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
551         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
552         {
553 
554             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);
555             error_counter ++;
556             test_control_return(1);
557         }
558 
559         /* Set memory error generation */
560         ux_test_utility_sim_mem_alloc_error_generation_start(test_n);
561 
562         /* Register. */
563         status  = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
564                                                 1,1, (VOID *)&hid_mouse_parameter);
565         status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
566                                                 1,0, (VOID *)&hid_keyboard_parameter);
567         status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
568                                                 1,2, (VOID *)&hid_remote_control_parameter);
569 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
570         /* Check error */
571         if (status == UX_SUCCESS)
572         {
573 
574             printf("ERROR #%d.%ld: registered when there is memory error\n", __LINE__, test_n);
575             error_counter ++;
576         }
577 #endif
578 
579         stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
580     }
581     ux_test_utility_sim_mem_alloc_error_generation_stop();
582     if (alloc_count) stepinfo("\n");
583 
584     /* Unregister. */
585     ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
586     ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
587     ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
588 
589     /* Register. */
590     status  = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
591                                             1,1, (VOID *)&hid_mouse_parameter);
592     status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
593                                             1,0, (VOID *)&hid_keyboard_parameter);
594     status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
595                                             1,2, (VOID *)&hid_remote_control_parameter);
596 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
597     if(status!=UX_SUCCESS)
598     {
599 
600         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
601         test_control_return(1);
602     }
603 #endif
604 #endif
605     /* Initialize the simulated device controller.  */
606     status =  _ux_dcd_sim_slave_initialize();
607 
608     /* Check for error.  */
609     if (status != UX_SUCCESS)
610     {
611 
612         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
613         test_control_return(1);
614     }
615 
616     /* Register all the USB host controllers available in this system */
617     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
618 
619     /* Check for error.  */
620     if (status != UX_SUCCESS)
621     {
622 
623         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
624         test_control_return(1);
625     }
626 
627     /* Create the main host simulation thread.  */
628     status =  tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
629             stack_pointer, UX_DEMO_STACK_SIZE,
630             20, 20, 1, TX_AUTO_START);
631 
632     /* Check for error.  */
633     if (status != TX_SUCCESS)
634     {
635 
636         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
637         test_control_return(1);
638     }
639 
640 #if defined(UX_DEVICE_STANDALONE)
641 
642     /* Create the main device simulation thread.  */
643     status =  tx_thread_create(&tx_demo_thread_device_simulation, "tx demo device simulation", tx_demo_thread_device_simulation_entry, 0,
644             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
645             20, 20, 1, TX_AUTO_START);
646 
647     /* Check for error.  */
648     if (status != TX_SUCCESS)
649     {
650 
651         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
652         test_control_return(1);
653     }
654 #endif
655 }
656 
657 #if defined(UX_DEVICE_STANDALONE)
tx_demo_thread_device_simulation_entry(ULONG arg)658 static void  tx_demo_thread_device_simulation_entry(ULONG arg)
659 {
660     while(1)
661     {
662         ux_system_tasks_run();
663         tx_thread_relinquish();
664     }
665 }
666 #endif
667 
tx_demo_thread_host_simulation_entry(ULONG arg)668 static void  tx_demo_thread_host_simulation_entry(ULONG arg)
669 {
670 
671 UINT                                                status;
672 UX_DEVICE                                           *device;
673 ULONG                                               mem_free;
674 ULONG                                               alloc_count;
675 ULONG                                               test_n;
676 UX_HCD                                              *hcd;
677 
678 
679     stepinfo(">>>>>>>>>> Thread start\n");
680 
681     hcd = &_ux_system_host->ux_system_host_hcd_array[0];
682 
683     ux_test_breakable_sleep(500, break_on_all_activated);
684 
685     /* Get device instance. */
686     status = ux_host_stack_device_get(0, &device);
687 
688     if (status != UX_SUCCESS)
689     {
690         printf("ERROR #%d: get_device fail, 0x%x\n", __LINE__, status);
691         test_control_return(1);
692     }
693 
694     stepinfo(">>>>>>>>>> Disconnect\n");
695 
696     ux_test_dcd_sim_slave_disconnect();
697     ux_test_hcd_sim_host_disconnect();
698 
699     if (hid_keyboard || hid_mouse)
700     {
701         printf("ERROR #%d\n", __LINE__);
702         test_control_return(1);
703     }
704 
705     stepinfo(">>>>>>>>>> Reset counts\n");
706 
707     ux_test_utility_sim_mem_alloc_count_reset();
708     mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
709 
710     rsc_mem_alloc_cnt_on_set_cfg = 0;
711     ux_test_hcd_sim_host_set_actions(log_on_SetCfg);
712 
713     stepinfo(">>>>>>>>>> Connect\n");
714 
715     ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
716     ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
717     ux_test_breakable_sleep(500, break_on_all_activated);
718 
719     /* Log create counts for further tests. */
720     rsc_enum_mem_alloc_count = rsc_mem_alloc_cnt_on_set_cfg;
721 
722     /* Log create counts when instances active for further tests. */
723     alloc_count = ux_test_utility_sim_mem_alloc_count();
724 
725     /* Lock log base for tests. */
726     ux_test_utility_sim_mem_alloc_log_lock();
727 
728     rsc_hid_mem_alloc_count = alloc_count - rsc_enum_mem_alloc_count;
729 
730     stepinfo("enum mem: %ld\n", rsc_enum_mem_alloc_count);
731     stepinfo("hid mem : %ld\n", rsc_hid_mem_alloc_count);
732     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);
733 
734     if (hid_mouse == UX_NULL
735 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
736         || hid_keyboard == UX_NULL
737 #endif
738         )
739     {
740         printf("ERROR #%d: %p %p\n", __LINE__, hid_keyboard, hid_mouse);
741         test_control_return(1);
742     }
743 
744     /* Simulate detach and attach for FS enumeration,
745        and test possible memory allocation error handlings.
746      */
747     if (rsc_hid_mem_alloc_count) stepinfo(">>>>>>>>>> Memory errors enumeration test\n");
748     mem_free = (~0);
749     for (test_n = 0; test_n < rsc_hid_mem_alloc_count; test_n ++)
750     {
751 
752         stepinfo("%4ld / %4ld\n", test_n, rsc_hid_mem_alloc_count - 1);
753 
754         /* Disconnect. */
755         ux_test_dcd_sim_slave_disconnect();
756         ux_test_hcd_sim_host_disconnect();
757 
758         /* Check number of devices.  */
759         if (hcd->ux_hcd_nb_devices != 0)
760         {
761             printf("ERROR #%d.%ld: number of devices (%d) must be 0\n", __LINE__, test_n, hcd->ux_hcd_nb_devices);
762             error_counter ++;
763         }
764 
765         /* Update memory free level (disconnect) */
766         if (mem_free == (~0))
767             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
768         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
769         {
770 
771             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);
772             error_counter ++;
773             test_control_return(1);
774         }
775 
776         /* Set memory error generation */
777         ux_test_utility_sim_mem_alloc_error_generation_start(test_n + rsc_enum_mem_alloc_count);
778 
779         /* Connect. */
780         error_callback_counter = 0;
781         ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
782 #if 1 /* @nick */
783         ux_test_hcd_sim_host_connect_no_wait(UX_FULL_SPEED_DEVICE);
784 
785         /* Wait for enum thread to complete. */
786         ux_test_wait_for_enum_thread_completion();
787 #else
788         ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
789 
790         /* Wait and break on errors. */
791         ux_test_breakable_sleep(400, sleep_break_on_error);
792 #endif
793 
794         /* Check error */
795         if (hid_mouse && hid_keyboard && hid_mouse_slave && hid_keyboard_slave && hid_remote_control && hid_remote_control_slave)
796         {
797 
798             printf("ERROR #%d.%ld: device detected when there is memory error\n", __LINE__, test_n);
799             error_counter ++;
800         }
801         stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
802         ux_test_utility_sim_mem_alloc_error_generation_stop();
803     }
804     if (alloc_count) stepinfo("\n");
805 
806     stepinfo(">>>>>>>>>> Test done\n");
807 
808     /* Now disconnect the device.  */
809     _ux_device_stack_disconnect();
810 
811     /* And deinitialize the class.  */
812     status =  ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
813 
814     /* Deinitialize the device side of usbx.  */
815     _ux_device_stack_uninitialize();
816 
817     /* And finally the usbx system resources.  */
818     _ux_system_uninitialize();
819 
820     if (error_counter)
821     {
822         printf("FAIL %ld errors!\n", error_counter);
823         test_control_return(1);
824     }
825 
826     /* Successful test.  */
827     printf("SUCCESS!\n");
828     test_control_return(0);
829 }
830 
demo_thread_hid_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)831 static UINT    demo_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
832 {
833     return(UX_SUCCESS);
834 }
835