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