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 34static int32_t g_running = 1; 35static struct termios g_orgOpts, g_newOpts; 36static struct HdfSBuf *g_data; 37static struct HdfSBuf *g_reply; 38static struct HdfRemoteService *g_acmService; 39static struct OsalThread g_thread; 40 41static 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 57static 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 86static 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 96static 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 119static 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 128static 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 139static 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 152int32_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