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