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