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 "securec.h"
38
39 #define USB_DEV_FS_PATH "/dev/bus/usb"
40 #define URB_COMPLETE_PROCESS_STACK_SIZE 8196
41
42 #define PATH_SIZE 24
43 #define TIME_SCALE 1024
44 #define RECV_COUNT_SIZE 10000
45 #define SLEEP_TIME 10
46
47 #define TEST_LENGTH 512
48 #define TEST_CYCLE 30
49 #define TEST_TIME 0xffffffff
50 #define TEST_PRINT_TIME 2
51 #define TEST_PRINT_TIME_UINT 1000
52 #define ENDPOINT_IN_OFFSET 7
53
54 static pid_t tid;
55 static int exitOk = false;
56 static int g_speedFlag = 0;
57 static unsigned int g_busNum = 1;
58 static unsigned int g_devAddr = 2;
59 static int fd;
60 static struct OsalSem sem;
61 static uint64_t g_send_count = 0;
62 static uint64_t g_recv_count = 0;
63 static uint64_t g_byteTotal = 0;
64 static struct UsbAdapterUrbs urb[TEST_CYCLE];
65 static struct UsbAdapterUrb *sendUrb = NULL;
66 static bool g_printData = false;
67 static unsigned int ifaceNum;
68 static unsigned char endNum;
69
CloseDevice(void)70 static void CloseDevice(void)
71 {
72 if (fd > 0) {
73 close(fd);
74 fd = 0;
75 }
76 return;
77 }
78
OpenDevice(void)79 static int OpenDevice(void)
80 {
81 char path[PATH_SIZE];
82 int ret;
83
84 ret = snprintf_s(path, PATH_SIZE, sizeof(path) - 1, USB_DEV_FS_PATH "/%03u/%03u", g_busNum, g_devAddr);
85 if (ret < 0) {
86 printf("path error\n");
87 return ret;
88 }
89
90 printf("open: %s\n", path);
91 fd = open(path, O_RDWR);
92 if (fd < 0) {
93 printf("open device failed! errno=%2d(%s)\n", errno, strerror(errno));
94 }
95
96 return fd;
97 }
98
ClaimInterface(unsigned int iface)99 static int ClaimInterface(unsigned int iface)
100 {
101 if (fd < 0 || iface < 0) {
102 printf("parameter error\n");
103 return -1;
104 }
105
106 int ret = ioctl(fd, USBDEVFS_CLAIMINTERFACE, &iface);
107 if (ret < 0) {
108 printf("claim failed: iface=%u, errno=%2d(%s)\n", iface, errno, strerror(errno));
109 return HDF_FAILURE;
110 }
111 printf("claim success: iface=%u\n", iface);
112 return HDF_SUCCESS;
113 }
114
FillUrb(struct UsbAdapterUrb * urb,int len)115 static void FillUrb(struct UsbAdapterUrb *urb, int len)
116 {
117 if (urb == NULL) {
118 urb = OsalMemCalloc(sizeof(*urb));
119 urb->userContext = (void *)(urb);
120 urb->type = USB_ADAPTER_URB_TYPE_BULK;
121 urb->streamId = 0;
122 urb->endPoint = endNum;
123 }
124 if ((endNum >> ENDPOINT_IN_OFFSET) == 0) {
125 memset_s(urb->buffer, len, 'c', len);
126 }
127 }
128
SignalHandler(int signo)129 void SignalHandler(int signo)
130 {
131 static uint32_t sigCnt = 0;
132 struct itimerval new_value, old_value;
133 double speed = 0;
134 switch (signo) {
135 case SIGALRM:
136 sigCnt++;
137 if (sigCnt * TEST_PRINT_TIME >= TEST_TIME) {
138 g_speedFlag = 1;
139 break;
140 }
141 speed = (g_byteTotal * 1.0) / (sigCnt * TEST_PRINT_TIME * TIME_SCALE * TIME_SCALE);
142 printf("\nSpeed:%f MB/s\n", speed);
143 new_value.it_value.tv_sec = TEST_PRINT_TIME;
144 new_value.it_value.tv_usec = 0;
145 new_value.it_interval.tv_sec = TEST_PRINT_TIME;
146 new_value.it_interval.tv_usec = 0;
147 setitimer(ITIMER_REAL, &new_value, &old_value);
148 break;
149 case SIGINT:
150 g_speedFlag = 1;
151 break;
152 default:
153 break;
154 }
155 }
156
SubmitRequest(uint32_t transNum)157 void SubmitRequest(uint32_t transNum)
158 {
159 int i;
160 int ret;
161 for (i = 0; i < TEST_CYCLE; i++) {
162 urb[i].inUse = 1;
163 urb[i].urbNum = transNum;
164 urb[i].urb->userContext = (void*)(&urb[i]);
165 sendUrb = urb[i].urb;
166 ret = ioctl(fd, USBDEVFS_SUBMITURB, sendUrb);
167 if (ret < 0) {
168 printf("SubmitBulkRequest: ret:%d errno=%d\n", ret, errno);
169 urb[i].inUse = 0;
170 continue;
171 }
172 g_send_count++;
173 }
174 }
175
SendProcess(void * argurb)176 static int SendProcess(void *argurb)
177 {
178 int i;
179 int ret;
180 while (!g_speedFlag) {
181 OsalSemWait(&sem, HDF_WAIT_FOREVER);
182 for (i = 0; i < TEST_CYCLE; i++) {
183 if (urb[i].inUse == 0) {
184 urb[i].inUse = 1;
185 urb[i].urb->userContext = (void*)(&urb[i]);
186 break;
187 }
188 }
189
190 if (i==TEST_CYCLE) {
191 i=TEST_CYCLE-1;
192 }
193 sendUrb = urb[i].urb;
194 FillUrb(sendUrb, TEST_LENGTH);
195 ret = ioctl(fd, USBDEVFS_SUBMITURB, sendUrb);
196 if (ret < 0) {
197 printf("SubmitBulkRequest: ret:%d errno=%d\n", ret, errno);
198 urb[i].inUse = 0;
199 continue;
200 }
201 g_send_count++;
202 }
203 return 0;
204 }
205
ReapProcess(void * argurb)206 static int ReapProcess(void *argurb)
207 {
208 int ret;
209 struct UsbAdapterUrb *urbrecv = NULL;
210 struct itimerval new_value, old_value;
211 if (signal(SIGUSR1, SignalHandler) == SIG_ERR) {
212 printf("signal SIGUSR1 failed");
213 return HDF_ERR_IO;
214 }
215 tid = syscall(SYS_gettid);
216
217 while (!g_speedFlag) {
218 ret = ioctl(fd, USBDEVFS_REAPURB, &urbrecv);
219 if (ret < 0) {
220 continue;
221 }
222 if (urbrecv == NULL) {
223 continue;
224 }
225 if (urbrecv->status == 0) {
226 if (g_byteTotal == 0) {
227 new_value.it_value.tv_sec = TEST_PRINT_TIME;
228 new_value.it_value.tv_usec = 0;
229 new_value.it_interval.tv_sec = TEST_PRINT_TIME;
230 new_value.it_interval.tv_usec = 0;
231 setitimer(ITIMER_REAL, &new_value, &old_value);
232 }
233 g_recv_count++;
234 g_byteTotal += urbrecv->actualLength;
235 }
236 unsigned char *recvBuf = (unsigned char*)urbrecv->buffer;
237
238 if (g_printData == true) {
239 for (int i = 0; i < urbrecv->actualLength; i++)
240 printf("%c", recvBuf[i]);
241 fflush(stdout);
242 } else if (g_recv_count % RECV_COUNT_SIZE == 0) {
243 printf("#");
244 fflush(stdout);
245 }
246
247 struct UsbAdapterUrbs *urbs = urbrecv->userContext;
248 urbs->inUse = 0;
249 OsalSemPost(&sem);
250 }
251 exitOk = true;
252 return 0;
253 }
254
BeginProcess(uint8_t endPoint)255 static int BeginProcess(uint8_t endPoint)
256 {
257 char *data = NULL;
258 struct timeval time;
259 int transNum = 0;
260 int i = 0;
261
262 if (fd < 0 || endPoint <= 0) {
263 printf("parameter error\n");
264 return -1;
265 }
266 for (i = 0; i < TEST_CYCLE; i++) {
267 urb[i].urb = calloc(1, sizeof(struct UsbAdapterUrb));
268 if (urb[i].urb == NULL) {
269 return -1;
270 }
271 urb[i].inUse = 0;
272 urb[i].urb->userContext = (void *)(&urb[i]);
273 urb[i].urb->type = USB_ADAPTER_URB_TYPE_BULK;
274 urb[i].urb->streamId = 0;
275 urb[i].urb->endPoint = endPoint;
276
277 data = OsalMemCalloc(TEST_LENGTH);
278 if (data == NULL) {
279 return -1;
280 }
281 memset_s(data, TEST_LENGTH, 'c', TEST_LENGTH);
282 data[TEST_LENGTH - 1] = '\0';
283 urb[i].urb->buffer = (void *)data;
284 urb[i].urb->bufferLength = TEST_LENGTH;
285 }
286
287 gettimeofday(&time, NULL);
288 if (signal(SIGINT, SignalHandler) == SIG_ERR) {
289 printf("signal SIGINT failed");
290 return HDF_ERR_IO;
291 }
292 signal(SIGALRM, SignalHandler);
293
294 printf("test NO SDK endpoint:%d\n", endPoint);
295 printf("Start: sec%ld usec%ld\n", time.tv_sec, time.tv_usec);
296
297 SubmitRequest(transNum);
298
299 while (!g_speedFlag) {
300 OsalMSleep(SLEEP_TIME);
301 }
302
303 kill(tid, SIGUSR1);
304 while (exitOk != true) {
305 OsalMSleep(SLEEP_TIME);
306 }
307 for (i = 0; i < TEST_CYCLE; i++) {
308 munmap(urb[i].urb->buffer, TEST_LENGTH);
309 free(urb[i].urb);
310 }
311 return HDF_SUCCESS;
312 }
313
ShowHelp(char * name)314 static void ShowHelp(char *name)
315 {
316 printf(">> usage:\n");
317 printf(">> %s [<busNum> <devAddr>] <ifaceNum> <endpoint> [<printdata>]\n", name);
318 printf("\n");
319 }
320
OptionParse(int argc,char * argv[])321 static bool OptionParse(int argc, char *argv[])
322 {
323 if (argc == 6) {
324 g_busNum = atoi(argv[1]);
325 g_devAddr = atoi(argv[2]);
326 ifaceNum = atoi(argv[3]);
327 endNum = atoi(argv[4]);
328 if ((endNum >> ENDPOINT_IN_OFFSET) != 0) {
329 g_printData = (strncmp(argv[5], "printdata", 1))?false:true;
330 }
331 } else if (argc == 5) {
332 g_busNum = atoi(argv[1]);
333 g_devAddr = atoi(argv[2]);
334 ifaceNum = atoi(argv[3]);
335 endNum = atoi(argv[4]);
336 } else if (argc == 3) {
337 ifaceNum = atoi(argv[1]);
338 endNum = atoi(argv[2]);
339 } else {
340 printf("Error: parameter error!\n\n");
341 ShowHelp(argv[0]);
342 return false;
343 }
344 return true;
345 }
346
OsalThreadOperate(void)347 static int OsalThreadOperate(void)
348 {
349 int ret;
350 struct OsalThread urbReapProcess;
351 struct OsalThread urbSendProcess;
352 struct OsalThreadParam threadCfg;
353
354 (void)memset_s(&threadCfg, sizeof(threadCfg), 0, sizeof(threadCfg));
355 threadCfg.name = "urb reap process";
356 threadCfg.priority = OSAL_THREAD_PRI_DEFAULT;
357 threadCfg.stackSize = URB_COMPLETE_PROCESS_STACK_SIZE;
358
359 ret = OsalThreadCreate(&urbReapProcess, (OsalThreadEntry)ReapProcess, NULL);
360 if (ret != HDF_SUCCESS) {
361 printf("OsalThreadCreate fail, ret=%d\n", ret);
362 return HDF_FAILURE;
363 }
364
365 ret = OsalThreadStart(&urbReapProcess, &threadCfg);
366 if (ret != HDF_SUCCESS) {
367 printf("OsalThreadStart fail, ret=%d\n", ret);
368 }
369
370 threadCfg.name = "urb send process";
371 threadCfg.priority = OSAL_THREAD_PRI_DEFAULT;
372 threadCfg.stackSize = URB_COMPLETE_PROCESS_STACK_SIZE;
373
374 ret = OsalThreadCreate(&urbSendProcess, (OsalThreadEntry)SendProcess, NULL);
375 if (ret != HDF_SUCCESS) {
376 printf("OsalThreadCreate fail, ret=%d\n", ret);
377 return HDF_FAILURE;
378 }
379
380 ret = OsalThreadStart(&urbSendProcess, &threadCfg);
381 if (ret != HDF_SUCCESS) {
382 printf("OsalThreadStart fail, ret=%d\n", ret);
383 }
384
385 ret = BeginProcess(endNum);
386 if (ret != HDF_SUCCESS) {
387 return HDF_FAILURE;
388 }
389 return HDF_SUCCESS;
390 }
391
main(int argc,char * argv[])392 int main(int argc, char *argv[])
393 {
394 int ret;
395 if (!OptionParse(argc, argv)) {
396 ret = -1;
397 goto ERR;
398 }
399 OsalSemInit(&sem, 0);
400
401 fd = OpenDevice();
402 if (fd < 0) {
403 ret = -1;
404 goto ERR;
405 }
406
407 ret = ClaimInterface(ifaceNum);
408 if (ret != HDF_SUCCESS) {
409 goto ERR;
410 }
411
412 ret = OsalThreadOperate();
413 if (ret != HDF_SUCCESS) {
414 goto ERR;
415 }
416 ERR:
417 if (ret != HDF_SUCCESS) {
418 printf("please check whether usb drv so is existing or not,like acm, ecm, if not, remove it and test again!\n");
419 }
420 CloseDevice();
421 return ret;
422 }
423
424