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