• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "usbhost_sdkapi_speed.h"
17 #include <dirent.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <inttypes.h>
21 #include <osal_sem.h>
22 #include <osal_thread.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/ioctl.h>
28 #include <sys/mman.h>
29 #include <sys/time.h>
30 #include <unistd.h>
31 
32 #include "hdf_base.h"
33 #include "hdf_log.h"
34 #include "hdf_usb_pnp_manage.h"
35 #include "osal_mem.h"
36 #include "osal_time.h"
37 #include "securec.h"
38 #include "usb_ddk_interface.h"
39 
40 #define HDF_LOG_TAG USB_HOST_ACM
41 
42 static unsigned int g_speedFlag = 0;
43 static uint64_t g_recv_count = 0;
44 static uint64_t g_send_count = 0;
45 static uint64_t g_byteTotal = 0;
46 static bool g_writeOrRead = TEST_WRITE;
47 static bool g_printData = false;
48 
49 static void AcmTestBulkCallback(struct UsbRequest *req);
50 static int32_t SerialBegin(struct AcmDevice * const acm);
51 
AcmDbAlloc(struct AcmDevice * const acm)52 static int32_t AcmDbAlloc(struct AcmDevice * const acm)
53 {
54     int32_t i, dbn;
55     struct AcmDb *db = NULL;
56     dbn = 0;
57     i = 0;
58     for (;;) {
59         db = &acm->db[dbn];
60         if (!db->use) {
61             db->use = 1;
62             db->len = 0;
63             return dbn;
64         }
65         dbn = (dbn + 1) % TEST_CYCLE;
66         if (++i >= TEST_CYCLE) {
67             return -1;
68         }
69     }
70 }
71 
AcmDbIsAvail(struct AcmDevice * const acm)72 static int32_t AcmDbIsAvail(struct AcmDevice * const acm)
73 {
74     int32_t i, n;
75     n = TEST_CYCLE;
76     for (i = 0; i < TEST_CYCLE; i++)
77         n -= acm->db[i].use;
78     return n;
79 }
80 
InterfaceIdToHandle(const struct AcmDevice * acm,uint8_t id)81 static UsbInterfaceHandle *InterfaceIdToHandle(const struct AcmDevice *acm, uint8_t id)
82 {
83     (void)pipe;
84     UsbInterfaceHandle *devHandle = NULL;
85 
86     if (id == 0xFF) {
87         devHandle = acm->ctrDevHandle;
88     } else {
89         for (int32_t i = 0; i < acm->interfaceCnt; i++) {
90             if (acm->iface[i]->info.interfaceIndex == id) {
91                 devHandle = acm->devHandle[i];
92                 break;
93             }
94         }
95     }
96     return devHandle;
97 }
98 
AcmStartDb(struct AcmDevice * acm,struct AcmDb * db,struct UsbPipeInfo * pipe)99 static int32_t AcmStartDb(struct AcmDevice *acm, struct AcmDb *db, struct UsbPipeInfo *pipe)
100 {
101     (void)acm;
102     (void)pipe;
103     int32_t rc;
104     rc = UsbSubmitRequestAsync(db->request);
105     if (rc < 0) {
106         HDF_LOGE("UsbSubmitRequestAsync failed, ret=%d \n", rc);
107         db->use = 0;
108     }
109     return rc;
110 }
111 
AcmDataBufAlloc(struct AcmDevice * const acm)112 static int32_t AcmDataBufAlloc(struct AcmDevice * const acm)
113 {
114     int32_t i;
115     struct AcmDb *db;
116     for (db = &acm->db[0], i = 0; i < TEST_CYCLE; i++, db++) {
117         db->buf = OsalMemCalloc(acm->dataSize);
118         if (!db->buf) {
119             while (i > 0) {
120                 --i;
121                 --db;
122                 OsalMemFree(db->buf);
123                 db->buf = NULL;
124             }
125             return -HDF_ERR_MALLOC_FAIL;
126         } else {
127             memset_s(db->buf, acm->dataSize, 'a', acm->dataSize);
128             db->instance = acm;
129         }
130     }
131     return 0;
132 }
133 
AcmTestBulkCallback(struct UsbRequest * req)134 static void AcmTestBulkCallback(struct UsbRequest *req)
135 {
136     if (req == NULL) {
137         printf("req is null\r\n");
138         return;
139     }
140     int32_t status = req->compInfo.status;
141     struct AcmDb *db = (struct AcmDb *)req->compInfo.userData;
142     struct itimerval new_value, old_value;
143 
144     if (status == 0) {
145         if (g_byteTotal == 0) {
146             new_value.it_value.tv_sec = TEST_PRINT_TIME;
147             new_value.it_value.tv_usec = 0;
148             new_value.it_interval.tv_sec = TEST_PRINT_TIME;
149             new_value.it_interval.tv_usec = 0;
150             setitimer(ITIMER_REAL, &new_value, &old_value);
151         }
152         g_recv_count++;
153         g_byteTotal += req->compInfo.actualLength;
154     } else {
155         printf("error status=%d\r\n", status);
156     }
157 
158     if (g_printData) {
159         for (unsigned int i = 0; i < req->compInfo.actualLength; i++) {
160             printf("%c", req->compInfo.buffer[i]);
161         }
162         fflush(stdout);
163     } else if (g_recv_count % TEST_RECV_COUNT == 0) {
164         printf("#");
165         fflush(stdout);
166     }
167 
168     db->use = 0;
169     if (!g_speedFlag) {
170         if (SerialBegin(db->instance) != HDF_SUCCESS) {
171             HDF_LOGW("%s:%d SerialBegin error!", __func__, __LINE__);
172         }
173         g_send_count++;
174     }
175 
176     return;
177 }
178 
SerialBegin(struct AcmDevice * acm)179 static int32_t SerialBegin(struct AcmDevice *acm)
180 {
181     uint32_t size = acm->dataSize;
182     int32_t dbn;
183     if (AcmDbIsAvail(acm) != 0) {
184         dbn = AcmDbAlloc(acm);
185     } else {
186         HDF_LOGE("no buf\n");
187         return 0;
188     }
189     if (dbn < 0) {
190         HDF_LOGE("AcmDbAlloc failed\n");
191         return HDF_FAILURE;
192     }
193     struct AcmDb *db = &acm->db[dbn];
194     db->len = acm->dataSize;
195     int32_t ret = AcmStartDb(acm, db, NULL);
196     if (ret != HDF_SUCCESS) {
197         HDF_LOGE("acmstartdb is failed\n");
198         return HDF_FAILURE;
199     }
200     return (int32_t)size;
201 }
202 
GetUsbInterfaceById(const struct AcmDevice * acm,uint8_t interfaceIndex)203 static struct UsbInterface *GetUsbInterfaceById(const struct AcmDevice *acm, uint8_t interfaceIndex)
204 {
205     return UsbClaimInterface(acm->session, acm->busNum, acm->devAddr, interfaceIndex);
206 }
207 
EnumePipe(const struct AcmDevice * acm,uint8_t interfaceIndex,UsbPipeType pipeType,UsbPipeDirection pipeDirection)208 static struct UsbPipeInfo *EnumePipe(
209     const struct AcmDevice *acm, uint8_t interfaceIndex, UsbPipeType pipeType, UsbPipeDirection pipeDirection)
210 {
211     struct UsbInterfaceInfo *info = NULL;
212     UsbInterfaceHandle *interfaceHandle = NULL;
213     if (USB_PIPE_TYPE_CONTROL == pipeType) {
214         info = &acm->ctrIface->info;
215         interfaceHandle = acm->ctrDevHandle;
216     } else {
217         info = &acm->iface[interfaceIndex]->info;
218         interfaceHandle = InterfaceIdToHandle(acm, info->interfaceIndex);
219     }
220 
221     for (uint8_t i = 0; i <= info->pipeNum; i++) {
222         struct UsbPipeInfo p;
223         int32_t ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);
224         if (ret < 0) {
225             continue;
226         }
227         if ((p.pipeDirection == pipeDirection) && (p.pipeType == pipeType)) {
228             struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi));
229             if (pi == NULL) {
230                 HDF_LOGE("%s: Alloc pipe failed", __func__);
231                 return NULL;
232             }
233             p.interfaceId = info->interfaceIndex;
234             *pi = p;
235             return pi;
236         }
237     }
238     return NULL;
239 }
240 
GetPipe(const struct AcmDevice * acm,UsbPipeType pipeType,UsbPipeDirection pipeDirection)241 static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm, UsbPipeType pipeType, UsbPipeDirection pipeDirection)
242 {
243     uint8_t i;
244     if (acm == NULL) {
245         HDF_LOGE("%s: invalid parmas", __func__);
246         return NULL;
247     }
248     for (i = 0; i < acm->interfaceCnt; i++) {
249         struct UsbPipeInfo *p = NULL;
250         if (!acm->iface[i]) {
251             continue;
252         }
253         p = EnumePipe(acm, i, pipeType, pipeDirection);
254         if (p == NULL) {
255             continue;
256         }
257         return p;
258     }
259     return NULL;
260 }
261 
SignalHandler(int32_t signo)262 static void SignalHandler(int32_t signo)
263 {
264     static uint32_t sigCnt = 0;
265     struct itimerval new_value, old_value;
266     double speed = 0;
267     switch (signo) {
268         case SIGALRM:
269             sigCnt++;
270             if (sigCnt * TEST_PRINT_TIME >= TEST_TIME) {
271                 g_speedFlag = 1;
272                 break;
273             }
274             speed = (g_byteTotal * TEST_FLOAT_COUNT) / (sigCnt * TEST_PRINT_TIME * TEST_BYTE_COUNT * TEST_BYTE_COUNT);
275             printf("\nSpeed:%f MB/s\n", speed);
276             new_value.it_value.tv_sec = TEST_PRINT_TIME;
277             new_value.it_value.tv_usec = 0;
278             new_value.it_interval.tv_sec = TEST_PRINT_TIME;
279             new_value.it_interval.tv_usec = 0;
280             setitimer(ITIMER_REAL, &new_value, &old_value);
281             break;
282         case SIGINT:
283             g_speedFlag = 1;
284             break;
285         default:
286             break;
287     }
288 }
289 
ShowHelp(const char * name)290 static void ShowHelp(const char *name)
291 {
292     printf(">> usage:\n");
293     printf(">>      %s [<busNum> <devAddr>]  <ifaceNum> <w>/<r> [printdata]> \n", name);
294     printf("\n");
295 }
296 
CheckParam(int32_t argc,const char * argv[])297 static struct AcmDevice *CheckParam(int32_t argc, const char *argv[])
298 {
299     int32_t busNum = 1;
300     int32_t devAddr = 2;
301     int32_t ifaceNum = 3;
302     struct AcmDevice *acm = NULL;
303 
304     if (argc == TEST_SIX_TYPE) {
305         busNum = atoi(argv[TEST_ONE_TYPE]);
306         devAddr = atoi(argv[TEST_TWO_TYPE]);
307         ifaceNum = atoi(argv[TEST_THREE_TYPE]);
308         g_writeOrRead = (strncmp(argv[TEST_FOUR_TYPE], "r", TEST_ONE_TYPE)) ? TEST_WRITE : TEST_READ;
309         if (g_writeOrRead == TEST_READ) {
310             g_printData = (strncmp(argv[TEST_FIVE_TYPE], "printdata", TEST_ONE_TYPE)) ? false : true;
311         }
312     } else if (argc == TEST_FIVE_TYPE) {
313         busNum = atoi(argv[TEST_ONE_TYPE]);
314         devAddr = atoi(argv[TEST_TWO_TYPE]);
315         ifaceNum = atoi(argv[TEST_THREE_TYPE]);
316         g_writeOrRead = (strncmp(argv[TEST_FOUR_TYPE], "r", TEST_ONE_TYPE)) ? TEST_WRITE : TEST_READ;
317     } else if (argc == TEST_THREE_TYPE) {
318         ifaceNum = atoi(argv[TEST_ONE_TYPE]);
319         g_writeOrRead = (strncmp(argv[TEST_TWO_TYPE], "r", TEST_ONE_TYPE)) ? TEST_WRITE : TEST_READ;
320     } else {
321         printf("Error: parameter error!\n\n");
322         ShowHelp(argv[0]);
323         goto END;
324     }
325 
326     acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*acm));
327     if (acm == NULL) {
328         HDF_LOGE("%s: Alloc usb serial device failed", __func__);
329         goto END;
330     }
331     acm->busNum = busNum;
332     acm->devAddr = devAddr;
333     acm->interfaceCnt = 1;
334     acm->interfaceIndex[0] = ifaceNum;
335 END:
336     return acm;
337 }
338 
InitUsbDdk(struct AcmDevice * acm)339 static int32_t InitUsbDdk(struct AcmDevice *acm)
340 {
341     int32_t ret = UsbInitHostSdk(NULL);
342     if (ret != HDF_SUCCESS) {
343         HDF_LOGE("%s: UsbInitHostSdk failed", __func__);
344         ret = HDF_ERR_IO;
345         goto END;
346     }
347 
348     for (int32_t i = 0; i < acm->interfaceCnt; i++) {
349         acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)acm, acm->interfaceIndex[i]);
350     }
351 
352     for (int32_t i = 0; i < acm->interfaceCnt; i++) {
353         if (acm->iface[i]) {
354             acm->devHandle[i] = UsbOpenInterface(acm->iface[i]);
355             if (acm->devHandle[i] == NULL) {
356                 HDF_LOGE("%s: UsbOpenInterface null", __func__);
357             }
358         } else {
359             ret = HDF_FAILURE;
360             goto END;
361         }
362     }
363     if (g_writeOrRead == TEST_WRITE) {
364         acm->dataPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT);
365     } else {
366         acm->dataPipe = GetPipe(acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN);
367     }
368     if (acm->dataPipe == NULL) {
369         HDF_LOGE("dataPipe is NULL\n");
370     }
371 
372     acm->dataSize = TEST_LENGTH;
373     if (AcmDataBufAlloc(acm) < 0) {
374         HDF_LOGE("%s:%d AcmDataBufAlloc fail", __func__, __LINE__);
375     }
376 END:
377     return ret;
378 }
379 
FillRequest(struct AcmDevice * const acm)380 static int32_t FillRequest(struct AcmDevice * const acm)
381 {
382     for (int32_t i = 0; i < TEST_CYCLE; i++) {
383         struct AcmDb *snd = &(acm->db[i]);
384         snd->request = UsbAllocRequest(InterfaceIdToHandle(acm, acm->dataPipe->interfaceId), 0, acm->dataSize);
385         if (snd->request == NULL) {
386             HDF_LOGE("%s:%d snd request fail", __func__, __LINE__);
387         }
388         int32_t rc;
389         acm->transmitting++;
390         struct UsbRequestParams parmas = {};
391         parmas.interfaceId = acm->dataPipe->interfaceId;
392         parmas.pipeAddress = acm->dataPipe->pipeAddress;
393         parmas.pipeId = acm->dataPipe->pipeId;
394         parmas.callback = AcmTestBulkCallback;
395         parmas.requestType = USB_REQUEST_PARAMS_DATA_TYPE;
396         parmas.timeout = USB_CTRL_SET_TIMEOUT;
397         parmas.dataReq.numIsoPackets = 0;
398         parmas.userData = (void *)snd;
399         parmas.dataReq.length = acm->dataSize;
400         parmas.dataReq.buffer = snd->buf;
401         parmas.dataReq.directon = (acm->dataPipe->pipeDirection >> USB_PIPE_DIR_OFFSET) & 0x1;
402         snd->dbNum = acm->transmitting;
403         rc = UsbFillRequest(snd->request, InterfaceIdToHandle(acm, acm->dataPipe->interfaceId), &parmas);
404         if (rc != HDF_SUCCESS) {
405             HDF_LOGE("%s:UsbFillRequest failed,ret=%d \n", __func__, rc);
406             return rc;
407         }
408     }
409 
410     return HDF_SUCCESS;
411 }
412 
main(int32_t argc,char * argv[])413 int32_t main(int32_t argc, char *argv[])
414 {
415     struct timeval time;
416     int32_t i;
417     int32_t ret;
418     struct AcmDevice *acm = NULL;
419 
420     acm = CheckParam(argc, (const char **)argv);
421     if (acm == NULL) {
422         ret = HDF_FAILURE;
423         goto END;
424     }
425 
426     ret = InitUsbDdk(acm);
427     if (ret != HDF_SUCCESS) {
428         goto END;
429     }
430 
431     ret = FillRequest(acm);
432     if (ret != HDF_SUCCESS) {
433         goto END;
434     }
435 
436     if (signal(SIGINT, SignalHandler) == SIG_ERR) {
437         HDF_LOGE("signal SIGINT failed");
438         return HDF_FAILURE;
439     }
440     if (signal(SIGALRM, SignalHandler) == SIG_ERR) {
441         HDF_LOGE("signal SIGINT failed");
442         return HDF_FAILURE;
443     }
444     gettimeofday(&time, NULL);
445 
446     printf("test SDK API [%s]\n", g_writeOrRead ? "write" : "read");
447     for (i = 0; i < TEST_CYCLE; i++) {
448         if (SerialBegin(acm) != HDF_SUCCESS) {
449             HDF_LOGW("%s:%d SerialBegin error!", __func__, __LINE__);
450         }
451         g_send_count++;
452     }
453 
454     while (!g_speedFlag) {
455         OsalMSleep(TEST_SLEEP_TIME);
456     }
457 END:
458     if (ret != HDF_SUCCESS) {
459         printf("please check whether usb drv so is existing or not,like acm,ecm,if not, remove it and test again!\n");
460     }
461     return ret;
462 }
463