1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "osal_thread.h"
17#include "signal.h"
18#include "usbhost_ddk_test.h"
19
20#define HDF_LOG_TAG USB_HOST_DDK_TEST
21#define STR_LEN     256
22#define STRTOL_BASE  10
23
24#define PARAM_CMD_LENGTH  3
25#define PARAM_SET_CMD_LEN 3
26#define PARAM_GET_CMD_LEN 2
27#define ARGV_CMD_API_TYPE 1
28#define ARGV_CMD_TYPE     (PARAM_GET_CMD_LEN - ARGV_CMD_API_TYPE)
29#define ARGV_CMD_PARAM    (PARAM_SET_CMD_LEN - ARGV_CMD_API_TYPE)
30#define READ_SLEEP_TIME   500
31int32_t run;
32
33#ifdef __LITEOS_USB_HOST_DDK_TEST__
34static struct OsalThread g_Getchar;
35#endif
36
37static void TestHelp(void)
38{
39    printf("usage: usbhost_ddk_test [options]\n");
40    printf("\n");
41    printf("options include:\n");
42    printf("  -h, --help                    : help info\n");
43    printf("  -A, --DDK                     : test host ddk api function for acm\n");
44    printf("  -a, --RAW                     : test host raw api function for acm\n");
45    printf("  -E, --ECM                     : test host ddk api function for ecm\n");
46    printf("  -R, --syncRead                : test sync read for acm\n");
47    printf("  -W, --syncWrite               : test sync write for acm\n");
48    printf("  -r, --asyncRead               : test async read for acm\n");
49    printf("  -w, --asyncWrite              : test async write for acm\n");
50    printf("  -c, --ctrlClassSync           : test class ctrl cmd for acm\n");
51    printf("  -s, --ctrlGetStatus           : test get status ctrl cmd for acm\n");
52    printf("  -C, --ctrlSyncDescriptor      : test sync get descriptor ctrl cmd for acm\n");
53    printf("  -d, --ctrlAsyncDescriptor     : test async get descriptor ctrl cmd for acm\n");
54    printf("  -g, --ctrlGetConfiguration    : test get configuration ctrl cmd for acm\n");
55    printf("  -i, --ctrlGetInterface        : test get interface ctrl cmd for acm\n");
56    printf("  -S, --speedTest               : test speed for acm\n");
57    printf("  -B, --setBaudrate             : test set baudrate for acm\n");
58    printf("  -b, --getBaudrate             : test get baudrate for acm\n");
59    printf("  -I, --addInterface [index}    : test add interface for acm(not raw api function) and ecm\n");
60    printf("  -D, --removeInterface [index] : test remove interface for acm(not raw api function) and ecm\n");
61    printf("\n");
62    printf("Examples:\n");
63    printf("  usbhost_ddk_test -AR      : test sync read for acm by host ddk api function\n");
64    printf("  usbhost_ddk_test -aw 123  : test async write 123 for acm by host raw api function\n");
65}
66
67static int32_t TestParaseCommand(int32_t paramNum, const char *cmdParam, int32_t *cmdType, char *apiType)
68{
69    if ((cmdParam == NULL) || (cmdType == NULL) || (apiType == NULL) || (strlen(cmdParam) < PARAM_CMD_LENGTH)) {
70        HDF_LOGE("%{public}s:%{public}d command or cmdType is NULL or cmdParam length is error", __func__, __LINE__);
71        return HDF_ERR_INVALID_PARAM;
72    }
73
74    uint32_t len = strlen(cmdParam);
75    for (uint32_t i = 0; i < len; i++) {
76        switch (cmdParam[i]) {
77            case 'A':
78                strcpy_s(apiType, DATA_MAX_LEN, "-SDK");
79                break;
80            case 'a':
81                strcpy_s(apiType, DATA_MAX_LEN, "-RAW");
82                break;
83            case 'E':
84                strcpy_s(apiType, DATA_MAX_LEN, "-ECM");
85                break;
86            case 'R':
87                if (paramNum != PARAM_GET_CMD_LEN) {
88                    return HDF_FAILURE;
89                }
90                *cmdType = HOST_ACM_SYNC_READ;
91                break;
92            case 'W':
93                if (paramNum != PARAM_SET_CMD_LEN) {
94                    return HDF_FAILURE;
95                }
96                *cmdType = HOST_ACM_SYNC_WRITE;
97                break;
98            case 'r':
99                if (paramNum != PARAM_GET_CMD_LEN) {
100                    return HDF_FAILURE;
101                }
102                *cmdType = HOST_ACM_ASYNC_READ;
103                break;
104            case 'w':
105                if (paramNum != PARAM_SET_CMD_LEN) {
106                    return HDF_FAILURE;
107                }
108                *cmdType = HOST_ACM_ASYNC_WRITE;
109                break;
110            case 'c':
111                if (paramNum != PARAM_GET_CMD_LEN) {
112                    return HDF_FAILURE;
113                }
114                *cmdType = HOST_ACM_CTRL_CLASS_SYNC;
115                break;
116            case 's':
117                if (paramNum != PARAM_GET_CMD_LEN) {
118                    return HDF_FAILURE;
119                }
120                *cmdType = HOST_ACM_CTRL_GET_STATUS;
121                break;
122            case 'C':
123                if (paramNum != PARAM_GET_CMD_LEN) {
124                    return HDF_FAILURE;
125                }
126                *cmdType = HOST_ACM_CTRL_SYNC_DESCRIPTOR;
127                break;
128            case 'd':
129                if (paramNum != PARAM_GET_CMD_LEN) {
130                    return HDF_FAILURE;
131                }
132                *cmdType = HOST_ACM_CTRL_ASYNC_DESCRIPTOR;
133                break;
134            case 'g':
135                if (paramNum != PARAM_GET_CMD_LEN) {
136                    return HDF_FAILURE;
137                }
138                *cmdType = HOST_ACM_CTRL_GET_CONFIGURATION;
139                break;
140            case 'i':
141                if (paramNum != PARAM_GET_CMD_LEN) {
142                    return HDF_FAILURE;
143                }
144                *cmdType = HOST_ACM_CTRL_GET_INTERFACE;
145                break;
146            case 'S':
147                if (paramNum != PARAM_GET_CMD_LEN) {
148                    return HDF_FAILURE;
149                }
150                *cmdType = HOST_ACM_SPEED_TEST;
151                break;
152            case 'B':
153                if (paramNum != PARAM_SET_CMD_LEN) {
154                    return HDF_FAILURE;
155                }
156                *cmdType = HOST_ACM_SET_BAUDRATE;
157                break;
158            case 'b':
159                if (paramNum != PARAM_GET_CMD_LEN) {
160                    return HDF_FAILURE;
161                }
162                *cmdType = HOST_ACM_GET_BAUDRATE;
163                break;
164            case 'I':
165                if (paramNum != PARAM_SET_CMD_LEN) {
166                    return HDF_FAILURE;
167                }
168                *cmdType = HOST_ACM_ADD_INTERFACE;
169                break;
170            case 'D':
171                if (paramNum != PARAM_SET_CMD_LEN) {
172                    return HDF_FAILURE;
173                }
174                *cmdType = HOST_ACM_REMOVE_INTERFACE;
175                break;
176            case '-':
177                break;
178            default:
179                return HDF_FAILURE;
180        }
181    }
182
183    return HDF_SUCCESS;
184}
185
186static void TestCmdLoopOther(int32_t cmdType, const char *param)
187{
188    switch (cmdType) {
189        case HOST_ACM_CTRL_CLASS_SYNC:
190            UsbHostDdkTestCtrlClass(NULL);
191            break;
192        case HOST_ACM_CTRL_GET_STATUS:
193            UsbHostDdkTestStdGetStatus(NULL);
194            break;
195        case HOST_ACM_CTRL_SYNC_DESCRIPTOR:
196            UsbHostDdkTestStdGetDes(NULL);
197            break;
198        case HOST_ACM_CTRL_ASYNC_DESCRIPTOR:
199            UsbHostDdkTestStdGetDesAsync(NULL);
200            usleep(READ_SLEEP_TIME);
201            break;
202        case HOST_ACM_CTRL_GET_CONFIGURATION:
203            TestStdGetConf();
204            break;
205        case HOST_ACM_CTRL_GET_INTERFACE:
206            TestStdGetInterface();
207            break;
208        case HOST_ACM_SET_BAUDRATE:
209            UsbHostDdkTestSetBaudrate((uint32_t)(strtoul(param, NULL, STRTOL_BASE)));
210            break;
211        case HOST_ACM_GET_BAUDRATE:
212            UsbHostDdkTestGetBaudrate(NULL);
213            break;
214        case HOST_ACM_ADD_INTERFACE:
215            UsbHostDdkTestAddInterface((uint32_t)(strtoul(param, NULL, STRTOL_BASE)));
216            break;
217        case HOST_ACM_REMOVE_INTERFACE:
218            UsbHostDdkTestRemoveInterface((uint32_t)(strtoul(param, NULL, STRTOL_BASE)));
219            break;
220        default:
221            break;
222    }
223}
224
225static int32_t TestCmdLoop(int32_t cmdType, const char *param)
226{
227    bool loopFlag = true;
228    bool asyncFlag = false;
229    int32_t cnt = 0;
230
231    if (TestGetExitFlag() == true) {
232        HDF_LOGD("%{public}s:%{public}d g_exitFlag is true!", __func__, __LINE__);
233        return HDF_FAILURE;
234    }
235
236    while ((loopFlag) && (!run)) {
237        switch (cmdType) {
238            case HOST_ACM_SYNC_READ:
239                UsbHostDdkTestSyncRead(NULL);
240                break;
241            case HOST_ACM_SYNC_WRITE:
242                UsbHostDdkTestSyncWrite(param);
243                break;
244            case HOST_ACM_ASYNC_READ:
245                if (UsbHostDdkTestAsyncRead(NULL) != HDF_SUCCESS) {
246#ifdef __LITEOS_USB_HOST_DDK_TEST__
247                    if (cnt++ > 10) {
248                        asyncFlag = false;
249                        return HDF_DEV_ERR_NO_DEVICE_SERVICE;
250                    }
251#else
252                    asyncFlag = false;
253#endif
254                } else {
255                    cnt = 0;
256                    asyncFlag = true;
257                    usleep(READ_SLEEP_TIME);
258                }
259                break;
260            case HOST_ACM_ASYNC_WRITE:
261                UsbHostDdkTestAsyncWrite(param);
262                break;
263            default:
264                TestCmdLoopOther(cmdType, param);
265                break;
266        }
267
268        if (!asyncFlag) {
269            loopFlag = false;
270        }
271    }
272    return HDF_SUCCESS;
273}
274
275#ifdef __LITEOS_USB_HOST_DDK_TEST__
276static void *SigHandle(void *arg)
277{
278    (void)arg;
279    run = 0;
280    return NULL;
281}
282
283static int32_t GetCharThread(void *arg)
284{
285    char str[STR_LEN] = {0};
286    while (run) {
287        str[0] = (char)getchar();
288    }
289    return 0;
290}
291#endif
292
293#define HDF_PROCESS_STACK_SIZE 100000
294static int32_t StartThreadGetChar()
295{
296#ifdef __LITEOS_USB_HOST_DDK_TEST__
297    int32_t ret;
298    struct OsalThreadParam threadCfg;
299    memset_s(&threadCfg, sizeof(threadCfg), 0, sizeof(threadCfg));
300    threadCfg.name = "get char process";
301    threadCfg.priority = OSAL_THREAD_PRI_DEFAULT;
302    threadCfg.stackSize = HDF_PROCESS_STACK_SIZE;
303
304    ret = OsalThreadCreate(&g_Getchar, (OsalThreadEntry)GetCharThread, NULL);
305    if (HDF_SUCCESS != ret) {
306        HDF_LOGE("%{public}s:%{public}d OsalThreadCreate failed, ret=%{public}d ", __func__, __LINE__, ret);
307        return HDF_ERR_DEVICE_BUSY;
308    }
309
310    ret = OsalThreadStart(&g_Getchar, &threadCfg);
311    if (HDF_SUCCESS != ret) {
312        HDF_LOGE("%{public}s:%{public}d OsalThreadStart failed, ret=%{public}d ", __func__, __LINE__, ret);
313        return HDF_ERR_DEVICE_BUSY;
314    }
315#endif
316    return 0;
317}
318
319int32_t main(int32_t argc, char *argv[])
320{
321    int32_t status;
322    int32_t cmdType;
323    char apiType[DATA_MAX_LEN];
324
325    if ((argc < ARGV_CMD_TYPE) || (argc < PARAM_GET_CMD_LEN) || (argv[ARGV_CMD_TYPE] == NULL)) {
326        HDF_LOGE("%{public}s:%{public}d invalid parma, argc=%{public}d", __func__, __LINE__, argc);
327        return HDF_FAILURE;
328    }
329
330    if ((argc == PARAM_GET_CMD_LEN) &&
331        ((!strcmp(argv[ARGV_CMD_TYPE], "-h")) || (!strcmp(argv[ARGV_CMD_TYPE], "--help")))) {
332        TestHelp();
333        return HDF_SUCCESS;
334    }
335    run = 1;
336
337    StartThreadGetChar();
338    status = TestParaseCommand(argc, argv[ARGV_CMD_TYPE], &cmdType, apiType);
339    if (status != HDF_SUCCESS) {
340        run = 0;
341        HDF_LOGE("%{public}s:%{public}d TestParaseCommand status=%{public}d err", __func__, __LINE__, status);
342        TestHelp();
343        return status;
344    }
345
346    status = UsbHostDdkTestInit(apiType);
347    if (status != HDF_SUCCESS) {
348        run = 0;
349        HDF_LOGE("%{public}s:%{public}d UsbHostDdkTestInit status=%{public}d err", __func__, __LINE__, status);
350        return status;
351    }
352
353    if (UsbHostDdkTestOpen(cmdType) != HDF_SUCCESS) {
354        goto OUT;
355    }
356#ifdef __LITEOS_USB_HOST_DDK_TEST__
357    (void)signal(SIGINT, SigHandle);
358#endif
359    status = TestCmdLoop(cmdType, argv[ARGV_CMD_PARAM]);
360    if (status == HDF_DEV_ERR_NO_DEVICE_SERVICE) {
361        goto OUT;
362    }
363
364    if ((cmdType != HOST_ACM_ADD_INTERFACE) && (cmdType != HOST_ACM_REMOVE_INTERFACE)) {
365        if (UsbHostDdkTestClose(cmdType) != HDF_SUCCESS) {
366            goto OUT;
367        }
368    }
369
370OUT:
371    run = 0;
372    TestExit();
373    return HDF_SUCCESS;
374}