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 "cdcacm.h"
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20
21 #include <signal.h>
22 #include <sys/time.h>
23 #include <termios.h>
24
25 #include "hdf_log.h"
26 #include "hdf_remote_service.h"
27 #include "hdf_sbuf.h"
28 #include "osal_time.h"
29 #include "servmgr_hdi.h"
30 #include "usb_dev_test.h"
31
32 #define HDF_LOG_TAG cdc_acm_test
33
34 static int32_t g_running = 1;
35 static struct termios g_orgOpts, g_newOpts;
36 static struct HdfSBuf *g_data;
37 static struct HdfSBuf *g_reply;
38 static struct HdfRemoteService *g_acmService;
39 static struct OsalThread g_thread;
40
TestWrite(char * buf)41 static void TestWrite(char *buf)
42 {
43 HdfSbufFlush(g_data);
44
45 if (HdfRemoteServiceWriteInterfaceToken(g_acmService, g_data) == false) {
46 HDF_LOGE("%{public}s:%{public}d write interface token fail", __func__, __LINE__);
47 return;
48 }
49
50 (void)HdfSbufWriteString(g_data, buf);
51 int32_t status = g_acmService->dispatcher->Dispatch(g_acmService, USB_SERIAL_WRITE, g_data, g_reply);
52 if (status != HDF_SUCCESS) {
53 HDF_LOGE("%{public}s: Dispatch USB_SERIAL_WRITE failed status = %{public}d", __func__, status);
54 }
55 }
56
TestRead(void)57 static void TestRead(void)
58 {
59 HdfSbufFlush(g_reply);
60
61 if (HdfRemoteServiceWriteInterfaceToken(g_acmService, g_data) == false) {
62 HDF_LOGE("%{public}s:%{public}d write interface token fail", __func__, __LINE__);
63 return;
64 }
65
66 int32_t status = g_acmService->dispatcher->Dispatch(g_acmService, USB_SERIAL_READ, g_data, g_reply);
67 if (status != HDF_SUCCESS) {
68 printf("%s: Dispatch USB_SERIAL_READ failed status = %d", __func__, status);
69 return;
70 }
71 const char *tmp = HdfSbufReadString(g_reply);
72 if (tmp && strlen(tmp) > 0) {
73 size_t len = strlen(tmp);
74 for (size_t i = 0; i < len; i++) {
75 if (tmp[i] == 0x0A || tmp[i] == 0x0D) {
76 printf("\r\n");
77 } else {
78 putchar(tmp[i]);
79 }
80 }
81 fflush(stdout);
82 }
83 }
84
85 #define SLEEP_100MS 100000
ReadThread(void * arg)86 static int32_t ReadThread(void *arg)
87 {
88 (void)arg;
89 while (g_running != 0) {
90 TestRead();
91 usleep(SLEEP_100MS);
92 }
93 return 0;
94 }
95 #define HDF_PROCESS_STACK_SIZE 100000
StartThreadRead(void)96 static int32_t StartThreadRead(void)
97 {
98 int32_t ret;
99 struct OsalThreadParam threadCfg;
100 memset_s(&threadCfg, sizeof(threadCfg), 0, sizeof(threadCfg));
101 threadCfg.name = "Read process";
102 threadCfg.priority = OSAL_THREAD_PRI_DEFAULT;
103 threadCfg.stackSize = HDF_PROCESS_STACK_SIZE;
104
105 ret = OsalThreadCreate(&g_thread, (OsalThreadEntry)ReadThread, NULL);
106 if (HDF_SUCCESS != ret) {
107 HDF_LOGE("%{public}s:%{public}d OsalThreadCreate failed, ret=%{public}d ", __func__, __LINE__, ret);
108 return HDF_ERR_DEVICE_BUSY;
109 }
110
111 ret = OsalThreadStart(&g_thread, &threadCfg);
112 if (HDF_SUCCESS != ret) {
113 HDF_LOGE("%{public}s:%{public}d OsalThreadStart failed, ret=%{public}d ", __func__, __LINE__, ret);
114 return HDF_ERR_DEVICE_BUSY;
115 }
116 return 0;
117 }
118
SetTermios(void)119 static void SetTermios(void)
120 {
121 tcgetattr(STDIN_FILENO, &g_orgOpts);
122 tcgetattr(STDIN_FILENO, &g_newOpts);
123 g_newOpts.c_lflag &= ~(ICANON | ECHOE | ECHOK | ECHONL);
124 tcsetattr(STDIN_FILENO, TCSANOW, &g_newOpts);
125 }
126
127 #define STR_LEN 256
WriteThread(void)128 static void WriteThread(void)
129 {
130 char str[STR_LEN] = {0};
131 while (g_running != 0) {
132 str[0] = (char)getchar();
133 if (g_running != 0) {
134 TestWrite(str);
135 }
136 }
137 }
138
StopAcmTest(int32_t signo)139 static void StopAcmTest(int32_t signo)
140 {
141 (void)signo;
142 int32_t status;
143 g_running = 0;
144 status = g_acmService->dispatcher->Dispatch(g_acmService, USB_SERIAL_CLOSE, g_data, g_reply);
145 if (status != HDF_SUCCESS) {
146 HDF_LOGE("%{public}s: Dispatch USB_SERIAL_CLOSE err", __func__);
147 }
148 tcsetattr(STDIN_FILENO, TCSANOW, &g_orgOpts);
149 printf("AcmTest exit.\n");
150 }
151
AcmTest(int32_t argc,const char * argv[])152 int32_t AcmTest(int32_t argc, const char *argv[])
153 {
154 (void)argc;
155 (void)argv;
156 int32_t status;
157 struct HDIServiceManager *servmgr = HDIServiceManagerGet();
158 if (servmgr == NULL) {
159 HDF_LOGE("%{public}s: HDIServiceManagerGet err", __func__);
160 return HDF_FAILURE;
161 }
162 g_acmService = servmgr->GetService(servmgr, "usbfn_cdcacm");
163 HDIServiceManagerRelease(servmgr);
164 if (g_acmService == NULL) {
165 HDF_LOGE("%{public}s: GetService err", __func__);
166 return HDF_FAILURE;
167 }
168
169 if (HdfRemoteServiceSetInterfaceDesc(g_acmService, "hdf.usb.usbfn") == false) {
170 HDF_LOGE("%{public}s:%{public}d set desc fail", __func__, __LINE__);
171 return HDF_FAILURE;
172 }
173
174 g_data = HdfSbufTypedObtain(SBUF_IPC);
175 g_reply = HdfSbufTypedObtain(SBUF_IPC);
176 if (g_data == NULL || g_reply == NULL) {
177 HDF_LOGE("%{public}s: GetService err", __func__);
178 return HDF_FAILURE;
179 }
180
181 if (HdfRemoteServiceWriteInterfaceToken(g_acmService, g_data) == false) {
182 HDF_LOGE("%{public}s:%{public}d write interface token fail", __func__, __LINE__);
183 return HDF_FAILURE;
184 }
185
186 status = g_acmService->dispatcher->Dispatch(g_acmService, USB_SERIAL_OPEN, g_data, g_reply);
187 if (status != HDF_SUCCESS) {
188 HDF_LOGE("%{public}s: Dispatch USB_SERIAL_OPEN err", __func__);
189 return HDF_FAILURE;
190 }
191 printf("Press any key to send.\n");
192 printf("Press CTRL-C to exit.\n");
193
194 (void)signal(SIGINT, StopAcmTest);
195 StartThreadRead();
196 SetTermios();
197 WriteThread();
198 return 0;
199 }
200