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 <osal_sem.h>
21 #include <osal_thread.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/ioctl.h>
27 #include <sys/mman.h>
28 #include <sys/time.h>
29 #include <unistd.h>
30 
31 #include "hdf_base.h"
32 #include "hdf_log.h"
33 #include "hdf_usb_pnp_manage.h"
34 #include "implementation/global_implementation.h"
35 #include "osal_mem.h"
36 #include "osal_time.h"
37 #include "securec.h"
38 #include "usb_ddk_interface.h"
39 #include "usb_pnp_notify.h"
40 
41 #define HDF_LOG_TAG USB_HOST_ACM
42 
43 static bool g_speedFlag = false;
44 static uint64_t g_recv_count = 0;
45 static uint64_t g_send_count = 0;
46 static uint64_t g_byteTotal = 0;
47 static bool g_writeOrRead = TEST_WRITE;
48 static bool g_printData = false;
49 static struct AcmDevice *g_acm = NULL;
50 static struct OsalSem timeSem;
51 static uint32_t sigCnt = 0;
52 
53 static void AcmTestBulkCallback(struct UsbRequest *req);
54 static int32_t SerialBegin(struct AcmDevice * const acm);
55 
AcmDbAlloc(struct AcmDevice * acm)56 static int32_t AcmDbAlloc(struct AcmDevice *acm)
57 {
58     int32_t i, dbn;
59     struct AcmDb *db = NULL;
60     dbn = 0;
61     i = 0;
62     while (true) {
63         if (TEST_CYCLE <= dbn) {
64             return -1;
65         }
66         db = &acm->db[dbn];
67         if (!db->use) {
68             db->use = 1;
69             db->len = 0;
70             return dbn;
71         }
72         dbn = (dbn + 1) % TEST_CYCLE;
73         if (++i >= TEST_CYCLE) {
74             return -1;
75         }
76     }
77 }
78 
AcmDbIsAvail(const struct AcmDevice * acm)79 static int32_t AcmDbIsAvail(const struct AcmDevice *acm)
80 {
81     int32_t i, n;
82     n = TEST_CYCLE;
83     for (i = 0; i < TEST_CYCLE; i++) {
84         n -= acm->db[i].use;
85     }
86     return n;
87 }
88 
InterfaceIdToHandle(const struct AcmDevice * acm,uint8_t id)89 static UsbInterfaceHandle *InterfaceIdToHandle(const struct AcmDevice *acm, uint8_t id)
90 {
91     UsbInterfaceHandle *devHandle = NULL;
92 
93     if (id == 0xFF) {
94         devHandle = acm->ctrDevHandle;
95     } else {
96         for (int32_t i = 0; i < acm->interfaceCnt; i++) {
97             if (acm->iface[i]->info.interfaceIndex == id) {
98                 devHandle = acm->devHandle[i];
99                 break;
100             }
101         }
102     }
103     return devHandle;
104 }
105 
AcmStartDb(struct AcmDevice * acm,struct AcmDb * const db,struct UsbPipeInfo * pipe)106 static int32_t AcmStartDb(struct AcmDevice *acm, struct AcmDb * const db, struct UsbPipeInfo *pipe)
107 {
108     (void)acm;
109     (void)pipe;
110     int32_t rc;
111     rc = UsbSubmitRequestAsync(db->request);
112     if (rc < 0) {
113         HDF_LOGE("UsbSubmitRequestAsync failed, ret=%{public}d ", rc);
114         db->use = 0;
115     }
116     return rc;
117 }
118 
AcmDataBufAlloc(struct AcmDevice * acm)119 static int32_t AcmDataBufAlloc(struct AcmDevice *acm)
120 {
121     int32_t i;
122     struct AcmDb *db = NULL;
123     if (acm == NULL) {
124         return 0;
125     }
126     for (db = &acm->db[0], i = 0; i < TEST_CYCLE; i++, db++) {
127         db->buf = OsalMemCalloc(acm->dataSize);
128         if (!db->buf) {
129             while (i != 0) {
130                 --i;
131                 --db;
132                 OsalMemFree(db->buf);
133                 db->buf = NULL;
134             }
135             return -HDF_ERR_MALLOC_FAIL;
136         } else {
137             memset_s(db->buf, acm->dataSize, 'a', acm->dataSize);
138             db->instance = acm;
139         }
140     }
141     return 0;
142 }
143 
AcmDataBufFree(const struct AcmDevice * acm)144 static int32_t AcmDataBufFree(const struct AcmDevice *acm)
145 {
146     int32_t i;
147     struct AcmDb *db;
148     for (db = (struct AcmDb *)&acm->db[0], i = 0; i < TEST_CYCLE; i++, db++) {
149         OsalMemFree(db->buf);
150         db->use = 0;
151     }
152     return 0;
153 }
154 
AcmTestBulkCallback(struct UsbRequest * req)155 static void AcmTestBulkCallback(struct UsbRequest *req)
156 {
157     if (req == NULL) {
158         printf("req is null\r\n");
159         return;
160     }
161     int32_t status = req->compInfo.status;
162     struct AcmDb *db = (struct AcmDb *)req->compInfo.userData;
163     if (status == 0) {
164         if (g_byteTotal == 0) {
165             OsalSemPost(&timeSem);
166         }
167         g_recv_count++;
168         g_byteTotal += req->compInfo.actualLength;
169     } else {
170         printf("error status=%d\r\n", status);
171     }
172 
173     if (g_printData) {
174         for (unsigned int i = 0; i < req->compInfo.actualLength; i++) {
175             printf("%c", req->compInfo.buffer[i]);
176         }
177         fflush(stdout);
178     } else if (g_recv_count % TEST_RECV_COUNT == 0) {
179         printf("#");
180         fflush(stdout);
181     }
182     if (db == NULL) {
183         return;
184     }
185     db->use = 0;
186     if (!g_speedFlag) {
187         if (SerialBegin(db->instance) != HDF_SUCCESS) {
188             HDF_LOGW("%{public}s:%{public}d SerialBegin error!", __func__, __LINE__);
189         }
190         g_send_count++;
191     }
192 }
193 
SerialBegin(struct AcmDevice * const acm)194 static int32_t SerialBegin(struct AcmDevice * const acm)
195 {
196     int32_t ret;
197     struct AcmDb *db = NULL;
198     int32_t dbn;
199     if (AcmDbIsAvail(acm) != 0) {
200         dbn = AcmDbAlloc(acm);
201     } else {
202         HDF_LOGE("no buf");
203         return 0;
204     }
205     if (dbn < 0) {
206         HDF_LOGE("AcmDbAlloc failed");
207         return HDF_FAILURE;
208     }
209     db = &acm->db[dbn];
210     db->len = (int)acm->dataSize;
211     ret = AcmStartDb(acm, db, NULL);
212     return ret;
213 }
214 
GetUsbInterfaceById(const struct AcmDevice * acm,uint8_t interfaceIndex)215 static struct UsbInterface *GetUsbInterfaceById(const struct AcmDevice *acm, uint8_t interfaceIndex)
216 {
217     return UsbClaimInterface(NULL, acm->busNum, acm->devAddr, interfaceIndex);
218 }
219 
EnumePipe(const struct AcmDevice * acm,uint8_t interfaceIndex,UsbPipeType pipeType,UsbPipeDirection pipeDirection)220 static struct UsbPipeInfo *EnumePipe(
221     const struct AcmDevice *acm, uint8_t interfaceIndex, UsbPipeType pipeType, UsbPipeDirection pipeDirection)
222 {
223     struct UsbInterfaceInfo *info = NULL;
224     UsbInterfaceHandle *interfaceHandle = NULL;
225     if (USB_PIPE_TYPE_CONTROL == pipeType) {
226         info = &acm->ctrIface->info;
227         interfaceHandle = acm->ctrDevHandle;
228     } else {
229         info = &acm->iface[interfaceIndex]->info;
230         interfaceHandle = InterfaceIdToHandle(acm, info->interfaceIndex);
231     }
232 
233     for (uint8_t i = 0; i <= info->pipeNum; i++) {
234         struct UsbPipeInfo p;
235         int32_t ret = UsbGetPipeInfo(interfaceHandle, info->curAltSetting, i, &p);
236         if (ret < 0) {
237             continue;
238         }
239         if ((p.pipeDirection == pipeDirection) && (p.pipeType == pipeType)) {
240             struct UsbPipeInfo *pi = OsalMemCalloc(sizeof(*pi));
241             if (pi == NULL) {
242                 HDF_LOGE("%{public}s: Alloc pipe failed", __func__);
243                 return NULL;
244             }
245             p.interfaceId = info->interfaceIndex;
246             *pi = p;
247             return pi;
248         }
249     }
250     return NULL;
251 }
252 
GetPipe(const struct AcmDevice * acm,UsbPipeType pipeType,UsbPipeDirection pipeDirection)253 static struct UsbPipeInfo *GetPipe(const struct AcmDevice *acm, UsbPipeType pipeType, UsbPipeDirection pipeDirection)
254 {
255     uint8_t i;
256     if (acm == NULL) {
257         HDF_LOGE("%{public}s: invalid parmas", __func__);
258         return NULL;
259     }
260     for (i = 0; i < acm->interfaceCnt; i++) {
261         struct UsbPipeInfo *p = NULL;
262         if (!acm->iface[i]) {
263             continue;
264         }
265         p = EnumePipe(acm, i, pipeType, pipeDirection);
266         if (p == NULL) {
267             continue;
268         }
269         return p;
270     }
271     return NULL;
272 }
273 
SpeedPrint(void)274 static void SpeedPrint(void)
275 {
276     double speed;
277     uint64_t count;
278 
279     sigCnt++;
280     count = (uint64_t)sigCnt * TEST_PRINT_TIME;
281     if (count >= TEST_TIME) {
282         g_speedFlag = true;
283     }
284     speed = (g_byteTotal * TEST_FLOAT_COUNT) / (sigCnt * TEST_PRINT_TIME * TEST_BYTE_COUNT * TEST_BYTE_COUNT);
285     printf("\nSpeed:%f MB/s\n", speed);
286 }
287 
ShowHelp(const char * name)288 static void ShowHelp(const char *name)
289 {
290     printf(">> usage:\n");
291     printf(">>      %s [<busNum> <devAddr>]  <ifaceNum> <w>/<r> [printdata]> \n", name);
292     printf("\n");
293 }
294 
UsbGetDevInfo(int32_t * const busNum,int32_t * const devNum)295 static void UsbGetDevInfo(int32_t * const busNum, int32_t * const devNum)
296 {
297     struct UsbGetDevicePara paraData;
298     struct usb_device *usbPnpDevice = NULL;
299     paraData.type = USB_PNP_DEVICE_VENDOR_PRODUCT_TYPE;
300     paraData.vendorId = USB_DEVICE_VENDOR_ID;
301     paraData.productId = USB_DEVICE_PRODUCT_ID;
302     usbPnpDevice = UsbPnpNotifyGetUsbDevice(paraData);
303     if (usbPnpDevice == NULL) {
304         HDF_LOGE("%{public}s:%{public}d UsbPnpNotifyGetUsbDevice is null!", __func__, __LINE__);
305         return;
306     }
307     *busNum = (int)usbPnpDevice->address;
308     *devNum = (int)usbPnpDevice->port_no;
309     printf("%s:%d busNum = %d, devNum = %d!\n", __func__, __LINE__, *busNum, *devNum);
310 }
311 
UsbSerialOpen(void)312 static int32_t UsbSerialOpen(void)
313 {
314     return HDF_SUCCESS;
315 }
316 
UsbSerialClose(void)317 static int32_t UsbSerialClose(void)
318 {
319     if (!g_speedFlag) {
320         g_speedFlag = true;
321     }
322     return HDF_SUCCESS;
323 }
324 
UsbSerialSpeedInit(const struct UsbSpeedTest * input,int32_t * ifaceNum)325 static int32_t UsbSerialSpeedInit(const struct UsbSpeedTest *input, int32_t *ifaceNum)
326 {
327     int32_t busNum = 1;
328     int32_t devAddr = 2;
329     if (input == NULL) {
330         return HDF_ERR_INVALID_PARAM;
331     }
332 
333     g_speedFlag = false;
334     g_send_count = 0;
335     g_recv_count = 0;
336     g_byteTotal = 0;
337     g_printData = false;
338     g_writeOrRead = TEST_WRITE;
339     sigCnt = 0;
340 
341     UsbGetDevInfo(&busNum, &devAddr);
342     if (input->paramNum == TEST_SIX_TYPE) {
343         busNum = input->busNum;
344         devAddr = input->devAddr;
345         *ifaceNum = input->ifaceNum;
346         g_writeOrRead = input->writeOrRead;
347         if (g_writeOrRead == TEST_READ) {
348             g_printData = input->printData;
349         }
350     } else if (input->paramNum == TEST_FIVE_TYPE) {
351         busNum = input->busNum;
352         devAddr = input->devAddr;
353         *ifaceNum = input->ifaceNum;
354         g_writeOrRead = input->writeOrRead;
355     } else if (input->paramNum == TEST_THREE_TYPE) {
356         *ifaceNum = input->ifaceNum;
357         g_writeOrRead = input->writeOrRead;
358     } else {
359         printf("Error: parameter error! \n\n");
360         ShowHelp("speedtest");
361         return HDF_FAILURE;
362     }
363 
364     g_acm->busNum = (uint8_t)busNum;
365     g_acm->devAddr = (uint8_t)devAddr;
366     g_acm->interfaceCnt = 1;
367     g_acm->interfaceIndex[0] = *ifaceNum;
368     OsalSemInit(&timeSem, 0);
369 
370     return HDF_SUCCESS;
371 }
372 
UsbSpeedDdkInit(void)373 static int32_t UsbSpeedDdkInit(void)
374 {
375     uint8_t i;
376     int32_t ret = UsbInitHostSdk(NULL);
377     if (ret != HDF_SUCCESS) {
378         HDF_LOGE("%{public}s:%{public}d UsbInitHostSdk failed", __func__, __LINE__);
379         return HDF_ERR_IO;
380     }
381 
382     for (i = 0; i < g_acm->interfaceCnt; i++) {
383         g_acm->iface[i] = GetUsbInterfaceById((const struct AcmDevice *)g_acm, g_acm->interfaceIndex[i]);
384     }
385 
386     for (i = 0; i < g_acm->interfaceCnt; i++) {
387         if (g_acm->iface[i]) {
388             g_acm->devHandle[i] = UsbOpenInterface(g_acm->iface[i]);
389             if (g_acm->devHandle[i] == NULL) {
390                 HDF_LOGI("%{public}s: UsbOpenInterface null", __func__);
391             }
392         } else {
393             HDF_LOGE("%{public}s:%{public}d g_acm->iface[%{public}hhu] is null.", __func__, __LINE__, i);
394             return HDF_FAILURE;
395         }
396     }
397     if (g_writeOrRead == TEST_WRITE) {
398         g_acm->dataPipe = GetPipe(g_acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_OUT);
399     } else {
400         g_acm->dataPipe = GetPipe(g_acm, USB_PIPE_TYPE_BULK, USB_PIPE_DIRECTION_IN);
401     }
402     if (g_acm->dataPipe == NULL) {
403         HDF_LOGE("%{public}s:%{public}d dataPipe is null", __func__, __LINE__);
404         return HDF_FAILURE;
405     }
406 
407     g_acm->dataSize = TEST_LENGTH;
408     if (AcmDataBufAlloc(g_acm) < 0) {
409         HDF_LOGE("%{public}s:%{public}d AcmDataBufAlloc failed", __func__, __LINE__);
410         return HDF_FAILURE;
411     }
412 
413     return ret;
414 }
415 
UsbSpeedRequestHandle(void)416 static int32_t UsbSpeedRequestHandle(void)
417 {
418     for (int32_t i = 0; i < TEST_CYCLE; i++) {
419         struct AcmDb *snd = &(g_acm->db[i]);
420         snd->request = UsbAllocRequest(InterfaceIdToHandle(g_acm, g_acm->dataPipe->interfaceId), 0, g_acm->dataSize);
421         if (snd->request == NULL) {
422             printf("%s:%d snd request fail", __func__, __LINE__);
423         }
424         g_acm->transmitting++;
425         struct UsbRequestParams parmas = {};
426         parmas.interfaceId = g_acm->dataPipe->interfaceId;
427         parmas.pipeAddress = g_acm->dataPipe->pipeAddress;
428         parmas.pipeId = g_acm->dataPipe->pipeId;
429         parmas.callback = AcmTestBulkCallback;
430         parmas.requestType = USB_REQUEST_PARAMS_DATA_TYPE;
431         parmas.timeout = USB_CTRL_SET_TIMEOUT;
432         parmas.dataReq.numIsoPackets = 0;
433         parmas.userData = (void *)snd;
434         parmas.dataReq.length = (int)g_acm->dataSize;
435         parmas.dataReq.buffer = snd->buf;
436         parmas.dataReq.directon = (((uint8_t)g_acm->dataPipe->pipeDirection) >> USB_PIPE_DIR_OFFSET) & 0x1;
437         snd->dbNum = g_acm->transmitting;
438         int32_t rc = UsbFillRequest(snd->request, InterfaceIdToHandle(g_acm, g_acm->dataPipe->interfaceId), &parmas);
439         if (rc != HDF_SUCCESS) {
440             printf("%s:UsbFillRequest failed,ret = %d \n", __func__, rc);
441             return rc;
442         }
443     }
444 
445     return HDF_SUCCESS;
446 }
447 
UsbSpeedDdkExit(void)448 static void UsbSpeedDdkExit(void)
449 {
450     uint8_t i;
451 
452     for (i = 0; i < TEST_CYCLE; i++) {
453         struct AcmDb *snd = &(g_acm->db[i]);
454         UsbCancelRequest(snd->request);
455         UsbFreeRequest(snd->request);
456     }
457     AcmDataBufFree(g_acm);
458     for (i = 0; i < g_acm->interfaceCnt; i++) {
459         UsbCloseInterface(g_acm->devHandle[i], false);
460         UsbReleaseInterface(g_acm->iface[i]);
461     }
462     UsbExitHostSdk(NULL);
463     OsalSemDestroy(&timeSem);
464     g_acm->busy = false;
465 }
466 
UsbSerialSpeed(struct HdfSBuf * data)467 static int32_t UsbSerialSpeed(struct HdfSBuf *data)
468 {
469     int32_t ifaceNum = 3;
470     int32_t ret = HDF_SUCCESS;
471     struct UsbSpeedTest *input = NULL;
472     uint32_t size = 0;
473     int32_t i;
474     if (g_acm->busy) {
475         printf("%s: speed test busy\n", __func__);
476         ret = HDF_ERR_IO;
477         goto END;
478     } else {
479         g_acm->busy = true;
480     }
481 
482     (void)HdfSbufReadBuffer(data, (const void **)&input, &size);
483     if ((input == NULL) || (size != sizeof(struct UsbSpeedTest))) {
484         printf("%s: sbuf read buffer failed", __func__);
485         ret = HDF_ERR_IO;
486         goto END;
487     }
488 
489     ret = UsbSerialSpeedInit(input, &ifaceNum);
490     if (ret != HDF_SUCCESS) {
491         goto END;
492     }
493 
494     ret = UsbSpeedDdkInit();
495     if (ret != HDF_SUCCESS) {
496         goto END;
497     }
498 
499     ret = UsbSpeedRequestHandle();
500     if (ret != HDF_SUCCESS) {
501         goto END;
502     }
503 
504     printf("test SDK API [%s]\n", g_writeOrRead ? "write" : "read");
505 
506     for (i = 0; i < TEST_CYCLE; i++) {
507         if (SerialBegin(g_acm) != HDF_SUCCESS) {
508             printf("SerialBegin error!\n");
509         }
510         g_send_count++;
511     }
512 
513     OsalSemWait(&timeSem, TEST_TIME);
514     while (!g_speedFlag) {
515         OsalSemWait(&timeSem, TEST_PRINT_TIME * TEST_PRINT_TIME_UINT);
516         SpeedPrint();
517     }
518 
519     UsbSpeedDdkExit();
520 
521 END:
522     if (ret != HDF_SUCCESS) {
523         printf("please check whether usb drv so is existing or not,like acm, ecm, if not, remove it and test again!\n");
524     }
525     return ret;
526 }
527 
AcmDeviceDispatch(struct HdfDeviceIoClient * const client,int32_t cmd,struct HdfSBuf * data,struct HdfSBuf * reply)528 static int32_t AcmDeviceDispatch(
529     struct HdfDeviceIoClient * const client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
530 {
531     (void)reply;
532     if (client == NULL) {
533         HDF_LOGE("%{public}s: client is NULL", __func__);
534         return HDF_ERR_INVALID_OBJECT;
535     }
536 
537     if (client->device == NULL) {
538         HDF_LOGE("%{public}s: client->device is NULL", __func__);
539         return HDF_ERR_INVALID_OBJECT;
540     }
541 
542     if (client->device->service == NULL) {
543         HDF_LOGE("%{public}s: client->device->service is NULL", __func__);
544         return HDF_ERR_INVALID_OBJECT;
545     }
546 
547     g_acm = (struct AcmDevice *)client->device->service;
548 
549     switch (cmd) {
550         case USB_SERIAL_OPEN:
551             return UsbSerialOpen();
552         case USB_SERIAL_CLOSE:
553             return UsbSerialClose();
554         case USB_SERIAL_SPEED:
555             return UsbSerialSpeed(data);
556         default:
557             return HDF_ERR_NOT_SUPPORT;
558     }
559 
560     return HDF_SUCCESS;
561 }
562 
AcmDriverBind(struct HdfDeviceObject * device)563 static int32_t AcmDriverBind(struct HdfDeviceObject *device)
564 {
565     if (device == NULL) {
566         HDF_LOGE("%{public}s: device is null", __func__);
567         return HDF_ERR_INVALID_OBJECT;
568     }
569 
570     g_acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*g_acm));
571     if (g_acm == NULL) {
572         HDF_LOGE("%{public}s: Alloc usb acm device failed", __func__);
573         return HDF_FAILURE;
574     }
575 
576     g_acm->device = device;
577     device->service = &(g_acm->service);
578     if (g_acm->device && g_acm->device->service) {
579         g_acm->device->service->Dispatch = AcmDeviceDispatch;
580     }
581     return HDF_SUCCESS;
582 }
583 
AcmDriverInit(struct HdfDeviceObject * device)584 static int32_t AcmDriverInit(struct HdfDeviceObject *device)
585 {
586     (void)device;
587     return 0;
588 }
589 
AcmDriverRelease(struct HdfDeviceObject * device)590 static void AcmDriverRelease(struct HdfDeviceObject *device)
591 {
592     (void)device;
593     return;
594 }
595 
596 struct HdfDriverEntry g_usbSdkApiSpeedDriverEntry = {
597     .moduleVersion = 1,
598     .moduleName = "usb_sdkapispeed",
599     .Bind = AcmDriverBind,
600     .Init = AcmDriverInit,
601     .Release = AcmDriverRelease,
602 };
603 
604 HDF_INIT(g_usbSdkApiSpeedDriverEntry);
605