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