1094332d3Sopenharmony_ci/* 2094332d3Sopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd. 3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License. 5094332d3Sopenharmony_ci * You may obtain a copy of the License at 6094332d3Sopenharmony_ci * 7094332d3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8094332d3Sopenharmony_ci * 9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and 13094332d3Sopenharmony_ci * limitations under the License. 14094332d3Sopenharmony_ci */ 15094332d3Sopenharmony_ci 16094332d3Sopenharmony_ci#include "../include/cdcacm.h" 17094332d3Sopenharmony_ci#include <unistd.h> 18094332d3Sopenharmony_ci#include "device_resource_if.h" 19094332d3Sopenharmony_ci#include "hdf_base.h" 20094332d3Sopenharmony_ci#include "hdf_device_object.h" 21094332d3Sopenharmony_ci#include "hdf_log.h" 22094332d3Sopenharmony_ci#include "osal_mem.h" 23094332d3Sopenharmony_ci#include "osal_time.h" 24094332d3Sopenharmony_ci#include "securec.h" 25094332d3Sopenharmony_ci#include "usbfn_device.h" 26094332d3Sopenharmony_ci#include "usbfn_interface.h" 27094332d3Sopenharmony_ci#include "usbfn_request.h" 28094332d3Sopenharmony_ci 29094332d3Sopenharmony_ci#define HDF_LOG_TAG hdf_cdc_acm 30094332d3Sopenharmony_ci#define UDC_NAME "invalid_udc_name" 31094332d3Sopenharmony_ci 32094332d3Sopenharmony_ci#define PENDING_FLAG 0 33094332d3Sopenharmony_ci#define CTRL_REQUEST_NUM 2 34094332d3Sopenharmony_ci#define QUEUE_SIZE 8 35094332d3Sopenharmony_ci#define WRITE_BUF_SIZE 8192 36094332d3Sopenharmony_ci#define READ_BUF_SIZE 8192 37094332d3Sopenharmony_ci 38094332d3Sopenharmony_ci#define PORT_RATE 9600 39094332d3Sopenharmony_ci#define DATA_BIT 8 40094332d3Sopenharmony_ci#define USBCDC_LEN 2 41094332d3Sopenharmony_ci#define RECEIVE_ALL_EVENTS 0xff 42094332d3Sopenharmony_cistatic const int32_t WAIT_UDC_MAX_LOOP = 3; 43094332d3Sopenharmony_cistatic const uint32_t WAIT_UDC_TIME = 100000; 44094332d3Sopenharmony_cistatic int32_t g_inFifo = 0; 45094332d3Sopenharmony_ci/* Usb Serial Related Functions */ 46094332d3Sopenharmony_ci 47094332d3Sopenharmony_cistatic int32_t UsbSerialInit(struct UsbAcmDevice *acm); 48094332d3Sopenharmony_cistatic int32_t UsbSerialRelease(struct UsbAcmDevice *acm); 49094332d3Sopenharmony_cistatic int32_t UsbSerialStartTx(struct UsbSerial *port) 50094332d3Sopenharmony_ci{ 51094332d3Sopenharmony_ci if (port == NULL) { 52094332d3Sopenharmony_ci return HDF_FAILURE; 53094332d3Sopenharmony_ci } 54094332d3Sopenharmony_ci struct DListHead *pool = &port->writePool; 55094332d3Sopenharmony_ci int32_t ret = HDF_FAILURE; 56094332d3Sopenharmony_ci if (port->acm == NULL) { 57094332d3Sopenharmony_ci return HDF_SUCCESS; 58094332d3Sopenharmony_ci } 59094332d3Sopenharmony_ci while (!port->writeBusy && !DListIsEmpty(pool)) { 60094332d3Sopenharmony_ci struct UsbFnRequest *req = NULL; 61094332d3Sopenharmony_ci uint32_t len; 62094332d3Sopenharmony_ci if (port->writeStarted >= QUEUE_SIZE) { 63094332d3Sopenharmony_ci break; 64094332d3Sopenharmony_ci } 65094332d3Sopenharmony_ci req = DLIST_FIRST_ENTRY(pool, struct UsbFnRequest, list); 66094332d3Sopenharmony_ci if (req == NULL) { 67094332d3Sopenharmony_ci break; 68094332d3Sopenharmony_ci } 69094332d3Sopenharmony_ci len = DataFifoRead(&port->writeFifo, req->buf, port->acm->dataInPipe.maxPacketSize); 70094332d3Sopenharmony_ci if (len == 0) { 71094332d3Sopenharmony_ci break; 72094332d3Sopenharmony_ci } 73094332d3Sopenharmony_ci req->length = len; 74094332d3Sopenharmony_ci DListRemove(&req->list); 75094332d3Sopenharmony_ci port->writeBusy = true; 76094332d3Sopenharmony_ci ret = UsbFnSubmitRequestAsync(req); 77094332d3Sopenharmony_ci port->writeBusy = false; 78094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 79094332d3Sopenharmony_ci HDF_LOGE("%{public}s: send request error %{public}d", __func__, ret); 80094332d3Sopenharmony_ci DListInsertTail(&req->list, pool); 81094332d3Sopenharmony_ci break; 82094332d3Sopenharmony_ci } 83094332d3Sopenharmony_ci port->writeStarted++; 84094332d3Sopenharmony_ci /* if acm is disconnect, abort immediately */ 85094332d3Sopenharmony_ci if (port->acm == NULL) { 86094332d3Sopenharmony_ci break; 87094332d3Sopenharmony_ci } 88094332d3Sopenharmony_ci } 89094332d3Sopenharmony_ci return ret; 90094332d3Sopenharmony_ci} 91094332d3Sopenharmony_ci 92094332d3Sopenharmony_cistatic uint32_t UsbSerialStartRx(struct UsbSerial *port) 93094332d3Sopenharmony_ci{ 94094332d3Sopenharmony_ci struct DListHead *pool = &port->readPool; 95094332d3Sopenharmony_ci struct UsbAcmPipe *out = &port->acm->dataOutPipe; 96094332d3Sopenharmony_ci while (!DListIsEmpty(pool)) { 97094332d3Sopenharmony_ci struct UsbFnRequest *req = NULL; 98094332d3Sopenharmony_ci int32_t ret; 99094332d3Sopenharmony_ci 100094332d3Sopenharmony_ci if (port->readStarted >= QUEUE_SIZE) { 101094332d3Sopenharmony_ci break; 102094332d3Sopenharmony_ci } 103094332d3Sopenharmony_ci 104094332d3Sopenharmony_ci req = DLIST_FIRST_ENTRY(pool, struct UsbFnRequest, list); 105094332d3Sopenharmony_ci DListRemove(&req->list); 106094332d3Sopenharmony_ci req->length = out->maxPacketSize; 107094332d3Sopenharmony_ci ret = UsbFnSubmitRequestAsync(req); 108094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 109094332d3Sopenharmony_ci HDF_LOGE("%{public}s: send request error %{public}d", __func__, ret); 110094332d3Sopenharmony_ci DListInsertTail(&req->list, pool); 111094332d3Sopenharmony_ci break; 112094332d3Sopenharmony_ci } 113094332d3Sopenharmony_ci port->readStarted++; 114094332d3Sopenharmony_ci /* if acm is disconnect, abort immediately */ 115094332d3Sopenharmony_ci if (port->acm == NULL) { 116094332d3Sopenharmony_ci break; 117094332d3Sopenharmony_ci } 118094332d3Sopenharmony_ci } 119094332d3Sopenharmony_ci return port->readStarted; 120094332d3Sopenharmony_ci} 121094332d3Sopenharmony_ci 122094332d3Sopenharmony_cistatic void UsbSerialRxPush(struct UsbSerial *port) 123094332d3Sopenharmony_ci{ 124094332d3Sopenharmony_ci struct DListHead *queue = &port->readQueue; 125094332d3Sopenharmony_ci bool disconnect = false; 126094332d3Sopenharmony_ci while (!DListIsEmpty(queue)) { 127094332d3Sopenharmony_ci struct UsbFnRequest *req; 128094332d3Sopenharmony_ci 129094332d3Sopenharmony_ci req = DLIST_FIRST_ENTRY(queue, struct UsbFnRequest, list); 130094332d3Sopenharmony_ci switch (req->status) { 131094332d3Sopenharmony_ci case USB_REQUEST_NO_DEVICE: 132094332d3Sopenharmony_ci disconnect = true; 133094332d3Sopenharmony_ci HDF_LOGV("%{public}s: the device is disconnected", __func__); 134094332d3Sopenharmony_ci break; 135094332d3Sopenharmony_ci case USB_REQUEST_COMPLETED: 136094332d3Sopenharmony_ci break; 137094332d3Sopenharmony_ci default: 138094332d3Sopenharmony_ci HDF_LOGV("%{public}s: unexpected status %{public}d", __func__, req->status); 139094332d3Sopenharmony_ci break; 140094332d3Sopenharmony_ci } 141094332d3Sopenharmony_ci 142094332d3Sopenharmony_ci if (g_inFifo && req->actual) { 143094332d3Sopenharmony_ci uint32_t size = req->actual; 144094332d3Sopenharmony_ci uint8_t *data = req->buf; 145094332d3Sopenharmony_ci 146094332d3Sopenharmony_ci if (DataFifoIsFull(&port->readFifo)) { 147094332d3Sopenharmony_ci DataFifoSkip(&port->readFifo, size); 148094332d3Sopenharmony_ci } 149094332d3Sopenharmony_ci uint32_t count = DataFifoWrite(&port->readFifo, data, size); 150094332d3Sopenharmony_ci if (count != size) { 151094332d3Sopenharmony_ci HDF_LOGW("%{public}s: write %{public}u less than expected %{public}u", __func__, count, size); 152094332d3Sopenharmony_ci } 153094332d3Sopenharmony_ci } 154094332d3Sopenharmony_ci 155094332d3Sopenharmony_ci DListRemove(&req->list); 156094332d3Sopenharmony_ci DListInsertTail(&req->list, &port->readPool); 157094332d3Sopenharmony_ci port->readStarted--; 158094332d3Sopenharmony_ci } 159094332d3Sopenharmony_ci 160094332d3Sopenharmony_ci if (!disconnect && port->acm) { 161094332d3Sopenharmony_ci UsbSerialStartRx(port); 162094332d3Sopenharmony_ci } 163094332d3Sopenharmony_ci} 164094332d3Sopenharmony_ci 165094332d3Sopenharmony_cistatic void UsbSerialFreeRequests(struct DListHead * const head, int32_t *allocated) 166094332d3Sopenharmony_ci{ 167094332d3Sopenharmony_ci struct UsbFnRequest *req = NULL; 168094332d3Sopenharmony_ci while (!DListIsEmpty(head)) { 169094332d3Sopenharmony_ci req = DLIST_FIRST_ENTRY(head, struct UsbFnRequest, list); 170094332d3Sopenharmony_ci DListRemove(&req->list); 171094332d3Sopenharmony_ci (void)UsbFnCancelRequest(req); 172094332d3Sopenharmony_ci (void)UsbFnFreeRequest(req); 173094332d3Sopenharmony_ci if (allocated) { 174094332d3Sopenharmony_ci (*allocated)--; 175094332d3Sopenharmony_ci } 176094332d3Sopenharmony_ci } 177094332d3Sopenharmony_ci} 178094332d3Sopenharmony_ci 179094332d3Sopenharmony_cistatic bool g_isStartRead = false; 180094332d3Sopenharmony_cistatic bool g_isReadDone = false; 181094332d3Sopenharmony_cistatic uint64_t g_readCnt = 0; 182094332d3Sopenharmony_cistruct timeval g_readTimeStart, g_readTimeEnd; 183094332d3Sopenharmony_cistatic float g_readSpeed = 0; 184094332d3Sopenharmony_cistatic bool g_isGetReadTimeStart = false; 185094332d3Sopenharmony_cistatic void UsbSerialReadComplete(uint8_t pipe, struct UsbFnRequest *req) 186094332d3Sopenharmony_ci{ 187094332d3Sopenharmony_ci struct UsbSerial *port = (struct UsbSerial *)req->context; 188094332d3Sopenharmony_ci if ((!g_isReadDone) && g_isStartRead && req->status == USB_REQUEST_COMPLETED) { 189094332d3Sopenharmony_ci g_readCnt += req->actual; 190094332d3Sopenharmony_ci if (!g_isGetReadTimeStart) { 191094332d3Sopenharmony_ci g_isGetReadTimeStart = true; 192094332d3Sopenharmony_ci gettimeofday(&g_readTimeStart, NULL); 193094332d3Sopenharmony_ci } 194094332d3Sopenharmony_ci } 195094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 196094332d3Sopenharmony_ci DListInsertTail(&req->list, &port->readQueue); 197094332d3Sopenharmony_ci UsbSerialRxPush(port); 198094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 199094332d3Sopenharmony_ci} 200094332d3Sopenharmony_ci 201094332d3Sopenharmony_cistatic int32_t SpeedReadThread(void *arg) 202094332d3Sopenharmony_ci{ 203094332d3Sopenharmony_ci (void)arg; 204094332d3Sopenharmony_ci g_readCnt = 0; 205094332d3Sopenharmony_ci g_isReadDone = false; 206094332d3Sopenharmony_ci g_readSpeed = 0; 207094332d3Sopenharmony_ci g_isGetReadTimeStart = false; 208094332d3Sopenharmony_ci double timeUse; 209094332d3Sopenharmony_ci double usec = 1000000; 210094332d3Sopenharmony_ci double k = 1024; 211094332d3Sopenharmony_ci struct timeval timeTmp; 212094332d3Sopenharmony_ci while (!g_isReadDone) { 213094332d3Sopenharmony_ci if (g_readCnt == 0) { 214094332d3Sopenharmony_ci OsalSleep(1); 215094332d3Sopenharmony_ci continue; 216094332d3Sopenharmony_ci } else { 217094332d3Sopenharmony_ci OsalSleep(1); 218094332d3Sopenharmony_ci } 219094332d3Sopenharmony_ci gettimeofday(&timeTmp, NULL); 220094332d3Sopenharmony_ci timeUse = (double)(timeTmp.tv_sec - g_readTimeStart.tv_sec) + (double)timeTmp.tv_usec / usec - 221094332d3Sopenharmony_ci (double)g_readTimeStart.tv_usec / usec; 222094332d3Sopenharmony_ci g_readSpeed = (float)((double)g_readCnt / k / k / timeUse); 223094332d3Sopenharmony_ci } 224094332d3Sopenharmony_ci timeUse = (double)(g_readTimeEnd.tv_sec - g_readTimeStart.tv_sec) + (double)g_readTimeEnd.tv_usec / usec - 225094332d3Sopenharmony_ci (double)g_readTimeStart.tv_usec / usec; 226094332d3Sopenharmony_ci HDF_LOGD("timeUse = %{public}lf", timeUse); 227094332d3Sopenharmony_ci g_readSpeed = (float)((double)g_readCnt / k / k / timeUse); 228094332d3Sopenharmony_ci HDF_LOGD("%{public}s: g_speed = %{public}f MB/s", __func__, g_readSpeed); 229094332d3Sopenharmony_ci return HDF_SUCCESS; 230094332d3Sopenharmony_ci} 231094332d3Sopenharmony_ci 232094332d3Sopenharmony_ci#define HDF_PROCESS_STACK_SIZE 100000 233094332d3Sopenharmony_cistruct OsalThread g_threadRead; 234094332d3Sopenharmony_cistatic int32_t StartThreadReadSpeed(struct UsbSerial *port) 235094332d3Sopenharmony_ci{ 236094332d3Sopenharmony_ci int32_t ret; 237094332d3Sopenharmony_ci struct OsalThreadParam threadCfg; 238094332d3Sopenharmony_ci ret = memset_s(&threadCfg, sizeof(threadCfg), 0, sizeof(threadCfg)); 239094332d3Sopenharmony_ci if (ret != EOK) { 240094332d3Sopenharmony_ci HDF_LOGE("%{public}s:%{public}d memset_s failed", __func__, __LINE__); 241094332d3Sopenharmony_ci return ret; 242094332d3Sopenharmony_ci } 243094332d3Sopenharmony_ci 244094332d3Sopenharmony_ci threadCfg.name = "speed read process"; 245094332d3Sopenharmony_ci threadCfg.priority = OSAL_THREAD_PRI_LOW; 246094332d3Sopenharmony_ci threadCfg.stackSize = HDF_PROCESS_STACK_SIZE; 247094332d3Sopenharmony_ci 248094332d3Sopenharmony_ci ret = OsalThreadCreate(&g_threadRead, (OsalThreadEntry)SpeedReadThread, port); 249094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 250094332d3Sopenharmony_ci HDF_LOGE("%{public}s:%{public}d OsalThreadCreate failed, ret=%{public}d ", __func__, __LINE__, ret); 251094332d3Sopenharmony_ci return HDF_ERR_DEVICE_BUSY; 252094332d3Sopenharmony_ci } 253094332d3Sopenharmony_ci 254094332d3Sopenharmony_ci ret = OsalThreadStart(&g_threadRead, &threadCfg); 255094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 256094332d3Sopenharmony_ci HDF_LOGE("%{public}s:%{public}d OsalThreadStart failed, ret=%{public}d ", __func__, __LINE__, ret); 257094332d3Sopenharmony_ci return HDF_ERR_DEVICE_BUSY; 258094332d3Sopenharmony_ci } 259094332d3Sopenharmony_ci return HDF_SUCCESS; 260094332d3Sopenharmony_ci} 261094332d3Sopenharmony_ci 262094332d3Sopenharmony_cistatic int32_t UsbSerialGetTempReadSpeed(struct UsbSerial *port, struct HdfSBuf *reply) 263094332d3Sopenharmony_ci{ 264094332d3Sopenharmony_ci (void)port; 265094332d3Sopenharmony_ci if (!HdfSbufWriteFloat(reply, g_readSpeed)) { 266094332d3Sopenharmony_ci HDF_LOGE("%{public}s: HdfSbufWriteFloat failed", __func__); 267094332d3Sopenharmony_ci return HDF_FAILURE; 268094332d3Sopenharmony_ci } 269094332d3Sopenharmony_ci return HDF_SUCCESS; 270094332d3Sopenharmony_ci} 271094332d3Sopenharmony_ci 272094332d3Sopenharmony_cistatic int32_t UsbSerialGetTempReadSpeedInt(struct UsbSerial *port, struct HdfSBuf *reply) 273094332d3Sopenharmony_ci{ 274094332d3Sopenharmony_ci (void)port; 275094332d3Sopenharmony_ci uint32_t calc = 10000; 276094332d3Sopenharmony_ci if (!HdfSbufWriteUint32(reply, (uint32_t)(g_readSpeed * calc))) { 277094332d3Sopenharmony_ci HDF_LOGE("%{public}s: HdfSbufWriteUint32 failed", __func__); 278094332d3Sopenharmony_ci return HDF_FAILURE; 279094332d3Sopenharmony_ci } 280094332d3Sopenharmony_ci return HDF_SUCCESS; 281094332d3Sopenharmony_ci} 282094332d3Sopenharmony_ci 283094332d3Sopenharmony_cistatic int32_t UsbSerialReadSpeedDone(struct UsbSerial *port) 284094332d3Sopenharmony_ci{ 285094332d3Sopenharmony_ci (void)port; 286094332d3Sopenharmony_ci gettimeofday(&g_readTimeEnd, NULL); 287094332d3Sopenharmony_ci g_isReadDone = true; 288094332d3Sopenharmony_ci g_isStartRead = false; 289094332d3Sopenharmony_ci return HDF_SUCCESS; 290094332d3Sopenharmony_ci} 291094332d3Sopenharmony_ci 292094332d3Sopenharmony_cistatic int32_t UsbSerialReadSpeedStart(struct UsbSerial *port) 293094332d3Sopenharmony_ci{ 294094332d3Sopenharmony_ci g_inFifo = 0; 295094332d3Sopenharmony_ci g_isStartRead = true; 296094332d3Sopenharmony_ci return StartThreadReadSpeed(port); 297094332d3Sopenharmony_ci} 298094332d3Sopenharmony_ci 299094332d3Sopenharmony_cistatic void UsbSerialWriteComplete(uint8_t pipe, struct UsbFnRequest *req) 300094332d3Sopenharmony_ci{ 301094332d3Sopenharmony_ci struct UsbSerial *port = (struct UsbSerial *)req->context; 302094332d3Sopenharmony_ci 303094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 304094332d3Sopenharmony_ci DListInsertTail(&req->list, &port->writePool); 305094332d3Sopenharmony_ci port->writeStarted--; 306094332d3Sopenharmony_ci 307094332d3Sopenharmony_ci switch (req->status) { 308094332d3Sopenharmony_ci case USB_REQUEST_COMPLETED: 309094332d3Sopenharmony_ci UsbSerialStartTx(port); 310094332d3Sopenharmony_ci break; 311094332d3Sopenharmony_ci case USB_REQUEST_NO_DEVICE: 312094332d3Sopenharmony_ci HDF_LOGV("%{public}s: acm device was disconnected", __func__); 313094332d3Sopenharmony_ci break; 314094332d3Sopenharmony_ci default: 315094332d3Sopenharmony_ci HDF_LOGV("%{public}s: unexpected status %{public}d", __func__, req->status); 316094332d3Sopenharmony_ci break; 317094332d3Sopenharmony_ci } 318094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 319094332d3Sopenharmony_ci} 320094332d3Sopenharmony_ci 321094332d3Sopenharmony_cistatic int32_t UsbSerialAllocReadRequests(struct UsbSerial *port, int32_t num) 322094332d3Sopenharmony_ci{ 323094332d3Sopenharmony_ci struct UsbAcmDevice *acm = port->acm; 324094332d3Sopenharmony_ci struct DListHead *head = &port->readPool; 325094332d3Sopenharmony_ci struct UsbFnRequest *req = NULL; 326094332d3Sopenharmony_ci int32_t i; 327094332d3Sopenharmony_ci 328094332d3Sopenharmony_ci for (i = 0; i < num; i++) { 329094332d3Sopenharmony_ci req = UsbFnAllocRequest(acm->dataIface.handle, acm->dataOutPipe.id, acm->dataOutPipe.maxPacketSize); 330094332d3Sopenharmony_ci if (!req) { 331094332d3Sopenharmony_ci return DListIsEmpty(head) ? HDF_FAILURE : HDF_SUCCESS; 332094332d3Sopenharmony_ci } 333094332d3Sopenharmony_ci 334094332d3Sopenharmony_ci req->complete = UsbSerialReadComplete; 335094332d3Sopenharmony_ci req->context = port; 336094332d3Sopenharmony_ci DListInsertTail(&req->list, head); 337094332d3Sopenharmony_ci port->readAllocated++; 338094332d3Sopenharmony_ci } 339094332d3Sopenharmony_ci return HDF_SUCCESS; 340094332d3Sopenharmony_ci} 341094332d3Sopenharmony_ci 342094332d3Sopenharmony_cistatic int32_t UsbSerialAllocWriteRequests(struct UsbSerial *port, int32_t num) 343094332d3Sopenharmony_ci{ 344094332d3Sopenharmony_ci struct UsbAcmDevice *acm = port->acm; 345094332d3Sopenharmony_ci struct DListHead *head = &port->writePool; 346094332d3Sopenharmony_ci struct UsbFnRequest *req = NULL; 347094332d3Sopenharmony_ci int32_t i; 348094332d3Sopenharmony_ci 349094332d3Sopenharmony_ci for (i = 0; i < num; i++) { 350094332d3Sopenharmony_ci req = UsbFnAllocRequest(acm->dataIface.handle, acm->dataInPipe.id, acm->dataInPipe.maxPacketSize); 351094332d3Sopenharmony_ci if (!req) { 352094332d3Sopenharmony_ci return DListIsEmpty(head) ? HDF_FAILURE : HDF_SUCCESS; 353094332d3Sopenharmony_ci } 354094332d3Sopenharmony_ci 355094332d3Sopenharmony_ci req->complete = UsbSerialWriteComplete; 356094332d3Sopenharmony_ci req->context = port; 357094332d3Sopenharmony_ci DListInsertTail(&req->list, head); 358094332d3Sopenharmony_ci port->writeAllocated++; 359094332d3Sopenharmony_ci } 360094332d3Sopenharmony_ci return HDF_SUCCESS; 361094332d3Sopenharmony_ci} 362094332d3Sopenharmony_ci 363094332d3Sopenharmony_cistatic void UsbSerialFreeFifo(struct DataFifo *fifo) 364094332d3Sopenharmony_ci{ 365094332d3Sopenharmony_ci void *buf = fifo->data; 366094332d3Sopenharmony_ci OsalMemFree(buf); 367094332d3Sopenharmony_ci DataFifoInit(fifo, 0, NULL); 368094332d3Sopenharmony_ci} 369094332d3Sopenharmony_ci 370094332d3Sopenharmony_cistatic int32_t UsbSerialStartIo(struct UsbSerial *port) 371094332d3Sopenharmony_ci{ 372094332d3Sopenharmony_ci struct DListHead *head = &port->readPool; 373094332d3Sopenharmony_ci int32_t ret = HDF_SUCCESS; 374094332d3Sopenharmony_ci uint32_t started; 375094332d3Sopenharmony_ci 376094332d3Sopenharmony_ci /* allocate requests for read/write */ 377094332d3Sopenharmony_ci if (port->readAllocated == 0) { 378094332d3Sopenharmony_ci ret = UsbSerialAllocReadRequests(port, QUEUE_SIZE); 379094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 380094332d3Sopenharmony_ci HDF_LOGE("%{public}s: UsbSerialAllocReadRequests failed:%{public}d", __func__, ret); 381094332d3Sopenharmony_ci return ret; 382094332d3Sopenharmony_ci } 383094332d3Sopenharmony_ci } 384094332d3Sopenharmony_ci if (port->writeAllocated == 0) { 385094332d3Sopenharmony_ci ret = UsbSerialAllocWriteRequests(port, QUEUE_SIZE); 386094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 387094332d3Sopenharmony_ci UsbSerialFreeRequests(head, &port->readAllocated); 388094332d3Sopenharmony_ci HDF_LOGE("%{public}s: UsbSerialAllocWriteRequests failed:%{public}d", __func__, ret); 389094332d3Sopenharmony_ci return ret; 390094332d3Sopenharmony_ci } 391094332d3Sopenharmony_ci } 392094332d3Sopenharmony_ci 393094332d3Sopenharmony_ci started = UsbSerialStartRx(port); 394094332d3Sopenharmony_ci if (started) { 395094332d3Sopenharmony_ci UsbSerialStartTx(port); 396094332d3Sopenharmony_ci } else { 397094332d3Sopenharmony_ci UsbSerialFreeRequests(head, &port->readAllocated); 398094332d3Sopenharmony_ci UsbSerialFreeRequests(&port->writePool, &port->writeAllocated); 399094332d3Sopenharmony_ci HDF_LOGE("%{public}s: UsbSerialStartRx failed", __func__); 400094332d3Sopenharmony_ci ret = HDF_ERR_IO; 401094332d3Sopenharmony_ci } 402094332d3Sopenharmony_ci 403094332d3Sopenharmony_ci return ret; 404094332d3Sopenharmony_ci} 405094332d3Sopenharmony_ci 406094332d3Sopenharmony_cistatic void UsbSerialStopIo(struct UsbSerial *port) 407094332d3Sopenharmony_ci{ 408094332d3Sopenharmony_ci if (port == NULL) { 409094332d3Sopenharmony_ci HDF_LOGE("%{public}s: port is null", __func__); 410094332d3Sopenharmony_ci return; 411094332d3Sopenharmony_ci } 412094332d3Sopenharmony_ci UsbSerialFreeRequests(&port->readPool, &port->readAllocated); 413094332d3Sopenharmony_ci UsbSerialFreeRequests(&port->writePool, &port->writeAllocated); 414094332d3Sopenharmony_ci UsbSerialFreeFifo(&port->writeFifo); 415094332d3Sopenharmony_ci UsbSerialFreeFifo(&port->readFifo); 416094332d3Sopenharmony_ci} 417094332d3Sopenharmony_ci 418094332d3Sopenharmony_cistatic int32_t UsbSerialAllocFifo(struct DataFifo *fifo, uint32_t size) 419094332d3Sopenharmony_ci{ 420094332d3Sopenharmony_ci if (!DataFifoIsInitialized(fifo)) { 421094332d3Sopenharmony_ci void *data = OsalMemAlloc(size); 422094332d3Sopenharmony_ci if (data == NULL) { 423094332d3Sopenharmony_ci HDF_LOGE("%{public}s: allocate fifo data buffer failed", __func__); 424094332d3Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 425094332d3Sopenharmony_ci } 426094332d3Sopenharmony_ci DataFifoInit(fifo, size, data); 427094332d3Sopenharmony_ci } 428094332d3Sopenharmony_ci return HDF_SUCCESS; 429094332d3Sopenharmony_ci} 430094332d3Sopenharmony_ci 431094332d3Sopenharmony_cistatic int32_t UsbSerialOpen(struct UsbSerial *port) 432094332d3Sopenharmony_ci{ 433094332d3Sopenharmony_ci int32_t ret; 434094332d3Sopenharmony_ci 435094332d3Sopenharmony_ci if (port == NULL) { 436094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 437094332d3Sopenharmony_ci } 438094332d3Sopenharmony_ci g_inFifo = 1; 439094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 440094332d3Sopenharmony_ci ret = UsbSerialAllocFifo(&port->writeFifo, WRITE_BUF_SIZE); 441094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 442094332d3Sopenharmony_ci HDF_LOGE("%{public}s: UsbSerialAllocFifo failed", __func__); 443094332d3Sopenharmony_ci goto OUT; 444094332d3Sopenharmony_ci } 445094332d3Sopenharmony_ci ret = UsbSerialAllocFifo(&port->readFifo, READ_BUF_SIZE); 446094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 447094332d3Sopenharmony_ci HDF_LOGE("%{public}s: UsbSerialAllocFifo failed", __func__); 448094332d3Sopenharmony_ci goto OUT; 449094332d3Sopenharmony_ci } 450094332d3Sopenharmony_ci 451094332d3Sopenharmony_ci /* the acm is enabled, start the io stream */ 452094332d3Sopenharmony_ci if (port->acm) { 453094332d3Sopenharmony_ci if (!port->suspended) { 454094332d3Sopenharmony_ci struct UsbAcmDevice *acm = port->acm; 455094332d3Sopenharmony_ci HDF_LOGD("%{public}s: start usb serial", __func__); 456094332d3Sopenharmony_ci ret = UsbSerialStartIo(port); 457094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 458094332d3Sopenharmony_ci goto OUT; 459094332d3Sopenharmony_ci } 460094332d3Sopenharmony_ci if (acm->notify && acm->notify->Connect) { 461094332d3Sopenharmony_ci acm->notify->Connect(acm); 462094332d3Sopenharmony_ci } 463094332d3Sopenharmony_ci } else { 464094332d3Sopenharmony_ci HDF_LOGD("%{public}s: delay start usb serial", __func__); 465094332d3Sopenharmony_ci port->startDelayed = true; 466094332d3Sopenharmony_ci } 467094332d3Sopenharmony_ci } 468094332d3Sopenharmony_ci 469094332d3Sopenharmony_ciOUT: 470094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 471094332d3Sopenharmony_ci return HDF_SUCCESS; 472094332d3Sopenharmony_ci} 473094332d3Sopenharmony_ci 474094332d3Sopenharmony_cistatic int32_t UsbSerialClose(struct UsbSerial *port) 475094332d3Sopenharmony_ci{ 476094332d3Sopenharmony_ci struct UsbAcmDevice *acm = NULL; 477094332d3Sopenharmony_ci 478094332d3Sopenharmony_ci if (port == NULL) { 479094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 480094332d3Sopenharmony_ci } 481094332d3Sopenharmony_ci 482094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 483094332d3Sopenharmony_ci 484094332d3Sopenharmony_ci HDF_LOGD("%{public}s: close usb serial", __func__); 485094332d3Sopenharmony_ci acm = port->acm; 486094332d3Sopenharmony_ci if (acm && !port->suspended) { 487094332d3Sopenharmony_ci if (acm->notify && acm->notify->Disconnect) { 488094332d3Sopenharmony_ci acm->notify->Disconnect(acm); 489094332d3Sopenharmony_ci } 490094332d3Sopenharmony_ci } 491094332d3Sopenharmony_ci DataFifoReset(&port->writeFifo); 492094332d3Sopenharmony_ci DataFifoReset(&port->readFifo); 493094332d3Sopenharmony_ci UsbSerialStopIo(port); 494094332d3Sopenharmony_ci port->startDelayed = false; 495094332d3Sopenharmony_ci 496094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 497094332d3Sopenharmony_ci return HDF_SUCCESS; 498094332d3Sopenharmony_ci} 499094332d3Sopenharmony_ci 500094332d3Sopenharmony_ci#define WRITE_SPEED_REQ_NUM 8 501094332d3Sopenharmony_cistruct UsbFnRequest *g_req[WRITE_SPEED_REQ_NUM] = {NULL}; 502094332d3Sopenharmony_cistatic bool g_isWriteDone = false; 503094332d3Sopenharmony_cistatic uint64_t g_writeCnt = 0; 504094332d3Sopenharmony_cistruct timeval g_timeStart, g_timeEnd; 505094332d3Sopenharmony_cistatic float g_speed = 0; 506094332d3Sopenharmony_cistatic bool g_isGetWriteTimeStart = false; 507094332d3Sopenharmony_cistatic void UsbSerialWriteSpeedComplete(uint8_t pipe, struct UsbFnRequest *req) 508094332d3Sopenharmony_ci{ 509094332d3Sopenharmony_ci switch (req->status) { 510094332d3Sopenharmony_ci case USB_REQUEST_COMPLETED: 511094332d3Sopenharmony_ci g_writeCnt += req->actual; 512094332d3Sopenharmony_ci if (!g_isGetWriteTimeStart) { 513094332d3Sopenharmony_ci g_isGetWriteTimeStart = true; 514094332d3Sopenharmony_ci gettimeofday(&g_timeStart, NULL); 515094332d3Sopenharmony_ci } 516094332d3Sopenharmony_ci if (g_isWriteDone) { 517094332d3Sopenharmony_ci UsbFnFreeRequest(req); 518094332d3Sopenharmony_ci req = NULL; 519094332d3Sopenharmony_ci } else { 520094332d3Sopenharmony_ci if (memset_s(req->buf, req->length, 'a', req->length) != EOK) { 521094332d3Sopenharmony_ci HDF_LOGE("%{public}s:%{public}d memset_s failed", __func__, __LINE__); 522094332d3Sopenharmony_ci return; 523094332d3Sopenharmony_ci } 524094332d3Sopenharmony_ci UsbFnSubmitRequestAsync(req); 525094332d3Sopenharmony_ci } 526094332d3Sopenharmony_ci break; 527094332d3Sopenharmony_ci case USB_REQUEST_NO_DEVICE: 528094332d3Sopenharmony_ci HDF_LOGV("%{public}s: acm device was disconnected", __func__); 529094332d3Sopenharmony_ci break; 530094332d3Sopenharmony_ci default: 531094332d3Sopenharmony_ci HDF_LOGD("%{public}s: req->status = %{public}d", __func__, req->status); 532094332d3Sopenharmony_ci break; 533094332d3Sopenharmony_ci } 534094332d3Sopenharmony_ci} 535094332d3Sopenharmony_ci 536094332d3Sopenharmony_cistatic int32_t SpeedThread(void *arg) 537094332d3Sopenharmony_ci{ 538094332d3Sopenharmony_ci g_writeCnt = 0; 539094332d3Sopenharmony_ci g_isWriteDone = false; 540094332d3Sopenharmony_ci g_isGetWriteTimeStart = false; 541094332d3Sopenharmony_ci g_speed = 0; 542094332d3Sopenharmony_ci double timeUse; 543094332d3Sopenharmony_ci double usec = 1000000; 544094332d3Sopenharmony_ci double k = 1024; 545094332d3Sopenharmony_ci struct timeval timeTmp; 546094332d3Sopenharmony_ci struct UsbSerial *port = (struct UsbSerial *)arg; 547094332d3Sopenharmony_ci 548094332d3Sopenharmony_ci for (int32_t i = 0; i < WRITE_SPEED_REQ_NUM; i++) { 549094332d3Sopenharmony_ci g_req[i] = UsbFnAllocRequest( 550094332d3Sopenharmony_ci port->acm->dataIface.handle, port->acm->dataInPipe.id, port->acm->dataInPipe.maxPacketSize); 551094332d3Sopenharmony_ci if (g_req[i] == NULL) { 552094332d3Sopenharmony_ci return HDF_FAILURE; 553094332d3Sopenharmony_ci } 554094332d3Sopenharmony_ci g_req[i]->complete = UsbSerialWriteSpeedComplete; 555094332d3Sopenharmony_ci g_req[i]->context = port; 556094332d3Sopenharmony_ci g_req[i]->length = port->acm->dataInPipe.maxPacketSize; 557094332d3Sopenharmony_ci int32_t ret = 558094332d3Sopenharmony_ci memset_s(g_req[i]->buf, port->acm->dataInPipe.maxPacketSize, 'a', port->acm->dataInPipe.maxPacketSize); 559094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 560094332d3Sopenharmony_ci HDF_LOGE("%{public}s:%{public}d memset_s failed", __func__, __LINE__); 561094332d3Sopenharmony_ci return ret; 562094332d3Sopenharmony_ci } 563094332d3Sopenharmony_ci UsbFnSubmitRequestAsync(g_req[i]); 564094332d3Sopenharmony_ci } 565094332d3Sopenharmony_ci while (!g_isWriteDone) { 566094332d3Sopenharmony_ci if (g_writeCnt == 0) { 567094332d3Sopenharmony_ci OsalSleep(1); 568094332d3Sopenharmony_ci continue; 569094332d3Sopenharmony_ci } else { 570094332d3Sopenharmony_ci OsalSleep(1); 571094332d3Sopenharmony_ci } 572094332d3Sopenharmony_ci gettimeofday(&timeTmp, NULL); 573094332d3Sopenharmony_ci timeUse = (double)(timeTmp.tv_sec - g_timeStart.tv_sec) + (double)timeTmp.tv_usec / usec - 574094332d3Sopenharmony_ci (double)g_timeStart.tv_usec / usec; 575094332d3Sopenharmony_ci g_speed = (float)((double)g_writeCnt / k / k / timeUse); 576094332d3Sopenharmony_ci } 577094332d3Sopenharmony_ci timeUse = (double)(g_timeEnd.tv_sec - g_timeStart.tv_sec) + (double)g_timeEnd.tv_usec / usec - 578094332d3Sopenharmony_ci (double)g_timeStart.tv_usec / usec; 579094332d3Sopenharmony_ci HDF_LOGE("timeUse = %{public}lf", timeUse); 580094332d3Sopenharmony_ci g_speed = (float)((double)g_writeCnt / k / k / timeUse); 581094332d3Sopenharmony_ci HDF_LOGD("%{public}s: g_speed = %{public}f MB/s", __func__, g_speed); 582094332d3Sopenharmony_ci return HDF_SUCCESS; 583094332d3Sopenharmony_ci} 584094332d3Sopenharmony_ci 585094332d3Sopenharmony_cistruct OsalThread g_thread; 586094332d3Sopenharmony_cistatic int32_t StartThreadSpeed(struct UsbSerial *port) 587094332d3Sopenharmony_ci{ 588094332d3Sopenharmony_ci struct OsalThreadParam threadCfg; 589094332d3Sopenharmony_ci int32_t ret = memset_s(&threadCfg, sizeof(threadCfg), 0, sizeof(threadCfg)); 590094332d3Sopenharmony_ci if (ret != EOK) { 591094332d3Sopenharmony_ci HDF_LOGE("%{public}s:%{public}d memset_s failed", __func__, __LINE__); 592094332d3Sopenharmony_ci return ret; 593094332d3Sopenharmony_ci } 594094332d3Sopenharmony_ci threadCfg.name = "speed test process"; 595094332d3Sopenharmony_ci threadCfg.priority = OSAL_THREAD_PRI_LOW; 596094332d3Sopenharmony_ci threadCfg.stackSize = HDF_PROCESS_STACK_SIZE; 597094332d3Sopenharmony_ci 598094332d3Sopenharmony_ci ret = OsalThreadCreate(&g_thread, (OsalThreadEntry)SpeedThread, port); 599094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 600094332d3Sopenharmony_ci HDF_LOGE("%{public}s:%{public}d OsalThreadCreate failed, ret=%{public}d ", __func__, __LINE__, ret); 601094332d3Sopenharmony_ci return HDF_ERR_DEVICE_BUSY; 602094332d3Sopenharmony_ci } 603094332d3Sopenharmony_ci 604094332d3Sopenharmony_ci ret = OsalThreadStart(&g_thread, &threadCfg); 605094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 606094332d3Sopenharmony_ci HDF_LOGE("%{public}s:%{public}d OsalThreadStart failed, ret=%{public}d ", __func__, __LINE__, ret); 607094332d3Sopenharmony_ci return HDF_ERR_DEVICE_BUSY; 608094332d3Sopenharmony_ci } 609094332d3Sopenharmony_ci return 0; 610094332d3Sopenharmony_ci} 611094332d3Sopenharmony_ci 612094332d3Sopenharmony_cistatic int32_t UsbSerialGetTempSpeed(struct UsbSerial *port, struct HdfSBuf *reply) 613094332d3Sopenharmony_ci{ 614094332d3Sopenharmony_ci (void)port; 615094332d3Sopenharmony_ci if (!HdfSbufWriteFloat(reply, g_speed)) { 616094332d3Sopenharmony_ci HDF_LOGE("%{public}s: HdfSbufWriteFloat failed", __func__); 617094332d3Sopenharmony_ci return HDF_FAILURE; 618094332d3Sopenharmony_ci } 619094332d3Sopenharmony_ci return HDF_SUCCESS; 620094332d3Sopenharmony_ci} 621094332d3Sopenharmony_ci 622094332d3Sopenharmony_cistatic int32_t UsbSerialGetTempSpeedInt(struct UsbSerial *port, struct HdfSBuf *reply) 623094332d3Sopenharmony_ci{ 624094332d3Sopenharmony_ci (void)port; 625094332d3Sopenharmony_ci uint32_t calc = 10000; 626094332d3Sopenharmony_ci if (!HdfSbufWriteUint32(reply, (uint32_t)(g_speed * calc))) { 627094332d3Sopenharmony_ci HDF_LOGE("%{public}s: HdfSbufWriteUint32 failed", __func__); 628094332d3Sopenharmony_ci return HDF_FAILURE; 629094332d3Sopenharmony_ci } 630094332d3Sopenharmony_ci return HDF_SUCCESS; 631094332d3Sopenharmony_ci} 632094332d3Sopenharmony_ci 633094332d3Sopenharmony_cistatic int32_t UsbSerialSpeedDone(struct UsbSerial *port) 634094332d3Sopenharmony_ci{ 635094332d3Sopenharmony_ci (void)port; 636094332d3Sopenharmony_ci gettimeofday(&g_timeEnd, NULL); 637094332d3Sopenharmony_ci g_isWriteDone = true; 638094332d3Sopenharmony_ci return HDF_SUCCESS; 639094332d3Sopenharmony_ci} 640094332d3Sopenharmony_ci 641094332d3Sopenharmony_cistatic int32_t UsbSerialSpeed(struct UsbSerial *port) 642094332d3Sopenharmony_ci{ 643094332d3Sopenharmony_ci StartThreadSpeed(port); 644094332d3Sopenharmony_ci return HDF_SUCCESS; 645094332d3Sopenharmony_ci} 646094332d3Sopenharmony_ci 647094332d3Sopenharmony_cistatic int32_t UsbSerialRead(struct UsbSerial *port, struct HdfSBuf *reply) 648094332d3Sopenharmony_ci{ 649094332d3Sopenharmony_ci uint32_t len, fifoLen; 650094332d3Sopenharmony_ci int32_t ret = HDF_SUCCESS; 651094332d3Sopenharmony_ci uint8_t *buf = NULL; 652094332d3Sopenharmony_ci uint32_t i; 653094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 654094332d3Sopenharmony_ci if (DataFifoIsEmpty(&port->readFifo)) { 655094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 656094332d3Sopenharmony_ci return 0; 657094332d3Sopenharmony_ci } 658094332d3Sopenharmony_ci fifoLen = DataFifoLen(&port->readFifo); 659094332d3Sopenharmony_ci buf = (uint8_t *)OsalMemCalloc(fifoLen + 1); 660094332d3Sopenharmony_ci if (buf == NULL) { 661094332d3Sopenharmony_ci HDF_LOGE("%{public}s: OsalMemCalloc error", __func__); 662094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 663094332d3Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 664094332d3Sopenharmony_ci } 665094332d3Sopenharmony_ci for (i = 0; i < fifoLen; i++) { 666094332d3Sopenharmony_ci len = DataFifoRead(&port->readFifo, buf + i, 1); 667094332d3Sopenharmony_ci if (len == 0) { 668094332d3Sopenharmony_ci HDF_LOGE("%{public}s: no data", __func__); 669094332d3Sopenharmony_ci ret = HDF_ERR_IO; 670094332d3Sopenharmony_ci goto OUT; 671094332d3Sopenharmony_ci } 672094332d3Sopenharmony_ci if (*(buf + i) == 0) { 673094332d3Sopenharmony_ci if (i == 0) { 674094332d3Sopenharmony_ci goto OUT; 675094332d3Sopenharmony_ci } 676094332d3Sopenharmony_ci break; 677094332d3Sopenharmony_ci } 678094332d3Sopenharmony_ci } 679094332d3Sopenharmony_ci 680094332d3Sopenharmony_ci if (!HdfSbufWriteString(reply, (const char *)buf)) { 681094332d3Sopenharmony_ci HDF_LOGE("%{public}s: sbuf write buffer failed", __func__); 682094332d3Sopenharmony_ci ret = HDF_ERR_IO; 683094332d3Sopenharmony_ci } 684094332d3Sopenharmony_ciOUT: 685094332d3Sopenharmony_ci if (port->acm) { 686094332d3Sopenharmony_ci UsbSerialStartRx(port); 687094332d3Sopenharmony_ci } 688094332d3Sopenharmony_ci OsalMemFree(buf); 689094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 690094332d3Sopenharmony_ci return ret; 691094332d3Sopenharmony_ci} 692094332d3Sopenharmony_ci 693094332d3Sopenharmony_cistatic int32_t UsbSerialWrite(struct UsbSerial *port, struct HdfSBuf *data) 694094332d3Sopenharmony_ci{ 695094332d3Sopenharmony_ci int32_t size; 696094332d3Sopenharmony_ci const char *tmp = NULL; 697094332d3Sopenharmony_ci 698094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 699094332d3Sopenharmony_ci 700094332d3Sopenharmony_ci tmp = HdfSbufReadString(data); 701094332d3Sopenharmony_ci if (tmp == NULL) { 702094332d3Sopenharmony_ci HDF_LOGE("%{public}s: sbuf read buffer failed", __func__); 703094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 704094332d3Sopenharmony_ci return HDF_ERR_IO; 705094332d3Sopenharmony_ci } 706094332d3Sopenharmony_ci char *buf = OsalMemCalloc(strlen(tmp) + 1); 707094332d3Sopenharmony_ci if (buf == NULL) { 708094332d3Sopenharmony_ci HDF_LOGE("%{public}s: OsalMemCalloc failed", __func__); 709094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 710094332d3Sopenharmony_ci return HDF_ERR_IO; 711094332d3Sopenharmony_ci } 712094332d3Sopenharmony_ci 713094332d3Sopenharmony_ci int32_t ret = strcpy_s(buf, strlen(tmp) + 1, tmp); 714094332d3Sopenharmony_ci if (ret != EOK) { 715094332d3Sopenharmony_ci HDF_LOGE("%{public}s: strcpy_s failed", __func__); 716094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 717094332d3Sopenharmony_ci OsalMemFree(buf); 718094332d3Sopenharmony_ci return HDF_ERR_IO; 719094332d3Sopenharmony_ci } 720094332d3Sopenharmony_ci 721094332d3Sopenharmony_ci size = (int32_t)DataFifoWrite(&port->writeFifo, (uint8_t *)buf, strlen(buf)); 722094332d3Sopenharmony_ci 723094332d3Sopenharmony_ci if (port->acm) { 724094332d3Sopenharmony_ci UsbSerialStartTx(port); 725094332d3Sopenharmony_ci } 726094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 727094332d3Sopenharmony_ci OsalMemFree(buf); 728094332d3Sopenharmony_ci return size; 729094332d3Sopenharmony_ci} 730094332d3Sopenharmony_ci 731094332d3Sopenharmony_cistatic int32_t UsbSerialGetBaudrate(struct UsbSerial *port, struct HdfSBuf *reply) 732094332d3Sopenharmony_ci{ 733094332d3Sopenharmony_ci uint32_t baudRate = LE32_TO_CPU(port->lineCoding.dwDTERate); 734094332d3Sopenharmony_ci if (!HdfSbufWriteBuffer(reply, &baudRate, sizeof(baudRate))) { 735094332d3Sopenharmony_ci HDF_LOGE("%{public}s: sbuf write buffer failed", __func__); 736094332d3Sopenharmony_ci return HDF_ERR_IO; 737094332d3Sopenharmony_ci } 738094332d3Sopenharmony_ci return HDF_SUCCESS; 739094332d3Sopenharmony_ci} 740094332d3Sopenharmony_ci 741094332d3Sopenharmony_cistatic int32_t UsbSerialSetBaudrate(struct UsbSerial *port, struct HdfSBuf *data) 742094332d3Sopenharmony_ci{ 743094332d3Sopenharmony_ci uint32_t size; 744094332d3Sopenharmony_ci uint32_t *baudRate = NULL; 745094332d3Sopenharmony_ci 746094332d3Sopenharmony_ci if (!HdfSbufReadBuffer(data, (const void **)&baudRate, &size)) { 747094332d3Sopenharmony_ci HDF_LOGE("%{public}s: sbuf read buffer failed", __func__); 748094332d3Sopenharmony_ci return HDF_ERR_IO; 749094332d3Sopenharmony_ci } 750094332d3Sopenharmony_ci port->lineCoding.dwDTERate = CPU_TO_LE32(*baudRate); 751094332d3Sopenharmony_ci if (port->acm) { 752094332d3Sopenharmony_ci port->acm->lineCoding.dwDTERate = CPU_TO_LE32(*baudRate); 753094332d3Sopenharmony_ci } 754094332d3Sopenharmony_ci return HDF_SUCCESS; 755094332d3Sopenharmony_ci} 756094332d3Sopenharmony_ci 757094332d3Sopenharmony_cistatic int32_t UsbSerialGetProp(struct UsbAcmDevice *acmDevice, struct HdfSBuf *data, struct HdfSBuf *reply) 758094332d3Sopenharmony_ci{ 759094332d3Sopenharmony_ci struct UsbFnInterface *intf = acmDevice->ctrlIface.fn; 760094332d3Sopenharmony_ci const char *propName = NULL; 761094332d3Sopenharmony_ci char propValue[USB_MAX_PACKET_SIZE] = {0}; 762094332d3Sopenharmony_ci int32_t ret; 763094332d3Sopenharmony_ci 764094332d3Sopenharmony_ci propName = HdfSbufReadString(data); 765094332d3Sopenharmony_ci if (propName == NULL) { 766094332d3Sopenharmony_ci return HDF_ERR_IO; 767094332d3Sopenharmony_ci } 768094332d3Sopenharmony_ci ret = UsbFnGetInterfaceProp(intf, propName, propValue); 769094332d3Sopenharmony_ci if (ret) { 770094332d3Sopenharmony_ci return HDF_ERR_IO; 771094332d3Sopenharmony_ci } 772094332d3Sopenharmony_ci if (!HdfSbufWriteString(reply, propValue)) { 773094332d3Sopenharmony_ci HDF_LOGE("%{public}s:failed to write result", __func__); 774094332d3Sopenharmony_ci return HDF_ERR_IO; 775094332d3Sopenharmony_ci } 776094332d3Sopenharmony_ci return HDF_SUCCESS; 777094332d3Sopenharmony_ci} 778094332d3Sopenharmony_ci 779094332d3Sopenharmony_cistatic int32_t UsbSerialSetProp(struct UsbAcmDevice *acmDevice, struct HdfSBuf *data) 780094332d3Sopenharmony_ci{ 781094332d3Sopenharmony_ci struct UsbFnInterface *intf = acmDevice->ctrlIface.fn; 782094332d3Sopenharmony_ci char tmp[USB_MAX_PACKET_SIZE] = {0}; 783094332d3Sopenharmony_ci 784094332d3Sopenharmony_ci const char *propName = HdfSbufReadString(data); 785094332d3Sopenharmony_ci if (propName == NULL) { 786094332d3Sopenharmony_ci return HDF_ERR_IO; 787094332d3Sopenharmony_ci } 788094332d3Sopenharmony_ci const char *propValue = HdfSbufReadString(data); 789094332d3Sopenharmony_ci if (propValue == NULL) { 790094332d3Sopenharmony_ci return HDF_ERR_IO; 791094332d3Sopenharmony_ci } 792094332d3Sopenharmony_ci (void)memset_s(&tmp, sizeof(tmp), 0, sizeof(tmp)); 793094332d3Sopenharmony_ci int32_t ret = snprintf_s(tmp, USB_MAX_PACKET_SIZE, USB_MAX_PACKET_SIZE - 1, "%s", propValue); 794094332d3Sopenharmony_ci if (ret < 0) { 795094332d3Sopenharmony_ci HDF_LOGE("%{public}s: snprintf_s failed", __func__); 796094332d3Sopenharmony_ci return HDF_FAILURE; 797094332d3Sopenharmony_ci } 798094332d3Sopenharmony_ci ret = UsbFnSetInterfaceProp(intf, propName, tmp); 799094332d3Sopenharmony_ci if (ret) { 800094332d3Sopenharmony_ci HDF_LOGE("%{public}s: UsbFnInterfaceSetProp failed", __func__); 801094332d3Sopenharmony_ci return HDF_ERR_IO; 802094332d3Sopenharmony_ci } 803094332d3Sopenharmony_ci return HDF_SUCCESS; 804094332d3Sopenharmony_ci} 805094332d3Sopenharmony_ci 806094332d3Sopenharmony_cistatic int32_t UsbSerialRegistPropAGet(const struct UsbFnInterface *intf, const char *name, const char *value) 807094332d3Sopenharmony_ci{ 808094332d3Sopenharmony_ci (void)intf; 809094332d3Sopenharmony_ci HDF_LOGE("%{public}s: name = %{public}s", __func__, name); 810094332d3Sopenharmony_ci HDF_LOGE("%{public}s: value = %{public}s", __func__, value); 811094332d3Sopenharmony_ci 812094332d3Sopenharmony_ci return 0; 813094332d3Sopenharmony_ci} 814094332d3Sopenharmony_ci 815094332d3Sopenharmony_cistatic int32_t UsbSerialRegistPropASet(const struct UsbFnInterface *intf, const char *name, const char *value) 816094332d3Sopenharmony_ci{ 817094332d3Sopenharmony_ci (void)intf; 818094332d3Sopenharmony_ci HDF_LOGE("%{public}s: name = %{public}s", __func__, name); 819094332d3Sopenharmony_ci HDF_LOGE("%{public}s: value = %{public}s", __func__, value); 820094332d3Sopenharmony_ci 821094332d3Sopenharmony_ci return 0; 822094332d3Sopenharmony_ci} 823094332d3Sopenharmony_ci 824094332d3Sopenharmony_cistatic int32_t UsbSerialRegistProp(struct UsbAcmDevice *acmDevice, struct HdfSBuf *data) 825094332d3Sopenharmony_ci{ 826094332d3Sopenharmony_ci struct UsbFnInterface *intf = acmDevice->ctrlIface.fn; 827094332d3Sopenharmony_ci struct UsbFnRegistInfo registInfo; 828094332d3Sopenharmony_ci int32_t ret; 829094332d3Sopenharmony_ci 830094332d3Sopenharmony_ci const char *propName = HdfSbufReadString(data); 831094332d3Sopenharmony_ci if (propName == NULL) { 832094332d3Sopenharmony_ci return HDF_ERR_IO; 833094332d3Sopenharmony_ci } 834094332d3Sopenharmony_ci const char *propValue = HdfSbufReadString(data); 835094332d3Sopenharmony_ci if (propValue == NULL) { 836094332d3Sopenharmony_ci return HDF_ERR_IO; 837094332d3Sopenharmony_ci } 838094332d3Sopenharmony_ci registInfo.name = propName; 839094332d3Sopenharmony_ci registInfo.value = propValue; 840094332d3Sopenharmony_ci registInfo.getProp = UsbSerialRegistPropAGet; 841094332d3Sopenharmony_ci registInfo.setProp = UsbSerialRegistPropASet; 842094332d3Sopenharmony_ci ret = UsbFnRegistInterfaceProp(intf, ®istInfo); 843094332d3Sopenharmony_ci if (ret) { 844094332d3Sopenharmony_ci HDF_LOGE("%{public}s: UsbFnInterfaceSetProp failed", __func__); 845094332d3Sopenharmony_ci return HDF_ERR_IO; 846094332d3Sopenharmony_ci } 847094332d3Sopenharmony_ci return HDF_SUCCESS; 848094332d3Sopenharmony_ci} 849094332d3Sopenharmony_ci 850094332d3Sopenharmony_cistatic int32_t AcmSerialCmd( 851094332d3Sopenharmony_ci struct UsbAcmDevice *acm, int32_t cmd, struct UsbSerial *port, struct HdfSBuf *data, struct HdfSBuf *reply) 852094332d3Sopenharmony_ci{ 853094332d3Sopenharmony_ci switch (cmd) { 854094332d3Sopenharmony_ci case USB_SERIAL_OPEN: 855094332d3Sopenharmony_ci return UsbSerialOpen(port); 856094332d3Sopenharmony_ci case USB_SERIAL_CLOSE: 857094332d3Sopenharmony_ci return UsbSerialClose(port); 858094332d3Sopenharmony_ci case USB_SERIAL_READ: 859094332d3Sopenharmony_ci return UsbSerialRead(port, reply); 860094332d3Sopenharmony_ci case USB_SERIAL_WRITE: 861094332d3Sopenharmony_ci return UsbSerialWrite(port, data); 862094332d3Sopenharmony_ci case USB_SERIAL_GET_BAUDRATE: 863094332d3Sopenharmony_ci return UsbSerialGetBaudrate(port, reply); 864094332d3Sopenharmony_ci case USB_SERIAL_SET_BAUDRATE: 865094332d3Sopenharmony_ci return UsbSerialSetBaudrate(port, data); 866094332d3Sopenharmony_ci case USB_SERIAL_SET_PROP: 867094332d3Sopenharmony_ci return UsbSerialSetProp(acm, data); 868094332d3Sopenharmony_ci case USB_SERIAL_GET_PROP: 869094332d3Sopenharmony_ci return UsbSerialGetProp(acm, data, reply); 870094332d3Sopenharmony_ci case USB_SERIAL_REGIST_PROP: 871094332d3Sopenharmony_ci return UsbSerialRegistProp(acm, data); 872094332d3Sopenharmony_ci case USB_SERIAL_WRITE_SPEED: 873094332d3Sopenharmony_ci return UsbSerialSpeed(port); 874094332d3Sopenharmony_ci case USB_SERIAL_WRITE_GET_TEMP_SPEED: 875094332d3Sopenharmony_ci return UsbSerialGetTempSpeed(port, reply); 876094332d3Sopenharmony_ci case USB_SERIAL_WRITE_SPEED_DONE: 877094332d3Sopenharmony_ci return UsbSerialSpeedDone(port); 878094332d3Sopenharmony_ci case USB_SERIAL_WRITE_GET_TEMP_SPEED_UINT32: 879094332d3Sopenharmony_ci return UsbSerialGetTempSpeedInt(port, reply); 880094332d3Sopenharmony_ci case USB_SERIAL_READ_SPEED: 881094332d3Sopenharmony_ci return UsbSerialReadSpeedStart(port); 882094332d3Sopenharmony_ci case USB_SERIAL_READ_GET_TEMP_SPEED: 883094332d3Sopenharmony_ci return UsbSerialGetTempReadSpeed(port, reply); 884094332d3Sopenharmony_ci case USB_SERIAL_READ_SPEED_DONE: 885094332d3Sopenharmony_ci return UsbSerialReadSpeedDone(port); 886094332d3Sopenharmony_ci case USB_SERIAL_READ_GET_TEMP_SPEED_UINT32: 887094332d3Sopenharmony_ci return UsbSerialGetTempReadSpeedInt(port, reply); 888094332d3Sopenharmony_ci default: 889094332d3Sopenharmony_ci return HDF_ERR_NOT_SUPPORT; 890094332d3Sopenharmony_ci } 891094332d3Sopenharmony_ci return HDF_SUCCESS; 892094332d3Sopenharmony_ci} 893094332d3Sopenharmony_ci 894094332d3Sopenharmony_cistatic int32_t AcmDeviceDispatch( 895094332d3Sopenharmony_ci struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply) 896094332d3Sopenharmony_ci{ 897094332d3Sopenharmony_ci if (client == NULL || client->device == NULL || client->device->service == NULL) { 898094332d3Sopenharmony_ci HDF_LOGE("%{public}s: client is NULL", __func__); 899094332d3Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 900094332d3Sopenharmony_ci } 901094332d3Sopenharmony_ci 902094332d3Sopenharmony_ci struct UsbAcmDevice *acm = (struct UsbAcmDevice *)client->device->service; 903094332d3Sopenharmony_ci if (!HdfDeviceObjectCheckInterfaceDesc(client->device, data)) { 904094332d3Sopenharmony_ci HDF_LOGE("%{public}s:%{public}d check interface desc fail", __func__, __LINE__); 905094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 906094332d3Sopenharmony_ci } 907094332d3Sopenharmony_ci 908094332d3Sopenharmony_ci switch (cmd) { 909094332d3Sopenharmony_ci case USB_SERIAL_INIT: 910094332d3Sopenharmony_ci return UsbSerialInit(acm); 911094332d3Sopenharmony_ci case USB_SERIAL_RELEASE: 912094332d3Sopenharmony_ci return UsbSerialRelease(acm); 913094332d3Sopenharmony_ci default: 914094332d3Sopenharmony_ci HDF_LOGE("%{public}s: unknown cmd %{public}d", __func__, cmd); 915094332d3Sopenharmony_ci break; 916094332d3Sopenharmony_ci } 917094332d3Sopenharmony_ci OsalMutexLock(&acm->lock); 918094332d3Sopenharmony_ci struct UsbSerial *port = acm->port; 919094332d3Sopenharmony_ci if (port == NULL) { 920094332d3Sopenharmony_ci OsalMutexUnlock(&acm->lock); 921094332d3Sopenharmony_ci HDF_LOGE("%{public}s: port is NULL", __func__); 922094332d3Sopenharmony_ci return HDF_ERR_IO; 923094332d3Sopenharmony_ci } 924094332d3Sopenharmony_ci int32_t ret = AcmSerialCmd(acm, cmd, port, data, reply); 925094332d3Sopenharmony_ci OsalMutexUnlock(&acm->lock); 926094332d3Sopenharmony_ci return ret; 927094332d3Sopenharmony_ci} 928094332d3Sopenharmony_ci 929094332d3Sopenharmony_cistatic void AcmDeviceDestroy(struct UsbAcmDevice *acm) 930094332d3Sopenharmony_ci{ 931094332d3Sopenharmony_ci if (acm == NULL) { 932094332d3Sopenharmony_ci return; 933094332d3Sopenharmony_ci } 934094332d3Sopenharmony_ci OsalMemFree(acm); 935094332d3Sopenharmony_ci} 936094332d3Sopenharmony_ci 937094332d3Sopenharmony_cistatic void AcmCtrlComplete(uint8_t pipe, struct UsbFnRequest *req) 938094332d3Sopenharmony_ci{ 939094332d3Sopenharmony_ci if (req == NULL) { 940094332d3Sopenharmony_ci return; 941094332d3Sopenharmony_ci } 942094332d3Sopenharmony_ci struct CtrlInfo *ctrlInfo = (struct CtrlInfo *)req->context; 943094332d3Sopenharmony_ci if (ctrlInfo == NULL) { 944094332d3Sopenharmony_ci return; 945094332d3Sopenharmony_ci } 946094332d3Sopenharmony_ci struct UsbAcmDevice *acm = ctrlInfo->acm; 947094332d3Sopenharmony_ci if (req->status != USB_REQUEST_COMPLETED) { 948094332d3Sopenharmony_ci HDF_LOGD("%{public}s: ctrl completion error %{public}d", __func__, req->status); 949094332d3Sopenharmony_ci goto OUT; 950094332d3Sopenharmony_ci } 951094332d3Sopenharmony_ci 952094332d3Sopenharmony_ci if (ctrlInfo->request == USB_DDK_CDC_REQ_SET_LINE_CODING) { 953094332d3Sopenharmony_ci struct UsbCdcLineCoding *value = req->buf; 954094332d3Sopenharmony_ci if (req->actual == sizeof(*value)) { 955094332d3Sopenharmony_ci acm->lineCoding = *value; 956094332d3Sopenharmony_ci HDF_LOGD("dwDTERate = %{public}d", acm->lineCoding.dwDTERate); 957094332d3Sopenharmony_ci HDF_LOGD("bCharFormat = %{public}d", acm->lineCoding.bCharFormat); 958094332d3Sopenharmony_ci HDF_LOGD("bParityType = %{public}d", acm->lineCoding.bParityType); 959094332d3Sopenharmony_ci HDF_LOGD("bDataBits = %{public}d", acm->lineCoding.bDataBits); 960094332d3Sopenharmony_ci } 961094332d3Sopenharmony_ci } 962094332d3Sopenharmony_ci 963094332d3Sopenharmony_ciOUT: 964094332d3Sopenharmony_ci DListInsertTail(&req->list, &acm->ctrlPool); 965094332d3Sopenharmony_ci} 966094332d3Sopenharmony_ci 967094332d3Sopenharmony_cistatic int32_t AcmAllocCtrlRequests(struct UsbAcmDevice *acm, int32_t num) 968094332d3Sopenharmony_ci{ 969094332d3Sopenharmony_ci struct DListHead *head = &acm->ctrlPool; 970094332d3Sopenharmony_ci struct UsbFnRequest *req = NULL; 971094332d3Sopenharmony_ci struct CtrlInfo *ctrlInfo = NULL; 972094332d3Sopenharmony_ci int32_t i; 973094332d3Sopenharmony_ci 974094332d3Sopenharmony_ci DListHeadInit(&acm->ctrlPool); 975094332d3Sopenharmony_ci acm->ctrlReqNum = 0; 976094332d3Sopenharmony_ci 977094332d3Sopenharmony_ci for (i = 0; i < num; i++) { 978094332d3Sopenharmony_ci ctrlInfo = (struct CtrlInfo *)OsalMemCalloc(sizeof(*ctrlInfo)); 979094332d3Sopenharmony_ci if (ctrlInfo == NULL) { 980094332d3Sopenharmony_ci HDF_LOGE("%{public}s: Allocate ctrlInfo failed", __func__); 981094332d3Sopenharmony_ci goto OUT; 982094332d3Sopenharmony_ci } 983094332d3Sopenharmony_ci ctrlInfo->acm = acm; 984094332d3Sopenharmony_ci req = UsbFnAllocCtrlRequest( 985094332d3Sopenharmony_ci acm->ctrlIface.handle, sizeof(struct UsbCdcLineCoding) + sizeof(struct UsbCdcLineCoding)); 986094332d3Sopenharmony_ci if (req == NULL) { 987094332d3Sopenharmony_ci goto OUT; 988094332d3Sopenharmony_ci } 989094332d3Sopenharmony_ci req->complete = AcmCtrlComplete; 990094332d3Sopenharmony_ci req->context = ctrlInfo; 991094332d3Sopenharmony_ci DListInsertTail(&req->list, head); 992094332d3Sopenharmony_ci acm->ctrlReqNum++; 993094332d3Sopenharmony_ci } 994094332d3Sopenharmony_ci return HDF_SUCCESS; 995094332d3Sopenharmony_ci 996094332d3Sopenharmony_ciOUT: 997094332d3Sopenharmony_ci return DListIsEmpty(head) ? HDF_FAILURE : HDF_SUCCESS; 998094332d3Sopenharmony_ci} 999094332d3Sopenharmony_ci 1000094332d3Sopenharmony_cistatic void AcmFreeCtrlRequests(struct UsbAcmDevice *acm) 1001094332d3Sopenharmony_ci{ 1002094332d3Sopenharmony_ci struct DListHead *head = &acm->ctrlPool; 1003094332d3Sopenharmony_ci struct UsbFnRequest *req = NULL; 1004094332d3Sopenharmony_ci 1005094332d3Sopenharmony_ci while (!DListIsEmpty(head)) { 1006094332d3Sopenharmony_ci req = DLIST_FIRST_ENTRY(head, struct UsbFnRequest, list); 1007094332d3Sopenharmony_ci DListRemove(&req->list); 1008094332d3Sopenharmony_ci OsalMemFree(req->context); 1009094332d3Sopenharmony_ci (void)UsbFnFreeRequest(req); 1010094332d3Sopenharmony_ci acm->ctrlReqNum--; 1011094332d3Sopenharmony_ci } 1012094332d3Sopenharmony_ci} 1013094332d3Sopenharmony_ci 1014094332d3Sopenharmony_cistatic int32_t AcmNotifySerialState(struct UsbAcmDevice *acm); 1015094332d3Sopenharmony_cistatic void AcmNotifyComplete(uint8_t pipe, struct UsbFnRequest *req) 1016094332d3Sopenharmony_ci{ 1017094332d3Sopenharmony_ci struct UsbAcmDevice *acm = (struct UsbAcmDevice *)req->context; 1018094332d3Sopenharmony_ci bool pending = false; 1019094332d3Sopenharmony_ci 1020094332d3Sopenharmony_ci if (acm == NULL) { 1021094332d3Sopenharmony_ci HDF_LOGE("%{public}s: acm is null", __func__); 1022094332d3Sopenharmony_ci return; 1023094332d3Sopenharmony_ci } 1024094332d3Sopenharmony_ci 1025094332d3Sopenharmony_ci OsalMutexLock(&acm->lock); 1026094332d3Sopenharmony_ci /* estimate pending */ 1027094332d3Sopenharmony_ci if (req->status == PENDING_FLAG) { 1028094332d3Sopenharmony_ci pending = acm->pending; 1029094332d3Sopenharmony_ci } 1030094332d3Sopenharmony_ci acm->notifyReq = req; 1031094332d3Sopenharmony_ci OsalMutexUnlock(&acm->lock); 1032094332d3Sopenharmony_ci if (pending) { 1033094332d3Sopenharmony_ci AcmNotifySerialState(acm); 1034094332d3Sopenharmony_ci } 1035094332d3Sopenharmony_ci} 1036094332d3Sopenharmony_ci 1037094332d3Sopenharmony_cistatic int32_t AcmAllocNotifyRequest(struct UsbAcmDevice *acm) 1038094332d3Sopenharmony_ci{ 1039094332d3Sopenharmony_ci /* allocate notification request, 2 means compatible liteOS and linux */ 1040094332d3Sopenharmony_ci acm->notifyReq = 1041094332d3Sopenharmony_ci UsbFnAllocRequest(acm->ctrlIface.handle, acm->notifyPipe.id, sizeof(struct UsbCdcNotification) * USBCDC_LEN); 1042094332d3Sopenharmony_ci if (acm->notifyReq == NULL) { 1043094332d3Sopenharmony_ci HDF_LOGE("%{public}s: allocate notify request failed", __func__); 1044094332d3Sopenharmony_ci return HDF_FAILURE; 1045094332d3Sopenharmony_ci } 1046094332d3Sopenharmony_ci acm->notifyReq->complete = AcmNotifyComplete; 1047094332d3Sopenharmony_ci acm->notifyReq->context = acm; 1048094332d3Sopenharmony_ci 1049094332d3Sopenharmony_ci return HDF_SUCCESS; 1050094332d3Sopenharmony_ci} 1051094332d3Sopenharmony_ci 1052094332d3Sopenharmony_cistatic void AcmFreeNotifyRequest(struct UsbAcmDevice *acm) 1053094332d3Sopenharmony_ci{ 1054094332d3Sopenharmony_ci int32_t ret; 1055094332d3Sopenharmony_ci 1056094332d3Sopenharmony_ci /* free notification request */ 1057094332d3Sopenharmony_ci ret = UsbFnFreeRequest(acm->notifyReq); 1058094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 1059094332d3Sopenharmony_ci HDF_LOGE("%{public}s: free notify request failed", __func__); 1060094332d3Sopenharmony_ci return; 1061094332d3Sopenharmony_ci } 1062094332d3Sopenharmony_ci acm->notifyReq = NULL; 1063094332d3Sopenharmony_ci} 1064094332d3Sopenharmony_ci 1065094332d3Sopenharmony_cistatic uint32_t AcmEnable(struct UsbAcmDevice *acm) 1066094332d3Sopenharmony_ci{ 1067094332d3Sopenharmony_ci struct UsbSerial *port = acm->port; 1068094332d3Sopenharmony_ci port->acm = acm; 1069094332d3Sopenharmony_ci acm->lineCoding = port->lineCoding; 1070094332d3Sopenharmony_ci return HDF_SUCCESS; 1071094332d3Sopenharmony_ci} 1072094332d3Sopenharmony_ci 1073094332d3Sopenharmony_cistatic uint32_t AcmDisable(struct UsbAcmDevice *acm) 1074094332d3Sopenharmony_ci{ 1075094332d3Sopenharmony_ci struct UsbSerial *port = acm->port; 1076094332d3Sopenharmony_ci 1077094332d3Sopenharmony_ci if (port == NULL) { 1078094332d3Sopenharmony_ci HDF_LOGE("%{public}s: port is null", __func__); 1079094332d3Sopenharmony_ci return HDF_FAILURE; 1080094332d3Sopenharmony_ci } 1081094332d3Sopenharmony_ci 1082094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 1083094332d3Sopenharmony_ci port->lineCoding = acm->lineCoding; 1084094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 1085094332d3Sopenharmony_ci 1086094332d3Sopenharmony_ci return HDF_SUCCESS; 1087094332d3Sopenharmony_ci} 1088094332d3Sopenharmony_ci 1089094332d3Sopenharmony_cistatic struct UsbFnRequest *AcmGetCtrlReq(struct UsbAcmDevice *acm) 1090094332d3Sopenharmony_ci{ 1091094332d3Sopenharmony_ci struct UsbFnRequest *req = NULL; 1092094332d3Sopenharmony_ci struct DListHead *pool = &acm->ctrlPool; 1093094332d3Sopenharmony_ci 1094094332d3Sopenharmony_ci if (!DListIsEmpty(pool)) { 1095094332d3Sopenharmony_ci req = DLIST_FIRST_ENTRY(pool, struct UsbFnRequest, list); 1096094332d3Sopenharmony_ci DListRemove(&req->list); 1097094332d3Sopenharmony_ci } 1098094332d3Sopenharmony_ci return req; 1099094332d3Sopenharmony_ci} 1100094332d3Sopenharmony_ci 1101094332d3Sopenharmony_cistatic void AcmSetup(struct UsbAcmDevice *acm, struct UsbFnCtrlRequest *setup) 1102094332d3Sopenharmony_ci{ 1103094332d3Sopenharmony_ci if (acm == NULL || setup == NULL) { 1104094332d3Sopenharmony_ci return; 1105094332d3Sopenharmony_ci } 1106094332d3Sopenharmony_ci struct UsbFnRequest *req = NULL; 1107094332d3Sopenharmony_ci struct CtrlInfo *ctrlInfo = NULL; 1108094332d3Sopenharmony_ci uint16_t value = LE16_TO_CPU(setup->value); 1109094332d3Sopenharmony_ci uint16_t length = LE16_TO_CPU(setup->length); 1110094332d3Sopenharmony_ci int32_t ret = 0; 1111094332d3Sopenharmony_ci 1112094332d3Sopenharmony_ci req = AcmGetCtrlReq(acm); 1113094332d3Sopenharmony_ci if (req == NULL) { 1114094332d3Sopenharmony_ci HDF_LOGE("%{public}s: control request pool is empty", __func__); 1115094332d3Sopenharmony_ci return; 1116094332d3Sopenharmony_ci } 1117094332d3Sopenharmony_ci 1118094332d3Sopenharmony_ci switch (setup->request) { 1119094332d3Sopenharmony_ci case USB_DDK_CDC_REQ_SET_LINE_CODING: 1120094332d3Sopenharmony_ci if (length != sizeof(struct UsbCdcLineCoding)) { 1121094332d3Sopenharmony_ci goto OUT; 1122094332d3Sopenharmony_ci } 1123094332d3Sopenharmony_ci ret = (int)length; 1124094332d3Sopenharmony_ci break; 1125094332d3Sopenharmony_ci case USB_DDK_CDC_REQ_GET_LINE_CODING: 1126094332d3Sopenharmony_ci ret = (int)MIN(length, sizeof(struct UsbCdcLineCoding)); 1127094332d3Sopenharmony_ci if (acm->lineCoding.dwDTERate == 0) { 1128094332d3Sopenharmony_ci acm->lineCoding = acm->port->lineCoding; 1129094332d3Sopenharmony_ci } 1130094332d3Sopenharmony_ci if (memcpy_s(req->buf, ret, &acm->lineCoding, ret) != EOK) { 1131094332d3Sopenharmony_ci return; 1132094332d3Sopenharmony_ci } 1133094332d3Sopenharmony_ci break; 1134094332d3Sopenharmony_ci case USB_DDK_CDC_REQ_SET_CONTROL_LINE_STATE: 1135094332d3Sopenharmony_ci ret = 0; 1136094332d3Sopenharmony_ci acm->handshakeBits = value; 1137094332d3Sopenharmony_ci break; 1138094332d3Sopenharmony_ci default: 1139094332d3Sopenharmony_ci HDF_LOGE("%{public}s: setup request is not supported", __func__); 1140094332d3Sopenharmony_ci break; 1141094332d3Sopenharmony_ci } 1142094332d3Sopenharmony_ci 1143094332d3Sopenharmony_ciOUT: 1144094332d3Sopenharmony_ci ctrlInfo = (struct CtrlInfo *)req->context; 1145094332d3Sopenharmony_ci ctrlInfo->request = setup->request; 1146094332d3Sopenharmony_ci req->length = (uint32_t)ret; 1147094332d3Sopenharmony_ci ret = UsbFnSubmitRequestAsync(req); 1148094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 1149094332d3Sopenharmony_ci HDF_LOGE("%{public}s: acm send setup response error", __func__); 1150094332d3Sopenharmony_ci } 1151094332d3Sopenharmony_ci} 1152094332d3Sopenharmony_ci 1153094332d3Sopenharmony_cistatic void AcmSuspend(struct UsbAcmDevice *acm) 1154094332d3Sopenharmony_ci{ 1155094332d3Sopenharmony_ci struct UsbSerial *port = acm->port; 1156094332d3Sopenharmony_ci 1157094332d3Sopenharmony_ci if (port == NULL) { 1158094332d3Sopenharmony_ci HDF_LOGE("%{public}s: port is null", __func__); 1159094332d3Sopenharmony_ci return; 1160094332d3Sopenharmony_ci } 1161094332d3Sopenharmony_ci 1162094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 1163094332d3Sopenharmony_ci port->suspended = true; 1164094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 1165094332d3Sopenharmony_ci} 1166094332d3Sopenharmony_ci 1167094332d3Sopenharmony_cistatic void AcmResume(struct UsbAcmDevice *acm) 1168094332d3Sopenharmony_ci{ 1169094332d3Sopenharmony_ci int32_t ret; 1170094332d3Sopenharmony_ci struct UsbSerial *port = acm->port; 1171094332d3Sopenharmony_ci if (port == NULL) { 1172094332d3Sopenharmony_ci HDF_LOGE("%{public}s: port is null", __func__); 1173094332d3Sopenharmony_ci return; 1174094332d3Sopenharmony_ci } 1175094332d3Sopenharmony_ci 1176094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 1177094332d3Sopenharmony_ci port->suspended = false; 1178094332d3Sopenharmony_ci if (!port->startDelayed) { 1179094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 1180094332d3Sopenharmony_ci return; 1181094332d3Sopenharmony_ci } 1182094332d3Sopenharmony_ci ret = UsbSerialStartIo(port); 1183094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 1184094332d3Sopenharmony_ci HDF_LOGE("%{public}s: UsbSerialStartIo failed", __func__); 1185094332d3Sopenharmony_ci } 1186094332d3Sopenharmony_ci if (acm->notify && acm->notify->Connect) { 1187094332d3Sopenharmony_ci acm->notify->Connect(acm); 1188094332d3Sopenharmony_ci } 1189094332d3Sopenharmony_ci port->startDelayed = false; 1190094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 1191094332d3Sopenharmony_ci} 1192094332d3Sopenharmony_ci 1193094332d3Sopenharmony_cistatic void UsbAcmEventCallback(struct UsbFnEvent *event) 1194094332d3Sopenharmony_ci{ 1195094332d3Sopenharmony_ci struct UsbAcmDevice *acm = NULL; 1196094332d3Sopenharmony_ci 1197094332d3Sopenharmony_ci if (event == NULL || event->context == NULL) { 1198094332d3Sopenharmony_ci HDF_LOGE("%{public}s: event is null", __func__); 1199094332d3Sopenharmony_ci return; 1200094332d3Sopenharmony_ci } 1201094332d3Sopenharmony_ci 1202094332d3Sopenharmony_ci acm = (struct UsbAcmDevice *)event->context; 1203094332d3Sopenharmony_ci switch (event->type) { 1204094332d3Sopenharmony_ci case USBFN_STATE_BIND: 1205094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive bind event", __func__); 1206094332d3Sopenharmony_ci break; 1207094332d3Sopenharmony_ci case USBFN_STATE_UNBIND: 1208094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive unbind event", __func__); 1209094332d3Sopenharmony_ci break; 1210094332d3Sopenharmony_ci case USBFN_STATE_ENABLE: 1211094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive enable event", __func__); 1212094332d3Sopenharmony_ci AcmEnable(acm); 1213094332d3Sopenharmony_ci break; 1214094332d3Sopenharmony_ci case USBFN_STATE_DISABLE: 1215094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive disable event", __func__); 1216094332d3Sopenharmony_ci AcmDisable(acm); 1217094332d3Sopenharmony_ci acm->enableEvtCnt = 0; 1218094332d3Sopenharmony_ci break; 1219094332d3Sopenharmony_ci case USBFN_STATE_SETUP: 1220094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive setup event", __func__); 1221094332d3Sopenharmony_ci if (event->setup != NULL) { 1222094332d3Sopenharmony_ci AcmSetup(acm, event->setup); 1223094332d3Sopenharmony_ci } 1224094332d3Sopenharmony_ci break; 1225094332d3Sopenharmony_ci case USBFN_STATE_SUSPEND: 1226094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive suspend event", __func__); 1227094332d3Sopenharmony_ci AcmSuspend(acm); 1228094332d3Sopenharmony_ci break; 1229094332d3Sopenharmony_ci case USBFN_STATE_RESUME: 1230094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive resume event", __func__); 1231094332d3Sopenharmony_ci AcmResume(acm); 1232094332d3Sopenharmony_ci break; 1233094332d3Sopenharmony_ci default: 1234094332d3Sopenharmony_ci break; 1235094332d3Sopenharmony_ci } 1236094332d3Sopenharmony_ci} 1237094332d3Sopenharmony_ci 1238094332d3Sopenharmony_cistatic int32_t AcmSendNotifyRequest( 1239094332d3Sopenharmony_ci struct UsbAcmDevice *acm, uint8_t type, uint16_t value, const void *data, uint32_t length) 1240094332d3Sopenharmony_ci{ 1241094332d3Sopenharmony_ci struct UsbFnRequest *req = acm->notifyReq; 1242094332d3Sopenharmony_ci struct UsbCdcNotification *notify = NULL; 1243094332d3Sopenharmony_ci int32_t ret; 1244094332d3Sopenharmony_ci 1245094332d3Sopenharmony_ci if (req == NULL || req->buf == NULL) { 1246094332d3Sopenharmony_ci HDF_LOGE("%{public}s: req is null", __func__); 1247094332d3Sopenharmony_ci return HDF_FAILURE; 1248094332d3Sopenharmony_ci } 1249094332d3Sopenharmony_ci 1250094332d3Sopenharmony_ci acm->notifyReq = NULL; 1251094332d3Sopenharmony_ci acm->pending = false; 1252094332d3Sopenharmony_ci req->length = sizeof(*notify) + length; 1253094332d3Sopenharmony_ci 1254094332d3Sopenharmony_ci notify = (struct UsbCdcNotification *)req->buf; 1255094332d3Sopenharmony_ci notify->bmRequestType = USB_DDK_DIR_IN | USB_DDK_TYPE_CLASS | USB_DDK_RECIP_INTERFACE; 1256094332d3Sopenharmony_ci notify->bNotificationType = type; 1257094332d3Sopenharmony_ci notify->wValue = CPU_TO_LE16(value); 1258094332d3Sopenharmony_ci notify->wIndex = CPU_TO_LE16(acm->ctrlIface.fn->info.index); 1259094332d3Sopenharmony_ci notify->wLength = CPU_TO_LE16(length); 1260094332d3Sopenharmony_ci ret = memcpy_s((void *)(notify + 1), length, data, length); 1261094332d3Sopenharmony_ci if (ret != EOK) { 1262094332d3Sopenharmony_ci HDF_LOGE("%{public}s: memcpy_s failed", __func__); 1263094332d3Sopenharmony_ci return HDF_FAILURE; 1264094332d3Sopenharmony_ci } 1265094332d3Sopenharmony_ci 1266094332d3Sopenharmony_ci ret = UsbFnSubmitRequestAsync(req); 1267094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 1268094332d3Sopenharmony_ci HDF_LOGE("%{public}s: send notify request failed", __func__); 1269094332d3Sopenharmony_ci acm->notifyReq = req; 1270094332d3Sopenharmony_ci } 1271094332d3Sopenharmony_ci 1272094332d3Sopenharmony_ci return ret; 1273094332d3Sopenharmony_ci} 1274094332d3Sopenharmony_ci 1275094332d3Sopenharmony_cistatic int32_t AcmNotifySerialState(struct UsbAcmDevice *acm) 1276094332d3Sopenharmony_ci{ 1277094332d3Sopenharmony_ci int32_t ret = 0; 1278094332d3Sopenharmony_ci uint16_t serialState; 1279094332d3Sopenharmony_ci 1280094332d3Sopenharmony_ci if (acm->notifyReq) { 1281094332d3Sopenharmony_ci HDF_LOGI("acm serial state %{public}04x", acm->serialState); 1282094332d3Sopenharmony_ci serialState = CPU_TO_LE16(acm->serialState); 1283094332d3Sopenharmony_ci ret = AcmSendNotifyRequest(acm, USB_DDK_CDC_NOTIFY_SERIAL_STATE, 0, &serialState, sizeof(acm->serialState)); 1284094332d3Sopenharmony_ci } else { 1285094332d3Sopenharmony_ci acm->pending = true; 1286094332d3Sopenharmony_ci } 1287094332d3Sopenharmony_ci 1288094332d3Sopenharmony_ci return ret; 1289094332d3Sopenharmony_ci} 1290094332d3Sopenharmony_ci 1291094332d3Sopenharmony_cistatic void AcmConnect(struct UsbAcmDevice *acm) 1292094332d3Sopenharmony_ci{ 1293094332d3Sopenharmony_ci if (acm == NULL) { 1294094332d3Sopenharmony_ci HDF_LOGE("%{public}s: acm is null", __func__); 1295094332d3Sopenharmony_ci return; 1296094332d3Sopenharmony_ci } 1297094332d3Sopenharmony_ci acm->serialState |= SERIAL_STATE_DSR | SERIAL_STATE_DCD; 1298094332d3Sopenharmony_ci AcmNotifySerialState(acm); 1299094332d3Sopenharmony_ci} 1300094332d3Sopenharmony_ci 1301094332d3Sopenharmony_cistatic void AcmDisconnect(struct UsbAcmDevice *acm) 1302094332d3Sopenharmony_ci{ 1303094332d3Sopenharmony_ci if (acm == NULL) { 1304094332d3Sopenharmony_ci HDF_LOGE("%{public}s: acm is null", __func__); 1305094332d3Sopenharmony_ci return; 1306094332d3Sopenharmony_ci } 1307094332d3Sopenharmony_ci acm->serialState &= ~(SERIAL_STATE_DSR | SERIAL_STATE_DCD); 1308094332d3Sopenharmony_ci AcmNotifySerialState(acm); 1309094332d3Sopenharmony_ci} 1310094332d3Sopenharmony_ci 1311094332d3Sopenharmony_cistatic int32_t AcmSendBreak(struct UsbAcmDevice *acm, int32_t duration) 1312094332d3Sopenharmony_ci{ 1313094332d3Sopenharmony_ci uint16_t state; 1314094332d3Sopenharmony_ci 1315094332d3Sopenharmony_ci if (acm == NULL) { 1316094332d3Sopenharmony_ci HDF_LOGE("%{public}s: acm is null", __func__); 1317094332d3Sopenharmony_ci return HDF_FAILURE; 1318094332d3Sopenharmony_ci } 1319094332d3Sopenharmony_ci 1320094332d3Sopenharmony_ci state = acm->serialState; 1321094332d3Sopenharmony_ci state &= ~SERIAL_STATE_BREAK; 1322094332d3Sopenharmony_ci if (duration != 0) { 1323094332d3Sopenharmony_ci state |= SERIAL_STATE_BREAK; 1324094332d3Sopenharmony_ci } 1325094332d3Sopenharmony_ci 1326094332d3Sopenharmony_ci acm->serialState = state; 1327094332d3Sopenharmony_ci return AcmNotifySerialState(acm); 1328094332d3Sopenharmony_ci} 1329094332d3Sopenharmony_ci 1330094332d3Sopenharmony_cistatic struct AcmNotifyMethod g_acmNotifyMethod = { 1331094332d3Sopenharmony_ci .Connect = AcmConnect, 1332094332d3Sopenharmony_ci .Disconnect = AcmDisconnect, 1333094332d3Sopenharmony_ci .SendBreak = AcmSendBreak, 1334094332d3Sopenharmony_ci}; 1335094332d3Sopenharmony_ci 1336094332d3Sopenharmony_cistatic int32_t AcmParseEachPipe(struct UsbAcmDevice *acm, struct UsbAcmInterface *iface) 1337094332d3Sopenharmony_ci{ 1338094332d3Sopenharmony_ci struct UsbFnInterface *fnIface = iface->fn; 1339094332d3Sopenharmony_ci uint32_t repetIdx = 0; 1340094332d3Sopenharmony_ci for (int32_t i = 0; i < fnIface->info.numPipes; i++) { 1341094332d3Sopenharmony_ci struct UsbFnPipeInfo pipeInfo; 1342094332d3Sopenharmony_ci (void)memset_s(&pipeInfo, sizeof(pipeInfo), 0, sizeof(pipeInfo)); 1343094332d3Sopenharmony_ci int32_t ret = UsbFnGetInterfacePipeInfo(fnIface, (uint8_t)i, &pipeInfo); 1344094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 1345094332d3Sopenharmony_ci HDF_LOGE("%{public}s: get pipe info error", __func__); 1346094332d3Sopenharmony_ci return ret; 1347094332d3Sopenharmony_ci } 1348094332d3Sopenharmony_ci switch (pipeInfo.type) { 1349094332d3Sopenharmony_ci case USB_PIPE_TYPE_INTERRUPT: 1350094332d3Sopenharmony_ci acm->notifyPipe.id = pipeInfo.id; 1351094332d3Sopenharmony_ci acm->notifyPipe.maxPacketSize = pipeInfo.maxPacketSize; 1352094332d3Sopenharmony_ci acm->ctrlIface = *iface; 1353094332d3Sopenharmony_ci break; 1354094332d3Sopenharmony_ci case USB_PIPE_TYPE_BULK: 1355094332d3Sopenharmony_ci if (pipeInfo.dir == USB_PIPE_DIRECTION_IN) { 1356094332d3Sopenharmony_ci acm->dataInPipe.id = pipeInfo.id; 1357094332d3Sopenharmony_ci acm->dataInPipe.maxPacketSize = pipeInfo.maxPacketSize; 1358094332d3Sopenharmony_ci acm->dataIface = *iface; 1359094332d3Sopenharmony_ci } else { 1360094332d3Sopenharmony_ci acm->dataOutPipe.id = pipeInfo.id; 1361094332d3Sopenharmony_ci acm->dataOutPipe.maxPacketSize = pipeInfo.maxPacketSize; 1362094332d3Sopenharmony_ci } 1363094332d3Sopenharmony_ci break; 1364094332d3Sopenharmony_ci default: 1365094332d3Sopenharmony_ci if (repetIdx < WAIT_UDC_MAX_LOOP) { 1366094332d3Sopenharmony_ci usleep(WAIT_UDC_TIME); 1367094332d3Sopenharmony_ci i--; 1368094332d3Sopenharmony_ci } 1369094332d3Sopenharmony_ci repetIdx++; 1370094332d3Sopenharmony_ci HDF_LOGE("%{public}s: pipe type %{public}d don't support", __func__, pipeInfo.type); 1371094332d3Sopenharmony_ci break; 1372094332d3Sopenharmony_ci } 1373094332d3Sopenharmony_ci } 1374094332d3Sopenharmony_ci 1375094332d3Sopenharmony_ci return HDF_SUCCESS; 1376094332d3Sopenharmony_ci} 1377094332d3Sopenharmony_ci 1378094332d3Sopenharmony_cistatic int32_t AcmParseAcmIface(struct UsbAcmDevice *acm, struct UsbFnInterface *fnIface) 1379094332d3Sopenharmony_ci{ 1380094332d3Sopenharmony_ci struct UsbAcmInterface iface; 1381094332d3Sopenharmony_ci UsbFnInterfaceHandle handle = UsbFnOpenInterface(fnIface); 1382094332d3Sopenharmony_ci if (handle == NULL) { 1383094332d3Sopenharmony_ci HDF_LOGE("%{public}s: open interface failed", __func__); 1384094332d3Sopenharmony_ci return HDF_FAILURE; 1385094332d3Sopenharmony_ci } 1386094332d3Sopenharmony_ci iface.fn = fnIface; 1387094332d3Sopenharmony_ci iface.handle = handle; 1388094332d3Sopenharmony_ci 1389094332d3Sopenharmony_ci int32_t ret = AcmParseEachPipe(acm, &iface); 1390094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 1391094332d3Sopenharmony_ci return HDF_FAILURE; 1392094332d3Sopenharmony_ci } 1393094332d3Sopenharmony_ci return HDF_SUCCESS; 1394094332d3Sopenharmony_ci} 1395094332d3Sopenharmony_ci 1396094332d3Sopenharmony_cistatic int32_t AcmParseEachIface(struct UsbAcmDevice *acm, struct UsbFnDevice *fnDev) 1397094332d3Sopenharmony_ci{ 1398094332d3Sopenharmony_ci struct UsbFnInterface *fnIface = NULL; 1399094332d3Sopenharmony_ci uint32_t i; 1400094332d3Sopenharmony_ci if (fnDev == NULL) { 1401094332d3Sopenharmony_ci return HDF_FAILURE; 1402094332d3Sopenharmony_ci } 1403094332d3Sopenharmony_ci for (i = 0; i < fnDev->numInterfaces; i++) { 1404094332d3Sopenharmony_ci fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i); 1405094332d3Sopenharmony_ci if (fnIface == NULL) { 1406094332d3Sopenharmony_ci HDF_LOGE("%{public}s: get interface failed", __func__); 1407094332d3Sopenharmony_ci return HDF_FAILURE; 1408094332d3Sopenharmony_ci } 1409094332d3Sopenharmony_ci 1410094332d3Sopenharmony_ci if (fnIface->info.subclass == USB_DDK_CDC_SUBCLASS_ACM) { 1411094332d3Sopenharmony_ci (void)AcmParseAcmIface(acm, fnIface); 1412094332d3Sopenharmony_ci fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i + 1); 1413094332d3Sopenharmony_ci if (fnIface == NULL) { 1414094332d3Sopenharmony_ci HDF_LOGE("%{public}s: get interface failed", __func__); 1415094332d3Sopenharmony_ci return HDF_FAILURE; 1416094332d3Sopenharmony_ci } 1417094332d3Sopenharmony_ci (void)AcmParseAcmIface(acm, fnIface); 1418094332d3Sopenharmony_ci return HDF_SUCCESS; 1419094332d3Sopenharmony_ci } 1420094332d3Sopenharmony_ci } 1421094332d3Sopenharmony_ci return HDF_FAILURE; 1422094332d3Sopenharmony_ci} 1423094332d3Sopenharmony_ci 1424094332d3Sopenharmony_cistatic int32_t AcmCreateFuncDevice(struct UsbAcmDevice *acm, struct DeviceResourceIface *iface) 1425094332d3Sopenharmony_ci{ 1426094332d3Sopenharmony_ci int32_t ret; 1427094332d3Sopenharmony_ci struct UsbFnDevice *fnDev = NULL; 1428094332d3Sopenharmony_ci 1429094332d3Sopenharmony_ci if (iface->GetString(acm->device->property, "udc_name", (const char **)&acm->udcName, UDC_NAME) != HDF_SUCCESS) { 1430094332d3Sopenharmony_ci HDF_LOGE("%{public}s: read udc_name failed, use default", __func__); 1431094332d3Sopenharmony_ci return HDF_FAILURE; 1432094332d3Sopenharmony_ci } 1433094332d3Sopenharmony_ci 1434094332d3Sopenharmony_ci fnDev = (struct UsbFnDevice *)UsbFnGetDevice(acm->udcName); 1435094332d3Sopenharmony_ci if (fnDev == NULL) { 1436094332d3Sopenharmony_ci HDF_LOGE("%{public}s: create usb function device failed", __func__); 1437094332d3Sopenharmony_ci return HDF_FAILURE; 1438094332d3Sopenharmony_ci } 1439094332d3Sopenharmony_ci 1440094332d3Sopenharmony_ci ret = AcmParseEachIface(acm, fnDev); 1441094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 1442094332d3Sopenharmony_ci HDF_LOGE("%{public}s: get pipes failed", __func__); 1443094332d3Sopenharmony_ci return HDF_FAILURE; 1444094332d3Sopenharmony_ci } 1445094332d3Sopenharmony_ci 1446094332d3Sopenharmony_ci acm->fnDev = fnDev; 1447094332d3Sopenharmony_ci return HDF_SUCCESS; 1448094332d3Sopenharmony_ci} 1449094332d3Sopenharmony_ci 1450094332d3Sopenharmony_cistatic int32_t AcmReleaseFuncDevice(struct UsbAcmDevice *acm) 1451094332d3Sopenharmony_ci{ 1452094332d3Sopenharmony_ci int32_t ret = HDF_SUCCESS; 1453094332d3Sopenharmony_ci if (acm->fnDev == NULL) { 1454094332d3Sopenharmony_ci HDF_LOGE("%{public}s: fnDev is null", __func__); 1455094332d3Sopenharmony_ci return HDF_FAILURE; 1456094332d3Sopenharmony_ci } 1457094332d3Sopenharmony_ci AcmFreeCtrlRequests(acm); 1458094332d3Sopenharmony_ci AcmFreeNotifyRequest(acm); 1459094332d3Sopenharmony_ci (void)UsbFnCloseInterface(acm->ctrlIface.handle); 1460094332d3Sopenharmony_ci (void)UsbFnCloseInterface(acm->dataIface.handle); 1461094332d3Sopenharmony_ci (void)UsbFnStopRecvInterfaceEvent(acm->ctrlIface.fn); 1462094332d3Sopenharmony_ci return ret; 1463094332d3Sopenharmony_ci} 1464094332d3Sopenharmony_ci 1465094332d3Sopenharmony_cistatic int32_t UsbSerialAlloc(struct UsbAcmDevice *acm) 1466094332d3Sopenharmony_ci{ 1467094332d3Sopenharmony_ci struct UsbSerial *port = NULL; 1468094332d3Sopenharmony_ci 1469094332d3Sopenharmony_ci port = (struct UsbSerial *)OsalMemCalloc(sizeof(*port)); 1470094332d3Sopenharmony_ci if (port == NULL) { 1471094332d3Sopenharmony_ci HDF_LOGE("%{public}s: Alloc usb serial port failed", __func__); 1472094332d3Sopenharmony_ci return HDF_FAILURE; 1473094332d3Sopenharmony_ci } 1474094332d3Sopenharmony_ci 1475094332d3Sopenharmony_ci if (OsalMutexInit(&port->lock) != HDF_SUCCESS) { 1476094332d3Sopenharmony_ci HDF_LOGE("%{public}s: init lock fail!", __func__); 1477094332d3Sopenharmony_ci OsalMemFree(port); 1478094332d3Sopenharmony_ci return HDF_FAILURE; 1479094332d3Sopenharmony_ci } 1480094332d3Sopenharmony_ci 1481094332d3Sopenharmony_ci DListHeadInit(&port->readPool); 1482094332d3Sopenharmony_ci DListHeadInit(&port->readQueue); 1483094332d3Sopenharmony_ci DListHeadInit(&port->writePool); 1484094332d3Sopenharmony_ci 1485094332d3Sopenharmony_ci port->lineCoding.dwDTERate = CPU_TO_LE32(PORT_RATE); 1486094332d3Sopenharmony_ci port->lineCoding.bCharFormat = USB_CDC_1_STOP_BITS; 1487094332d3Sopenharmony_ci port->lineCoding.bParityType = USB_CDC_NO_PARITY; 1488094332d3Sopenharmony_ci port->lineCoding.bDataBits = DATA_BIT; 1489094332d3Sopenharmony_ci 1490094332d3Sopenharmony_ci acm->port = port; 1491094332d3Sopenharmony_ci return HDF_SUCCESS; 1492094332d3Sopenharmony_ci} 1493094332d3Sopenharmony_ci 1494094332d3Sopenharmony_cistatic void UsbSerialFree(struct UsbAcmDevice *acm) 1495094332d3Sopenharmony_ci{ 1496094332d3Sopenharmony_ci struct UsbSerial *port = acm->port; 1497094332d3Sopenharmony_ci 1498094332d3Sopenharmony_ci if (port == NULL) { 1499094332d3Sopenharmony_ci HDF_LOGE("%{public}s: port is null", __func__); 1500094332d3Sopenharmony_ci return; 1501094332d3Sopenharmony_ci } 1502094332d3Sopenharmony_ci OsalMemFree(port); 1503094332d3Sopenharmony_ci acm->port = NULL; 1504094332d3Sopenharmony_ci} 1505094332d3Sopenharmony_ci 1506094332d3Sopenharmony_ci/* HdfDriverEntry implementations */ 1507094332d3Sopenharmony_cistatic int32_t AcmDriverBind(struct HdfDeviceObject *device) 1508094332d3Sopenharmony_ci{ 1509094332d3Sopenharmony_ci struct UsbAcmDevice *acm = NULL; 1510094332d3Sopenharmony_ci 1511094332d3Sopenharmony_ci if (device == NULL) { 1512094332d3Sopenharmony_ci HDF_LOGE("%{public}s: device is null", __func__); 1513094332d3Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 1514094332d3Sopenharmony_ci } 1515094332d3Sopenharmony_ci 1516094332d3Sopenharmony_ci acm = (struct UsbAcmDevice *)OsalMemCalloc(sizeof(*acm)); 1517094332d3Sopenharmony_ci if (acm == NULL) { 1518094332d3Sopenharmony_ci HDF_LOGE("%{public}s: Alloc usb acm device failed", __func__); 1519094332d3Sopenharmony_ci return HDF_FAILURE; 1520094332d3Sopenharmony_ci } 1521094332d3Sopenharmony_ci 1522094332d3Sopenharmony_ci if (OsalMutexInit(&acm->lock) != HDF_SUCCESS) { 1523094332d3Sopenharmony_ci HDF_LOGE("%{public}s: init lock fail!", __func__); 1524094332d3Sopenharmony_ci OsalMemFree(acm); 1525094332d3Sopenharmony_ci return HDF_FAILURE; 1526094332d3Sopenharmony_ci } 1527094332d3Sopenharmony_ci 1528094332d3Sopenharmony_ci if (HdfDeviceObjectSetInterfaceDesc(device, "hdf.usb.usbfn") != HDF_SUCCESS) { 1529094332d3Sopenharmony_ci HDF_LOGE(" Set Desc fail!"); 1530094332d3Sopenharmony_ci OsalMemFree(acm); 1531094332d3Sopenharmony_ci return HDF_FAILURE; 1532094332d3Sopenharmony_ci } 1533094332d3Sopenharmony_ci 1534094332d3Sopenharmony_ci acm->device = device; 1535094332d3Sopenharmony_ci device->service = &(acm->service); 1536094332d3Sopenharmony_ci acm->device->service->Dispatch = AcmDeviceDispatch; 1537094332d3Sopenharmony_ci acm->notify = NULL; 1538094332d3Sopenharmony_ci acm->initFlag = false; 1539094332d3Sopenharmony_ci return HDF_SUCCESS; 1540094332d3Sopenharmony_ci} 1541094332d3Sopenharmony_ci 1542094332d3Sopenharmony_cistatic int32_t UsbSerialInit(struct UsbAcmDevice *acm) 1543094332d3Sopenharmony_ci{ 1544094332d3Sopenharmony_ci struct DeviceResourceIface *iface = NULL; 1545094332d3Sopenharmony_ci int32_t ret; 1546094332d3Sopenharmony_ci 1547094332d3Sopenharmony_ci if (acm == NULL || acm->initFlag) { 1548094332d3Sopenharmony_ci HDF_LOGE("%{public}s: acm is null", __func__); 1549094332d3Sopenharmony_ci return HDF_FAILURE; 1550094332d3Sopenharmony_ci } 1551094332d3Sopenharmony_ci iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); 1552094332d3Sopenharmony_ci if (iface == NULL || iface->GetUint32 == NULL) { 1553094332d3Sopenharmony_ci HDF_LOGE("%{public}s: face is invalid", __func__); 1554094332d3Sopenharmony_ci return HDF_FAILURE; 1555094332d3Sopenharmony_ci } 1556094332d3Sopenharmony_ci 1557094332d3Sopenharmony_ci ret = AcmCreateFuncDevice(acm, iface); 1558094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 1559094332d3Sopenharmony_ci HDF_LOGE("%{public}s: AcmCreateFuncDevice failed", __func__); 1560094332d3Sopenharmony_ci return HDF_FAILURE; 1561094332d3Sopenharmony_ci } 1562094332d3Sopenharmony_ci 1563094332d3Sopenharmony_ci ret = UsbSerialAlloc(acm); 1564094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 1565094332d3Sopenharmony_ci HDF_LOGE("%{public}s: UsbSerialAlloc failed", __func__); 1566094332d3Sopenharmony_ci goto ERR; 1567094332d3Sopenharmony_ci } 1568094332d3Sopenharmony_ci 1569094332d3Sopenharmony_ci ret = AcmAllocCtrlRequests(acm, CTRL_REQUEST_NUM); 1570094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 1571094332d3Sopenharmony_ci HDF_LOGE("%{public}s: AcmAllocCtrlRequests failed", __func__); 1572094332d3Sopenharmony_ci goto ERR; 1573094332d3Sopenharmony_ci } 1574094332d3Sopenharmony_ci 1575094332d3Sopenharmony_ci ret = AcmAllocNotifyRequest(acm); 1576094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 1577094332d3Sopenharmony_ci HDF_LOGE("%{public}s: AcmAllocNotifyRequest failed", __func__); 1578094332d3Sopenharmony_ci goto ERR; 1579094332d3Sopenharmony_ci } 1580094332d3Sopenharmony_ci 1581094332d3Sopenharmony_ci ret = UsbFnStartRecvInterfaceEvent(acm->ctrlIface.fn, RECEIVE_ALL_EVENTS, UsbAcmEventCallback, acm); 1582094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 1583094332d3Sopenharmony_ci HDF_LOGE("%{public}s: register event callback failed", __func__); 1584094332d3Sopenharmony_ci goto ERR; 1585094332d3Sopenharmony_ci } 1586094332d3Sopenharmony_ci 1587094332d3Sopenharmony_ci acm->notify = &g_acmNotifyMethod; 1588094332d3Sopenharmony_ci acm->initFlag = true; 1589094332d3Sopenharmony_ci return HDF_SUCCESS; 1590094332d3Sopenharmony_ci 1591094332d3Sopenharmony_ciERR: 1592094332d3Sopenharmony_ci UsbSerialFree(acm); 1593094332d3Sopenharmony_ci (void)AcmReleaseFuncDevice(acm); 1594094332d3Sopenharmony_ci return ret; 1595094332d3Sopenharmony_ci} 1596094332d3Sopenharmony_ci 1597094332d3Sopenharmony_cistatic int32_t UsbSerialRelease(struct UsbAcmDevice *acm) 1598094332d3Sopenharmony_ci{ 1599094332d3Sopenharmony_ci if (acm == NULL || acm->initFlag == false) { 1600094332d3Sopenharmony_ci HDF_LOGE("%{public}s: acm is null", __func__); 1601094332d3Sopenharmony_ci return HDF_FAILURE; 1602094332d3Sopenharmony_ci } 1603094332d3Sopenharmony_ci OsalMutexLock(&acm->lock); 1604094332d3Sopenharmony_ci (void)AcmReleaseFuncDevice(acm); 1605094332d3Sopenharmony_ci UsbSerialFree(acm); 1606094332d3Sopenharmony_ci acm->initFlag = false; 1607094332d3Sopenharmony_ci OsalMutexUnlock(&acm->lock); 1608094332d3Sopenharmony_ci return 0; 1609094332d3Sopenharmony_ci} 1610094332d3Sopenharmony_ci 1611094332d3Sopenharmony_cistatic int32_t AcmDriverInit(struct HdfDeviceObject *device) 1612094332d3Sopenharmony_ci{ 1613094332d3Sopenharmony_ci (void)device; 1614094332d3Sopenharmony_ci HDF_LOGI("%{public}s: do nothing", __func__); 1615094332d3Sopenharmony_ci return 0; 1616094332d3Sopenharmony_ci} 1617094332d3Sopenharmony_ci 1618094332d3Sopenharmony_cistatic void AcmDriverRelease(struct HdfDeviceObject *device) 1619094332d3Sopenharmony_ci{ 1620094332d3Sopenharmony_ci struct UsbAcmDevice *acm = NULL; 1621094332d3Sopenharmony_ci if (device == NULL) { 1622094332d3Sopenharmony_ci HDF_LOGE("%{public}s: device is NULL", __func__); 1623094332d3Sopenharmony_ci return; 1624094332d3Sopenharmony_ci } 1625094332d3Sopenharmony_ci 1626094332d3Sopenharmony_ci acm = (struct UsbAcmDevice *)device->service; 1627094332d3Sopenharmony_ci if (acm == NULL) { 1628094332d3Sopenharmony_ci HDF_LOGE("%{public}s: acm is null", __func__); 1629094332d3Sopenharmony_ci return; 1630094332d3Sopenharmony_ci } 1631094332d3Sopenharmony_ci (void)OsalMutexDestroy(&acm->lock); 1632094332d3Sopenharmony_ci AcmDeviceDestroy(acm); 1633094332d3Sopenharmony_ci device->service = NULL; 1634094332d3Sopenharmony_ci} 1635094332d3Sopenharmony_ci 1636094332d3Sopenharmony_cistruct HdfDriverEntry g_acmDriverEntry = { 1637094332d3Sopenharmony_ci .moduleVersion = 1, 1638094332d3Sopenharmony_ci .moduleName = "usbfn_cdcacm", 1639094332d3Sopenharmony_ci .Bind = AcmDriverBind, 1640094332d3Sopenharmony_ci .Init = AcmDriverInit, 1641094332d3Sopenharmony_ci .Release = AcmDriverRelease, 1642094332d3Sopenharmony_ci}; 1643094332d3Sopenharmony_ci 1644094332d3Sopenharmony_ciHDF_INIT(g_acmDriverEntry); 1645