1 #include <stdio.h>
2 #include "tx_api.h"
3 #include "ux_api.h"
4 #include "ux_system.h"
5 #include "ux_utility.h"
6 #include "ux_hcd_sim_host.h"
7 #include "ux_test.h"
8 #include "ux_device_stack.h"
9 #include "ux_test_utility_sim.h"
10
11
12 static UX_SLAVE_TRANSFER transfer_request;
13 static UX_SYSTEM_SLAVE system_slave;
14 static UX_SLAVE_CLASS slave_classes[UX_MAX_SLAVE_INTERFACES];
15 static UX_SLAVE_INTERFACE slave_interfaces[UX_MAX_SLAVE_INTERFACES];
16
17 static UINT test_entry_count = 0;
18 static UINT test_entry_class[UX_MAX_SLAVE_INTERFACES] = {0, 0, 0, 0};
_test_entry_log_reset(void)19 static inline void _test_entry_log_reset(void)
20 {
21 test_entry_class[0] = 0;
22 test_entry_class[1] = 0;
23 test_entry_class[2] = 0;
24 test_entry_class[3] = 0;
25 test_entry_count = 0;
26 }
27 #define TEST_ENTRY_LOG_SAVE(c) \
28 if (test_entry_count < UX_MAX_SLAVE_INTERFACES) { test_entry_class[test_entry_count++] = c; }
29 #define TEST_ENTRY_LOG_CHECK_FAIL(c1,c2,c3,c4) \
30 (test_entry_class[0] != c1) || (test_entry_class[1] != c2) || \
31 (test_entry_class[2] != c3) || (test_entry_class[3] != c4)
32
33 typedef struct _REQ_ACCEPTED {
34 UCHAR type;
35 UCHAR request;
36 } REQ_ACCEPTED;
37 typedef struct _CLASS_REQ_ACCEPTED {
38 UCHAR bClass;
39 UCHAR n_req;
40 REQ_ACCEPTED *req;
41 } CLASS_REQ_ACCEPTED;
42 static REQ_ACCEPTED cdc_acm_req[] = {
43 {0x21, 0x00}, /* SEND_ENCAPSULATED_COMMAND */
44 {0xA1, 0x01}, /* GET_ENCAPSULATED_RESPONSE */
45 {0x21, 0x02}, /* SET_COMM_FEATURE */
46 {0xA1, 0x03}, /* GET_COMM_FEATURE */
47 {0x21, 0x04}, /* CLEAR_COMM_FEATURE */
48 {0x21, 0x05}, /* SET_LINE_CODING */
49 {0xA1, 0x06}, /* GET_LINE_CODING */
50 {0x21, 0x07}, /* SET_CONTROL_LINE_STATE */
51 {0x21, 0x08}, /* SEND_BREAK */
52 };
53 static REQ_ACCEPTED printer_req[] = {
54 {0xA1, 0x00}, /* GET_DEVICE_ID */
55 {0xA1, 0x01}, /* GET_PORT_STATUS */
56 {0x21, 0x02}, /* SOFT_RESET */
57 };
58 static REQ_ACCEPTED storage_req[] = {
59 {0x21, 0xFF}, /* Bulk-Only Reset */
60 {0xA1, 0xFE}, /* Get Max LUN */
61 };
62 static REQ_ACCEPTED hid_req[] = {
63 {0xA1, 0x01}, /* GET_REPORT */
64 {0xA1, 0x02}, /* GET_IDLE */
65 {0xA1, 0x03}, /* GET_PROTOCOL */
66 {0x21, 0x09}, /* SET_REPORT */
67 {0x21, 0x0A}, /* SET_IDLE */
68 {0x21, 0x0B}, /* SET_PROTOCOL */
69 };
70 static CLASS_REQ_ACCEPTED class_req_accepted[] = {
71 {0x02, sizeof(cdc_acm_req)/sizeof(REQ_ACCEPTED), cdc_acm_req},
72 {0x07, sizeof(printer_req)/sizeof(REQ_ACCEPTED), printer_req},
73 {0x08, sizeof(storage_req)/sizeof(REQ_ACCEPTED), storage_req},
74 {0x03, sizeof(hid_req)/sizeof(REQ_ACCEPTED), hid_req},
75 };
76
_test_class_entry(struct UX_SLAVE_CLASS_COMMAND_STRUCT * cmd)77 UINT _test_class_entry(struct UX_SLAVE_CLASS_COMMAND_STRUCT *cmd)
78 {
79 UX_SLAVE_DEVICE *device = &_ux_system_slave -> ux_system_slave_device;
80 UX_SLAVE_CLASS *cmd_class = cmd -> ux_slave_class_command_class_ptr;
81 UX_SLAVE_TRANSFER *transfer = &transfer_request;
82 INT i, j;
83
84 stepinfo(" entry call: %p (%x)\n", cmd_class, (unsigned)cmd_class -> ux_slave_class_interface->ux_slave_interface_descriptor.bInterfaceClass);
85 TEST_ENTRY_LOG_SAVE(cmd_class -> ux_slave_class_interface->ux_slave_interface_descriptor.bInterfaceClass);
86 for (i = 0; i < sizeof(class_req_accepted)/sizeof(CLASS_REQ_ACCEPTED); i++)
87 {
88 if (cmd_class->ux_slave_class_interface->ux_slave_interface_descriptor.bInterfaceClass == class_req_accepted[i].bClass)
89 {
90 for (j = 0; j < class_req_accepted[i].n_req; j++)
91 {
92 if (transfer->ux_slave_transfer_request_setup[UX_SETUP_REQUEST] == class_req_accepted[i].req[j].request &&
93 transfer->ux_slave_transfer_request_setup[UX_SETUP_REQUEST_TYPE] == class_req_accepted[i].req[j].type)
94 {
95 return(UX_SUCCESS);
96 }
97 }
98 }
99 }
100 return (UX_NO_CLASS_MATCH);
101 }
102
103 #ifdef CTEST
test_application_define(void * first_unused_memory)104 void test_application_define(void *first_unused_memory)
105 #else
106 void usbx_ux_device_stack_class_control_request_test_application_define(void *first_unused_memory)
107 #endif
108 {
109
110 UINT status = 0;
111 UCHAR request_type = UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
112 UCHAR request = 0;
113 INT i;
114
115
116 /* Inform user. */
117 printf("Running USB Device Stack Class Control Request Process Test ........ ");
118 if (UX_MAX_SLAVE_INTERFACES < 4)
119 {
120 printf("Supported number of interface: %d (<4)\n", UX_MAX_SLAVE_INTERFACES);
121 printf("Skipped\n");
122 test_control_return(0);
123 return;
124 }
125
126 _ux_system_slave = &system_slave;
127 for (i = 0; i < UX_MAX_SLAVE_INTERFACES; i++)
128 {
129 if (i > 3)
130 {
131 system_slave.ux_system_slave_interface_class_array[i] = UX_NULL;
132 continue;
133 }
134 system_slave.ux_system_slave_interface_class_array[i] = &slave_classes[i];
135 slave_classes[i].ux_slave_class_interface = &slave_interfaces[i];
136 slave_classes[i].ux_slave_class_entry_function = _test_class_entry;
137 slave_interfaces[i].ux_slave_interface_descriptor.bInterfaceClass = 0x00;
138 }
139 stepinfo("class array: %p %p %p %p ...\n",
140 system_slave.ux_system_slave_interface_class_array[0],
141 system_slave.ux_system_slave_interface_class_array[1],
142 system_slave.ux_system_slave_interface_class_array[2],
143 system_slave.ux_system_slave_interface_class_array[3]);
144
145 struct _test_struct {
146 /* Interface */
147 UCHAR ifc_class[4]; /* 2:CDC, 7:PRINT, 8:MSC, 3:HID */
148 /* Input */
149 UCHAR setup[8];
150 /* Output check */
151 UINT status;
152 UCHAR cmd_class[4]; /* 2:CDC, 7:PRINT, 8:MSC, 3:HID */
153 } tests[] = {
154 /* class type req value index length return class */
155 { {0x07, 0x02, 0x03, 0x08}, {0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, UX_SUCCESS, {0x07, 0x00, 0x00, 0x00}},
156 { {0x07, 0x02, 0x03, 0x08}, {0xA1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}, UX_SUCCESS, {0x07, 0x00, 0x00, 0x00}},
157 { {0x07, 0x02, 0x03, 0x08}, {0xA1, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, UX_ERROR, {0x00, 0x00, 0x00, 0x00}},
158 { {0x07, 0x02, 0x03, 0x08}, {0xA1, 0x00, 0x00, 0x00, 0x05, 0x01, 0x00, 0x00}, UX_ERROR, {0x00, 0x00, 0x00, 0x00}},
159 { {0x07, 0x02, 0x03, 0x08}, {0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, UX_NO_CLASS_MATCH, {0x07, 0x00, 0x00, 0x00}},
160 { {0x07, 0x02, 0x03, 0x08}, {0x21, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}, UX_SUCCESS, {0x02, 0x00, 0x00, 0x00}},
161 { {0x07, 0x02, 0x03, 0x08}, {0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00}, UX_NO_CLASS_MATCH, {0x03, 0x00, 0x00, 0x00}},
162 { {0x07, 0x02, 0x03, 0x08}, {0x21, 0x0A, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00}, UX_SUCCESS, {0x03, 0x00, 0x00, 0x00}},
163 { {0x07, 0x02, 0x03, 0x08}, {0xA1, 0xFE, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00}, UX_SUCCESS, {0x08, 0x00, 0x00, 0x00}},
164 { {0x07, 0x02, 0x03, 0x08}, {0xA1, 0xFE, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00}, UX_ERROR, {0x00, 0x00, 0x00, 0x00}},
165
166 /* class type req value index length return class */
167 { {0x02, 0x07, 0x03, 0x08}, {0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, UX_NO_CLASS_MATCH, {0x02, 0x00, 0x00, 0x00}},
168 { {0x02, 0x07, 0x03, 0x08}, {0xA1, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, UX_SUCCESS, {0x02, 0x07, 0x00, 0x00}},
169 { {0x02, 0x07, 0x03, 0x08}, {0x21, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}, UX_SUCCESS, {0x02, 0x00, 0x00, 0x00}},
170 { {0x02, 0x07, 0x03, 0x08}, {0xA1, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}, UX_SUCCESS, {0x07, 0x00, 0x00, 0x00}},
171 { {0x02, 0x07, 0x03, 0x08}, {0xA1, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, UX_NO_CLASS_MATCH, {0x02, 0x00, 0x00, 0x00}},
172 { {0x02, 0x07, 0x03, 0x08}, {0xA1, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00}, UX_SUCCESS, {0x03, 0x00, 0x00, 0x00}},
173 { {0x02, 0x07, 0x03, 0x08}, {0xA1, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00}, UX_ERROR, {0x00, 0x00, 0x00, 0x00}},
174
175 /* class type req value index length return class */
176 { {0x03, 0x08, 0x07, 0x02}, {0xA1, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00}, UX_SUCCESS, {0x03, 0x07, 0x00, 0x00}},
177 { {0x03, 0x08, 0x07, 0x02}, {0xA1, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00}, UX_NO_CLASS_MATCH, {0x03, 0x00, 0x00, 0x00}},
178 { {0x03, 0x08, 0x07, 0x02}, {0xA1, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00}, UX_ERROR, {0x00, 0x00, 0x00, 0x00}},
179 };
180 for (i = 0; i < sizeof(tests)/sizeof(struct _test_struct); i ++)
181 {
182
183 _test_entry_log_reset();
184
185 slave_interfaces[0].ux_slave_interface_descriptor.bInterfaceClass = tests[i].ifc_class[0];
186 slave_interfaces[1].ux_slave_interface_descriptor.bInterfaceClass = tests[i].ifc_class[1];
187 slave_interfaces[2].ux_slave_interface_descriptor.bInterfaceClass = tests[i].ifc_class[2];
188 slave_interfaces[3].ux_slave_interface_descriptor.bInterfaceClass = tests[i].ifc_class[3];
189
190 transfer_request.ux_slave_transfer_request_completion_code = UX_SUCCESS;
191 transfer_request.ux_slave_transfer_request_setup[0] = tests[i].setup[0];
192 transfer_request.ux_slave_transfer_request_setup[UX_SETUP_REQUEST] = tests[i].setup[UX_SETUP_REQUEST];
193 transfer_request.ux_slave_transfer_request_setup[UX_SETUP_INDEX] = tests[i].setup[UX_SETUP_INDEX];
194 transfer_request.ux_slave_transfer_request_setup[UX_SETUP_INDEX + 1] = tests[i].setup[UX_SETUP_INDEX + 1];
195
196 stepinfo(" test #%2d: {%x %x %x %x} {%x %x .. %x %x ..} %x {%x %x %x %x}\n", i,
197 tests[i].ifc_class[0], tests[i].ifc_class[1], tests[i].ifc_class[2], tests[i].ifc_class[3],
198 tests[i].setup[0], tests[i].setup[UX_SETUP_REQUEST], tests[i].setup[UX_SETUP_INDEX], tests[i].setup[UX_SETUP_INDEX + 1],
199 tests[i].status, tests[i].cmd_class[0], tests[i].cmd_class[1], tests[i].cmd_class[2], tests[i].cmd_class[3]);
200
201 status = _ux_device_stack_control_request_process(&transfer_request);
202 if (status != tests[i].status)
203 {
204 printf("ERROR #%d: %2d {%x %x %x %x} {%x %x .. %x %x ..}, status = %x, expected %x\n", __LINE__,
205 i, tests[i].ifc_class[0], tests[i].ifc_class[1], tests[i].ifc_class[2], tests[i].ifc_class[3],
206 tests[i].setup[0], tests[i].setup[UX_SETUP_REQUEST], tests[i].setup[UX_SETUP_INDEX], tests[i].setup[UX_SETUP_INDEX + 1],
207 status, tests[i].status);
208 test_control_return(1);
209 return;
210 }
211 if (TEST_ENTRY_LOG_CHECK_FAIL(tests[i].cmd_class[0], tests[i].cmd_class[1], tests[i].cmd_class[2], tests[i].cmd_class[3]))
212 {
213 printf("ERROR #%d: %2d {%x %x %x %x} {%x %x .. %x %x ..}, class call {%x %x %x %x}, expected {%x %x %x %x}\n", __LINE__,
214 i, tests[i].ifc_class[0], tests[i].ifc_class[1], tests[i].ifc_class[2], tests[i].ifc_class[3],
215 tests[i].setup[0], tests[i].setup[UX_SETUP_REQUEST], tests[i].setup[UX_SETUP_INDEX], tests[i].setup[UX_SETUP_INDEX + 1],
216 test_entry_class[0], test_entry_class[1], test_entry_class[2], test_entry_class[3],
217 tests[i].cmd_class[0], tests[i].cmd_class[1], tests[i].cmd_class[2], tests[i].cmd_class[3]);
218 test_control_return(1);
219 return;
220 }
221 }
222
223 printf("SUCCESS!\n");
224 test_control_return(0);
225
226 return;
227 }
228