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