1 /*
2  * Copyright (c) 2021-2023 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_nosdk_speed.h"
17 
18 #include <dirent.h>
19 #include <errno.h>
20 #include <fcntl.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/syscall.h>
30 #include <sys/time.h>
31 #include <time.h>
32 #include <unistd.h>
33 
34 #include "implementation/global_implementation.h"
35 #include "liteos_ddk_usb.h"
36 #include "osal_mem.h"
37 #include "osal_time.h"
38 #include "usb_pnp_notify.h"
39 
40 #define USB_DEV_FS_PATH                 "/dev/bus/usb"
41 #define URB_COMPLETE_PROCESS_STACK_SIZE 8196
42 #define ENDPOINT_IN_OFFSET              7
43 #define DEFAULT_BUSNUM                  1
44 #define DEFAULT_DEVADDR                 2
45 static int32_t g_speedFlag = 0;
46 static int32_t g_busNum = DEFAULT_BUSNUM;
47 static int32_t g_devAddr = DEFAULT_DEVADDR;
48 static struct OsalSem g_sem;
49 static uint64_t g_send_count = 0;
50 static uint64_t g_recv_count = 0;
51 static uint64_t g_byteTotal = 0;
52 static struct UsbAdapterUrbs urb[TEST_CYCLE];
53 static struct urb *g_sendUrb = NULL;
54 static bool g_printData = false;
55 static uint8_t g_endNum;
56 static struct OsalSem g_timeSem;
57 static struct usb_device *g_fd = NULL;
58 static uint32_t g_sigCnt = 0;
59 static UsbAdapterHostEndpoint *g_uhe = NULL;
60 static bool g_writeOrRead = TEST_WRITE;
61 static struct AcmDevice *g_acm = NULL;
62 
CloseDevice(void)63 static void CloseDevice(void)
64 {
65     return;
66 }
67 
OpenDevice(void)68 static int32_t OpenDevice(void)
69 {
70     struct UsbGetDevicePara paraData;
71     paraData.type = USB_PNP_DEVICE_ADDRESS_TYPE;
72     paraData.busNum = (uint8_t)g_busNum;
73     paraData.devNum = (uint8_t)g_devAddr;
74     g_fd = UsbPnpNotifyGetUsbDevice(paraData);
75     if (g_fd == NULL) {
76         HDF_LOGE("%{public}s: UsbPnpNotifyGetUsbDevice err", __func__);
77         return -1;
78     }
79     return 0;
80 }
81 
ClaimInterface(int32_t iface)82 static int32_t ClaimInterface(int32_t iface)
83 {
84     HDF_LOGI("%{public}s: claim success: iface=%{public}d", __func__, iface);
85     return HDF_SUCCESS;
86 }
87 
SpeedPrint(void)88 static void SpeedPrint(void)
89 {
90     double speed;
91     uint64_t count;
92 
93     g_sigCnt++;
94     count = (uint64_t)g_sigCnt * TEST_PRINT_TIME;
95     if (count >= TEST_TIME) {
96         g_speedFlag = true;
97     }
98     speed =
99         (g_byteTotal * TEST_DOUBLE_COUNT) / (g_sigCnt * TEST_PRINT_TIME * TEST_BYTE_COUNT_UINT * TEST_BYTE_COUNT_UINT);
100     printf("\nSpeed:%f MB/s\n", speed);
101 }
102 
SendProcess(void * argurb)103 static int32_t SendProcess(void *argurb)
104 {
105     (void)argurb;
106     int32_t i;
107     while (!g_speedFlag) {
108         OsalSemWait(&g_sem, HDF_WAIT_FOREVER);
109         for (i = 0; i < TEST_CYCLE; i++) {
110             if (urb[i].inUse == 0) {
111                 urb[i].inUse = 1;
112                 break;
113             }
114         }
115 
116         if (i == TEST_CYCLE) {
117             i = TEST_CYCLE - 1;
118         }
119         g_sendUrb = urb[i].urb;
120         int32_t err = usb_setup_endpoint(g_fd, g_uhe, TEST_BYTE_COUNT_UINT);
121         if (err < 0) {
122             DPRINTFN(0, "setup failed err:%d\n", err);
123             return err;
124         }
125         err = usb_submit_urb(g_sendUrb, 0);
126         if (err < 0) {
127             HDF_LOGI("SubmitBulkRequest: err:%{public}d", err);
128             urb[i].inUse = 0;
129             continue;
130         }
131         g_send_count++;
132     }
133     return 0;
134 }
135 
UrbCompleteHandle(const struct urb * curUrb)136 static void UrbCompleteHandle(const struct urb *curUrb)
137 {
138     if (g_printData) {
139         for (int32_t i = 0; i < curUrb->actual_length; i++) {
140             printf("%c", *(((char *)curUrb->transfer_buffer) + i));
141         }
142         fflush(stdout);
143     } else if (g_recv_count % TEST_PRINT_MAX_RANGE == 0) {
144         printf("#");
145         fflush(stdout);
146     }
147 }
148 
UrbComplete(struct urb * curUrb)149 static void UrbComplete(struct urb *curUrb)
150 {
151     int32_t i;
152     for (i = 0; i < TEST_CYCLE; i++) {
153         if (urb[i].urb == curUrb) {
154             if (g_byteTotal == 0) {
155                 OsalSemPost(&g_timeSem);
156             }
157             g_recv_count++;
158             g_byteTotal += curUrb->actual_length;
159             UrbCompleteHandle(curUrb);
160             urb[i].inUse = 0;
161             OsalSemPost(&g_sem);
162             break;
163         }
164     }
165 }
166 
BeginProcessHandleFirst(void)167 static int32_t BeginProcessHandleFirst(void)
168 {
169     char *data = NULL;
170     for (int32_t i = 0; i < TEST_CYCLE; i++) {
171         if (urb[i].urb == NULL) {
172             urb[i].urb = OsalMemCalloc(sizeof(struct urb));
173             if (urb[i].urb == NULL) {
174                 HDF_LOGE("%{public}s:%{public}d urb calloc err", __func__, __LINE__);
175                 return -1;
176             }
177         }
178         urb[i].inUse = 0;
179         urb[i].urb->dev = g_fd;
180         urb[i].urb->endpoint = g_uhe;
181         urb[i].urb->complete = UrbComplete;
182 
183         if (data == NULL) {
184             data = OsalMemCalloc(TEST_LENGTH);
185             if (data == NULL) {
186                 HDF_LOGE("%{public}s:%{public}d data calloc err", __func__, __LINE__);
187                 return -1;
188             }
189         }
190 
191         if (memset_s(data, TEST_LENGTH, 'c', TEST_LENGTH) != EOK) {
192             HDF_LOGE("%{public}s:%{public}d memset_s failed.", __func__, __LINE__);
193             return -1;
194         }
195         data[TEST_LENGTH - 1] = '\0';
196         urb[i].urb->transfer_buffer = (void *)data;
197         urb[i].urb->transfer_buffer_length = TEST_LENGTH;
198     }
199 
200     return HDF_SUCCESS;
201 }
202 
BeginProcess(unsigned char endPoint)203 static int32_t BeginProcess(unsigned char endPoint)
204 {
205     const int32_t transNum = 0;
206     if (endPoint == 0) {
207         HDF_LOGE("%{public}s:%{public}d parameter error", __func__, __LINE__);
208         return -1;
209     }
210 
211     g_uhe = usb_find_host_endpoint(g_fd, USB_REQUEST_TYPE_BULK, endPoint);
212     if (g_uhe == NULL) {
213         HDF_LOGE("%{public}s:%{public}d usb_find_host_endpoint error", __func__, __LINE__);
214         return -1;
215     }
216     int32_t ret = BeginProcessHandleFirst();
217     if (ret != HDF_SUCCESS) {
218         return ret;
219     }
220 
221     HDF_LOGI("%{public}s:%{public}d test NO SDK endpoint:%{public}u", __func__, __LINE__, endPoint);
222 
223     int32_t i;
224     for (i = 0; i < TEST_CYCLE; i++) {
225         if (urb[i].inUse == 0) {
226             urb[i].inUse = 1;
227             urb[i].urbNum = transNum;
228             g_sendUrb = urb[i].urb;
229             ret = usb_setup_endpoint(g_fd, g_uhe, TEST_BYTE_COUNT_UINT);
230             if (ret < 0) {
231                 DPRINTFN(0, "setup failed ret:%d\n", ret);
232                 return ret;
233             }
234             ret = usb_submit_urb(g_sendUrb, 0);
235             if (ret < 0) {
236                 HDF_LOGI("%{public}s:%{public}d SubmitBulkRequest: ret:%{public}d", __func__, __LINE__, ret);
237                 urb[i].inUse = 0;
238                 continue;
239             }
240             g_send_count++;
241         }
242     }
243 
244     OsalSemWait(&g_timeSem, TEST_TIME);
245     while (!g_speedFlag) {
246         OsalSemWait(&g_timeSem, TEST_PRINT_TIME * TEST_PRINT_TIME_UINT);
247         SpeedPrint();
248     }
249 
250     for (i = 0; i < TEST_CYCLE; i++) {
251         usb_kill_urb(urb[i].urb);
252     }
253 
254     return HDF_SUCCESS;
255 }
256 
ShowHelp(const char * name)257 static void ShowHelp(const char *name)
258 {
259     printf(">> usage:\n");
260     printf(">>      %s [<busNum> <devAddr>]  <ifaceNum> <endpoint> [<printdata>]\n", name);
261     printf("\n");
262 }
263 
UsbGetDevInfo(int32_t * const busNum,int32_t * const devNum)264 static void UsbGetDevInfo(int32_t * const busNum, int32_t * const devNum)
265 {
266     struct UsbGetDevicePara paraData;
267     struct usb_device *usbPnpDevice = NULL;
268     paraData.type = USB_PNP_DEVICE_VENDOR_PRODUCT_TYPE;
269     paraData.vendorId = USB_DEVICE_VENDOR_ID;
270     paraData.productId = USB_DEVICE_PRODUCT_ID;
271     usbPnpDevice = UsbPnpNotifyGetUsbDevice(paraData);
272     if (usbPnpDevice == NULL) {
273         HDF_LOGE("%{public}s:%{public}d UsbPnpNotifyGetUsbDevice is NULL!", __func__, __LINE__);
274         return;
275     }
276     *busNum = (int)usbPnpDevice->address;
277     *devNum = (int)usbPnpDevice->port_no;
278     printf("%s:%d busNum=%d devNum=%d!\n", __func__, __LINE__, *busNum, *devNum);
279 }
280 
UsbSerialOpen(void)281 static int32_t UsbSerialOpen(void)
282 {
283     return HDF_SUCCESS;
284 }
UsbSerialClose(void)285 static int32_t UsbSerialClose(void)
286 {
287     if (!g_speedFlag) {
288         g_speedFlag = true;
289     }
290     return HDF_SUCCESS;
291 }
292 
UsbSerialSpeedInit(const struct UsbSpeedTest * const input,int32_t * const ifaceNum)293 static int32_t UsbSerialSpeedInit(const struct UsbSpeedTest * const input, int32_t * const ifaceNum)
294 {
295     int32_t ret = HDF_SUCCESS;
296     if (input == NULL) {
297         HDF_LOGE("%{public}s:%{public}d input is null", __func__, __LINE__);
298         return HDF_ERR_INVALID_PARAM;
299     }
300 
301     g_speedFlag = false;
302     g_send_count = 0;
303     g_recv_count = 0;
304     g_byteTotal = 0;
305     g_printData = false;
306     g_writeOrRead = TEST_WRITE;
307     g_sigCnt = 0;
308     g_busNum = DEFAULT_BUSNUM;
309     g_devAddr = DEFAULT_DEVADDR;
310 
311     UsbGetDevInfo(&g_busNum, &g_devAddr);
312     if (input->paramNum == INPUT_COMPARE_PARAMNUM) {
313         g_busNum = input->busNum;
314         g_devAddr = input->devAddr;
315         *ifaceNum = input->ifaceNum;
316         g_endNum = input->writeOrRead;
317         g_writeOrRead = ((g_endNum >> ENDPOINT_IN_OFFSET) == 0) ? TEST_WRITE : TEST_READ;
318         if (g_writeOrRead == TEST_READ) {
319             g_printData = input->printData;
320         }
321     } else if (input->paramNum == INPUT_COMPARE_NUMTWO) {
322         g_busNum = input->busNum;
323         g_devAddr = input->devAddr;
324         *ifaceNum = input->ifaceNum;
325         g_endNum = input->writeOrRead;
326         g_writeOrRead = ((g_endNum >> ENDPOINT_IN_OFFSET) == 0) ? TEST_WRITE : TEST_READ;
327     } else if (input->paramNum == INPUT_COMPARE_NUMONE) {
328         *ifaceNum = input->ifaceNum;
329         g_endNum = input->writeOrRead;
330         g_writeOrRead = ((g_endNum >> ENDPOINT_IN_OFFSET) == 0) ? TEST_WRITE : TEST_READ;
331     } else {
332         printf("Error: parameter error! \n\n");
333         ShowHelp("speedtest");
334         return HDF_FAILURE;
335     }
336     OsalSemInit(&g_sem, 0);
337     OsalSemInit(&g_timeSem, 0);
338 
339     return ret;
340 }
341 
UsbSerialSpeedThreadCreate(void)342 static int32_t UsbSerialSpeedThreadCreate(void)
343 {
344     int32_t ret;
345     struct OsalThread urbSendProcess;
346     struct OsalThreadParam threadCfg;
347     ret = memset_s(&threadCfg, sizeof(threadCfg), 0, sizeof(threadCfg));
348     if (ret != EOK) {
349         HDF_LOGE("%{public}s:%{public}d memset_s failed", __func__, __LINE__);
350         return ret;
351     }
352     threadCfg.name = "urb send process";
353     threadCfg.priority = OSAL_THREAD_PRI_DEFAULT;
354     threadCfg.stackSize = URB_COMPLETE_PROCESS_STACK_SIZE;
355 
356     ret = OsalThreadCreate(&urbSendProcess, (OsalThreadEntry)SendProcess, NULL);
357     if (ret != HDF_SUCCESS) {
358         HDF_LOGE("OsalThreadCreate failed, ret = %{public}d", ret);
359         return ret;
360     }
361 
362     ret = OsalThreadStart(&urbSendProcess, &threadCfg);
363     if (ret != HDF_SUCCESS) {
364         HDF_LOGE("OsalThreadStart failed, ret = %{public}d", ret);
365         return ret;
366     }
367 
368     return ret;
369 }
370 
UsbSerialSpeed(struct HdfSBuf * data)371 static int32_t UsbSerialSpeed(struct HdfSBuf *data)
372 {
373     int32_t ifaceNum = 3;
374     int32_t ret;
375     struct UsbSpeedTest *input = NULL;
376     uint32_t size = 0;
377     if (g_acm->busy) {
378         HDF_LOGE("%{public}s: %{public}d speed test busy", __func__, __LINE__);
379         ret = HDF_ERR_IO;
380         goto END;
381     } else {
382         g_acm->busy = true;
383     }
384 
385     (void)HdfSbufReadBuffer(data, (const void **)&input, &size);
386     if (input == NULL || size != sizeof(struct UsbSpeedTest)) {
387         HDF_LOGE("%{public}s: %{public}d sbuf read buffer failed", __func__, __LINE__);
388         ret = HDF_ERR_IO;
389         goto END;
390     }
391 
392     ret = UsbSerialSpeedInit(input, &ifaceNum);
393     if (ret != HDF_SUCCESS) {
394         goto END;
395     }
396 
397     OpenDevice();
398 
399     ret = ClaimInterface(ifaceNum);
400     if (ret != HDF_SUCCESS) {
401         goto END;
402     }
403 
404     ret = UsbSerialSpeedThreadCreate();
405     if (ret != HDF_SUCCESS) {
406         goto END;
407     }
408 
409     ret = BeginProcess(g_endNum);
410     if (ret != HDF_SUCCESS) {
411         goto END;
412     }
413 
414 END:
415     g_acm->busy = false;
416     if (ret != HDF_SUCCESS) {
417         printf("please check whether usb drv so is existing or not,like g_acm, ecm,if not,remove it and test again!\n");
418     }
419     CloseDevice();
420     return ret;
421 }
422 
AcmDeviceDispatch(struct HdfDeviceIoClient * const client,int32_t cmd,struct HdfSBuf * const data,struct HdfSBuf * const reply)423 static int32_t AcmDeviceDispatch(
424     struct HdfDeviceIoClient * const client, int32_t cmd, struct HdfSBuf * const data, struct HdfSBuf * const reply)
425 {
426     (void)reply;
427     if (client == NULL) {
428         HDF_LOGE("%{public}s: client is NULL", __func__);
429         return HDF_ERR_INVALID_OBJECT;
430     }
431 
432     if (client->device == NULL) {
433         HDF_LOGE("%{public}s: client->device is NULL", __func__);
434         return HDF_ERR_INVALID_OBJECT;
435     }
436 
437     if (client->device->service == NULL) {
438         HDF_LOGE("%{public}s: client->device->service is NULL", __func__);
439         return HDF_ERR_INVALID_OBJECT;
440     }
441 
442     g_acm = (struct AcmDevice *)client->device->service;
443 
444     switch (cmd) {
445         case USB_SERIAL_OPEN:
446             return UsbSerialOpen();
447         case USB_SERIAL_CLOSE:
448             return UsbSerialClose();
449         case USB_SERIAL_SPEED:
450             return UsbSerialSpeed(data);
451         default:
452             return HDF_ERR_NOT_SUPPORT;
453     }
454 
455     return HDF_SUCCESS;
456 }
457 
AcmDriverBind(struct HdfDeviceObject * device)458 static int32_t AcmDriverBind(struct HdfDeviceObject *device)
459 {
460     if (device == NULL) {
461         HDF_LOGE("%{public}s: device is null", __func__);
462         return HDF_ERR_INVALID_OBJECT;
463     }
464 
465     g_acm = (struct AcmDevice *)OsalMemCalloc(sizeof(*g_acm));
466     if (g_acm == NULL) {
467         HDF_LOGE("%{public}s: Alloc usb g_acm device failed", __func__);
468         return HDF_FAILURE;
469     }
470 
471     g_acm->device = device;
472     device->service = &(g_acm->service);
473     if (g_acm->device && g_acm->device->service) {
474         g_acm->device->service->Dispatch = AcmDeviceDispatch;
475     }
476     return HDF_SUCCESS;
477 }
478 
AcmDriverInit(struct HdfDeviceObject * device)479 static int32_t AcmDriverInit(struct HdfDeviceObject *device)
480 {
481     (void)device;
482     return 0;
483 }
484 
AcmDriverRelease(struct HdfDeviceObject * device)485 static void AcmDriverRelease(struct HdfDeviceObject *device)
486 {
487     (void)device;
488     return;
489 }
490 
491 struct HdfDriverEntry g_usbNoSdkSpeedDriverEntry = {
492     .moduleVersion = 1,
493     .moduleName = "usb_nosdkspeed",
494     .Bind = AcmDriverBind,
495     .Init = AcmDriverInit,
496     .Release = AcmDriverRelease,
497 };
498 
499 HDF_INIT(g_usbNoSdkSpeedDriverEntry);
500