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