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 #define STRTOL_BASE 10
49
50 static pid_t g_tid;
51 static int32_t g_exitOk = false;
52 static int32_t g_speedFlag = 0;
53 static unsigned int g_busNum = 1;
54 static unsigned int g_devAddr = 2;
55 static int32_t g_fd;
56 static struct OsalSem sem;
57 static uint64_t g_send_count = 0;
58 static uint64_t g_recv_count = 0;
59 static uint64_t g_byteTotal = 0;
60 static struct UsbAdapterUrbs urb[TEST_CYCLE];
61 static struct UsbAdapterUrb *g_sendUrb = NULL;
62 static bool g_printData = false;
63 static unsigned int g_ifaceNum;
64 static unsigned char g_endNum;
65
CloseDevice(void)66 static void CloseDevice(void)
67 {
68 if (g_fd > 0) {
69 close(g_fd);
70 g_fd = 0;
71 }
72 return;
73 }
74
OpenDevice(void)75 static int32_t OpenDevice(void)
76 {
77 char path[PATH_MAX_LENGTH];
78 int32_t ret;
79
80 ret = sprintf_s(path, sizeof(char) * PATH_MAX_LENGTH, USB_DEV_FS_PATH "/%03u/%03u", g_busNum, g_devAddr);
81 if (ret < 0) {
82 HDF_LOGE("%{public}s: sprintf_s path failed", __func__);
83 return ret;
84 }
85
86 HDF_LOGI("%{public}s: open file action", __func__);
87 g_fd = open(path, O_RDWR);
88
89 if (g_fd < 0) {
90 HDF_LOGE("%{public}s: open device failed errno = %{public}d %{public}s", __func__, errno, strerror(errno));
91 }
92
93 return g_fd;
94 }
95
ClaimInterface(unsigned int iface)96 static int32_t ClaimInterface(unsigned int iface)
97 {
98 if (g_fd < 0 || iface == 0) {
99 HDF_LOGE("%{public}s: parameter error", __func__);
100 return -1;
101 }
102
103 int32_t ret = ioctl(g_fd, USBDEVFS_CLAIMINTERFACE, &iface);
104 if (ret < 0) {
105 HDF_LOGE("%{public}s: sprintf_s path failed claim failed: iface = %{public}u errno = %{public}d %{public}s",
106 __func__, iface, errno, strerror(errno));
107 return HDF_FAILURE;
108 }
109 HDF_LOGI("%{public}s: claim success: iface = %{public}u", __func__, iface);
110 return HDF_SUCCESS;
111 }
112
FillUrb(struct UsbAdapterUrb * urb,int32_t len)113 static void FillUrb(struct UsbAdapterUrb *urb, int32_t len)
114 {
115 if (urb == NULL) {
116 HDF_LOGE("%{public}s: urb is null", __func__);
117 return;
118 }
119 urb->userContext = (void *)(urb);
120 urb->type = USB_ADAPTER_URB_TYPE_BULK;
121 urb->streamId = 0;
122 urb->endPoint = g_endNum;
123 if ((g_endNum >> ENDPOINT_IN_OFFSET) == 0) {
124 int32_t ret = memset_s(urb->buffer, len, 'c', len);
125 if (ret != EOK) {
126 HDF_LOGE("%{public}s: memset_s failed: ret = %{public}d", __func__, ret);
127 }
128 }
129 }
130
SignalHandler(int32_t signo)131 static void SignalHandler(int32_t signo)
132 {
133 static uint32_t sigCnt = 0;
134 struct itimerval new_value, old_value;
135 switch (signo) {
136 case SIGALRM:
137 sigCnt++;
138 if (sigCnt * TEST_PRINT_TIME >= TEST_TIME) {
139 g_speedFlag = 1;
140 break;
141 }
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 HDF_LOGE("%{public}s: ret:%{public}d errno = %{public}d", __func__, 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 HDF_LOGE("%{public}s: signal SIGUSR1 failed", __func__);
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 HDF_LOGI("%{public}s: recvbuf %{public}c", __func__, recvBuf[i]);
221 }
222 fflush(stdout);
223 } else if (g_recv_count % 10000 == 0) {
224 HDF_LOGI("%{public}s: #", __func__);
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("%{public}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("%{public}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 HDF_LOGI("%{public}s: usage:", __func__);
315 HDF_LOGI("%{public}s: name is %{public}s [<busNum> <devAddr>] <g_ifaceNum> <endpoint> [<printdata>]",
316 __func__, name);
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)strtoul(argv[1], NULL, STRTOL_BASE);
324 g_devAddr = (unsigned int)strtoul(argv[2], NULL, STRTOL_BASE); // 2 means get second char of argv
325 g_ifaceNum = (unsigned int)strtoul(argv[3], NULL, STRTOL_BASE); // 3 means get third char of argv
326 g_endNum = (unsigned char)strtoul(argv[4], NULL, STRTOL_BASE); // 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)strtoul(argv[1], NULL, STRTOL_BASE);
332 g_devAddr = (unsigned int)strtoul(argv[2], NULL, STRTOL_BASE); // 2 means get second char of argv
333 g_ifaceNum = (unsigned int)strtoul(argv[3], NULL, STRTOL_BASE); // 3 means get third char of argv
334 g_endNum = (unsigned char)strtoul(argv[4], NULL, STRTOL_BASE); // 4 means get fourth char of argv
335 } else if (argc == 3) {
336 g_ifaceNum = (unsigned int)strtoul(argv[1], NULL, STRTOL_BASE);
337 g_endNum = (unsigned char)strtoul(argv[2], NULL, STRTOL_BASE); // 2 means get second char of argv
338 } else {
339 HDF_LOGE("%{public}s: parameter error!", __func__);
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 HDF_LOGE("%{public}s: OsalThreadCreate failed, ret=%{public}d", __func__, ret);
368 goto ERR;
369 }
370
371 ret = OsalThreadStart(&urbReapProcess, &threadCfg);
372 if (ret != HDF_SUCCESS) {
373 HDF_LOGE("%{public}s: OsalThreadStart failed, ret=%{public}d", __func__, 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 HDF_LOGE("%{public}s: OsalThreadCreate failed, ret=%{public}d", __func__, ret);
383 goto ERR;
384 }
385
386 ret = OsalThreadStart(&urbSendProcess, &threadCfg);
387 if (ret != HDF_SUCCESS) {
388 HDF_LOGE("%{public}s: OsalThreadStart failed, ret=%{public}d", __func__, 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 HDF_LOGE("%{public}s: please check whether usb drv so is existing or not,like acm, ecm, if not, \
399 remove it and test again! ret=%{public}d", __func__, ret);
400 }
401 CloseDevice();
402 return ret;
403 }
404