1 /* This file tests the
2 * _ux_device_class_hid_control_request
3 * _ux_device_class_hid_interrupt_thread
4 */
5
6 #include "usbx_test_common_hid.h"
7
8 #include "ux_test_dcd_sim_slave.h"
9 #include "ux_test_hcd_sim_host.h"
10 #include "ux_test_utility_sim.h"
11
12 #include "ux_host_class_hid_mouse.h"
13 #include "ux_host_class_hid_keyboard.h"
14
15 #include "ux_host_stack.h"
16
17 #define DUMMY_USBX_MEMORY_SIZE (64*1024)
18
19 static UCHAR dummy_usbx_memory[DUMMY_USBX_MEMORY_SIZE];
20
21 static UX_SLAVE_CLASS_HID *slave_hid = UX_NULL;
22 static UX_SLAVE_CLASS_HID_EVENT slave_hid_event;
23
24 #define HOST_BUFFER_LENGTH 32
25
26 static UCHAR host_buffer[HOST_BUFFER_LENGTH];
27 static ULONG host_buffer_length;
28
29 static UCHAR hid_report_descriptor[] = {
30
31 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
32 0x09, 0x06, // USAGE (Keyboard)
33 0xa1, 0x01, // COLLECTION (Application)
34 0x05, 0x07, // USAGE_PAGE (Keyboard)
35 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
36 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
37 0x15, 0x00, // LOGICAL_MINIMUM (0)
38 0x25, 0x01, // LOGICAL_MAXIMUM (1)
39 0x75, 0x01, // REPORT_SIZE (1)
40 0x95, 0x08, // REPORT_COUNT (8)
41 0x81, 0x02, // INPUT (Data,Var,Abs)
42 0x95, 0x01, // REPORT_COUNT (1)
43 0x75, 0x08, // REPORT_SIZE (8)
44 0x81, 0x03, // INPUT (Cnst,Var,Abs)
45 0x95, 0x05, // REPORT_COUNT (5)
46 0x75, 0x01, // REPORT_SIZE (1)
47 0x05, 0x08, // USAGE_PAGE (LEDs)
48 0x19, 0x01, // USAGE_MINIMUM (Num Lock)
49 0x29, 0x05, // USAGE_MAXIMUM (Kana)
50 0x91, 0x02, // OUTPUT (Data,Var,Abs)
51 0x95, 0x01, // REPORT_COUNT (1)
52 0x75, 0x03, // REPORT_SIZE (3)
53 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
54 0x95, 0x06, // REPORT_COUNT (6)
55 0x75, 0x08, // REPORT_SIZE (8)
56 0x15, 0x00, // LOGICAL_MINIMUM (0)
57 0x25, 0x65, // LOGICAL_MAXIMUM (101)
58 0x05, 0x07, // USAGE_PAGE (Keyboard)
59 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
60 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
61 0x81, 0x00, // INPUT (Data,Ary,Abs)
62 0xc0 // END_COLLECTION
63 };
64 #define HID_REPORT_LENGTH sizeof(hid_report_descriptor)/sizeof(hid_report_descriptor[0])
65
66 /* Configuration descriptor 9 bytes */
67 #define CFG_DESC(wTotalLength, bNumInterfaces, bConfigurationValue)\
68 /* Configuration 1 descriptor 9 bytes */\
69 0x09, 0x02, LSB(wTotalLength), MSB(wTotalLength),\
70 (bNumInterfaces), (bConfigurationValue), 0x00,\
71 0x40, 0x00,
72 #define CFG_DESC_LEN 9
73
74 /* HID Mouse interface descriptors 9+9+7=25 bytes */
75 #define HID_MOUSE_IFC_DESC_ALL(ifc, interrupt_epa) \
76 /* Interface descriptor */\
77 0x09, 0x04, (ifc), 0x00, 0x01, 0x03, 0x00, 0x00, 0x00,\
78 /* HID descriptor */\
79 0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),\
80 MSB(HID_REPORT_LENGTH),\
81 /* Endpoint descriptor (Interrupt) */\
82 0x07, 0x05, (interrupt_epa), 0x03, 0x08, 0x00, 0x08,
83 #define HID_MOUSE_IFC_DESC_ALL_LEN 25
84
85 /* HID Mouse interface descriptors 9+9+7+7=32 bytes */
86 #define HID_TEST_IFC_DESC_ALL(ifc, epa0, epa0_type, epa1, epa1_type) \
87 /* Interface descriptor */\
88 0x09, 0x04, (ifc), 0x00, 0x02, 0x03, 0x00, 0x00, 0x00,\
89 /* HID descriptor */\
90 0x09, 0x21, 0x10, 0x01, 0x21, 0x01, 0x22, LSB(HID_REPORT_LENGTH),\
91 MSB(HID_REPORT_LENGTH),\
92 /* Endpoint descriptor */\
93 0x07, 0x05, (epa0), (epa0_type), 0x08, 0x00, 0x08,\
94 /* Endpoint descriptor */\
95 0x07, 0x05, (epa1), (epa1_type), 0x08, 0x00, 0x08,
96 #define HID_TEST_IFC_DESC_ALL_LEN 32
97
98 static UCHAR device_framework_full_speed[] = {
99
100 /* Device descriptor @ 0 */
101 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08,
102 0x81, 0x0A, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x01,
104
105 /* Configuration descriptor @ 18 */
106 CFG_DESC(CFG_DESC_LEN+2*HID_TEST_IFC_DESC_ALL_LEN, 2, 1)
107 /* Interrupt IN @ 1st */
108 HID_TEST_IFC_DESC_ALL(0, 0x81, 3, 0x02, 3)
109 /* HID interface but no interrupt IN */
110 HID_TEST_IFC_DESC_ALL(1, 0x84, 2, 0x03, 3)
111 };
112 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
113 #define DEVICE_FRAMEWORK_OFFSET_FS_EP_MPS (DEVICE_FRAMEWORK_LENGTH_FULL_SPEED-HID_TEST_IFC_DESC_ALL_LEN-7-7+4)
114
115
116 static UCHAR device_framework_high_speed[] = {
117
118 /* Device descriptor */
119 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
120 0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02,
121 0x03, 0x01,
122
123 /* Device qualifier descriptor */
124 0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
125 0x01, 0x00,
126
127 CFG_DESC(CFG_DESC_LEN+HID_MOUSE_IFC_DESC_ALL_LEN+HID_TEST_IFC_DESC_ALL_LEN, 2, 1)
128 /* Good HID interface. */
129 HID_MOUSE_IFC_DESC_ALL(0, 0x81)
130 /* Interrupt IN @ 2nd. */
131 HID_TEST_IFC_DESC_ALL(1, 0x03, 3, 0x84, 3)
132 };
133 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
134 #define DEVICE_FRAMEWORK_OFFSET_HS_EP_MPS (DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED-HID_TEST_IFC_DESC_ALL_LEN-7+4)
135
136
137 /* String Device Framework :
138 Byte 0 and 1 : Word containing the language ID : 0x0904 for US
139 Byte 2 : Byte containing the index of the descriptor
140 Byte 3 : Byte containing the length of the descriptor string
141 */
142
143 #define STRING_FRAMEWORK_LENGTH 40
144 static UCHAR string_framework[] = {
145
146 /* Manufacturer string descriptor : Index 1 */
147 0x09, 0x04, 0x01, 0x0c,
148 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c,
149 0x6f, 0x67, 0x69, 0x63,
150
151 /* Product string descriptor : Index 2 */
152 0x09, 0x04, 0x02, 0x0c,
153 0x55, 0x53, 0x42, 0x20, 0x4b, 0x65, 0x79, 0x62,
154 0x6f, 0x61, 0x72, 0x64,
155
156 /* Serial Number string descriptor : Index 3 */
157 0x09, 0x04, 0x03, 0x04,
158 0x30, 0x30, 0x30, 0x31
159 };
160
161
162 /* Multiple languages are supported on the device, to add
163 a language besides english, the unicode language code must
164 be appended to the language_id_framework array and the length
165 adjusted accordingly. */
166 #define LANGUAGE_ID_FRAMEWORK_LENGTH 2
167 static UCHAR language_id_framework[] = {
168
169 /* English. */
170 0x09, 0x04
171 };
172
173
174 UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter);
175
176
ux_system_host_change_function(ULONG a,UX_HOST_CLASS * b,VOID * c)177 static UINT ux_system_host_change_function(ULONG a, UX_HOST_CLASS *b, VOID *c)
178 {
179 return 0;
180 }
181
instance_activate_callback(VOID * parameter)182 static VOID instance_activate_callback(VOID *parameter)
183 {
184
185 slave_hid = (UX_SLAVE_CLASS_HID *)parameter;
186 }
187
error_callback(UINT system_level,UINT system_context,UINT error_code)188 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
189 {
190
191 // printf("Error on line %d: 0x%x, 0x%x, 0x%x\n", __LINE__, system_level, system_context, error_code);
192 }
193
194 /* Define what the initial system looks like. */
195
196 #ifdef CTEST
test_application_define(void * first_unused_memory)197 void test_application_define(void *first_unused_memory)
198 #else
199 void usbx_ux_device_class_hid_wMaxPacketSize_test_application_define(void *first_unused_memory)
200 #endif
201 {
202
203 UINT status;
204 CHAR * stack_pointer;
205 CHAR * memory_pointer;
206
207
208 /* Inform user. */
209 printf("Running ux_device_class_hid_ wMaxPacketSize tests .................. ");
210 stepinfo("\n");
211
212 /* Initialize the free memory pointer */
213 stack_pointer = (CHAR *) usbx_memory;
214 memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
215
216 /* Initialize USBX. Memory */
217 status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
218
219 /* Check for error. */
220 if (status != UX_SUCCESS)
221 {
222
223 printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
224 test_control_return(1);
225 }
226
227 /* Register the error callback. */
228 _ux_utility_error_callback_register(error_callback);
229
230 /* The code below is required for installing the host portion of USBX */
231 status = ux_host_stack_initialize(ux_system_host_change_function);
232 if (status != UX_SUCCESS)
233 {
234
235 printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
236 test_control_return(1);
237 }
238
239 status = ux_host_stack_class_register(_ux_system_host_class_hid_name, ux_host_class_hid_entry);
240 if (status != UX_SUCCESS)
241 {
242
243 printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
244 test_control_return(1);
245 }
246 #if 0
247 /* Register the HID client(s). */
248 status = ux_host_class_hid_client_register(_ux_system_host_class_hid_client_keyboard_name, ux_host_class_hid_keyboard_entry);
249 if (status != UX_SUCCESS)
250 {
251
252 printf("Error on line %d, error code: %d\n", __LINE__, status);
253 test_control_return(1);
254 }
255 #endif
256 /* The code below is required for installing the device portion of USBX. No call back for
257 device status change in this example. */
258 status = ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
259 device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
260 string_framework, STRING_FRAMEWORK_LENGTH,
261 language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
262 if(status!=UX_SUCCESS)
263 {
264
265 printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
266 test_control_return(1);
267 }
268
269 /* Initialize the hid class parameters. */
270 hid_parameter.ux_device_class_hid_parameter_report_address = hid_report_descriptor;
271 hid_parameter.ux_device_class_hid_parameter_report_length = HID_REPORT_LENGTH;
272 hid_parameter.ux_device_class_hid_parameter_callback = demo_thread_hid_callback;
273 hid_parameter.ux_slave_class_hid_instance_activate = instance_activate_callback;
274
275 /* Initialize the device hid class. The class is connected with interface 2 */
276 status = ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry,
277 1, 0, (VOID *)&hid_parameter);
278 if(status!=UX_SUCCESS)
279 {
280
281 printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
282 test_control_return(1);
283 }
284
285 /* Initialize the simulated device controller. */
286 status = _ux_dcd_sim_slave_initialize();
287
288 /* Check for error. */
289 if (status != UX_SUCCESS)
290 {
291
292 printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
293 test_control_return(1);
294 }
295
296 /* Register all the USB host controllers available in this system */
297 status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, _ux_test_hcd_sim_host_initialize,0,0);
298
299 /* Check for error. */
300 if (status != UX_SUCCESS)
301 {
302
303 printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
304 test_control_return(1);
305 }
306
307 /* Create the main host simulation thread. */
308 status = tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0,
309 stack_pointer, UX_DEMO_STACK_SIZE,
310 20, 20, 1, TX_AUTO_START);
311
312 /* Check for error. */
313 if (status != TX_SUCCESS)
314 {
315
316 printf("Error on line %d, error code: 0x%x\n", __LINE__, status);
317 test_control_return(1);
318 }
319 }
320
_hid_report_callback(UX_HOST_CLASS_HID_REPORT_CALLBACK * callback)321 static VOID _hid_report_callback(UX_HOST_CLASS_HID_REPORT_CALLBACK *callback)
322 {
323 ULONG length;
324 length = callback->ux_host_class_hid_report_callback_actual_length;
325 if (length > HOST_BUFFER_LENGTH)
326 length = HOST_BUFFER_LENGTH;
327 _ux_utility_memory_copy(host_buffer,
328 callback->ux_host_class_hid_report_callback_buffer,
329 length);
330 host_buffer_length = length;
331 }
332
tx_demo_thread_host_simulation_entry(ULONG arg)333 static void tx_demo_thread_host_simulation_entry(ULONG arg)
334 {
335
336 UINT status;
337 UX_DEVICE *device;
338 UINT i;
339 struct _test {
340 ULONG speed;
341 ULONG wMaxPacketSize;
342 } tests[] = {
343 {UX_FULL_SPEED_DEVICE, 0},
344 {UX_FULL_SPEED_DEVICE, 128},
345 {UX_FULL_SPEED_DEVICE, 8+(2<<11)},
346 {UX_FULL_SPEED_DEVICE, 0xFFFF},
347 {UX_FULL_SPEED_DEVICE, 16},
348 {UX_HIGH_SPEED_DEVICE, 16},
349 {UX_HIGH_SPEED_DEVICE, 16+(1<<11)},
350 {UX_HIGH_SPEED_DEVICE, 0xFFFF},
351 {UX_HIGH_SPEED_DEVICE, 32},
352 };
353 #define N_TESTS (sizeof(tests)/sizeof(struct _test))
354
355 stepinfo(">>>>>>>>>> Get HID class instance\n");
356
357 /* Find the HID class */
358 status = demo_class_hid_get();
359 if (status != UX_SUCCESS)
360 {
361
362 printf("Error on line %d, error code: %d\n", __LINE__, status);
363 test_control_return(1);
364 }
365 if (slave_hid == UX_NULL)
366 {
367 printf("Error on line %d, HID slave instance error\n", __LINE__);
368 test_control_return(1);
369 }
370
371 /* Get device instance. */
372 status = ux_host_stack_device_get(0, &device);
373 if (status != UX_SUCCESS)
374 {
375 printf("ERROR #%d: get_device fail, 0x%x\n", __LINE__, status);
376 test_control_return(1);
377 }
378
379 /* No exit on assert hit. */
380 ux_test_assert_hit_exit(0);
381
382 for (i = 0; i < N_TESTS; i ++)
383 {
384
385 ux_test_dcd_sim_slave_disconnect();
386 ux_test_hcd_sim_host_disconnect();
387
388 status = demo_class_hid_get();
389
390 if (tests[i].speed == UX_HIGH_SPEED_DEVICE)
391 _ux_utility_short_put(device_framework_high_speed+DEVICE_FRAMEWORK_OFFSET_HS_EP_MPS, tests[i].wMaxPacketSize);
392 else
393 _ux_utility_short_put(device_framework_full_speed+DEVICE_FRAMEWORK_OFFSET_FS_EP_MPS, tests[i].wMaxPacketSize);
394
395 ux_test_dcd_sim_slave_connect(tests[i].speed);
396 ux_test_hcd_sim_host_connect(tests[i].speed);
397
398 /* Find the HID class */
399 status = demo_class_hid_get();
400
401 /* Set configuration. */
402 _ux_host_stack_configuration_set(device -> ux_device_first_configuration);
403 }
404
405 stepinfo(">>>>>>>>>> Test done\n");
406
407 /* Now disconnect the device. */
408 _ux_device_stack_disconnect();
409
410 /* And deinitialize the class. */
411 status = ux_device_stack_class_unregister(_ux_system_slave_class_hid_name, ux_device_class_hid_entry);
412
413 /* Deinitialize the device side of usbx. */
414 _ux_device_stack_uninitialize();
415
416 /* And finally the usbx system resources. */
417 _ux_system_uninitialize();
418
419 /* Successful test. */
420 printf("SUCCESS!\n");
421 test_control_return(0);
422 }
423
demo_thread_hid_callback(UX_SLAVE_CLASS_HID * class,UX_SLAVE_CLASS_HID_EVENT * event)424 static UINT demo_thread_hid_callback(UX_SLAVE_CLASS_HID *class, UX_SLAVE_CLASS_HID_EVENT *event)
425 {
426 return(UX_SUCCESS);
427 }
428