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