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 fdsan_close_with_tag(g_fd, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
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 fdsan_exchange_owner_tag(g_fd, 0, fdsan_create_owner_tag(FDSAN_OWNER_TYPE_FILE, LOG_DOMAIN));
93
94 return g_fd;
95 }
96
ClaimInterface(unsigned int iface)97 static int32_t ClaimInterface(unsigned int iface)
98 {
99 if (g_fd < 0 || iface == 0) {
100 HDF_LOGE("%{public}s: parameter error", __func__);
101 return -1;
102 }
103
104 int32_t ret = ioctl(g_fd, USBDEVFS_CLAIMINTERFACE, &iface);
105 if (ret < 0) {
106 HDF_LOGE("%{public}s: sprintf_s path failed claim failed: iface = %{public}u errno = %{public}d %{public}s",
107 __func__, iface, errno, strerror(errno));
108 return HDF_FAILURE;
109 }
110 HDF_LOGI("%{public}s: claim success: iface = %{public}u", __func__, 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 if (urb == NULL) {
117 HDF_LOGE("%{public}s: urb is null", __func__);
118 return;
119 }
120 urb->userContext = (void *)(urb);
121 urb->type = USB_ADAPTER_URB_TYPE_BULK;
122 urb->streamId = 0;
123 urb->endPoint = g_endNum;
124 if ((g_endNum >> ENDPOINT_IN_OFFSET) == 0) {
125 int32_t ret = memset_s(urb->buffer, len, 'c', len);
126 if (ret != EOK) {
127 HDF_LOGE("%{public}s: memset_s failed: ret = %{public}d", __func__, ret);
128 }
129 }
130 }
131
SignalHandler(int32_t signo)132 static void SignalHandler(int32_t signo)
133 {
134 static uint32_t sigCnt = 0;
135 struct itimerval new_value, old_value;
136 switch (signo) {
137 case SIGALRM:
138 sigCnt++;
139 if (sigCnt * TEST_PRINT_TIME >= TEST_TIME) {
140 g_speedFlag = 1;
141 break;
142 }
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
SendProcess(void * argurb)157 static int32_t SendProcess(void *argurb)
158 {
159 (void)argurb;
160 int32_t i;
161 while (!g_speedFlag) {
162 OsalSemWait(&sem, HDF_WAIT_FOREVER);
163 for (i = 0; i < TEST_CYCLE; i++) {
164 if (urb[i].inUse == 0) {
165 urb[i].inUse = 1;
166 urb[i].urb->userContext = (void *)(&urb[i]);
167 break;
168 }
169 }
170
171 if (i == TEST_CYCLE) {
172 i = TEST_CYCLE - 1;
173 }
174 g_sendUrb = urb[i].urb;
175 FillUrb(g_sendUrb, TEST_LENGTH);
176 int32_t ret = ioctl(g_fd, USBDEVFS_SUBMITURB, g_sendUrb);
177 if (ret < 0) {
178 HDF_LOGE("%{public}s: ret:%{public}d errno = %{public}d", __func__, ret, errno);
179 urb[i].inUse = 0;
180 continue;
181 }
182 g_send_count++;
183 }
184 return 0;
185 }
186
ReapProcess(void * const argurb)187 static int32_t ReapProcess(void * const argurb)
188 {
189 (void)argurb;
190 struct UsbAdapterUrb *urbrecv = NULL;
191 struct itimerval new_value, old_value;
192 if (signal(SIGUSR1, SignalHandler) == SIG_ERR) {
193 HDF_LOGE("%{public}s: signal SIGUSR1 failed", __func__);
194 return HDF_ERR_IO;
195 }
196 g_tid = (pid_t)syscall(SYS_gettid);
197
198 while (!g_speedFlag) {
199 int32_t r = ioctl(g_fd, USBDEVFS_REAPURB, &urbrecv);
200 if (r < 0) {
201 continue;
202 }
203 if (urbrecv == NULL) {
204 continue;
205 }
206 if (urbrecv->status == 0) {
207 if (g_byteTotal == 0) {
208 new_value.it_value.tv_sec = TEST_PRINT_TIME;
209 new_value.it_value.tv_usec = 0;
210 new_value.it_interval.tv_sec = TEST_PRINT_TIME;
211 new_value.it_interval.tv_usec = 0;
212 setitimer(ITIMER_REAL, &new_value, &old_value);
213 }
214 g_recv_count++;
215 g_byteTotal += urbrecv->actualLength;
216 }
217 unsigned char *recvBuf = (unsigned char *)urbrecv->buffer;
218
219 if (g_printData) {
220 for (int32_t i = 0; i < urbrecv->actualLength; i++) {
221 HDF_LOGI("%{public}s: recvbuf %{public}c", __func__, recvBuf[i]);
222 }
223 fflush(stdout);
224 } else if (g_recv_count % 10000 == 0) {
225 HDF_LOGI("%{public}s: #", __func__);
226 fflush(stdout);
227 }
228
229 struct UsbAdapterUrbs *urbs = urbrecv->userContext;
230 urbs->inUse = 0;
231 OsalSemPost(&sem);
232 }
233 g_exitOk = true;
234 return 0;
235 }
236
FillUrbData(unsigned char endPoint)237 static int32_t FillUrbData(unsigned char endPoint)
238 {
239 int32_t i;
240 char *data = NULL;
241 for (i = 0; i < TEST_CYCLE; i++) {
242 urb[i].urb = calloc(1, sizeof(struct UsbAdapterUrb));
243 if (urb[i].urb == NULL) {
244 return -1;
245 }
246 urb[i].inUse = 0;
247 urb[i].urb->userContext = (void *)(&urb[i]);
248 urb[i].urb->type = USB_ADAPTER_URB_TYPE_BULK;
249 urb[i].urb->streamId = 0;
250 urb[i].urb->endPoint = endPoint;
251
252 data = OsalMemCalloc(TEST_LENGTH); // AllocMemTest(TEST_LENGTH)
253 if (data == NULL) {
254 return -1;
255 }
256 (void)memset_s(data, TEST_LENGTH, 'c', TEST_LENGTH);
257 data[TEST_LENGTH - 1] = '\0';
258 urb[i].urb->buffer = (void *)data;
259 urb[i].urb->bufferLength = TEST_LENGTH;
260 }
261 return HDF_SUCCESS;
262 }
263
BeginProcess(unsigned char endPoint)264 static int32_t BeginProcess(unsigned char endPoint)
265 {
266 int32_t ret;
267 struct timeval time;
268 int32_t transNum = 0;
269 int32_t i;
270
271 if ((g_fd < 0) || (endPoint == 0)) {
272 HDF_LOGE("%{public}s: g_fd or endPoint is invalied", __func__);
273 return -1;
274 }
275
276 ret = FillUrbData(endPoint);
277 if (ret != HDF_SUCCESS) {
278 HDF_LOGE("%{public}s: Fill urb data failed", __func__);
279 return ret;
280 }
281 gettimeofday(&time, NULL);
282 (void)signal(SIGINT, SignalHandler);
283 (void)signal(SIGALRM, SignalHandler);
284
285 for (i = 0; i < TEST_CYCLE; i++) {
286 urb[i].inUse = 1;
287 urb[i].urbNum = transNum;
288 urb[i].urb->userContext = (void *)(&urb[i]);
289 g_sendUrb = urb[i].urb;
290 ret = ioctl(g_fd, USBDEVFS_SUBMITURB, g_sendUrb);
291 if (ret < 0) {
292 urb[i].inUse = 0;
293 continue;
294 }
295 g_send_count++;
296 }
297
298 while (!g_speedFlag) {
299 OsalMSleep(10);
300 }
301
302 kill(g_tid, SIGUSR1);
303 while (!g_exitOk) {
304 OsalMSleep(10);
305 }
306 for (i = 0; i < TEST_CYCLE; i++) {
307 munmap(urb[i].urb->buffer, TEST_LENGTH);
308 free(urb[i].urb);
309 }
310 return HDF_SUCCESS;
311 }
312
ShowHelp(char * name)313 static void ShowHelp(char *name)
314 {
315 HDF_LOGI("%{public}s: usage:", __func__);
316 HDF_LOGI("%{public}s: name is %{public}s [<busNum> <devAddr>] <g_ifaceNum> <endpoint> [<printdata>]",
317 __func__, name);
318 }
319
FillParamData(int32_t argc,char * argv[])320 static void FillParamData(int32_t argc, char *argv[])
321 {
322 if (argc == TEST_SIX_TYPE) {
323 g_busNum = (unsigned int)strtoul(argv[TEST_ONE_TYPE], NULL, STRTOL_BASE);
324 g_devAddr = (unsigned int)strtoul(argv[TEST_TWO_TYPE], NULL, STRTOL_BASE); // 2 means get second char of argv
325 g_ifaceNum = (unsigned int)strtoul(argv[TEST_THREE_TYPE], NULL, STRTOL_BASE); // 3 means get third char of argv
326 g_endNum = (unsigned char)strtoul(argv[TEST_FOUR_TYPE], NULL, STRTOL_BASE); // 4 means get fourth char of argv
327 if ((g_endNum >> ENDPOINT_IN_OFFSET) != 0) { // the offset value is 7
328 g_printData = (strncmp(argv[TEST_FIVE_TYPE], "printdata", TEST_ONE_TYPE)) ? false : true;
329 }
330 } else if (argc == TEST_FIVE_TYPE) {
331 g_busNum = (unsigned int)strtoul(argv[TEST_ONE_TYPE], NULL, STRTOL_BASE);
332 g_devAddr = (unsigned int)strtoul(argv[TEST_TWO_TYPE], NULL, STRTOL_BASE); // 2 means get second char of argv
333 g_ifaceNum = (unsigned int)strtoul(argv[TEST_THREE_TYPE], NULL, STRTOL_BASE); // 3 means get third char of argv
334 g_endNum = (unsigned char)strtoul(argv[TEST_FOUR_TYPE], NULL, STRTOL_BASE); // 4 means get fourth char of argv
335 } else if (argc == TEST_THREE_TYPE) {
336 g_ifaceNum = (unsigned int)strtoul(argv[TEST_ONE_TYPE], NULL, STRTOL_BASE);
337 g_endNum = (unsigned char)strtoul(argv[TEST_TWO_TYPE], NULL, STRTOL_BASE); // 2 means get second char of argv
338 } else {
339 HDF_LOGE("%{public}s: parameter error!", __func__);
340 ShowHelp(argv[TEST_ZERO_TYPE]);
341 return HDF_FAILURE;
342 }
343 }
344
PrintErrorLog(int32_t ret)345 static void PrintErrorLog(int32_t ret)
346 {
347 if (ret != HDF_SUCCESS) {
348 HDF_LOGE("%{public}s: please check whether usb drv so is existing or not,like acm, ecm, if not, \
349 remove it and test again! ret=%{public}d", __func__, ret);
350 }
351 }
352
main(int32_t argc,char * argv[])353 int32_t main(int32_t argc, char *argv[])
354 {
355 int32_t ret;
356 FillParamData(argc, argv[]);
357 OsalSemInit(&sem, 0);
358 g_fd = OpenDevice();
359 if (g_fd < 0) {
360 ret = -1;
361 PrintErrorLog(ret);
362 }
363
364 ret = ClaimInterface(g_ifaceNum);
365 if (ret != HDF_SUCCESS) {
366 PrintErrorLog(ret);
367 }
368
369 struct OsalThread urbReapProcess;
370 struct OsalThread urbSendProcess;
371 struct OsalThreadParam threadCfg;
372
373 (void)memset_s(&threadCfg, sizeof(threadCfg), 0, sizeof(threadCfg));
374 threadCfg.name = "urb reap process";
375 threadCfg.priority = OSAL_THREAD_PRI_DEFAULT;
376 threadCfg.stackSize = URB_COMPLETE_PROCESS_STACK_SIZE;
377
378 ret = OsalThreadCreate(&urbReapProcess, (OsalThreadEntry)ReapProcess, NULL);
379 if (ret != HDF_SUCCESS) {
380 HDF_LOGE("%{public}s: OsalThreadCreate failed, ret=%{public}d", __func__, ret);
381 PrintErrorLog(ret);
382 }
383
384 ret = OsalThreadStart(&urbReapProcess, &threadCfg);
385 if (ret != HDF_SUCCESS) {
386 HDF_LOGE("%{public}s: OsalThreadStart failed, ret=%{public}d", __func__, ret);
387 }
388
389 threadCfg.name = "urb send process";
390 threadCfg.priority = OSAL_THREAD_PRI_DEFAULT;
391 threadCfg.stackSize = URB_COMPLETE_PROCESS_STACK_SIZE;
392
393 ret = OsalThreadCreate(&urbSendProcess, (OsalThreadEntry)SendProcess, NULL);
394 if (ret != HDF_SUCCESS) {
395 HDF_LOGE("%{public}s: OsalThreadCreate failed, ret=%{public}d", __func__, ret);
396 PrintErrorLog(ret);
397 }
398
399 ret = OsalThreadStart(&urbSendProcess, &threadCfg);
400 if (ret != HDF_SUCCESS) {
401 HDF_LOGE("%{public}s: OsalThreadStart failed, ret=%{public}d", __func__, ret);
402 }
403
404 ret = BeginProcess(g_endNum);
405 if (ret != HDF_SUCCESS) {
406 PrintErrorLog(ret);
407 }
408 CloseDevice();
409 return ret;
410 }
411