1094332d3Sopenharmony_ci/* 2094332d3Sopenharmony_ci * Copyright (c) 2021 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 "cdcecm.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_sem.h" 24094332d3Sopenharmony_ci#include "osal_time.h" 25094332d3Sopenharmony_ci#include "securec.h" 26094332d3Sopenharmony_ci#include "usbfn_device.h" 27094332d3Sopenharmony_ci#include "usbfn_interface.h" 28094332d3Sopenharmony_ci#include "usbfn_request.h" 29094332d3Sopenharmony_ci 30094332d3Sopenharmony_ci#define HDF_LOG_TAG cdc_ecm 31094332d3Sopenharmony_ci#define UDC_NAME "invalid_udc_name" 32094332d3Sopenharmony_ci 33094332d3Sopenharmony_ci#define QUEUE_SIZE 8 34094332d3Sopenharmony_ci#define WRITE_BUF_SIZE 8192 35094332d3Sopenharmony_ci#define READ_BUF_SIZE 8192 36094332d3Sopenharmony_ci#define ECM_STATUS_BYTECOUNT 16 37094332d3Sopenharmony_ci#define ECM_BIT 9728000 38094332d3Sopenharmony_ci#define USBCDC_LEN 2 39094332d3Sopenharmony_ci#define RECEIVE_ALL_EVENTS 0xff 40094332d3Sopenharmony_cistatic const int32_t WAIT_UDC_MAX_LOOP = 3; 41094332d3Sopenharmony_cistatic const uint32_t WAIT_UDC_TIME = 100000; 42094332d3Sopenharmony_ci 43094332d3Sopenharmony_cistatic int32_t EcmInit(struct HdfDeviceObject *device); 44094332d3Sopenharmony_cistatic int32_t EcmRelease(struct HdfDeviceObject *device); 45094332d3Sopenharmony_ci 46094332d3Sopenharmony_cistatic inline unsigned EcmBitrate(void) 47094332d3Sopenharmony_ci{ 48094332d3Sopenharmony_ci return ECM_BIT; 49094332d3Sopenharmony_ci} 50094332d3Sopenharmony_ci 51094332d3Sopenharmony_ci/* Usb Serial Related Functions */ 52094332d3Sopenharmony_cistatic int32_t UsbEcmStartTx(struct UsbEcm *port) 53094332d3Sopenharmony_ci{ 54094332d3Sopenharmony_ci struct DListHead *pool = &port->writePool; 55094332d3Sopenharmony_ci if (port->ecm == NULL) { 56094332d3Sopenharmony_ci return HDF_SUCCESS; 57094332d3Sopenharmony_ci } 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 OsalMutexLock(&port->lockWriteFifo); 67094332d3Sopenharmony_ci len = DataFifoRead(&port->writeFifo, req->buf, port->ecm->dataInPipe.maxPacketSize); 68094332d3Sopenharmony_ci OsalMutexUnlock(&port->lockWriteFifo); 69094332d3Sopenharmony_ci if (len == 0) { 70094332d3Sopenharmony_ci break; 71094332d3Sopenharmony_ci } 72094332d3Sopenharmony_ci req->length = len; 73094332d3Sopenharmony_ci DListRemove(&req->list); 74094332d3Sopenharmony_ci port->writeBusy = true; 75094332d3Sopenharmony_ci int32_t ret = UsbFnSubmitRequestAsync(req); 76094332d3Sopenharmony_ci port->writeBusy = false; 77094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 78094332d3Sopenharmony_ci HDF_LOGE("%{public}s: send request error %{public}d", __func__, ret); 79094332d3Sopenharmony_ci DListInsertTail(&req->list, pool); 80094332d3Sopenharmony_ci break; 81094332d3Sopenharmony_ci } 82094332d3Sopenharmony_ci port->writeStarted++; 83094332d3Sopenharmony_ci /* if ecm is disconnect, abort immediately */ 84094332d3Sopenharmony_ci if (port->ecm == NULL) { 85094332d3Sopenharmony_ci break; 86094332d3Sopenharmony_ci } 87094332d3Sopenharmony_ci } 88094332d3Sopenharmony_ci return HDF_SUCCESS; 89094332d3Sopenharmony_ci} 90094332d3Sopenharmony_ci 91094332d3Sopenharmony_cistatic uint32_t UsbEcmStartRx(struct UsbEcm *port) 92094332d3Sopenharmony_ci{ 93094332d3Sopenharmony_ci struct DListHead *pool = &port->readPool; 94094332d3Sopenharmony_ci struct UsbEcmPipe *out = &port->ecm->dataOutPipe; 95094332d3Sopenharmony_ci 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 ecm is disconnect, abort immediately */ 115094332d3Sopenharmony_ci if (port->ecm == NULL) { 116094332d3Sopenharmony_ci break; 117094332d3Sopenharmony_ci } 118094332d3Sopenharmony_ci } 119094332d3Sopenharmony_ci return port->readStarted; 120094332d3Sopenharmony_ci} 121094332d3Sopenharmony_ci 122094332d3Sopenharmony_cistatic void UsbEcmRxPush(struct UsbEcm *port) 123094332d3Sopenharmony_ci{ 124094332d3Sopenharmony_ci struct DListHead *queue = &port->readQueue; 125094332d3Sopenharmony_ci bool disconnect = false; 126094332d3Sopenharmony_ci 127094332d3Sopenharmony_ci while (!DListIsEmpty(queue)) { 128094332d3Sopenharmony_ci struct UsbFnRequest *req; 129094332d3Sopenharmony_ci 130094332d3Sopenharmony_ci req = DLIST_FIRST_ENTRY(queue, struct UsbFnRequest, list); 131094332d3Sopenharmony_ci switch (req->status) { 132094332d3Sopenharmony_ci case USB_REQUEST_NO_DEVICE: 133094332d3Sopenharmony_ci disconnect = true; 134094332d3Sopenharmony_ci HDF_LOGV("%{public}s: the device is disconnected", __func__); 135094332d3Sopenharmony_ci break; 136094332d3Sopenharmony_ci case USB_REQUEST_COMPLETED: 137094332d3Sopenharmony_ci break; 138094332d3Sopenharmony_ci default: 139094332d3Sopenharmony_ci HDF_LOGV("%{public}s: unexpected status %{public}d", __func__, req->status); 140094332d3Sopenharmony_ci break; 141094332d3Sopenharmony_ci } 142094332d3Sopenharmony_ci if (req->actual && req->status == 0) { 143094332d3Sopenharmony_ci uint32_t size = req->actual; 144094332d3Sopenharmony_ci uint8_t *data = req->buf; 145094332d3Sopenharmony_ci OsalMutexLock(&port->lockReadFifo); 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 OsalMutexUnlock(&port->lockReadFifo); 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->ecm) { 161094332d3Sopenharmony_ci UsbEcmStartRx(port); 162094332d3Sopenharmony_ci } 163094332d3Sopenharmony_ci} 164094332d3Sopenharmony_ci 165094332d3Sopenharmony_cistatic void UsbEcmFreeRequests(const struct DListHead *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)UsbFnFreeRequest(req); 172094332d3Sopenharmony_ci if (allocated) { 173094332d3Sopenharmony_ci (*allocated)--; 174094332d3Sopenharmony_ci } 175094332d3Sopenharmony_ci } 176094332d3Sopenharmony_ci} 177094332d3Sopenharmony_ci 178094332d3Sopenharmony_cistatic void UsbEcmReadComplete(uint8_t pipe, struct UsbFnRequest *req) 179094332d3Sopenharmony_ci{ 180094332d3Sopenharmony_ci struct UsbEcm *port = (struct UsbEcm *)req->context; 181094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 182094332d3Sopenharmony_ci DListInsertTail(&req->list, &port->readQueue); 183094332d3Sopenharmony_ci UsbEcmRxPush(port); 184094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 185094332d3Sopenharmony_ci} 186094332d3Sopenharmony_ci 187094332d3Sopenharmony_cistatic void UsbEcmWriteComplete(uint8_t pipe, struct UsbFnRequest *req) 188094332d3Sopenharmony_ci{ 189094332d3Sopenharmony_ci struct UsbEcm *port = (struct UsbEcm *)req->context; 190094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 191094332d3Sopenharmony_ci DListInsertTail(&req->list, &port->writePool); 192094332d3Sopenharmony_ci port->writeStarted--; 193094332d3Sopenharmony_ci 194094332d3Sopenharmony_ci switch (req->status) { 195094332d3Sopenharmony_ci case USB_REQUEST_COMPLETED: 196094332d3Sopenharmony_ci UsbEcmStartTx(port); 197094332d3Sopenharmony_ci break; 198094332d3Sopenharmony_ci case USB_REQUEST_NO_DEVICE: 199094332d3Sopenharmony_ci HDF_LOGV("%{public}s: ecm device was disconnected", __func__); 200094332d3Sopenharmony_ci break; 201094332d3Sopenharmony_ci default: 202094332d3Sopenharmony_ci HDF_LOGV("%{public}s: unexpected status %{public}d", __func__, req->status); 203094332d3Sopenharmony_ci break; 204094332d3Sopenharmony_ci } 205094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 206094332d3Sopenharmony_ci} 207094332d3Sopenharmony_ci 208094332d3Sopenharmony_cistatic int32_t UsbEcmAllocReadRequests(struct UsbEcm *port, int32_t num) 209094332d3Sopenharmony_ci{ 210094332d3Sopenharmony_ci struct UsbEcmDevice *ecm = port->ecm; 211094332d3Sopenharmony_ci struct DListHead *head = &port->readPool; 212094332d3Sopenharmony_ci struct UsbFnRequest *req = NULL; 213094332d3Sopenharmony_ci int32_t i; 214094332d3Sopenharmony_ci 215094332d3Sopenharmony_ci for (i = 0; i < num; i++) { 216094332d3Sopenharmony_ci req = UsbFnAllocRequest(ecm->dataIface.handle, ecm->dataOutPipe.id, ecm->dataOutPipe.maxPacketSize); 217094332d3Sopenharmony_ci if (!req) { 218094332d3Sopenharmony_ci return DListIsEmpty(head) ? HDF_FAILURE : HDF_SUCCESS; 219094332d3Sopenharmony_ci } 220094332d3Sopenharmony_ci 221094332d3Sopenharmony_ci req->complete = UsbEcmReadComplete; 222094332d3Sopenharmony_ci req->context = port; 223094332d3Sopenharmony_ci DListInsertTail(&req->list, head); 224094332d3Sopenharmony_ci port->readAllocated++; 225094332d3Sopenharmony_ci } 226094332d3Sopenharmony_ci return HDF_SUCCESS; 227094332d3Sopenharmony_ci} 228094332d3Sopenharmony_ci 229094332d3Sopenharmony_cistatic int32_t UsbEcmAllocWriteRequests(struct UsbEcm *port, int32_t num) 230094332d3Sopenharmony_ci{ 231094332d3Sopenharmony_ci struct UsbEcmDevice *ecm = port->ecm; 232094332d3Sopenharmony_ci struct DListHead *head = &port->writePool; 233094332d3Sopenharmony_ci struct UsbFnRequest *req = NULL; 234094332d3Sopenharmony_ci int32_t i; 235094332d3Sopenharmony_ci 236094332d3Sopenharmony_ci for (i = 0; i < num; i++) { 237094332d3Sopenharmony_ci req = UsbFnAllocRequest(ecm->dataIface.handle, ecm->dataInPipe.id, ecm->dataInPipe.maxPacketSize); 238094332d3Sopenharmony_ci if (!req) { 239094332d3Sopenharmony_ci return DListIsEmpty(head) ? HDF_FAILURE : HDF_SUCCESS; 240094332d3Sopenharmony_ci } 241094332d3Sopenharmony_ci 242094332d3Sopenharmony_ci req->complete = UsbEcmWriteComplete; 243094332d3Sopenharmony_ci req->context = port; 244094332d3Sopenharmony_ci DListInsertTail(&req->list, head); 245094332d3Sopenharmony_ci port->writeAllocated++; 246094332d3Sopenharmony_ci } 247094332d3Sopenharmony_ci return HDF_SUCCESS; 248094332d3Sopenharmony_ci} 249094332d3Sopenharmony_ci 250094332d3Sopenharmony_cistatic int32_t UsbEcmStartIo(struct UsbEcm *port) 251094332d3Sopenharmony_ci{ 252094332d3Sopenharmony_ci struct DListHead *head = &port->readPool; 253094332d3Sopenharmony_ci int32_t ret = HDF_SUCCESS; 254094332d3Sopenharmony_ci uint32_t started; 255094332d3Sopenharmony_ci 256094332d3Sopenharmony_ci /* allocate requests for read/write */ 257094332d3Sopenharmony_ci if (port->readAllocated == 0) { 258094332d3Sopenharmony_ci ret = UsbEcmAllocReadRequests(port, QUEUE_SIZE); 259094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 260094332d3Sopenharmony_ci return ret; 261094332d3Sopenharmony_ci } 262094332d3Sopenharmony_ci } 263094332d3Sopenharmony_ci if (port->writeAllocated == 0) { 264094332d3Sopenharmony_ci ret = UsbEcmAllocWriteRequests(port, QUEUE_SIZE); 265094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 266094332d3Sopenharmony_ci UsbEcmFreeRequests(head, &port->readAllocated); 267094332d3Sopenharmony_ci return ret; 268094332d3Sopenharmony_ci } 269094332d3Sopenharmony_ci } 270094332d3Sopenharmony_ci 271094332d3Sopenharmony_ci started = UsbEcmStartRx(port); 272094332d3Sopenharmony_ci if (started) { 273094332d3Sopenharmony_ci UsbEcmStartTx(port); 274094332d3Sopenharmony_ci } else { 275094332d3Sopenharmony_ci UsbEcmFreeRequests(head, &port->readAllocated); 276094332d3Sopenharmony_ci UsbEcmFreeRequests(&port->writePool, &port->writeAllocated); 277094332d3Sopenharmony_ci ret = HDF_ERR_IO; 278094332d3Sopenharmony_ci } 279094332d3Sopenharmony_ci 280094332d3Sopenharmony_ci return ret; 281094332d3Sopenharmony_ci} 282094332d3Sopenharmony_ci 283094332d3Sopenharmony_ci 284094332d3Sopenharmony_cistatic int32_t UsbEcmAllocFifo(struct DataFifo *fifo, uint32_t size) 285094332d3Sopenharmony_ci{ 286094332d3Sopenharmony_ci if (!DataFifoIsInitialized(fifo)) { 287094332d3Sopenharmony_ci void *data = OsalMemAlloc(size); 288094332d3Sopenharmony_ci if (data == NULL) { 289094332d3Sopenharmony_ci HDF_LOGE("%{public}s: allocate fifo data buffer failed", __func__); 290094332d3Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 291094332d3Sopenharmony_ci } 292094332d3Sopenharmony_ci DataFifoInit(fifo, size, data); 293094332d3Sopenharmony_ci } 294094332d3Sopenharmony_ci return HDF_SUCCESS; 295094332d3Sopenharmony_ci} 296094332d3Sopenharmony_ci 297094332d3Sopenharmony_cistatic int32_t UsbEcmOpen(struct UsbEcm *port) 298094332d3Sopenharmony_ci{ 299094332d3Sopenharmony_ci int32_t ret; 300094332d3Sopenharmony_ci 301094332d3Sopenharmony_ci if (port == NULL) { 302094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 303094332d3Sopenharmony_ci } 304094332d3Sopenharmony_ci 305094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 306094332d3Sopenharmony_ci ret = UsbEcmAllocFifo(&port->writeFifo, WRITE_BUF_SIZE); 307094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 308094332d3Sopenharmony_ci HDF_LOGE("%{public}s: UsbEcmAllocFifo failed", __func__); 309094332d3Sopenharmony_ci goto OUT; 310094332d3Sopenharmony_ci } 311094332d3Sopenharmony_ci ret = UsbEcmAllocFifo(&port->readFifo, READ_BUF_SIZE); 312094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 313094332d3Sopenharmony_ci HDF_LOGE("%{public}s: UsbEcmAllocFifo failed", __func__); 314094332d3Sopenharmony_ci goto OUT; 315094332d3Sopenharmony_ci } 316094332d3Sopenharmony_ci DataFifoReset(&port->writeFifo); 317094332d3Sopenharmony_ci DataFifoReset(&port->readFifo); 318094332d3Sopenharmony_ci 319094332d3Sopenharmony_ci if (port->refCount++) { 320094332d3Sopenharmony_ci HDF_LOGE("%{public}s: refCount failed", __func__); 321094332d3Sopenharmony_ci goto OUT; 322094332d3Sopenharmony_ci } 323094332d3Sopenharmony_ci 324094332d3Sopenharmony_ci /* the ecm is enabled, start the io stream */ 325094332d3Sopenharmony_ci if (port->ecm) { 326094332d3Sopenharmony_ci HDF_LOGD("%{public}s: start usb io", __func__); 327094332d3Sopenharmony_ci ret = UsbEcmStartIo(port); 328094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 329094332d3Sopenharmony_ci goto OUT; 330094332d3Sopenharmony_ci } 331094332d3Sopenharmony_ci } 332094332d3Sopenharmony_ci 333094332d3Sopenharmony_ciOUT: 334094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 335094332d3Sopenharmony_ci return HDF_SUCCESS; 336094332d3Sopenharmony_ci} 337094332d3Sopenharmony_ci 338094332d3Sopenharmony_cistatic int32_t UsbEcmClose(struct UsbEcm *port) 339094332d3Sopenharmony_ci{ 340094332d3Sopenharmony_ci if (port == NULL) { 341094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 342094332d3Sopenharmony_ci } 343094332d3Sopenharmony_ci 344094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 345094332d3Sopenharmony_ci if (port->refCount != 1) { 346094332d3Sopenharmony_ci --port->refCount; 347094332d3Sopenharmony_ci goto OUT; 348094332d3Sopenharmony_ci } 349094332d3Sopenharmony_ci 350094332d3Sopenharmony_ci HDF_LOGD("%{public}s: close usb serial", __func__); 351094332d3Sopenharmony_ci 352094332d3Sopenharmony_ci DataFifoReset(&port->writeFifo); 353094332d3Sopenharmony_ci DataFifoReset(&port->readFifo); 354094332d3Sopenharmony_ci port->refCount = 0; 355094332d3Sopenharmony_ci 356094332d3Sopenharmony_ciOUT: 357094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 358094332d3Sopenharmony_ci return HDF_SUCCESS; 359094332d3Sopenharmony_ci} 360094332d3Sopenharmony_ci 361094332d3Sopenharmony_cistatic int32_t UsbEcmRead(struct UsbEcm *port, struct HdfSBuf *reply) 362094332d3Sopenharmony_ci{ 363094332d3Sopenharmony_ci uint32_t len; 364094332d3Sopenharmony_ci int32_t ret = HDF_SUCCESS; 365094332d3Sopenharmony_ci uint8_t *buf = NULL; 366094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 367094332d3Sopenharmony_ci OsalMutexLock(&port->lockReadFifo); 368094332d3Sopenharmony_ci if (DataFifoIsEmpty(&port->readFifo)) { 369094332d3Sopenharmony_ci OsalMutexUnlock(&port->lockReadFifo); 370094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 371094332d3Sopenharmony_ci return 0; 372094332d3Sopenharmony_ci } 373094332d3Sopenharmony_ci 374094332d3Sopenharmony_ci buf = (uint8_t *)OsalMemCalloc(DataFifoLen(&port->readFifo) + sizeof(uint32_t)); 375094332d3Sopenharmony_ci if (buf == NULL) { 376094332d3Sopenharmony_ci HDF_LOGE("%{public}s: OsalMemCalloc error", __func__); 377094332d3Sopenharmony_ci OsalMutexUnlock(&port->lockReadFifo); 378094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 379094332d3Sopenharmony_ci return HDF_ERR_MALLOC_FAIL; 380094332d3Sopenharmony_ci } 381094332d3Sopenharmony_ci 382094332d3Sopenharmony_ci len = DataFifoRead(&port->readFifo, buf, DataFifoLen(&port->readFifo)); 383094332d3Sopenharmony_ci if (len == 0) { 384094332d3Sopenharmony_ci HDF_LOGE("%{public}s: no data", __func__); 385094332d3Sopenharmony_ci ret = HDF_ERR_IO; 386094332d3Sopenharmony_ci OsalMutexUnlock(&port->lockReadFifo); 387094332d3Sopenharmony_ci goto OUT; 388094332d3Sopenharmony_ci } 389094332d3Sopenharmony_ci OsalMutexUnlock(&port->lockReadFifo); 390094332d3Sopenharmony_ci 391094332d3Sopenharmony_ci bool bufok = HdfSbufWriteBuffer(reply, (const void *)buf, len); 392094332d3Sopenharmony_ci if (!bufok) { 393094332d3Sopenharmony_ci HDF_LOGE("UsbEcmRead HdfSbufWriteBuffer error"); 394094332d3Sopenharmony_ci ret = HDF_ERR_IO; 395094332d3Sopenharmony_ci goto OUT; 396094332d3Sopenharmony_ci } 397094332d3Sopenharmony_ci 398094332d3Sopenharmony_ciOUT: 399094332d3Sopenharmony_ci if (port->ecm) { 400094332d3Sopenharmony_ci UsbEcmStartRx(port); 401094332d3Sopenharmony_ci } 402094332d3Sopenharmony_ci OsalMemFree(buf); 403094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 404094332d3Sopenharmony_ci return ret; 405094332d3Sopenharmony_ci} 406094332d3Sopenharmony_ci 407094332d3Sopenharmony_cistatic int32_t UsbEcmWrite(struct UsbEcm *port, struct HdfSBuf *data) 408094332d3Sopenharmony_ci{ 409094332d3Sopenharmony_ci uint32_t size = 0; 410094332d3Sopenharmony_ci uint8_t *buf = NULL; 411094332d3Sopenharmony_ci 412094332d3Sopenharmony_ci if (!HdfSbufReadBuffer(data, (const void **)&buf, &size)) { 413094332d3Sopenharmony_ci HDF_LOGE("UsbEcmWrite HdfSbufReadBuffer err"); 414094332d3Sopenharmony_ci return HDF_ERR_IO; 415094332d3Sopenharmony_ci } 416094332d3Sopenharmony_ci 417094332d3Sopenharmony_ci OsalMutexLock(&port->lock); 418094332d3Sopenharmony_ci if (size > 0 && buf != NULL) { 419094332d3Sopenharmony_ci OsalMutexLock(&port->lockWriteFifo); 420094332d3Sopenharmony_ci size = DataFifoWrite(&port->writeFifo, buf, size); 421094332d3Sopenharmony_ci OsalMutexUnlock(&port->lockWriteFifo); 422094332d3Sopenharmony_ci } 423094332d3Sopenharmony_ci if (port->ecm) { 424094332d3Sopenharmony_ci UsbEcmStartTx(port); 425094332d3Sopenharmony_ci } 426094332d3Sopenharmony_ci OsalMutexUnlock(&port->lock); 427094332d3Sopenharmony_ci return HDF_SUCCESS; 428094332d3Sopenharmony_ci} 429094332d3Sopenharmony_ci 430094332d3Sopenharmony_civoid UsbFnNotifyRequest(struct UsbFnRequest *req, struct UsbEcmDevice *ecm) 431094332d3Sopenharmony_ci{ 432094332d3Sopenharmony_ci int32_t status; 433094332d3Sopenharmony_ci ecm->notifyReq = NULL; 434094332d3Sopenharmony_ci status = UsbFnSubmitRequestAsync(req); 435094332d3Sopenharmony_ci if (status < 0) { 436094332d3Sopenharmony_ci ecm->notifyReq = req; 437094332d3Sopenharmony_ci HDF_LOGD("notify --> %{public}d", status); 438094332d3Sopenharmony_ci } 439094332d3Sopenharmony_ci} 440094332d3Sopenharmony_ci 441094332d3Sopenharmony_cistatic void EcmDoNotify(struct UsbEcmDevice *ecm) 442094332d3Sopenharmony_ci{ 443094332d3Sopenharmony_ci struct UsbFnRequest *req = ecm->notifyReq; 444094332d3Sopenharmony_ci struct UsbCdcNotification *event = NULL; 445094332d3Sopenharmony_ci uint32_t *data = NULL; 446094332d3Sopenharmony_ci 447094332d3Sopenharmony_ci if (!req) { 448094332d3Sopenharmony_ci return; 449094332d3Sopenharmony_ci } 450094332d3Sopenharmony_ci ecm->isOpen = true; 451094332d3Sopenharmony_ci event = (struct UsbCdcNotification *)req->buf; 452094332d3Sopenharmony_ci if (event == NULL) { 453094332d3Sopenharmony_ci return; 454094332d3Sopenharmony_ci } 455094332d3Sopenharmony_ci switch (ecm->notifyState) { 456094332d3Sopenharmony_ci case ECM_NOTIFY_NONE: 457094332d3Sopenharmony_ci return; 458094332d3Sopenharmony_ci 459094332d3Sopenharmony_ci case ECM_NOTIFY_CONNECT: 460094332d3Sopenharmony_ci event->bNotificationType = USB_DDK_CDC_NOTIFY_NETWORK_CONNECTION; 461094332d3Sopenharmony_ci if (ecm->isOpen) { 462094332d3Sopenharmony_ci event->wValue = CPU_TO_LE16(1); 463094332d3Sopenharmony_ci } else { 464094332d3Sopenharmony_ci event->wValue = CPU_TO_LE16(0); 465094332d3Sopenharmony_ci } 466094332d3Sopenharmony_ci event->wLength = 0; 467094332d3Sopenharmony_ci req->length = sizeof(*event); 468094332d3Sopenharmony_ci 469094332d3Sopenharmony_ci HDF_LOGD("notify connect %{public}s", ecm->isOpen ? "true" : "false"); 470094332d3Sopenharmony_ci ecm->notifyState = ECM_NOTIFY_SPEED; 471094332d3Sopenharmony_ci break; 472094332d3Sopenharmony_ci 473094332d3Sopenharmony_ci case ECM_NOTIFY_SPEED: 474094332d3Sopenharmony_ci event->bNotificationType = USB_DDK_CDC_NOTIFY_SPEED_CHANGE; 475094332d3Sopenharmony_ci event->wValue = CPU_TO_LE16(0); 476094332d3Sopenharmony_ci event->wLength = CPU_TO_LE16(0x08); 477094332d3Sopenharmony_ci req->length = ECM_STATUS_BYTECOUNT; 478094332d3Sopenharmony_ci 479094332d3Sopenharmony_ci /* SPEED_CHANGE data is up/down speeds in bits/sec */ 480094332d3Sopenharmony_ci data = (uint32_t *)((char *)req->buf + sizeof(*event)); 481094332d3Sopenharmony_ci data[0] = CPU_TO_LE32(EcmBitrate()); 482094332d3Sopenharmony_ci data[1] = data[0]; 483094332d3Sopenharmony_ci 484094332d3Sopenharmony_ci HDF_LOGD("notify speed %{public}d", EcmBitrate()); 485094332d3Sopenharmony_ci ecm->notifyState = ECM_NOTIFY_NONE; 486094332d3Sopenharmony_ci break; 487094332d3Sopenharmony_ci 488094332d3Sopenharmony_ci default: 489094332d3Sopenharmony_ci break; 490094332d3Sopenharmony_ci } 491094332d3Sopenharmony_ci event->bmRequestType = 0xA1; 492094332d3Sopenharmony_ci event->wIndex = CPU_TO_LE16(ecm->ctrlId); 493094332d3Sopenharmony_ci UsbFnNotifyRequest(req, ecm); 494094332d3Sopenharmony_ci} 495094332d3Sopenharmony_ci 496094332d3Sopenharmony_cistatic void EcmNotifyComplete(uint8_t pipe, struct UsbFnRequest *req) 497094332d3Sopenharmony_ci{ 498094332d3Sopenharmony_ci struct UsbEcmDevice *ecm = req->context; 499094332d3Sopenharmony_ci struct UsbCdcNotification *event = req->buf; 500094332d3Sopenharmony_ci ecm->notifyReq = req; 501094332d3Sopenharmony_ci if (req->status == 0) { 502094332d3Sopenharmony_ci EcmDoNotify(ecm); 503094332d3Sopenharmony_ci } else { 504094332d3Sopenharmony_ci HDF_LOGD("event %{public}d --> %{public}d", event->bNotificationType, req->status); 505094332d3Sopenharmony_ci } 506094332d3Sopenharmony_ci} 507094332d3Sopenharmony_ci 508094332d3Sopenharmony_cistatic int32_t EcmSetup(const struct UsbEcmDevice *ecm, const struct UsbFnCtrlRequest *ctrl) 509094332d3Sopenharmony_ci{ 510094332d3Sopenharmony_ci struct UsbFnRequest *req = ecm->ep0Req; 511094332d3Sopenharmony_ci int32_t ret = -1; 512094332d3Sopenharmony_ci uint16_t index = LE16_TO_CPU(ctrl->index); 513094332d3Sopenharmony_ci uint16_t value = LE16_TO_CPU(ctrl->value); 514094332d3Sopenharmony_ci uint16_t length = LE16_TO_CPU(ctrl->length); 515094332d3Sopenharmony_ci 516094332d3Sopenharmony_ci switch ((ctrl->reqType << 0x08) | ctrl->request) { 517094332d3Sopenharmony_ci case ((USB_DDK_DIR_OUT | USB_DDK_TYPE_CLASS | USB_DDK_RECIP_INTERFACE) << 0x08) | 518094332d3Sopenharmony_ci USB_DDK_CDC_SET_ETHERNET_PACKET_FILTER: 519094332d3Sopenharmony_ci if (length != 0 || index != ecm->ctrlId) { 520094332d3Sopenharmony_ci break; 521094332d3Sopenharmony_ci } 522094332d3Sopenharmony_ci HDF_LOGD("packet filter %{public}02x", value); 523094332d3Sopenharmony_ci ret = 0; 524094332d3Sopenharmony_ci break; 525094332d3Sopenharmony_ci 526094332d3Sopenharmony_ci default: 527094332d3Sopenharmony_ci HDF_LOGW( 528094332d3Sopenharmony_ci "invalid control req%{public}02x.%{public}02x v%{public}04x i%{public}04x l%{public}hu", 529094332d3Sopenharmony_ci ctrl->reqType, ctrl->request, value, index, length); 530094332d3Sopenharmony_ci } 531094332d3Sopenharmony_ci 532094332d3Sopenharmony_ci if (ret >= 0) { 533094332d3Sopenharmony_ci HDF_LOGD("ecm req%{public}02x.%{public}02x v%{public}04x i%{public}04x l%{public}d", 534094332d3Sopenharmony_ci ctrl->reqType, ctrl->request, value, index, length); 535094332d3Sopenharmony_ci req->length = (uint32_t)ret; 536094332d3Sopenharmony_ci ret = UsbFnSubmitRequestSync(req, 0); 537094332d3Sopenharmony_ci if (ret < 0) { 538094332d3Sopenharmony_ci HDF_LOGD("ecm req %{public}02x.%{public}02x response err %{public}d", ctrl->reqType, ctrl->request, ret); 539094332d3Sopenharmony_ci } 540094332d3Sopenharmony_ci } 541094332d3Sopenharmony_ci 542094332d3Sopenharmony_ci return value; 543094332d3Sopenharmony_ci} 544094332d3Sopenharmony_ci 545094332d3Sopenharmony_cistatic int32_t EcmDeviceDispatch( 546094332d3Sopenharmony_ci struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply) 547094332d3Sopenharmony_ci{ 548094332d3Sopenharmony_ci struct UsbEcmDevice *ecm = NULL; 549094332d3Sopenharmony_ci struct UsbEcm *port = NULL; 550094332d3Sopenharmony_ci int32_t ret; 551094332d3Sopenharmony_ci if (client == NULL || client->device == NULL || client->device->service == NULL) { 552094332d3Sopenharmony_ci HDF_LOGE("%{public}s: client is NULL", __func__); 553094332d3Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 554094332d3Sopenharmony_ci } 555094332d3Sopenharmony_ci if (data == NULL || reply == NULL) { 556094332d3Sopenharmony_ci HDF_LOGE("%{public}s: data or reply is NULL", __func__); 557094332d3Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 558094332d3Sopenharmony_ci } 559094332d3Sopenharmony_ci 560094332d3Sopenharmony_ci if (HdfDeviceObjectCheckInterfaceDesc(client->device, data) == false) { 561094332d3Sopenharmony_ci HDF_LOGE("%{public}s:%{public}d check interface desc fail", __func__, __LINE__); 562094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 563094332d3Sopenharmony_ci } 564094332d3Sopenharmony_ci 565094332d3Sopenharmony_ci switch (cmd) { 566094332d3Sopenharmony_ci case USB_ECM_INIT: 567094332d3Sopenharmony_ci return EcmInit(client->device); 568094332d3Sopenharmony_ci case USB_ECM_RELEASE: 569094332d3Sopenharmony_ci return EcmRelease(client->device); 570094332d3Sopenharmony_ci default: 571094332d3Sopenharmony_ci break; 572094332d3Sopenharmony_ci } 573094332d3Sopenharmony_ci ecm = (struct UsbEcmDevice *)client->device->service; 574094332d3Sopenharmony_ci port = ecm->port; 575094332d3Sopenharmony_ci if (port == NULL) { 576094332d3Sopenharmony_ci return HDF_ERR_IO; 577094332d3Sopenharmony_ci } 578094332d3Sopenharmony_ci OsalMutexLock(&port->lockRW); 579094332d3Sopenharmony_ci switch (cmd) { 580094332d3Sopenharmony_ci case USB_ECM_OPEN: 581094332d3Sopenharmony_ci ret = UsbEcmOpen(port); 582094332d3Sopenharmony_ci break; 583094332d3Sopenharmony_ci case USB_ECM_CLOSE: 584094332d3Sopenharmony_ci ret = UsbEcmClose(port); 585094332d3Sopenharmony_ci break; 586094332d3Sopenharmony_ci case USB_ECM_READ: 587094332d3Sopenharmony_ci ret = UsbEcmRead(port, reply); 588094332d3Sopenharmony_ci break; 589094332d3Sopenharmony_ci case USB_ECM_WRITE: 590094332d3Sopenharmony_ci ret = UsbEcmWrite(port, data); 591094332d3Sopenharmony_ci break; 592094332d3Sopenharmony_ci default: 593094332d3Sopenharmony_ci ret = HDF_ERR_NOT_SUPPORT; 594094332d3Sopenharmony_ci break; 595094332d3Sopenharmony_ci } 596094332d3Sopenharmony_ci OsalMutexUnlock(&port->lockRW); 597094332d3Sopenharmony_ci return ret; 598094332d3Sopenharmony_ci} 599094332d3Sopenharmony_ci 600094332d3Sopenharmony_cistatic int32_t EcmEnable(struct UsbEcmDevice *ecm) 601094332d3Sopenharmony_ci{ 602094332d3Sopenharmony_ci (void)ecm; 603094332d3Sopenharmony_ci return HDF_SUCCESS; 604094332d3Sopenharmony_ci} 605094332d3Sopenharmony_ci 606094332d3Sopenharmony_cistatic void EcmDisable(const struct UsbEcmDevice *ecm) 607094332d3Sopenharmony_ci{ 608094332d3Sopenharmony_ci (void)ecm; 609094332d3Sopenharmony_ci return; 610094332d3Sopenharmony_ci} 611094332d3Sopenharmony_ci 612094332d3Sopenharmony_cistatic void UsbEcmEventCallback(struct UsbFnEvent *event) 613094332d3Sopenharmony_ci{ 614094332d3Sopenharmony_ci struct UsbEcmDevice *ecm = NULL; 615094332d3Sopenharmony_ci 616094332d3Sopenharmony_ci if (event == NULL || event->context == NULL) { 617094332d3Sopenharmony_ci HDF_LOGE("%{public}s: event is null", __func__); 618094332d3Sopenharmony_ci return; 619094332d3Sopenharmony_ci } 620094332d3Sopenharmony_ci 621094332d3Sopenharmony_ci ecm = (struct UsbEcmDevice *)event->context; 622094332d3Sopenharmony_ci switch (event->type) { 623094332d3Sopenharmony_ci case USBFN_STATE_BIND: 624094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive bind event", __func__); 625094332d3Sopenharmony_ci break; 626094332d3Sopenharmony_ci case USBFN_STATE_UNBIND: 627094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive unbind event", __func__); 628094332d3Sopenharmony_ci break; 629094332d3Sopenharmony_ci case USBFN_STATE_ENABLE: 630094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive enable event", __func__); 631094332d3Sopenharmony_ci EcmEnable(ecm); 632094332d3Sopenharmony_ci break; 633094332d3Sopenharmony_ci case USBFN_STATE_DISABLE: 634094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive disable event", __func__); 635094332d3Sopenharmony_ci EcmDisable(ecm); 636094332d3Sopenharmony_ci break; 637094332d3Sopenharmony_ci case USBFN_STATE_SETUP: 638094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive setup event", __func__); 639094332d3Sopenharmony_ci if (event->setup != NULL) { 640094332d3Sopenharmony_ci EcmSetup(ecm, event->setup); 641094332d3Sopenharmony_ci } 642094332d3Sopenharmony_ci break; 643094332d3Sopenharmony_ci case USBFN_STATE_SUSPEND: 644094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive suspend event", __func__); 645094332d3Sopenharmony_ci break; 646094332d3Sopenharmony_ci case USBFN_STATE_RESUME: 647094332d3Sopenharmony_ci HDF_LOGI("%{public}s: receive resume event", __func__); 648094332d3Sopenharmony_ci break; 649094332d3Sopenharmony_ci default: 650094332d3Sopenharmony_ci break; 651094332d3Sopenharmony_ci } 652094332d3Sopenharmony_ci} 653094332d3Sopenharmony_ci 654094332d3Sopenharmony_cistatic int32_t EcmAllocNotifyRequest(struct UsbEcmDevice *ecm) 655094332d3Sopenharmony_ci{ 656094332d3Sopenharmony_ci /* allocate notification request */ 657094332d3Sopenharmony_ci ecm->notifyReq = 658094332d3Sopenharmony_ci UsbFnAllocRequest(ecm->ctrlIface.handle, ecm->notifyPipe.id, sizeof(struct UsbCdcNotification) * USBCDC_LEN); 659094332d3Sopenharmony_ci if (ecm->notifyReq == NULL) { 660094332d3Sopenharmony_ci HDF_LOGE("%{public}s: allocate notify request failed", __func__); 661094332d3Sopenharmony_ci return HDF_FAILURE; 662094332d3Sopenharmony_ci } 663094332d3Sopenharmony_ci ecm->notifyReq->complete = EcmNotifyComplete; 664094332d3Sopenharmony_ci ecm->notifyReq->context = ecm; 665094332d3Sopenharmony_ci 666094332d3Sopenharmony_ci return HDF_SUCCESS; 667094332d3Sopenharmony_ci} 668094332d3Sopenharmony_ci 669094332d3Sopenharmony_cistatic int32_t EcmAllocEp0Request(struct UsbEcmDevice *ecm) 670094332d3Sopenharmony_ci{ 671094332d3Sopenharmony_ci /* allocate notification request */ 672094332d3Sopenharmony_ci ecm->ep0Req = UsbFnAllocCtrlRequest(ecm->ctrlIface.handle, ECM_STATUS_BYTECOUNT); 673094332d3Sopenharmony_ci if (ecm->ep0Req == NULL) { 674094332d3Sopenharmony_ci HDF_LOGE("%{public}s: allocate ep0Req request failed", __func__); 675094332d3Sopenharmony_ci return HDF_FAILURE; 676094332d3Sopenharmony_ci } 677094332d3Sopenharmony_ci return HDF_SUCCESS; 678094332d3Sopenharmony_ci} 679094332d3Sopenharmony_ci 680094332d3Sopenharmony_cistatic int32_t EcmParseEachPipe(struct UsbEcmDevice *ecm, struct UsbEcmInterface *iface) 681094332d3Sopenharmony_ci{ 682094332d3Sopenharmony_ci struct UsbFnInterface *fnIface = iface->fn; 683094332d3Sopenharmony_ci uint32_t repetIdx = 0; 684094332d3Sopenharmony_ci for (int32_t i = 0; i < fnIface->info.numPipes; i++) { 685094332d3Sopenharmony_ci struct UsbFnPipeInfo pipeInfo; 686094332d3Sopenharmony_ci (void)memset_s(&pipeInfo, sizeof(pipeInfo), 0, sizeof(pipeInfo)); 687094332d3Sopenharmony_ci int32_t ret = UsbFnGetInterfacePipeInfo(fnIface, (uint8_t)i, &pipeInfo); 688094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 689094332d3Sopenharmony_ci HDF_LOGE("%{public}s: get pipe info error", __func__); 690094332d3Sopenharmony_ci return HDF_FAILURE; 691094332d3Sopenharmony_ci } 692094332d3Sopenharmony_ci 693094332d3Sopenharmony_ci switch (pipeInfo.type) { 694094332d3Sopenharmony_ci case USB_PIPE_TYPE_INTERRUPT: 695094332d3Sopenharmony_ci ecm->notifyPipe.id = pipeInfo.id; 696094332d3Sopenharmony_ci ecm->notifyPipe.maxPacketSize = pipeInfo.maxPacketSize; 697094332d3Sopenharmony_ci ecm->ctrlIface = *iface; 698094332d3Sopenharmony_ci break; 699094332d3Sopenharmony_ci case USB_PIPE_TYPE_BULK: 700094332d3Sopenharmony_ci if (pipeInfo.dir == USB_PIPE_DIRECTION_IN) { 701094332d3Sopenharmony_ci ecm->dataInPipe.id = pipeInfo.id; 702094332d3Sopenharmony_ci ecm->dataInPipe.maxPacketSize = pipeInfo.maxPacketSize; 703094332d3Sopenharmony_ci ecm->dataIface = *iface; 704094332d3Sopenharmony_ci } else { 705094332d3Sopenharmony_ci ecm->dataOutPipe.id = pipeInfo.id; 706094332d3Sopenharmony_ci ecm->dataOutPipe.maxPacketSize = pipeInfo.maxPacketSize; 707094332d3Sopenharmony_ci } 708094332d3Sopenharmony_ci break; 709094332d3Sopenharmony_ci default: 710094332d3Sopenharmony_ci if (repetIdx < WAIT_UDC_MAX_LOOP) { 711094332d3Sopenharmony_ci usleep(WAIT_UDC_TIME); 712094332d3Sopenharmony_ci i--; 713094332d3Sopenharmony_ci } 714094332d3Sopenharmony_ci repetIdx++; 715094332d3Sopenharmony_ci HDF_LOGE("%{public}s: pipe type %{public}d don't support", __func__, pipeInfo.type); 716094332d3Sopenharmony_ci break; 717094332d3Sopenharmony_ci } 718094332d3Sopenharmony_ci } 719094332d3Sopenharmony_ci 720094332d3Sopenharmony_ci return HDF_SUCCESS; 721094332d3Sopenharmony_ci} 722094332d3Sopenharmony_ci 723094332d3Sopenharmony_cistatic int32_t EcmParseEcmIface(struct UsbEcmDevice *ecm, struct UsbFnInterface *fnIface) 724094332d3Sopenharmony_ci{ 725094332d3Sopenharmony_ci int32_t ret; 726094332d3Sopenharmony_ci struct UsbEcmInterface iface; 727094332d3Sopenharmony_ci UsbFnInterfaceHandle handle = UsbFnOpenInterface(fnIface); 728094332d3Sopenharmony_ci if (handle == NULL) { 729094332d3Sopenharmony_ci HDF_LOGE("%{public}s: open interface failed", __func__); 730094332d3Sopenharmony_ci return HDF_FAILURE; 731094332d3Sopenharmony_ci } 732094332d3Sopenharmony_ci iface.fn = fnIface; 733094332d3Sopenharmony_ci iface.handle = handle; 734094332d3Sopenharmony_ci 735094332d3Sopenharmony_ci ret = EcmParseEachPipe(ecm, &iface); 736094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 737094332d3Sopenharmony_ci return HDF_FAILURE; 738094332d3Sopenharmony_ci } 739094332d3Sopenharmony_ci return HDF_SUCCESS; 740094332d3Sopenharmony_ci} 741094332d3Sopenharmony_ci 742094332d3Sopenharmony_cistatic int32_t EcmParseEachIface(struct UsbEcmDevice *ecm, struct UsbFnDevice *fnDev) 743094332d3Sopenharmony_ci{ 744094332d3Sopenharmony_ci struct UsbFnInterface *fnIface = NULL; 745094332d3Sopenharmony_ci uint32_t i; 746094332d3Sopenharmony_ci 747094332d3Sopenharmony_ci for (i = 0; i < fnDev->numInterfaces; i++) { 748094332d3Sopenharmony_ci fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i); 749094332d3Sopenharmony_ci if (fnIface == NULL) { 750094332d3Sopenharmony_ci HDF_LOGE("%{public}s: get interface failed", __func__); 751094332d3Sopenharmony_ci return HDF_FAILURE; 752094332d3Sopenharmony_ci } 753094332d3Sopenharmony_ci 754094332d3Sopenharmony_ci if (fnIface->info.subclass == USB_DDK_CDC_SUBCLASS_ETHERNET) { 755094332d3Sopenharmony_ci (void)EcmParseEcmIface(ecm, fnIface); 756094332d3Sopenharmony_ci fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i + 1); 757094332d3Sopenharmony_ci if (fnIface == NULL) { 758094332d3Sopenharmony_ci HDF_LOGE("%{public}s: get interface failed", __func__); 759094332d3Sopenharmony_ci return HDF_FAILURE; 760094332d3Sopenharmony_ci } 761094332d3Sopenharmony_ci (void)EcmParseEcmIface(ecm, fnIface); 762094332d3Sopenharmony_ci return HDF_SUCCESS; 763094332d3Sopenharmony_ci } 764094332d3Sopenharmony_ci } 765094332d3Sopenharmony_ci 766094332d3Sopenharmony_ci return HDF_FAILURE; 767094332d3Sopenharmony_ci} 768094332d3Sopenharmony_ci 769094332d3Sopenharmony_cistatic int32_t EcmCreateFuncDevice(struct UsbEcmDevice *ecm, struct DeviceResourceIface *iface) 770094332d3Sopenharmony_ci{ 771094332d3Sopenharmony_ci struct UsbFnDevice *fnDev = NULL; 772094332d3Sopenharmony_ci int32_t ret; 773094332d3Sopenharmony_ci 774094332d3Sopenharmony_ci if (iface->GetString(ecm->device->property, "udc_name", (const char **)&ecm->udcName, UDC_NAME) != HDF_SUCCESS) { 775094332d3Sopenharmony_ci HDF_LOGE("%{public}s: read udc_name failed, use default", __func__); 776094332d3Sopenharmony_ci return HDF_FAILURE; 777094332d3Sopenharmony_ci } 778094332d3Sopenharmony_ci 779094332d3Sopenharmony_ci fnDev = (struct UsbFnDevice *)UsbFnGetDevice(ecm->udcName); 780094332d3Sopenharmony_ci if (fnDev == NULL) { 781094332d3Sopenharmony_ci HDF_LOGE("%{public}s: create usb function device failed", __func__); 782094332d3Sopenharmony_ci return HDF_FAILURE; 783094332d3Sopenharmony_ci } 784094332d3Sopenharmony_ci 785094332d3Sopenharmony_ci ret = EcmParseEachIface(ecm, fnDev); 786094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 787094332d3Sopenharmony_ci HDF_LOGE("%{public}s: get pipes failed", __func__); 788094332d3Sopenharmony_ci goto ERR; 789094332d3Sopenharmony_ci } 790094332d3Sopenharmony_ci 791094332d3Sopenharmony_ci ecm->fnDev = fnDev; 792094332d3Sopenharmony_ci return HDF_SUCCESS; 793094332d3Sopenharmony_ci 794094332d3Sopenharmony_ciERR: 795094332d3Sopenharmony_ci return ret; 796094332d3Sopenharmony_ci} 797094332d3Sopenharmony_ci 798094332d3Sopenharmony_cistatic void EcmFreeNotifyRequest(struct UsbEcmDevice *ecm) 799094332d3Sopenharmony_ci{ 800094332d3Sopenharmony_ci int32_t ret; 801094332d3Sopenharmony_ci 802094332d3Sopenharmony_ci /* free notification request */ 803094332d3Sopenharmony_ci ret = UsbFnFreeRequest(ecm->notifyReq); 804094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 805094332d3Sopenharmony_ci HDF_LOGE("%{public}s: free notify request failed", __func__); 806094332d3Sopenharmony_ci return; 807094332d3Sopenharmony_ci } 808094332d3Sopenharmony_ci ecm->notifyReq = NULL; 809094332d3Sopenharmony_ci} 810094332d3Sopenharmony_ci 811094332d3Sopenharmony_cistatic int32_t EcmReleaseFuncDevice(struct UsbEcmDevice *ecm) 812094332d3Sopenharmony_ci{ 813094332d3Sopenharmony_ci int32_t ret = HDF_SUCCESS; 814094332d3Sopenharmony_ci if (ecm->fnDev == NULL) { 815094332d3Sopenharmony_ci HDF_LOGE("%{public}s: fnDev is null", __func__); 816094332d3Sopenharmony_ci return HDF_FAILURE; 817094332d3Sopenharmony_ci } 818094332d3Sopenharmony_ci (void)UsbFnFreeRequest(ecm->ep0Req); 819094332d3Sopenharmony_ci (void)EcmFreeNotifyRequest(ecm); 820094332d3Sopenharmony_ci UsbFnCloseInterface(ecm->ctrlIface.handle); 821094332d3Sopenharmony_ci (void)UsbFnCloseInterface(ecm->dataIface.handle); 822094332d3Sopenharmony_ci (void)UsbFnStopRecvInterfaceEvent(ecm->ctrlIface.fn); 823094332d3Sopenharmony_ci return ret; 824094332d3Sopenharmony_ci} 825094332d3Sopenharmony_ci 826094332d3Sopenharmony_cistatic int32_t UsbEcmAlloc(struct UsbEcmDevice *ecm) 827094332d3Sopenharmony_ci{ 828094332d3Sopenharmony_ci struct UsbEcm *port = NULL; 829094332d3Sopenharmony_ci 830094332d3Sopenharmony_ci port = (struct UsbEcm *)OsalMemCalloc(sizeof(*port)); 831094332d3Sopenharmony_ci if (port == NULL) { 832094332d3Sopenharmony_ci HDF_LOGE("%{public}s: Alloc usb serial port failed", __func__); 833094332d3Sopenharmony_ci return HDF_FAILURE; 834094332d3Sopenharmony_ci } 835094332d3Sopenharmony_ci 836094332d3Sopenharmony_ci if (OsalMutexInit(&port->lock) != HDF_SUCCESS) { 837094332d3Sopenharmony_ci HDF_LOGE("%{public}s: init lock fail!", __func__); 838094332d3Sopenharmony_ci OsalMemFree(port); 839094332d3Sopenharmony_ci return HDF_FAILURE; 840094332d3Sopenharmony_ci } 841094332d3Sopenharmony_ci 842094332d3Sopenharmony_ci if (OsalMutexInit(&port->lockRW) != HDF_SUCCESS) { 843094332d3Sopenharmony_ci HDF_LOGE("%{public}s: init lock fail!", __func__); 844094332d3Sopenharmony_ci OsalMutexDestroy(&port->lock); 845094332d3Sopenharmony_ci OsalMemFree(port); 846094332d3Sopenharmony_ci return HDF_FAILURE; 847094332d3Sopenharmony_ci } 848094332d3Sopenharmony_ci 849094332d3Sopenharmony_ci if (OsalMutexInit(&port->lockReadFifo) != HDF_SUCCESS) { 850094332d3Sopenharmony_ci HDF_LOGE("%{public}s: init lock fail!", __func__); 851094332d3Sopenharmony_ci OsalMutexDestroy(&port->lock); 852094332d3Sopenharmony_ci OsalMutexDestroy(&port->lockRW); 853094332d3Sopenharmony_ci OsalMemFree(port); 854094332d3Sopenharmony_ci return HDF_FAILURE; 855094332d3Sopenharmony_ci } 856094332d3Sopenharmony_ci 857094332d3Sopenharmony_ci if (OsalMutexInit(&port->lockWriteFifo) != HDF_SUCCESS) { 858094332d3Sopenharmony_ci HDF_LOGE("%{public}s: init lock fail!", __func__); 859094332d3Sopenharmony_ci OsalMutexDestroy(&port->lock); 860094332d3Sopenharmony_ci OsalMutexDestroy(&port->lockRW); 861094332d3Sopenharmony_ci OsalMutexDestroy(&port->lockReadFifo); 862094332d3Sopenharmony_ci OsalMemFree(port); 863094332d3Sopenharmony_ci return HDF_FAILURE; 864094332d3Sopenharmony_ci } 865094332d3Sopenharmony_ci DListHeadInit(&port->readPool); 866094332d3Sopenharmony_ci DListHeadInit(&port->readQueue); 867094332d3Sopenharmony_ci DListHeadInit(&port->writePool); 868094332d3Sopenharmony_ci 869094332d3Sopenharmony_ci ecm->port = port; 870094332d3Sopenharmony_ci return HDF_SUCCESS; 871094332d3Sopenharmony_ci} 872094332d3Sopenharmony_ci 873094332d3Sopenharmony_cistatic void UsbEcmFree(struct UsbEcmDevice *ecm) 874094332d3Sopenharmony_ci{ 875094332d3Sopenharmony_ci if (ecm != NULL && ecm->port != NULL) { 876094332d3Sopenharmony_ci OsalMutexDestroy(&ecm->port->lock); 877094332d3Sopenharmony_ci OsalMutexDestroy(&ecm->port->lockRW); 878094332d3Sopenharmony_ci OsalMutexDestroy(&ecm->port->lockReadFifo); 879094332d3Sopenharmony_ci OsalMutexDestroy(&ecm->port->lockWriteFifo); 880094332d3Sopenharmony_ci OsalMemFree(ecm->port); 881094332d3Sopenharmony_ci ecm->port = NULL; 882094332d3Sopenharmony_ci } 883094332d3Sopenharmony_ci} 884094332d3Sopenharmony_ci 885094332d3Sopenharmony_ci/* HdfDriverEntry implementations */ 886094332d3Sopenharmony_cistatic int32_t EcmDriverBind(struct HdfDeviceObject *device) 887094332d3Sopenharmony_ci{ 888094332d3Sopenharmony_ci struct UsbEcmDevice *ecm = NULL; 889094332d3Sopenharmony_ci 890094332d3Sopenharmony_ci if (device == NULL) { 891094332d3Sopenharmony_ci HDF_LOGE("%{public}s: device is null", __func__); 892094332d3Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 893094332d3Sopenharmony_ci } 894094332d3Sopenharmony_ci 895094332d3Sopenharmony_ci ecm = (struct UsbEcmDevice *)OsalMemCalloc(sizeof(*ecm)); 896094332d3Sopenharmony_ci if (ecm == NULL) { 897094332d3Sopenharmony_ci HDF_LOGE("%{public}s: Alloc usb ecm device failed", __func__); 898094332d3Sopenharmony_ci return HDF_FAILURE; 899094332d3Sopenharmony_ci } 900094332d3Sopenharmony_ci ecm->ctrlId = 0; 901094332d3Sopenharmony_ci ecm->dataId = 1; 902094332d3Sopenharmony_ci if (OsalMutexInit(&ecm->lock) != HDF_SUCCESS) { 903094332d3Sopenharmony_ci HDF_LOGE("%{public}s: init lock fail!", __func__); 904094332d3Sopenharmony_ci OsalMemFree(ecm); 905094332d3Sopenharmony_ci return HDF_FAILURE; 906094332d3Sopenharmony_ci } 907094332d3Sopenharmony_ci 908094332d3Sopenharmony_ci if (HdfDeviceObjectSetInterfaceDesc(device, "hdf.usb.usbfn") != HDF_SUCCESS) { 909094332d3Sopenharmony_ci HDF_LOGE(" Set Desc fail!"); 910094332d3Sopenharmony_ci OsalMemFree(ecm); 911094332d3Sopenharmony_ci return HDF_FAILURE; 912094332d3Sopenharmony_ci } 913094332d3Sopenharmony_ci 914094332d3Sopenharmony_ci ecm->device = device; 915094332d3Sopenharmony_ci device->service = &(ecm->service); 916094332d3Sopenharmony_ci if (ecm->device->service) { 917094332d3Sopenharmony_ci ecm->device->service->Dispatch = EcmDeviceDispatch; 918094332d3Sopenharmony_ci } 919094332d3Sopenharmony_ci return HDF_SUCCESS; 920094332d3Sopenharmony_ci} 921094332d3Sopenharmony_ci 922094332d3Sopenharmony_cistatic int32_t EcmInit(struct HdfDeviceObject *device) 923094332d3Sopenharmony_ci{ 924094332d3Sopenharmony_ci struct UsbEcmDevice *ecm = NULL; 925094332d3Sopenharmony_ci struct DeviceResourceIface *iface = NULL; 926094332d3Sopenharmony_ci int32_t ret; 927094332d3Sopenharmony_ci 928094332d3Sopenharmony_ci if (device == NULL) { 929094332d3Sopenharmony_ci HDF_LOGE("%{public}s: device is null", __func__); 930094332d3Sopenharmony_ci return HDF_ERR_INVALID_OBJECT; 931094332d3Sopenharmony_ci } 932094332d3Sopenharmony_ci 933094332d3Sopenharmony_ci ecm = (struct UsbEcmDevice *)device->service; 934094332d3Sopenharmony_ci if (ecm == NULL || ecm->initFlag) { 935094332d3Sopenharmony_ci HDF_LOGE("%{public}s: ecm is null", __func__); 936094332d3Sopenharmony_ci return HDF_FAILURE; 937094332d3Sopenharmony_ci } 938094332d3Sopenharmony_ci 939094332d3Sopenharmony_ci iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); 940094332d3Sopenharmony_ci if (iface == NULL || iface->GetUint32 == NULL) { 941094332d3Sopenharmony_ci HDF_LOGE("%{public}s: face is invalid", __func__); 942094332d3Sopenharmony_ci return HDF_FAILURE; 943094332d3Sopenharmony_ci } 944094332d3Sopenharmony_ci 945094332d3Sopenharmony_ci ret = EcmCreateFuncDevice(ecm, iface); 946094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 947094332d3Sopenharmony_ci HDF_LOGE("%{public}s: EcmCreateFuncDevice failed", __func__); 948094332d3Sopenharmony_ci return ret; 949094332d3Sopenharmony_ci } 950094332d3Sopenharmony_ci 951094332d3Sopenharmony_ci ret = UsbEcmAlloc(ecm); 952094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 953094332d3Sopenharmony_ci HDF_LOGE("%{public}s: UsbEcmAlloc failed", __func__); 954094332d3Sopenharmony_ci return ret; 955094332d3Sopenharmony_ci } 956094332d3Sopenharmony_ci 957094332d3Sopenharmony_ci ret = EcmAllocEp0Request(ecm); 958094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 959094332d3Sopenharmony_ci HDF_LOGE("%{public}s: EcmAllocEp0Request failed", __func__); 960094332d3Sopenharmony_ci goto ERR; 961094332d3Sopenharmony_ci } 962094332d3Sopenharmony_ci 963094332d3Sopenharmony_ci ret = EcmAllocNotifyRequest(ecm); 964094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 965094332d3Sopenharmony_ci HDF_LOGE("%{public}s: EcmAllocNotifyRequest failed", __func__); 966094332d3Sopenharmony_ci goto ERR; 967094332d3Sopenharmony_ci } 968094332d3Sopenharmony_ci 969094332d3Sopenharmony_ci ret = UsbFnStartRecvInterfaceEvent(ecm->ctrlIface.fn, RECEIVE_ALL_EVENTS, UsbEcmEventCallback, ecm); 970094332d3Sopenharmony_ci if (ret != HDF_SUCCESS) { 971094332d3Sopenharmony_ci HDF_LOGE("%{public}s: register event callback failed", __func__); 972094332d3Sopenharmony_ci goto ERR; 973094332d3Sopenharmony_ci } 974094332d3Sopenharmony_ci ecm->initFlag = true; 975094332d3Sopenharmony_ci return ret; 976094332d3Sopenharmony_ciERR: 977094332d3Sopenharmony_ci UsbEcmFree(ecm); 978094332d3Sopenharmony_ci (void)EcmReleaseFuncDevice(ecm); 979094332d3Sopenharmony_ci return ret; 980094332d3Sopenharmony_ci} 981094332d3Sopenharmony_ci 982094332d3Sopenharmony_cistatic int32_t EcmRelease(struct HdfDeviceObject *device) 983094332d3Sopenharmony_ci{ 984094332d3Sopenharmony_ci struct UsbEcmDevice *ecm = NULL; 985094332d3Sopenharmony_ci 986094332d3Sopenharmony_ci if (device == NULL) { 987094332d3Sopenharmony_ci HDF_LOGE("%{public}s: device is NULL", __func__); 988094332d3Sopenharmony_ci return HDF_FAILURE; 989094332d3Sopenharmony_ci } 990094332d3Sopenharmony_ci 991094332d3Sopenharmony_ci ecm = (struct UsbEcmDevice *)device->service; 992094332d3Sopenharmony_ci if (ecm == NULL) { 993094332d3Sopenharmony_ci HDF_LOGE("%{public}s: ecm is null", __func__); 994094332d3Sopenharmony_ci return HDF_FAILURE; 995094332d3Sopenharmony_ci } 996094332d3Sopenharmony_ci if (ecm->initFlag == false) { 997094332d3Sopenharmony_ci HDF_LOGE("%{public}s: ecm not init!", __func__); 998094332d3Sopenharmony_ci return HDF_FAILURE; 999094332d3Sopenharmony_ci } 1000094332d3Sopenharmony_ci UsbEcmFree(ecm); 1001094332d3Sopenharmony_ci (void)EcmReleaseFuncDevice(ecm); 1002094332d3Sopenharmony_ci ecm->initFlag = false; 1003094332d3Sopenharmony_ci return HDF_SUCCESS; 1004094332d3Sopenharmony_ci} 1005094332d3Sopenharmony_ci 1006094332d3Sopenharmony_cistatic int32_t EcmDriverInit(struct HdfDeviceObject *device) 1007094332d3Sopenharmony_ci{ 1008094332d3Sopenharmony_ci (void)device; 1009094332d3Sopenharmony_ci HDF_LOGE("%{public}s: usbfn do nothing...", __func__); 1010094332d3Sopenharmony_ci return 0; 1011094332d3Sopenharmony_ci} 1012094332d3Sopenharmony_ci 1013094332d3Sopenharmony_cistatic void EcmDriverRelease(struct HdfDeviceObject *device) 1014094332d3Sopenharmony_ci{ 1015094332d3Sopenharmony_ci struct UsbEcmDevice *ecm = NULL; 1016094332d3Sopenharmony_ci if (device == NULL) { 1017094332d3Sopenharmony_ci HDF_LOGE("%{public}s: device is NULL", __func__); 1018094332d3Sopenharmony_ci return; 1019094332d3Sopenharmony_ci } 1020094332d3Sopenharmony_ci 1021094332d3Sopenharmony_ci ecm = (struct UsbEcmDevice *)device->service; 1022094332d3Sopenharmony_ci if (ecm == NULL) { 1023094332d3Sopenharmony_ci HDF_LOGE("%{public}s: ecm is null", __func__); 1024094332d3Sopenharmony_ci return; 1025094332d3Sopenharmony_ci } 1026094332d3Sopenharmony_ci 1027094332d3Sopenharmony_ci (void)OsalMutexDestroy(&ecm->lock); 1028094332d3Sopenharmony_ci OsalMemFree(ecm); 1029094332d3Sopenharmony_ci device->service = NULL; 1030094332d3Sopenharmony_ci} 1031094332d3Sopenharmony_ci 1032094332d3Sopenharmony_cistruct HdfDriverEntry g_ecmDriverEntry = { 1033094332d3Sopenharmony_ci .moduleVersion = 1, 1034094332d3Sopenharmony_ci .moduleName = "usbfn_cdcecm", 1035094332d3Sopenharmony_ci .Bind = EcmDriverBind, 1036094332d3Sopenharmony_ci .Init = EcmDriverInit, 1037094332d3Sopenharmony_ci .Release = EcmDriverRelease, 1038094332d3Sopenharmony_ci}; 1039094332d3Sopenharmony_ci 1040094332d3Sopenharmony_ciHDF_INIT(g_ecmDriverEntry); 1041