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