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