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 
_is_mouse(UX_HOST_CLASS_HID_CLIENT * client)254 static UINT _is_mouse(UX_HOST_CLASS_HID_CLIENT *client)
255 {
256     return(UX_SUCCESS == _ux_utility_memory_compare(client->ux_host_class_hid_client_name,
257                 _ux_system_host_class_hid_client_mouse_name,
258                 _ux_utility_string_length_get(_ux_system_host_class_hid_client_mouse_name)));
259 }
_is_keyboard(UX_HOST_CLASS_HID_CLIENT * client)260 static UINT _is_keyboard(UX_HOST_CLASS_HID_CLIENT *client)
261 {
262     return(UX_SUCCESS == _ux_utility_memory_compare(client->ux_host_class_hid_client_name,
263                 _ux_system_host_class_hid_client_keyboard_name,
264                 _ux_utility_string_length_get(_ux_system_host_class_hid_client_keyboard_name)));
265 }
ux_system_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)266 static UINT ux_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
267 {
268 
269 UX_HOST_CLASS_HID_CLIENT *client = (UX_HOST_CLASS_HID_CLIENT *)inst;
270 
271     // if(event >= UX_HID_CLIENT_INSERTION) printf("hChg: ev %lx, cls %p, inst %p, %s\n", event, cls, inst, _is_mouse(client) ? "Mouse" : _is_keyboard(client) ? "Keyboard" : "Remote Control");
272     switch(event)
273     {
274 
275         case UX_HID_CLIENT_INSERTION:
276             if (_is_mouse(client))
277                 hid_mouse = (UX_HOST_CLASS_HID_MOUSE *)client->ux_host_class_hid_client_local_instance;
278             else
279             {
280                 if (_is_keyboard(client))
281                     hid_keyboard = (UX_HOST_CLASS_HID_KEYBOARD *)client->ux_host_class_hid_client_local_instance;
282                 else
283                     hid_remote_control = (UX_HOST_CLASS_HID_REMOTE_CONTROL *)client->ux_host_class_hid_client_local_instance;
284             }
285         break;
286 
287         case UX_HID_CLIENT_REMOVAL:
288             if (_is_mouse(client))
289                 hid_mouse = UX_NULL;
290             else
291             {
292                 if (_is_keyboard(client))
293                     hid_keyboard = UX_NULL;
294                 else
295                     hid_remote_control = UX_NULL;
296             }
297         break;
298 
299         default:
300         break;
301     }
302     return 0;
303 }
304 
mouse_instance_activate_callback(VOID * parameter)305 static VOID mouse_instance_activate_callback(VOID *parameter)
306 {
307     // printf("dMouse: %p\n", parameter);
308     hid_mouse_slave = (UX_SLAVE_CLASS_HID *)parameter;
309 }
310 
keyboard_instance_activate_callback(VOID * parameter)311 static VOID keyboard_instance_activate_callback(VOID *parameter)
312 {
313     // printf("dKeyboard: %p\n", parameter);
314     hid_keyboard_slave = (UX_SLAVE_CLASS_HID *)parameter;
315 }
316 
remote_control_instance_activate_callback(VOID * parameter)317 static VOID remote_control_instance_activate_callback(VOID *parameter)
318 {
319     // printf("dKeyboard: %p\n", parameter);
320     hid_remote_control_slave = (UX_SLAVE_CLASS_HID *)parameter;
321 }
322 
instance_deactivate_callback(VOID * parameter)323 static VOID instance_deactivate_callback(VOID *parameter)
324 {
325     // printf("dRm: %p\n", parameter);
326     if ((VOID *)hid_mouse_slave == parameter)
327         hid_mouse_slave = UX_NULL;
328 
329     if ((VOID *)hid_keyboard_slave == parameter)
330         hid_keyboard_slave = UX_NULL;
331 
332     if ((VOID *)hid_remote_control_slave == parameter)
333         hid_remote_control_slave = UX_NULL;
334 }
335 
error_callback(UINT system_level,UINT system_context,UINT error_code)336 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
337 {
338     if (error_code == UX_MEMORY_INSUFFICIENT)
339         error_callback_counter ++;
340     // printf("ERROR #%d: 0x%x, 0x%x, 0x%x\n", __LINE__, system_level, system_context, error_code);
341 }
342 
break_on_all_activated(VOID)343 static UINT break_on_all_activated(VOID)
344 {
345 
346     if (hid_mouse_slave == UX_NULL)
347         return 0;
348     if (hid_keyboard_slave == UX_NULL)
349         return 0;
350     if (hid_remote_control_slave == UX_NULL)
351         return 0;
352     if (hid_mouse == UX_NULL)
353         return 0;
354     if (hid_keyboard == UX_NULL)
355         return 0;
356     if (hid_remote_control == UX_NULL)
357         return 0;
358 
359     return 1;
360 }
361 
362 
break_on_all_removed(VOID)363 static UINT break_on_all_removed(VOID)
364 {
365     if (hid_mouse_slave || hid_keyboard_slave || hid_remote_control_slave)
366         return 0;
367     if (hid_mouse || hid_keyboard || hid_remote_control)
368         return 0;
369 
370     return 1;
371 }
372 
373 
sleep_break_on_error(VOID)374 static UINT  sleep_break_on_error(VOID)
375 {
376 
377     if (error_callback_counter >= 3)
378         return error_callback_counter;
379 
380     return UX_SUCCESS;
381 }
382 
383 
ux_test_hcd_entry_set_cfg(UX_TEST_ACTION * action,VOID * _params)384 static VOID ux_test_hcd_entry_set_cfg(UX_TEST_ACTION *action, VOID *_params)
385 {
386     rsc_mem_alloc_cnt_on_set_cfg = ux_test_utility_sim_mem_alloc_count();
387 }
388 
389 static UX_TEST_SETUP _SetConfigure = UX_TEST_SETUP_SetConfigure;
390 
391 static UX_TEST_HCD_SIM_ACTION log_on_SetCfg[] = {
392 /* function, request to match,
393    port action, port status,
394    request action, request EP, request data, request actual length, request status,
395    status, additional callback,
396    no_return */
397 {   UX_HCD_TRANSFER_REQUEST, &_SetConfigure,
398         UX_FALSE, UX_TEST_PORT_STATUS_DISC,
399         UX_TEST_SETUP_MATCH_REQ, 0, UX_NULL, 0, 0,
400         UX_SUCCESS, ux_test_hcd_entry_set_cfg,
401         UX_TRUE}, /* Invoke callback & continue */
402 {   0   }
403 };
404 
405 /* Define what the initial system looks like.  */
406 
407 #ifdef CTEST
test_application_define(void * first_unused_memory)408 void test_application_define(void *first_unused_memory)
409 #else
410 void    usbx_ux_device_class_hid_basic_memory_test_application_define(void *first_unused_memory)
411 #endif
412 {
413 
414 UINT                                                status;
415 CHAR                                               *stack_pointer;
416 CHAR                                               *memory_pointer;
417 ULONG                                               mem_free;
418 ULONG                                               alloc_count;
419 ULONG                                               test_n;
420 
421     /* Inform user.  */
422     printf("Running UX Class HID Basic Memory test ............................. ");
423     stepinfo("\n");
424 
425     /* Initialize memory logger. */
426     ux_test_utility_sim_mem_alloc_log_enable(UX_TRUE);
427     ux_test_utility_sim_mem_alloc_count_reset();
428 
429     /* Initialize the free memory pointer */
430     stack_pointer = (CHAR *) usbx_memory;
431     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
432 
433     /* Initialize USBX. Memory */
434     status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
435 
436     /* Check for error.  */
437     if (status != UX_SUCCESS)
438     {
439 
440         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
441         test_control_return(1);
442     }
443 
444     /* Register the error callback. */
445     _ux_utility_error_callback_register(error_callback);
446 
447     /* The code below is required for installing the host portion of USBX */
448     status =  ux_host_stack_initialize(ux_system_host_change_function);
449     if (status != UX_SUCCESS)
450     {
451 
452         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
453         test_control_return(1);
454     }
455 
456     status =  ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
457     if (status != UX_SUCCESS)
458     {
459 
460         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
461         test_control_return(1);
462     }
463 
464     /* Register the HID client(s).  */
465     status |= ux_host_class_hid_client_register(_ux_system_host_class_hid_client_mouse_name, ux_host_class_hid_mouse_entry);
466     status |= ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
467     status |= ux_host_class_hid_client_register(_ux_system_host_class_hid_client_remote_control_name, ux_host_class_hid_remote_control_entry);
468 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
469     if (status != UX_SUCCESS)
470     {
471 
472         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
473         test_control_return(1);
474     }
475 #endif
476 
477     /* The code below is required for installing the device portion of USBX. No call back for
478        device status change in this example. */
479     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
480                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
481                                        string_framework, STRING_FRAMEWORK_LENGTH,
482                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
483     if(status!=UX_SUCCESS)
484     {
485 
486         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
487         test_control_return(1);
488     }
489 
490     /* Initialize the hid class parameters for mouse and keyboard.  */
491     hid_mouse_parameter.ux_device_class_hid_parameter_report_address    = hid_mouse_report;
492     hid_mouse_parameter.ux_device_class_hid_parameter_report_length     = HID_MOUSE_REPORT_LENGTH;
493     hid_mouse_parameter.ux_device_class_hid_parameter_callback          = demo_thread_hid_callback;
494     hid_mouse_parameter.ux_slave_class_hid_instance_activate            = mouse_instance_activate_callback;
495     hid_mouse_parameter.ux_slave_class_hid_instance_deactivate          = instance_deactivate_callback;
496 
497     hid_keyboard_parameter.ux_device_class_hid_parameter_report_address = hid_keyboard_report;
498     hid_keyboard_parameter.ux_device_class_hid_parameter_report_length  = HID_KEYBOARD_REPORT_LENGTH;
499     hid_keyboard_parameter.ux_device_class_hid_parameter_callback       = demo_thread_hid_callback;
500     hid_keyboard_parameter.ux_slave_class_hid_instance_activate         = keyboard_instance_activate_callback;
501     hid_keyboard_parameter.ux_slave_class_hid_instance_deactivate       = instance_deactivate_callback;
502 
503     hid_remote_control_parameter.ux_device_class_hid_parameter_report_address = hid_remote_control_report;
504     hid_remote_control_parameter.ux_device_class_hid_parameter_report_length  = HID_REMOTE_CONTROL_REPORT_LENGTH;
505     hid_remote_control_parameter.ux_device_class_hid_parameter_callback       = demo_thread_hid_callback;
506     hid_remote_control_parameter.ux_slave_class_hid_instance_activate =         remote_control_instance_activate_callback;
507     hid_remote_control_parameter.ux_slave_class_hid_instance_deactivate =       instance_deactivate_callback;
508 
509     stepinfo(">>>>>>>>>> Test HID Class Initialize/deinitialize memory\n");
510 
511     stepinfo(">>>>>>>>>> - Reset counts\n");
512     ux_test_utility_sim_mem_alloc_count_reset();
513     mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
514 
515     stepinfo(">>>>>>>>>> - _class_register\n");
516 
517     /* Initilize the device hid class. */
518     status  = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
519                                              1,1, (VOID *)&hid_mouse_parameter);
520     status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
521                                              1,0, (VOID *)&hid_keyboard_parameter);
522     status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
523                                              1,2, (VOID *)&hid_remote_control_parameter);
524 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
525     if(status!=UX_SUCCESS)
526     {
527 
528         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
529         test_control_return(1);
530     }
531 #endif
532 #if 1
533     /* Log create counts when instances active for further tests. */
534     alloc_count = ux_test_utility_sim_mem_alloc_count();
535 
536     /* Lock log base for tests. */
537     ux_test_utility_sim_mem_alloc_log_lock();
538 
539     stepinfo("init & uninit alloc : %ld\n", alloc_count);
540     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);
541 
542     if (alloc_count) stepinfo(">>>>>>>>>> - Init/deinit memory errors test\n");
543     mem_free = (~0);
544     for (test_n = 0; test_n < alloc_count; test_n ++)
545     {
546 
547         stepinfo("%4ld / %4ld\n", test_n, alloc_count - 1);
548 
549         /* Unregister. */
550         ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
551         ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
552         ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
553 
554         /* Update memory free level (disconnect) */
555         if (mem_free == (~0))
556             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
557         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
558         {
559 
560             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);
561             error_counter ++;
562             test_control_return(1);
563         }
564 
565         /* Set memory error generation */
566         ux_test_utility_sim_mem_alloc_error_generation_start(test_n);
567 
568         /* Register. */
569         status  = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
570                                                 1,1, (VOID *)&hid_mouse_parameter);
571         status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
572                                                 1,0, (VOID *)&hid_keyboard_parameter);
573         status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
574                                                 1,2, (VOID *)&hid_remote_control_parameter);
575 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
576         /* Check error */
577         if (status == UX_SUCCESS)
578         {
579 
580             printf("ERROR #%d.%ld: registered when there is memory error\n", __LINE__, test_n);
581             error_counter ++;
582         }
583 #endif
584 
585         stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
586     }
587     ux_test_utility_sim_mem_alloc_error_generation_stop();
588     if (alloc_count) stepinfo("\n");
589 
590     /* Unregister. */
591     ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
592     ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
593     ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
594 
595     /* Register. */
596     status  = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
597                                             1,1, (VOID *)&hid_mouse_parameter);
598     status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
599                                             1,0, (VOID *)&hid_keyboard_parameter);
600     status |= ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
601                                             1,2, (VOID *)&hid_remote_control_parameter);
602 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
603     if(status!=UX_SUCCESS)
604     {
605 
606         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
607         test_control_return(1);
608     }
609 #endif
610 #endif
611     /* Initialize the simulated device controller.  */
612     status =  _ux_dcd_sim_slave_initialize();
613 
614     /* Check for error.  */
615     if (status != UX_SUCCESS)
616     {
617 
618         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
619         test_control_return(1);
620     }
621 
622     /* Register all the USB host controllers available in this system */
623     status =  ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
624 
625     /* Check for error.  */
626     if (status != UX_SUCCESS)
627     {
628 
629         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
630         test_control_return(1);
631     }
632 
633     /* Create the main host simulation thread.  */
634     status =  tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
635             stack_pointer, UX_DEMO_STACK_SIZE,
636             20, 20, 1, TX_AUTO_START);
637 
638     /* Check for error.  */
639     if (status != TX_SUCCESS)
640     {
641 
642         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
643         test_control_return(1);
644     }
645 
646 #if defined(UX_DEVICE_STANDALONE)
647 
648     /* Create the main device simulation thread.  */
649     status =  tx_thread_create(&tx_demo_thread_device_simulation, "tx demo device simulation", tx_demo_thread_device_simulation_entry, 0,
650             stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE,
651             20, 20, 1, TX_AUTO_START);
652 
653     /* Check for error.  */
654     if (status != TX_SUCCESS)
655     {
656 
657         printf("ERROR #%d, code 0x%x\n", __LINE__, status);
658         test_control_return(1);
659     }
660 #endif
661 }
662 
663 #if defined(UX_DEVICE_STANDALONE)
tx_demo_thread_device_simulation_entry(ULONG arg)664 static void  tx_demo_thread_device_simulation_entry(ULONG arg)
665 {
666     while(1)
667     {
668         ux_system_tasks_run();
669         tx_thread_relinquish();
670     }
671 }
672 #endif
673 
tx_demo_thread_host_simulation_entry(ULONG arg)674 static void  tx_demo_thread_host_simulation_entry(ULONG arg)
675 {
676 
677 UINT                                                status;
678 UX_DEVICE                                           *device;
679 ULONG                                               mem_free;
680 ULONG                                               alloc_count;
681 ULONG                                               test_n;
682 UX_HCD                                              *hcd;
683 
684 
685     stepinfo(">>>>>>>>>> Thread start\n");
686 
687     hcd = &_ux_system_host->ux_system_host_hcd_array[0];
688 
689     ux_test_breakable_sleep(500, break_on_all_activated);
690 
691     /* Get device instance. */
692     status = ux_host_stack_device_get(0, &device);
693 
694     if (status != UX_SUCCESS)
695     {
696         printf("ERROR #%d: get_device fail, 0x%x\n", __LINE__, status);
697         test_control_return(1);
698     }
699 
700     stepinfo(">>>>>>>>>> Disconnect\n");
701 
702     ux_test_dcd_sim_slave_disconnect();
703     ux_test_hcd_sim_host_disconnect();
704 
705     if (hid_keyboard || hid_mouse)
706     {
707         printf("ERROR #%d\n", __LINE__);
708         test_control_return(1);
709     }
710 
711     stepinfo(">>>>>>>>>> Reset counts\n");
712 
713     ux_test_utility_sim_mem_alloc_count_reset();
714     mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
715 
716     rsc_mem_alloc_cnt_on_set_cfg = 0;
717     ux_test_hcd_sim_host_set_actions(log_on_SetCfg);
718 
719     stepinfo(">>>>>>>>>> Connect\n");
720 
721     ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
722     ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
723     ux_test_breakable_sleep(500, break_on_all_activated);
724 
725     /* Log create counts for further tests. */
726     rsc_enum_mem_alloc_count = rsc_mem_alloc_cnt_on_set_cfg;
727 
728     /* Log create counts when instances active for further tests. */
729     alloc_count = ux_test_utility_sim_mem_alloc_count();
730 
731     /* Lock log base for tests. */
732     ux_test_utility_sim_mem_alloc_log_lock();
733 
734     rsc_hid_mem_alloc_count = alloc_count - rsc_enum_mem_alloc_count;
735 
736     stepinfo("enum mem: %ld\n", rsc_enum_mem_alloc_count);
737     stepinfo("hid mem : %ld\n", rsc_hid_mem_alloc_count);
738     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);
739 
740     if (hid_mouse == UX_NULL
741 #if UX_MAX_SLAVE_CLASS_DRIVER > 1
742         || hid_keyboard == UX_NULL
743 #endif
744         )
745     {
746         printf("ERROR #%d: %p %p\n", __LINE__, hid_keyboard, hid_mouse);
747         test_control_return(1);
748     }
749 
750     /* Simulate detach and attach for FS enumeration,
751        and test possible memory allocation error handlings.
752      */
753     if (rsc_hid_mem_alloc_count) stepinfo(">>>>>>>>>> Memory errors enumeration test\n");
754     mem_free = (~0);
755     for (test_n = 0; test_n < rsc_hid_mem_alloc_count; test_n ++)
756     {
757 
758         stepinfo("%4ld / %4ld\n", test_n, rsc_hid_mem_alloc_count - 1);
759 
760         /* Disconnect. */
761         ux_test_dcd_sim_slave_disconnect();
762         ux_test_hcd_sim_host_disconnect();
763 
764         /* Check number of devices.  */
765         if (hcd->ux_hcd_nb_devices != 0)
766         {
767             printf("ERROR #%d.%ld: number of devices (%d) must be 0\n", __LINE__, test_n, hcd->ux_hcd_nb_devices);
768             error_counter ++;
769         }
770 
771         /* Update memory free level (disconnect) */
772         if (mem_free == (~0))
773             mem_free = _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available;
774         else if (mem_free != _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available)
775         {
776 
777             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);
778             error_counter ++;
779             test_control_return(1);
780         }
781 
782         /* Set memory error generation */
783         ux_test_utility_sim_mem_alloc_error_generation_start(test_n + rsc_enum_mem_alloc_count);
784 
785         /* Connect. */
786         error_callback_counter = 0;
787         ux_test_dcd_sim_slave_connect(UX_FULL_SPEED_DEVICE);
788 #if 1 /* @nick */
789         ux_test_hcd_sim_host_connect_no_wait(UX_FULL_SPEED_DEVICE);
790 
791         /* Wait for enum thread to complete. */
792         ux_test_wait_for_enum_thread_completion();
793 #else
794         ux_test_hcd_sim_host_connect(UX_FULL_SPEED_DEVICE);
795 
796         /* Wait and break on errors. */
797         ux_test_breakable_sleep(400, sleep_break_on_error);
798 #endif
799 
800         /* Check error */
801         if (hid_mouse && hid_keyboard && hid_mouse_slave && hid_keyboard_slave && hid_remote_control && hid_remote_control_slave)
802         {
803 
804             printf("ERROR #%d.%ld: device detected when there is memory error\n", __LINE__, test_n);
805             error_counter ++;
806         }
807         stepinfo("mem free: %ld\n", _ux_system -> ux_system_memory_byte_pool[UX_MEMORY_BYTE_POOL_REGULAR] -> ux_byte_pool_available);
808         ux_test_utility_sim_mem_alloc_error_generation_stop();
809     }
810     if (alloc_count) stepinfo("\n");
811 
812     stepinfo(">>>>>>>>>> Test done\n");
813 
814     /* Now disconnect the device.  */
815     _ux_device_stack_disconnect();
816 
817     /* And deinitialize the class.  */
818     status =  ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
819 
820     /* Deinitialize the device side of usbx.  */
821     _ux_device_stack_uninitialize();
822 
823     /* And finally the usbx system resources.  */
824     _ux_system_uninitialize();
825 
826     if (error_counter)
827     {
828         printf("FAIL %ld errors!\n", error_counter);
829         test_control_return(1);
830     }
831 
832     /* Successful test.  */
833     printf("SUCCESS!\n");
834     test_control_return(0);
835 }
836 
demo_thread_hid_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)837 static UINT    demo_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
838 {
839     return(UX_SUCCESS);
840 }
841