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