1/* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "cdcecm.h" 17#include <unistd.h> 18#include "device_resource_if.h" 19#include "hdf_base.h" 20#include "hdf_device_object.h" 21#include "hdf_log.h" 22#include "osal_mem.h" 23#include "osal_sem.h" 24#include "osal_time.h" 25#include "securec.h" 26#include "usbfn_device.h" 27#include "usbfn_interface.h" 28#include "usbfn_request.h" 29 30#define HDF_LOG_TAG cdc_ecm 31#define UDC_NAME "invalid_udc_name" 32 33#define QUEUE_SIZE 8 34#define WRITE_BUF_SIZE 8192 35#define READ_BUF_SIZE 8192 36#define ECM_STATUS_BYTECOUNT 16 37#define ECM_BIT 9728000 38#define USBCDC_LEN 2 39#define RECEIVE_ALL_EVENTS 0xff 40static const int32_t WAIT_UDC_MAX_LOOP = 3; 41static const uint32_t WAIT_UDC_TIME = 100000; 42 43static int32_t EcmInit(struct HdfDeviceObject *device); 44static int32_t EcmRelease(struct HdfDeviceObject *device); 45 46static inline unsigned EcmBitrate(void) 47{ 48 return ECM_BIT; 49} 50 51/* Usb Serial Related Functions */ 52static int32_t UsbEcmStartTx(struct UsbEcm *port) 53{ 54 struct DListHead *pool = &port->writePool; 55 if (port->ecm == NULL) { 56 return HDF_SUCCESS; 57 } 58 59 while (!port->writeBusy && !DListIsEmpty(pool)) { 60 struct UsbFnRequest *req = NULL; 61 uint32_t len; 62 if (port->writeStarted >= QUEUE_SIZE) { 63 break; 64 } 65 req = DLIST_FIRST_ENTRY(pool, struct UsbFnRequest, list); 66 OsalMutexLock(&port->lockWriteFifo); 67 len = DataFifoRead(&port->writeFifo, req->buf, port->ecm->dataInPipe.maxPacketSize); 68 OsalMutexUnlock(&port->lockWriteFifo); 69 if (len == 0) { 70 break; 71 } 72 req->length = len; 73 DListRemove(&req->list); 74 port->writeBusy = true; 75 int32_t ret = UsbFnSubmitRequestAsync(req); 76 port->writeBusy = false; 77 if (ret != HDF_SUCCESS) { 78 HDF_LOGE("%{public}s: send request error %{public}d", __func__, ret); 79 DListInsertTail(&req->list, pool); 80 break; 81 } 82 port->writeStarted++; 83 /* if ecm is disconnect, abort immediately */ 84 if (port->ecm == NULL) { 85 break; 86 } 87 } 88 return HDF_SUCCESS; 89} 90 91static uint32_t UsbEcmStartRx(struct UsbEcm *port) 92{ 93 struct DListHead *pool = &port->readPool; 94 struct UsbEcmPipe *out = &port->ecm->dataOutPipe; 95 96 while (!DListIsEmpty(pool)) { 97 struct UsbFnRequest *req = NULL; 98 int32_t ret; 99 100 if (port->readStarted >= QUEUE_SIZE) { 101 break; 102 } 103 104 req = DLIST_FIRST_ENTRY(pool, struct UsbFnRequest, list); 105 DListRemove(&req->list); 106 req->length = out->maxPacketSize; 107 ret = UsbFnSubmitRequestAsync(req); 108 if (ret != HDF_SUCCESS) { 109 HDF_LOGE("%{public}s: send request error %{public}d", __func__, ret); 110 DListInsertTail(&req->list, pool); 111 break; 112 } 113 port->readStarted++; 114 /* if ecm is disconnect, abort immediately */ 115 if (port->ecm == NULL) { 116 break; 117 } 118 } 119 return port->readStarted; 120} 121 122static void UsbEcmRxPush(struct UsbEcm *port) 123{ 124 struct DListHead *queue = &port->readQueue; 125 bool disconnect = false; 126 127 while (!DListIsEmpty(queue)) { 128 struct UsbFnRequest *req; 129 130 req = DLIST_FIRST_ENTRY(queue, struct UsbFnRequest, list); 131 switch (req->status) { 132 case USB_REQUEST_NO_DEVICE: 133 disconnect = true; 134 HDF_LOGV("%{public}s: the device is disconnected", __func__); 135 break; 136 case USB_REQUEST_COMPLETED: 137 break; 138 default: 139 HDF_LOGV("%{public}s: unexpected status %{public}d", __func__, req->status); 140 break; 141 } 142 if (req->actual && req->status == 0) { 143 uint32_t size = req->actual; 144 uint8_t *data = req->buf; 145 OsalMutexLock(&port->lockReadFifo); 146 if (DataFifoIsFull(&port->readFifo)) { 147 DataFifoSkip(&port->readFifo, size); 148 } 149 uint32_t count = DataFifoWrite(&port->readFifo, data, size); 150 if (count != size) { 151 HDF_LOGW("%{public}s: write %{public}u less than expected %{public}u", __func__, count, size); 152 } 153 OsalMutexUnlock(&port->lockReadFifo); 154 } 155 DListRemove(&req->list); 156 DListInsertTail(&req->list, &port->readPool); 157 port->readStarted--; 158 } 159 160 if (!disconnect && port->ecm) { 161 UsbEcmStartRx(port); 162 } 163} 164 165static void UsbEcmFreeRequests(const struct DListHead *head, int32_t *allocated) 166{ 167 struct UsbFnRequest *req = NULL; 168 while (!DListIsEmpty(head)) { 169 req = DLIST_FIRST_ENTRY(head, struct UsbFnRequest, list); 170 DListRemove(&req->list); 171 (void)UsbFnFreeRequest(req); 172 if (allocated) { 173 (*allocated)--; 174 } 175 } 176} 177 178static void UsbEcmReadComplete(uint8_t pipe, struct UsbFnRequest *req) 179{ 180 struct UsbEcm *port = (struct UsbEcm *)req->context; 181 OsalMutexLock(&port->lock); 182 DListInsertTail(&req->list, &port->readQueue); 183 UsbEcmRxPush(port); 184 OsalMutexUnlock(&port->lock); 185} 186 187static void UsbEcmWriteComplete(uint8_t pipe, struct UsbFnRequest *req) 188{ 189 struct UsbEcm *port = (struct UsbEcm *)req->context; 190 OsalMutexLock(&port->lock); 191 DListInsertTail(&req->list, &port->writePool); 192 port->writeStarted--; 193 194 switch (req->status) { 195 case USB_REQUEST_COMPLETED: 196 UsbEcmStartTx(port); 197 break; 198 case USB_REQUEST_NO_DEVICE: 199 HDF_LOGV("%{public}s: ecm device was disconnected", __func__); 200 break; 201 default: 202 HDF_LOGV("%{public}s: unexpected status %{public}d", __func__, req->status); 203 break; 204 } 205 OsalMutexUnlock(&port->lock); 206} 207 208static int32_t UsbEcmAllocReadRequests(struct UsbEcm *port, int32_t num) 209{ 210 struct UsbEcmDevice *ecm = port->ecm; 211 struct DListHead *head = &port->readPool; 212 struct UsbFnRequest *req = NULL; 213 int32_t i; 214 215 for (i = 0; i < num; i++) { 216 req = UsbFnAllocRequest(ecm->dataIface.handle, ecm->dataOutPipe.id, ecm->dataOutPipe.maxPacketSize); 217 if (!req) { 218 return DListIsEmpty(head) ? HDF_FAILURE : HDF_SUCCESS; 219 } 220 221 req->complete = UsbEcmReadComplete; 222 req->context = port; 223 DListInsertTail(&req->list, head); 224 port->readAllocated++; 225 } 226 return HDF_SUCCESS; 227} 228 229static int32_t UsbEcmAllocWriteRequests(struct UsbEcm *port, int32_t num) 230{ 231 struct UsbEcmDevice *ecm = port->ecm; 232 struct DListHead *head = &port->writePool; 233 struct UsbFnRequest *req = NULL; 234 int32_t i; 235 236 for (i = 0; i < num; i++) { 237 req = UsbFnAllocRequest(ecm->dataIface.handle, ecm->dataInPipe.id, ecm->dataInPipe.maxPacketSize); 238 if (!req) { 239 return DListIsEmpty(head) ? HDF_FAILURE : HDF_SUCCESS; 240 } 241 242 req->complete = UsbEcmWriteComplete; 243 req->context = port; 244 DListInsertTail(&req->list, head); 245 port->writeAllocated++; 246 } 247 return HDF_SUCCESS; 248} 249 250static int32_t UsbEcmStartIo(struct UsbEcm *port) 251{ 252 struct DListHead *head = &port->readPool; 253 int32_t ret = HDF_SUCCESS; 254 uint32_t started; 255 256 /* allocate requests for read/write */ 257 if (port->readAllocated == 0) { 258 ret = UsbEcmAllocReadRequests(port, QUEUE_SIZE); 259 if (ret != HDF_SUCCESS) { 260 return ret; 261 } 262 } 263 if (port->writeAllocated == 0) { 264 ret = UsbEcmAllocWriteRequests(port, QUEUE_SIZE); 265 if (ret != HDF_SUCCESS) { 266 UsbEcmFreeRequests(head, &port->readAllocated); 267 return ret; 268 } 269 } 270 271 started = UsbEcmStartRx(port); 272 if (started) { 273 UsbEcmStartTx(port); 274 } else { 275 UsbEcmFreeRequests(head, &port->readAllocated); 276 UsbEcmFreeRequests(&port->writePool, &port->writeAllocated); 277 ret = HDF_ERR_IO; 278 } 279 280 return ret; 281} 282 283 284static int32_t UsbEcmAllocFifo(struct DataFifo *fifo, uint32_t size) 285{ 286 if (!DataFifoIsInitialized(fifo)) { 287 void *data = OsalMemAlloc(size); 288 if (data == NULL) { 289 HDF_LOGE("%{public}s: allocate fifo data buffer failed", __func__); 290 return HDF_ERR_MALLOC_FAIL; 291 } 292 DataFifoInit(fifo, size, data); 293 } 294 return HDF_SUCCESS; 295} 296 297static int32_t UsbEcmOpen(struct UsbEcm *port) 298{ 299 int32_t ret; 300 301 if (port == NULL) { 302 return HDF_ERR_INVALID_PARAM; 303 } 304 305 OsalMutexLock(&port->lock); 306 ret = UsbEcmAllocFifo(&port->writeFifo, WRITE_BUF_SIZE); 307 if (ret != HDF_SUCCESS) { 308 HDF_LOGE("%{public}s: UsbEcmAllocFifo failed", __func__); 309 goto OUT; 310 } 311 ret = UsbEcmAllocFifo(&port->readFifo, READ_BUF_SIZE); 312 if (ret != HDF_SUCCESS) { 313 HDF_LOGE("%{public}s: UsbEcmAllocFifo failed", __func__); 314 goto OUT; 315 } 316 DataFifoReset(&port->writeFifo); 317 DataFifoReset(&port->readFifo); 318 319 if (port->refCount++) { 320 HDF_LOGE("%{public}s: refCount failed", __func__); 321 goto OUT; 322 } 323 324 /* the ecm is enabled, start the io stream */ 325 if (port->ecm) { 326 HDF_LOGD("%{public}s: start usb io", __func__); 327 ret = UsbEcmStartIo(port); 328 if (ret != HDF_SUCCESS) { 329 goto OUT; 330 } 331 } 332 333OUT: 334 OsalMutexUnlock(&port->lock); 335 return HDF_SUCCESS; 336} 337 338static int32_t UsbEcmClose(struct UsbEcm *port) 339{ 340 if (port == NULL) { 341 return HDF_ERR_INVALID_PARAM; 342 } 343 344 OsalMutexLock(&port->lock); 345 if (port->refCount != 1) { 346 --port->refCount; 347 goto OUT; 348 } 349 350 HDF_LOGD("%{public}s: close usb serial", __func__); 351 352 DataFifoReset(&port->writeFifo); 353 DataFifoReset(&port->readFifo); 354 port->refCount = 0; 355 356OUT: 357 OsalMutexUnlock(&port->lock); 358 return HDF_SUCCESS; 359} 360 361static int32_t UsbEcmRead(struct UsbEcm *port, struct HdfSBuf *reply) 362{ 363 uint32_t len; 364 int32_t ret = HDF_SUCCESS; 365 uint8_t *buf = NULL; 366 OsalMutexLock(&port->lock); 367 OsalMutexLock(&port->lockReadFifo); 368 if (DataFifoIsEmpty(&port->readFifo)) { 369 OsalMutexUnlock(&port->lockReadFifo); 370 OsalMutexUnlock(&port->lock); 371 return 0; 372 } 373 374 buf = (uint8_t *)OsalMemCalloc(DataFifoLen(&port->readFifo) + sizeof(uint32_t)); 375 if (buf == NULL) { 376 HDF_LOGE("%{public}s: OsalMemCalloc error", __func__); 377 OsalMutexUnlock(&port->lockReadFifo); 378 OsalMutexUnlock(&port->lock); 379 return HDF_ERR_MALLOC_FAIL; 380 } 381 382 len = DataFifoRead(&port->readFifo, buf, DataFifoLen(&port->readFifo)); 383 if (len == 0) { 384 HDF_LOGE("%{public}s: no data", __func__); 385 ret = HDF_ERR_IO; 386 OsalMutexUnlock(&port->lockReadFifo); 387 goto OUT; 388 } 389 OsalMutexUnlock(&port->lockReadFifo); 390 391 bool bufok = HdfSbufWriteBuffer(reply, (const void *)buf, len); 392 if (!bufok) { 393 HDF_LOGE("UsbEcmRead HdfSbufWriteBuffer error"); 394 ret = HDF_ERR_IO; 395 goto OUT; 396 } 397 398OUT: 399 if (port->ecm) { 400 UsbEcmStartRx(port); 401 } 402 OsalMemFree(buf); 403 OsalMutexUnlock(&port->lock); 404 return ret; 405} 406 407static int32_t UsbEcmWrite(struct UsbEcm *port, struct HdfSBuf *data) 408{ 409 uint32_t size = 0; 410 uint8_t *buf = NULL; 411 412 if (!HdfSbufReadBuffer(data, (const void **)&buf, &size)) { 413 HDF_LOGE("UsbEcmWrite HdfSbufReadBuffer err"); 414 return HDF_ERR_IO; 415 } 416 417 OsalMutexLock(&port->lock); 418 if (size > 0 && buf != NULL) { 419 OsalMutexLock(&port->lockWriteFifo); 420 size = DataFifoWrite(&port->writeFifo, buf, size); 421 OsalMutexUnlock(&port->lockWriteFifo); 422 } 423 if (port->ecm) { 424 UsbEcmStartTx(port); 425 } 426 OsalMutexUnlock(&port->lock); 427 return HDF_SUCCESS; 428} 429 430void UsbFnNotifyRequest(struct UsbFnRequest *req, struct UsbEcmDevice *ecm) 431{ 432 int32_t status; 433 ecm->notifyReq = NULL; 434 status = UsbFnSubmitRequestAsync(req); 435 if (status < 0) { 436 ecm->notifyReq = req; 437 HDF_LOGD("notify --> %{public}d", status); 438 } 439} 440 441static void EcmDoNotify(struct UsbEcmDevice *ecm) 442{ 443 struct UsbFnRequest *req = ecm->notifyReq; 444 struct UsbCdcNotification *event = NULL; 445 uint32_t *data = NULL; 446 447 if (!req) { 448 return; 449 } 450 ecm->isOpen = true; 451 event = (struct UsbCdcNotification *)req->buf; 452 if (event == NULL) { 453 return; 454 } 455 switch (ecm->notifyState) { 456 case ECM_NOTIFY_NONE: 457 return; 458 459 case ECM_NOTIFY_CONNECT: 460 event->bNotificationType = USB_DDK_CDC_NOTIFY_NETWORK_CONNECTION; 461 if (ecm->isOpen) { 462 event->wValue = CPU_TO_LE16(1); 463 } else { 464 event->wValue = CPU_TO_LE16(0); 465 } 466 event->wLength = 0; 467 req->length = sizeof(*event); 468 469 HDF_LOGD("notify connect %{public}s", ecm->isOpen ? "true" : "false"); 470 ecm->notifyState = ECM_NOTIFY_SPEED; 471 break; 472 473 case ECM_NOTIFY_SPEED: 474 event->bNotificationType = USB_DDK_CDC_NOTIFY_SPEED_CHANGE; 475 event->wValue = CPU_TO_LE16(0); 476 event->wLength = CPU_TO_LE16(0x08); 477 req->length = ECM_STATUS_BYTECOUNT; 478 479 /* SPEED_CHANGE data is up/down speeds in bits/sec */ 480 data = (uint32_t *)((char *)req->buf + sizeof(*event)); 481 data[0] = CPU_TO_LE32(EcmBitrate()); 482 data[1] = data[0]; 483 484 HDF_LOGD("notify speed %{public}d", EcmBitrate()); 485 ecm->notifyState = ECM_NOTIFY_NONE; 486 break; 487 488 default: 489 break; 490 } 491 event->bmRequestType = 0xA1; 492 event->wIndex = CPU_TO_LE16(ecm->ctrlId); 493 UsbFnNotifyRequest(req, ecm); 494} 495 496static void EcmNotifyComplete(uint8_t pipe, struct UsbFnRequest *req) 497{ 498 struct UsbEcmDevice *ecm = req->context; 499 struct UsbCdcNotification *event = req->buf; 500 ecm->notifyReq = req; 501 if (req->status == 0) { 502 EcmDoNotify(ecm); 503 } else { 504 HDF_LOGD("event %{public}d --> %{public}d", event->bNotificationType, req->status); 505 } 506} 507 508static int32_t EcmSetup(const struct UsbEcmDevice *ecm, const struct UsbFnCtrlRequest *ctrl) 509{ 510 struct UsbFnRequest *req = ecm->ep0Req; 511 int32_t ret = -1; 512 uint16_t index = LE16_TO_CPU(ctrl->index); 513 uint16_t value = LE16_TO_CPU(ctrl->value); 514 uint16_t length = LE16_TO_CPU(ctrl->length); 515 516 switch ((ctrl->reqType << 0x08) | ctrl->request) { 517 case ((USB_DDK_DIR_OUT | USB_DDK_TYPE_CLASS | USB_DDK_RECIP_INTERFACE) << 0x08) | 518 USB_DDK_CDC_SET_ETHERNET_PACKET_FILTER: 519 if (length != 0 || index != ecm->ctrlId) { 520 break; 521 } 522 HDF_LOGD("packet filter %{public}02x", value); 523 ret = 0; 524 break; 525 526 default: 527 HDF_LOGW( 528 "invalid control req%{public}02x.%{public}02x v%{public}04x i%{public}04x l%{public}hu", 529 ctrl->reqType, ctrl->request, value, index, length); 530 } 531 532 if (ret >= 0) { 533 HDF_LOGD("ecm req%{public}02x.%{public}02x v%{public}04x i%{public}04x l%{public}d", 534 ctrl->reqType, ctrl->request, value, index, length); 535 req->length = (uint32_t)ret; 536 ret = UsbFnSubmitRequestSync(req, 0); 537 if (ret < 0) { 538 HDF_LOGD("ecm req %{public}02x.%{public}02x response err %{public}d", ctrl->reqType, ctrl->request, ret); 539 } 540 } 541 542 return value; 543} 544 545static int32_t EcmDeviceDispatch( 546 struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply) 547{ 548 struct UsbEcmDevice *ecm = NULL; 549 struct UsbEcm *port = NULL; 550 int32_t ret; 551 if (client == NULL || client->device == NULL || client->device->service == NULL) { 552 HDF_LOGE("%{public}s: client is NULL", __func__); 553 return HDF_ERR_INVALID_OBJECT; 554 } 555 if (data == NULL || reply == NULL) { 556 HDF_LOGE("%{public}s: data or reply is NULL", __func__); 557 return HDF_ERR_INVALID_OBJECT; 558 } 559 560 if (HdfDeviceObjectCheckInterfaceDesc(client->device, data) == false) { 561 HDF_LOGE("%{public}s:%{public}d check interface desc fail", __func__, __LINE__); 562 return HDF_ERR_INVALID_PARAM; 563 } 564 565 switch (cmd) { 566 case USB_ECM_INIT: 567 return EcmInit(client->device); 568 case USB_ECM_RELEASE: 569 return EcmRelease(client->device); 570 default: 571 break; 572 } 573 ecm = (struct UsbEcmDevice *)client->device->service; 574 port = ecm->port; 575 if (port == NULL) { 576 return HDF_ERR_IO; 577 } 578 OsalMutexLock(&port->lockRW); 579 switch (cmd) { 580 case USB_ECM_OPEN: 581 ret = UsbEcmOpen(port); 582 break; 583 case USB_ECM_CLOSE: 584 ret = UsbEcmClose(port); 585 break; 586 case USB_ECM_READ: 587 ret = UsbEcmRead(port, reply); 588 break; 589 case USB_ECM_WRITE: 590 ret = UsbEcmWrite(port, data); 591 break; 592 default: 593 ret = HDF_ERR_NOT_SUPPORT; 594 break; 595 } 596 OsalMutexUnlock(&port->lockRW); 597 return ret; 598} 599 600static int32_t EcmEnable(struct UsbEcmDevice *ecm) 601{ 602 (void)ecm; 603 return HDF_SUCCESS; 604} 605 606static void EcmDisable(const struct UsbEcmDevice *ecm) 607{ 608 (void)ecm; 609 return; 610} 611 612static void UsbEcmEventCallback(struct UsbFnEvent *event) 613{ 614 struct UsbEcmDevice *ecm = NULL; 615 616 if (event == NULL || event->context == NULL) { 617 HDF_LOGE("%{public}s: event is null", __func__); 618 return; 619 } 620 621 ecm = (struct UsbEcmDevice *)event->context; 622 switch (event->type) { 623 case USBFN_STATE_BIND: 624 HDF_LOGI("%{public}s: receive bind event", __func__); 625 break; 626 case USBFN_STATE_UNBIND: 627 HDF_LOGI("%{public}s: receive unbind event", __func__); 628 break; 629 case USBFN_STATE_ENABLE: 630 HDF_LOGI("%{public}s: receive enable event", __func__); 631 EcmEnable(ecm); 632 break; 633 case USBFN_STATE_DISABLE: 634 HDF_LOGI("%{public}s: receive disable event", __func__); 635 EcmDisable(ecm); 636 break; 637 case USBFN_STATE_SETUP: 638 HDF_LOGI("%{public}s: receive setup event", __func__); 639 if (event->setup != NULL) { 640 EcmSetup(ecm, event->setup); 641 } 642 break; 643 case USBFN_STATE_SUSPEND: 644 HDF_LOGI("%{public}s: receive suspend event", __func__); 645 break; 646 case USBFN_STATE_RESUME: 647 HDF_LOGI("%{public}s: receive resume event", __func__); 648 break; 649 default: 650 break; 651 } 652} 653 654static int32_t EcmAllocNotifyRequest(struct UsbEcmDevice *ecm) 655{ 656 /* allocate notification request */ 657 ecm->notifyReq = 658 UsbFnAllocRequest(ecm->ctrlIface.handle, ecm->notifyPipe.id, sizeof(struct UsbCdcNotification) * USBCDC_LEN); 659 if (ecm->notifyReq == NULL) { 660 HDF_LOGE("%{public}s: allocate notify request failed", __func__); 661 return HDF_FAILURE; 662 } 663 ecm->notifyReq->complete = EcmNotifyComplete; 664 ecm->notifyReq->context = ecm; 665 666 return HDF_SUCCESS; 667} 668 669static int32_t EcmAllocEp0Request(struct UsbEcmDevice *ecm) 670{ 671 /* allocate notification request */ 672 ecm->ep0Req = UsbFnAllocCtrlRequest(ecm->ctrlIface.handle, ECM_STATUS_BYTECOUNT); 673 if (ecm->ep0Req == NULL) { 674 HDF_LOGE("%{public}s: allocate ep0Req request failed", __func__); 675 return HDF_FAILURE; 676 } 677 return HDF_SUCCESS; 678} 679 680static int32_t EcmParseEachPipe(struct UsbEcmDevice *ecm, struct UsbEcmInterface *iface) 681{ 682 struct UsbFnInterface *fnIface = iface->fn; 683 uint32_t repetIdx = 0; 684 for (int32_t i = 0; i < fnIface->info.numPipes; i++) { 685 struct UsbFnPipeInfo pipeInfo; 686 (void)memset_s(&pipeInfo, sizeof(pipeInfo), 0, sizeof(pipeInfo)); 687 int32_t ret = UsbFnGetInterfacePipeInfo(fnIface, (uint8_t)i, &pipeInfo); 688 if (ret != HDF_SUCCESS) { 689 HDF_LOGE("%{public}s: get pipe info error", __func__); 690 return HDF_FAILURE; 691 } 692 693 switch (pipeInfo.type) { 694 case USB_PIPE_TYPE_INTERRUPT: 695 ecm->notifyPipe.id = pipeInfo.id; 696 ecm->notifyPipe.maxPacketSize = pipeInfo.maxPacketSize; 697 ecm->ctrlIface = *iface; 698 break; 699 case USB_PIPE_TYPE_BULK: 700 if (pipeInfo.dir == USB_PIPE_DIRECTION_IN) { 701 ecm->dataInPipe.id = pipeInfo.id; 702 ecm->dataInPipe.maxPacketSize = pipeInfo.maxPacketSize; 703 ecm->dataIface = *iface; 704 } else { 705 ecm->dataOutPipe.id = pipeInfo.id; 706 ecm->dataOutPipe.maxPacketSize = pipeInfo.maxPacketSize; 707 } 708 break; 709 default: 710 if (repetIdx < WAIT_UDC_MAX_LOOP) { 711 usleep(WAIT_UDC_TIME); 712 i--; 713 } 714 repetIdx++; 715 HDF_LOGE("%{public}s: pipe type %{public}d don't support", __func__, pipeInfo.type); 716 break; 717 } 718 } 719 720 return HDF_SUCCESS; 721} 722 723static int32_t EcmParseEcmIface(struct UsbEcmDevice *ecm, struct UsbFnInterface *fnIface) 724{ 725 int32_t ret; 726 struct UsbEcmInterface iface; 727 UsbFnInterfaceHandle handle = UsbFnOpenInterface(fnIface); 728 if (handle == NULL) { 729 HDF_LOGE("%{public}s: open interface failed", __func__); 730 return HDF_FAILURE; 731 } 732 iface.fn = fnIface; 733 iface.handle = handle; 734 735 ret = EcmParseEachPipe(ecm, &iface); 736 if (ret != HDF_SUCCESS) { 737 return HDF_FAILURE; 738 } 739 return HDF_SUCCESS; 740} 741 742static int32_t EcmParseEachIface(struct UsbEcmDevice *ecm, struct UsbFnDevice *fnDev) 743{ 744 struct UsbFnInterface *fnIface = NULL; 745 uint32_t i; 746 747 for (i = 0; i < fnDev->numInterfaces; i++) { 748 fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i); 749 if (fnIface == NULL) { 750 HDF_LOGE("%{public}s: get interface failed", __func__); 751 return HDF_FAILURE; 752 } 753 754 if (fnIface->info.subclass == USB_DDK_CDC_SUBCLASS_ETHERNET) { 755 (void)EcmParseEcmIface(ecm, fnIface); 756 fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i + 1); 757 if (fnIface == NULL) { 758 HDF_LOGE("%{public}s: get interface failed", __func__); 759 return HDF_FAILURE; 760 } 761 (void)EcmParseEcmIface(ecm, fnIface); 762 return HDF_SUCCESS; 763 } 764 } 765 766 return HDF_FAILURE; 767} 768 769static int32_t EcmCreateFuncDevice(struct UsbEcmDevice *ecm, struct DeviceResourceIface *iface) 770{ 771 struct UsbFnDevice *fnDev = NULL; 772 int32_t ret; 773 774 if (iface->GetString(ecm->device->property, "udc_name", (const char **)&ecm->udcName, UDC_NAME) != HDF_SUCCESS) { 775 HDF_LOGE("%{public}s: read udc_name failed, use default", __func__); 776 return HDF_FAILURE; 777 } 778 779 fnDev = (struct UsbFnDevice *)UsbFnGetDevice(ecm->udcName); 780 if (fnDev == NULL) { 781 HDF_LOGE("%{public}s: create usb function device failed", __func__); 782 return HDF_FAILURE; 783 } 784 785 ret = EcmParseEachIface(ecm, fnDev); 786 if (ret != HDF_SUCCESS) { 787 HDF_LOGE("%{public}s: get pipes failed", __func__); 788 goto ERR; 789 } 790 791 ecm->fnDev = fnDev; 792 return HDF_SUCCESS; 793 794ERR: 795 return ret; 796} 797 798static void EcmFreeNotifyRequest(struct UsbEcmDevice *ecm) 799{ 800 int32_t ret; 801 802 /* free notification request */ 803 ret = UsbFnFreeRequest(ecm->notifyReq); 804 if (ret != HDF_SUCCESS) { 805 HDF_LOGE("%{public}s: free notify request failed", __func__); 806 return; 807 } 808 ecm->notifyReq = NULL; 809} 810 811static int32_t EcmReleaseFuncDevice(struct UsbEcmDevice *ecm) 812{ 813 int32_t ret = HDF_SUCCESS; 814 if (ecm->fnDev == NULL) { 815 HDF_LOGE("%{public}s: fnDev is null", __func__); 816 return HDF_FAILURE; 817 } 818 (void)UsbFnFreeRequest(ecm->ep0Req); 819 (void)EcmFreeNotifyRequest(ecm); 820 UsbFnCloseInterface(ecm->ctrlIface.handle); 821 (void)UsbFnCloseInterface(ecm->dataIface.handle); 822 (void)UsbFnStopRecvInterfaceEvent(ecm->ctrlIface.fn); 823 return ret; 824} 825 826static int32_t UsbEcmAlloc(struct UsbEcmDevice *ecm) 827{ 828 struct UsbEcm *port = NULL; 829 830 port = (struct UsbEcm *)OsalMemCalloc(sizeof(*port)); 831 if (port == NULL) { 832 HDF_LOGE("%{public}s: Alloc usb serial port failed", __func__); 833 return HDF_FAILURE; 834 } 835 836 if (OsalMutexInit(&port->lock) != HDF_SUCCESS) { 837 HDF_LOGE("%{public}s: init lock fail!", __func__); 838 OsalMemFree(port); 839 return HDF_FAILURE; 840 } 841 842 if (OsalMutexInit(&port->lockRW) != HDF_SUCCESS) { 843 HDF_LOGE("%{public}s: init lock fail!", __func__); 844 OsalMutexDestroy(&port->lock); 845 OsalMemFree(port); 846 return HDF_FAILURE; 847 } 848 849 if (OsalMutexInit(&port->lockReadFifo) != HDF_SUCCESS) { 850 HDF_LOGE("%{public}s: init lock fail!", __func__); 851 OsalMutexDestroy(&port->lock); 852 OsalMutexDestroy(&port->lockRW); 853 OsalMemFree(port); 854 return HDF_FAILURE; 855 } 856 857 if (OsalMutexInit(&port->lockWriteFifo) != HDF_SUCCESS) { 858 HDF_LOGE("%{public}s: init lock fail!", __func__); 859 OsalMutexDestroy(&port->lock); 860 OsalMutexDestroy(&port->lockRW); 861 OsalMutexDestroy(&port->lockReadFifo); 862 OsalMemFree(port); 863 return HDF_FAILURE; 864 } 865 DListHeadInit(&port->readPool); 866 DListHeadInit(&port->readQueue); 867 DListHeadInit(&port->writePool); 868 869 ecm->port = port; 870 return HDF_SUCCESS; 871} 872 873static void UsbEcmFree(struct UsbEcmDevice *ecm) 874{ 875 if (ecm != NULL && ecm->port != NULL) { 876 OsalMutexDestroy(&ecm->port->lock); 877 OsalMutexDestroy(&ecm->port->lockRW); 878 OsalMutexDestroy(&ecm->port->lockReadFifo); 879 OsalMutexDestroy(&ecm->port->lockWriteFifo); 880 OsalMemFree(ecm->port); 881 ecm->port = NULL; 882 } 883} 884 885/* HdfDriverEntry implementations */ 886static int32_t EcmDriverBind(struct HdfDeviceObject *device) 887{ 888 struct UsbEcmDevice *ecm = NULL; 889 890 if (device == NULL) { 891 HDF_LOGE("%{public}s: device is null", __func__); 892 return HDF_ERR_INVALID_OBJECT; 893 } 894 895 ecm = (struct UsbEcmDevice *)OsalMemCalloc(sizeof(*ecm)); 896 if (ecm == NULL) { 897 HDF_LOGE("%{public}s: Alloc usb ecm device failed", __func__); 898 return HDF_FAILURE; 899 } 900 ecm->ctrlId = 0; 901 ecm->dataId = 1; 902 if (OsalMutexInit(&ecm->lock) != HDF_SUCCESS) { 903 HDF_LOGE("%{public}s: init lock fail!", __func__); 904 OsalMemFree(ecm); 905 return HDF_FAILURE; 906 } 907 908 if (HdfDeviceObjectSetInterfaceDesc(device, "hdf.usb.usbfn") != HDF_SUCCESS) { 909 HDF_LOGE(" Set Desc fail!"); 910 OsalMemFree(ecm); 911 return HDF_FAILURE; 912 } 913 914 ecm->device = device; 915 device->service = &(ecm->service); 916 if (ecm->device->service) { 917 ecm->device->service->Dispatch = EcmDeviceDispatch; 918 } 919 return HDF_SUCCESS; 920} 921 922static int32_t EcmInit(struct HdfDeviceObject *device) 923{ 924 struct UsbEcmDevice *ecm = NULL; 925 struct DeviceResourceIface *iface = NULL; 926 int32_t ret; 927 928 if (device == NULL) { 929 HDF_LOGE("%{public}s: device is null", __func__); 930 return HDF_ERR_INVALID_OBJECT; 931 } 932 933 ecm = (struct UsbEcmDevice *)device->service; 934 if (ecm == NULL || ecm->initFlag) { 935 HDF_LOGE("%{public}s: ecm is null", __func__); 936 return HDF_FAILURE; 937 } 938 939 iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); 940 if (iface == NULL || iface->GetUint32 == NULL) { 941 HDF_LOGE("%{public}s: face is invalid", __func__); 942 return HDF_FAILURE; 943 } 944 945 ret = EcmCreateFuncDevice(ecm, iface); 946 if (ret != HDF_SUCCESS) { 947 HDF_LOGE("%{public}s: EcmCreateFuncDevice failed", __func__); 948 return ret; 949 } 950 951 ret = UsbEcmAlloc(ecm); 952 if (ret != HDF_SUCCESS) { 953 HDF_LOGE("%{public}s: UsbEcmAlloc failed", __func__); 954 return ret; 955 } 956 957 ret = EcmAllocEp0Request(ecm); 958 if (ret != HDF_SUCCESS) { 959 HDF_LOGE("%{public}s: EcmAllocEp0Request failed", __func__); 960 goto ERR; 961 } 962 963 ret = EcmAllocNotifyRequest(ecm); 964 if (ret != HDF_SUCCESS) { 965 HDF_LOGE("%{public}s: EcmAllocNotifyRequest failed", __func__); 966 goto ERR; 967 } 968 969 ret = UsbFnStartRecvInterfaceEvent(ecm->ctrlIface.fn, RECEIVE_ALL_EVENTS, UsbEcmEventCallback, ecm); 970 if (ret != HDF_SUCCESS) { 971 HDF_LOGE("%{public}s: register event callback failed", __func__); 972 goto ERR; 973 } 974 ecm->initFlag = true; 975 return ret; 976ERR: 977 UsbEcmFree(ecm); 978 (void)EcmReleaseFuncDevice(ecm); 979 return ret; 980} 981 982static int32_t EcmRelease(struct HdfDeviceObject *device) 983{ 984 struct UsbEcmDevice *ecm = NULL; 985 986 if (device == NULL) { 987 HDF_LOGE("%{public}s: device is NULL", __func__); 988 return HDF_FAILURE; 989 } 990 991 ecm = (struct UsbEcmDevice *)device->service; 992 if (ecm == NULL) { 993 HDF_LOGE("%{public}s: ecm is null", __func__); 994 return HDF_FAILURE; 995 } 996 if (ecm->initFlag == false) { 997 HDF_LOGE("%{public}s: ecm not init!", __func__); 998 return HDF_FAILURE; 999 } 1000 UsbEcmFree(ecm); 1001 (void)EcmReleaseFuncDevice(ecm); 1002 ecm->initFlag = false; 1003 return HDF_SUCCESS; 1004} 1005 1006static int32_t EcmDriverInit(struct HdfDeviceObject *device) 1007{ 1008 (void)device; 1009 HDF_LOGE("%{public}s: usbfn do nothing...", __func__); 1010 return 0; 1011} 1012 1013static void EcmDriverRelease(struct HdfDeviceObject *device) 1014{ 1015 struct UsbEcmDevice *ecm = NULL; 1016 if (device == NULL) { 1017 HDF_LOGE("%{public}s: device is NULL", __func__); 1018 return; 1019 } 1020 1021 ecm = (struct UsbEcmDevice *)device->service; 1022 if (ecm == NULL) { 1023 HDF_LOGE("%{public}s: ecm is null", __func__); 1024 return; 1025 } 1026 1027 (void)OsalMutexDestroy(&ecm->lock); 1028 OsalMemFree(ecm); 1029 device->service = NULL; 1030} 1031 1032struct HdfDriverEntry g_ecmDriverEntry = { 1033 .moduleVersion = 1, 1034 .moduleName = "usbfn_cdcecm", 1035 .Bind = EcmDriverBind, 1036 .Init = EcmDriverInit, 1037 .Release = EcmDriverRelease, 1038}; 1039 1040HDF_INIT(g_ecmDriverEntry); 1041