• 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     HDF_LOGD("%{public}s: enter", __func__);
316     int32_t ret;
317 
318     if (port == NULL) {
319         HDF_LOGE("%{public}s: port is null", __func__);
320         return HDF_ERR_INVALID_PARAM;
321     }
322 
323     OsalMutexLock(&port->lock);
324     ret = UsbEcmAllocFifo(&port->writeFifo, WRITE_BUF_SIZE);
325     if (ret != HDF_SUCCESS) {
326         HDF_LOGE("%{public}s: UsbEcmAllocFifo failed", __func__);
327         goto OUT;
328     }
329     ret = UsbEcmAllocFifo(&port->readFifo, READ_BUF_SIZE);
330     if (ret != HDF_SUCCESS) {
331         HDF_LOGE("%{public}s: UsbEcmAllocFifo failed", __func__);
332         goto OUT;
333     }
334     DataFifoReset(&port->writeFifo);
335     DataFifoReset(&port->readFifo);
336 
337     if (port->refCount++) {
338         HDF_LOGE("%{public}s: refCount failed", __func__);
339         goto OUT;
340     }
341 
342     /* the ecm is enabled, start the io stream */
343     if (port->ecm) {
344         HDF_LOGD("%{public}s: start usb io", __func__);
345         ret = UsbEcmStartIo(port);
346         if (ret != HDF_SUCCESS) {
347             goto OUT;
348         }
349     }
350 
351 OUT:
352     OsalMutexUnlock(&port->lock);
353     HDF_LOGD("%{public}s: exit", __func__);
354     return HDF_SUCCESS;
355 }
356 
UsbEcmClose(struct UsbEcm * port)357 static int32_t UsbEcmClose(struct UsbEcm *port)
358 {
359     HDF_LOGD("%{public}s: enter", __func__);
360     if (port == NULL) {
361         HDF_LOGE("%{public}s: port is null", __func__);
362         return HDF_ERR_INVALID_PARAM;
363     }
364 
365     OsalMutexLock(&port->lock);
366     if (port->refCount != 1) {
367         --port->refCount;
368         goto OUT;
369     }
370 
371     HDF_LOGD("%{public}s: close usb serial", __func__);
372 
373     DataFifoReset(&port->writeFifo);
374     DataFifoReset(&port->readFifo);
375     port->refCount = 0;
376 
377 OUT:
378     OsalMutexUnlock(&port->lock);
379     HDF_LOGD("%{public}s: exit", __func__);
380     return HDF_SUCCESS;
381 }
382 
UsbEcmRead(struct UsbEcm * port,struct HdfSBuf * reply)383 static int32_t UsbEcmRead(struct UsbEcm *port, struct HdfSBuf *reply)
384 {
385     HDF_LOGI("%{public}s: enter", __func__);
386     uint32_t len;
387     int32_t ret = HDF_SUCCESS;
388     uint8_t *buf = NULL;
389     OsalMutexLock(&port->lock);
390     OsalMutexLock(&port->lockReadFifo);
391     if (DataFifoIsEmpty(&port->readFifo)) {
392         OsalMutexUnlock(&port->lockReadFifo);
393         OsalMutexUnlock(&port->lock);
394         HDF_LOGI("%{public}s: data fifl is empty", __func__);
395         return 0;
396     }
397 
398     buf = (uint8_t *)OsalMemCalloc(DataFifoLen(&port->readFifo) + sizeof(uint32_t));
399     if (buf == NULL) {
400         HDF_LOGE("%{public}s: OsalMemCalloc error", __func__);
401         OsalMutexUnlock(&port->lockReadFifo);
402         OsalMutexUnlock(&port->lock);
403         return HDF_ERR_MALLOC_FAIL;
404     }
405 
406     len = DataFifoRead(&port->readFifo, buf, DataFifoLen(&port->readFifo));
407     if (len == 0) {
408         HDF_LOGE("%{public}s: no data", __func__);
409         ret = HDF_ERR_IO;
410         OsalMutexUnlock(&port->lockReadFifo);
411         goto OUT;
412     }
413     OsalMutexUnlock(&port->lockReadFifo);
414 
415     bool bufok = HdfSbufWriteBuffer(reply, (const void *)buf, len);
416     if (!bufok) {
417         HDF_LOGE("UsbEcmRead HdfSbufWriteBuffer error");
418         ret = HDF_ERR_IO;
419         goto OUT;
420     }
421 
422 OUT:
423     if (port->ecm) {
424         UsbEcmStartRx(port);
425     }
426     OsalMemFree(buf);
427     OsalMutexUnlock(&port->lock);
428     HDF_LOGD("%{public}s: exit", __func__);
429     return ret;
430 }
431 
UsbEcmWrite(struct UsbEcm * port,struct HdfSBuf * data)432 static int32_t UsbEcmWrite(struct UsbEcm *port, struct HdfSBuf *data)
433 {
434     HDF_LOGD("%{public}s: enter", __func__);
435     uint32_t size = 0;
436     uint8_t *buf = NULL;
437 
438     if (!HdfSbufReadBuffer(data, (const void **)&buf, &size)) {
439         HDF_LOGE("UsbEcmWrite HdfSbufReadBuffer err");
440         return HDF_ERR_IO;
441     }
442 
443     OsalMutexLock(&port->lock);
444     if (size > 0 && buf != NULL) {
445         OsalMutexLock(&port->lockWriteFifo);
446         size = DataFifoWrite(&port->writeFifo, buf, size);
447         OsalMutexUnlock(&port->lockWriteFifo);
448     } else {
449         HDF_LOGE("%{public}s: buf is null", __func__);
450     }
451     if (port->ecm) {
452         UsbEcmStartTx(port);
453     }
454     OsalMutexUnlock(&port->lock);
455     HDF_LOGD("%{public}s: exit", __func__);
456     return HDF_SUCCESS;
457 }
458 
UsbFnNotifyRequest(struct UsbFnRequest * req,struct UsbEcmDevice * ecm)459 void UsbFnNotifyRequest(struct UsbFnRequest *req, struct UsbEcmDevice *ecm)
460 {
461     int32_t status;
462     ecm->notifyReq = NULL;
463     status = UsbFnSubmitRequestAsync(req);
464     if (status < 0) {
465         ecm->notifyReq = req;
466         HDF_LOGD("notify --> %{public}d", status);
467     }
468 }
469 
EcmDoNotify(struct UsbEcmDevice * ecm)470 static void EcmDoNotify(struct UsbEcmDevice *ecm)
471 {
472     struct UsbFnRequest *req = ecm->notifyReq;
473     struct UsbCdcNotification *event = NULL;
474     uint32_t *data = NULL;
475 
476     if (!req) {
477         return;
478     }
479     ecm->isOpen = true;
480     event = (struct UsbCdcNotification *)req->buf;
481     if (event == NULL) {
482         return;
483     }
484     switch (ecm->notifyState) {
485         case ECM_NOTIFY_NONE:
486             return;
487 
488         case ECM_NOTIFY_CONNECT:
489             event->bNotificationType = USB_DDK_CDC_NOTIFY_NETWORK_CONNECTION;
490             if (ecm->isOpen) {
491                 event->wValue = CPU_TO_LE16(1);
492             } else {
493                 event->wValue = CPU_TO_LE16(0);
494             }
495             event->wLength = 0;
496             req->length = sizeof(*event);
497 
498             HDF_LOGD("notify connect %{public}s", ecm->isOpen ? "true" : "false");
499             ecm->notifyState = ECM_NOTIFY_SPEED;
500             break;
501 
502         case ECM_NOTIFY_SPEED:
503             event->bNotificationType = USB_DDK_CDC_NOTIFY_SPEED_CHANGE;
504             event->wValue = CPU_TO_LE16(0);
505             event->wLength = CPU_TO_LE16(0x08);
506             req->length = ECM_STATUS_BYTECOUNT;
507 
508             /* SPEED_CHANGE data is up/down speeds in bits/sec */
509             data = (uint32_t *)((char *)req->buf + sizeof(*event));
510             data[0] = CPU_TO_LE32(EcmBitrate());
511             data[1] = data[0];
512 
513             HDF_LOGD("notify speed %{public}d", EcmBitrate());
514             ecm->notifyState = ECM_NOTIFY_NONE;
515             break;
516 
517         default:
518             break;
519     }
520     event->bmRequestType = 0xA1;
521     event->wIndex = CPU_TO_LE16(ecm->ctrlId);
522     UsbFnNotifyRequest(req, ecm);
523 }
524 
EcmNotifyComplete(uint8_t pipe,struct UsbFnRequest * req)525 static void EcmNotifyComplete(uint8_t pipe, struct UsbFnRequest *req)
526 {
527     struct UsbEcmDevice *ecm = req->context;
528     struct UsbCdcNotification *event = req->buf;
529     ecm->notifyReq = req;
530     if (req->status == 0) {
531         EcmDoNotify(ecm);
532     } else {
533         HDF_LOGD("event %{public}d --> %{public}d", event->bNotificationType, req->status);
534     }
535 }
536 
EcmSetup(const struct UsbEcmDevice * ecm,const struct UsbFnCtrlRequest * ctrl)537 static int32_t EcmSetup(const struct UsbEcmDevice *ecm, const struct UsbFnCtrlRequest *ctrl)
538 {
539     struct UsbFnRequest *req = ecm->ep0Req;
540     int32_t ret = -1;
541     uint16_t index = LE16_TO_CPU(ctrl->index);
542     uint16_t value = LE16_TO_CPU(ctrl->value);
543     uint16_t length = LE16_TO_CPU(ctrl->length);
544 
545     switch ((ctrl->reqType << 0x08) | ctrl->request) {
546         case ((USB_DDK_DIR_OUT | USB_DDK_TYPE_CLASS | USB_DDK_RECIP_INTERFACE) << 0x08) |
547             USB_DDK_CDC_SET_ETHERNET_PACKET_FILTER:
548             if (length != 0 || index != ecm->ctrlId) {
549                 break;
550             }
551             HDF_LOGD("packet filter %{public}02x", value);
552             ret = 0;
553             break;
554 
555         default:
556             HDF_LOGW(
557                 "invalid control req%{public}02x.%{public}02x v%{public}04x i%{public}04x l%{public}hu",
558                 ctrl->reqType, ctrl->request, value, index, length);
559     }
560 
561     if (ret >= 0) {
562         HDF_LOGD("ecm req%{public}02x.%{public}02x v%{public}04x i%{public}04x l%{public}d",
563             ctrl->reqType, ctrl->request, value, index, length);
564         req->length = (uint32_t)ret;
565         ret = UsbFnSubmitRequestSync(req, 0);
566         if (ret < 0) {
567             HDF_LOGD("ecm req %{public}02x.%{public}02x response err %{public}d", ctrl->reqType, ctrl->request, ret);
568         }
569     }
570 
571     return value;
572 }
573 
EcmDeviceDispatch(struct HdfDeviceIoClient * client,int32_t cmd,struct HdfSBuf * data,struct HdfSBuf * reply)574 static int32_t EcmDeviceDispatch(
575     struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
576 {
577     struct UsbEcmDevice *ecm = NULL;
578     struct UsbEcm *port = NULL;
579     int32_t ret;
580     if (client == NULL || client->device == NULL || client->device->service == NULL) {
581         HDF_LOGE("%{public}s: client is NULL", __func__);
582         return HDF_ERR_INVALID_OBJECT;
583     }
584     if (data == NULL || reply == NULL) {
585         HDF_LOGE("%{public}s: data or reply is NULL", __func__);
586         return HDF_ERR_INVALID_OBJECT;
587     }
588 
589     if (HdfDeviceObjectCheckInterfaceDesc(client->device, data) == false) {
590         HDF_LOGE("%{public}s:%{public}d check interface desc fail", __func__, __LINE__);
591         return HDF_ERR_INVALID_PARAM;
592     }
593 
594     switch (cmd) {
595         case USB_ECM_INIT:
596             return EcmInit(client->device);
597         case USB_ECM_RELEASE:
598             return EcmRelease(client->device);
599         default:
600             break;
601     }
602     ecm = (struct UsbEcmDevice *)client->device->service;
603     port = ecm->port;
604     if (port == NULL) {
605         return HDF_ERR_IO;
606     }
607     OsalMutexLock(&port->lockRW);
608     switch (cmd) {
609         case USB_ECM_OPEN:
610             ret = UsbEcmOpen(port);
611             break;
612         case USB_ECM_CLOSE:
613             ret = UsbEcmClose(port);
614             break;
615         case USB_ECM_READ:
616             ret = UsbEcmRead(port, reply);
617             break;
618         case USB_ECM_WRITE:
619             ret = UsbEcmWrite(port, data);
620             break;
621         default:
622             ret = HDF_ERR_NOT_SUPPORT;
623             break;
624     }
625     OsalMutexUnlock(&port->lockRW);
626     return ret;
627 }
628 
EcmEnable(struct UsbEcmDevice * ecm)629 static int32_t EcmEnable(struct UsbEcmDevice *ecm)
630 {
631     (void)ecm;
632     return HDF_SUCCESS;
633 }
634 
EcmDisable(const struct UsbEcmDevice * ecm)635 static void EcmDisable(const struct UsbEcmDevice *ecm)
636 {
637     (void)ecm;
638     return;
639 }
640 
UsbEcmEventCallback(struct UsbFnEvent * event)641 static void UsbEcmEventCallback(struct UsbFnEvent *event)
642 {
643     struct UsbEcmDevice *ecm = NULL;
644 
645     if (event == NULL || event->context == NULL) {
646         HDF_LOGE("%{public}s: event is null", __func__);
647         return;
648     }
649 
650     ecm = (struct UsbEcmDevice *)event->context;
651     switch (event->type) {
652         case USBFN_STATE_BIND:
653             HDF_LOGI("%{public}s: receive bind event", __func__);
654             break;
655         case USBFN_STATE_UNBIND:
656             HDF_LOGI("%{public}s: receive unbind event", __func__);
657             break;
658         case USBFN_STATE_ENABLE:
659             HDF_LOGI("%{public}s: receive enable event", __func__);
660             EcmEnable(ecm);
661             break;
662         case USBFN_STATE_DISABLE:
663             HDF_LOGI("%{public}s: receive disable event", __func__);
664             EcmDisable(ecm);
665             break;
666         case USBFN_STATE_SETUP:
667             HDF_LOGI("%{public}s: receive setup event", __func__);
668             if (event->setup != NULL) {
669                 EcmSetup(ecm, event->setup);
670             }
671             break;
672         case USBFN_STATE_SUSPEND:
673             HDF_LOGI("%{public}s: receive suspend event", __func__);
674             break;
675         case USBFN_STATE_RESUME:
676             HDF_LOGI("%{public}s: receive resume event", __func__);
677             break;
678         default:
679             break;
680     }
681 }
682 
EcmAllocNotifyRequest(struct UsbEcmDevice * ecm)683 static int32_t EcmAllocNotifyRequest(struct UsbEcmDevice *ecm)
684 {
685     /* allocate notification request */
686     ecm->notifyReq =
687         UsbFnAllocRequest(ecm->ctrlIface.handle, ecm->notifyPipe.id, sizeof(struct UsbCdcNotification) * USBCDC_LEN);
688     if (ecm->notifyReq == NULL) {
689         HDF_LOGE("%{public}s: allocate notify request failed", __func__);
690         return HDF_FAILURE;
691     }
692     ecm->notifyReq->complete = EcmNotifyComplete;
693     ecm->notifyReq->context = ecm;
694 
695     return HDF_SUCCESS;
696 }
697 
EcmAllocEp0Request(struct UsbEcmDevice * ecm)698 static int32_t EcmAllocEp0Request(struct UsbEcmDevice *ecm)
699 {
700     /* allocate notification request */
701     ecm->ep0Req = UsbFnAllocCtrlRequest(ecm->ctrlIface.handle, ECM_STATUS_BYTECOUNT);
702     if (ecm->ep0Req == NULL) {
703         HDF_LOGE("%{public}s: allocate ep0Req request failed", __func__);
704         return HDF_FAILURE;
705     }
706     return HDF_SUCCESS;
707 }
708 
EcmParseEachPipe(struct UsbEcmDevice * ecm,struct UsbEcmInterface * iface)709 static int32_t EcmParseEachPipe(struct UsbEcmDevice *ecm, struct UsbEcmInterface *iface)
710 {
711     struct UsbFnInterface *fnIface = iface->fn;
712     uint32_t repetIdx = 0;
713     for (int32_t i = 0; i < fnIface->info.numPipes; i++) {
714         struct UsbFnPipeInfo pipeInfo;
715         (void)memset_s(&pipeInfo, sizeof(pipeInfo), 0, sizeof(pipeInfo));
716         int32_t ret = UsbFnGetInterfacePipeInfo(fnIface, (uint8_t)i, &pipeInfo);
717         if (ret != HDF_SUCCESS) {
718             HDF_LOGE("%{public}s: get pipe info error", __func__);
719             return HDF_FAILURE;
720         }
721 
722         switch (pipeInfo.type) {
723             case USB_PIPE_TYPE_INTERRUPT:
724                 ecm->notifyPipe.id = pipeInfo.id;
725                 ecm->notifyPipe.maxPacketSize = pipeInfo.maxPacketSize;
726                 ecm->ctrlIface = *iface;
727                 break;
728             case USB_PIPE_TYPE_BULK:
729                 if (pipeInfo.dir == USB_PIPE_DIRECTION_IN) {
730                     ecm->dataInPipe.id = pipeInfo.id;
731                     ecm->dataInPipe.maxPacketSize = pipeInfo.maxPacketSize;
732                     ecm->dataIface = *iface;
733                 } else {
734                     ecm->dataOutPipe.id = pipeInfo.id;
735                     ecm->dataOutPipe.maxPacketSize = pipeInfo.maxPacketSize;
736                 }
737                 break;
738             default:
739                 if (repetIdx < WAIT_UDC_MAX_LOOP) {
740                     usleep(WAIT_UDC_TIME);
741                     i--;
742                 }
743                 repetIdx++;
744                 HDF_LOGE("%{public}s: pipe type %{public}d don't support", __func__, pipeInfo.type);
745                 break;
746         }
747     }
748 
749     return HDF_SUCCESS;
750 }
751 
EcmParseEcmIface(struct UsbEcmDevice * ecm,struct UsbFnInterface * fnIface)752 static int32_t EcmParseEcmIface(struct UsbEcmDevice *ecm, struct UsbFnInterface *fnIface)
753 {
754     int32_t ret;
755     struct UsbEcmInterface iface;
756     UsbFnInterfaceHandle handle = UsbFnOpenInterface(fnIface);
757     if (handle == NULL) {
758         HDF_LOGE("%{public}s: open interface failed", __func__);
759         return HDF_FAILURE;
760     }
761     iface.fn = fnIface;
762     iface.handle = handle;
763 
764     ret = EcmParseEachPipe(ecm, &iface);
765     if (ret != HDF_SUCCESS) {
766         return HDF_FAILURE;
767     }
768     return HDF_SUCCESS;
769 }
770 
EcmParseEachIface(struct UsbEcmDevice * ecm,struct UsbFnDevice * fnDev)771 static int32_t EcmParseEachIface(struct UsbEcmDevice *ecm, struct UsbFnDevice *fnDev)
772 {
773     struct UsbFnInterface *fnIface = NULL;
774     uint32_t i;
775 
776     for (i = 0; i < fnDev->numInterfaces; i++) {
777         fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
778         if (fnIface == NULL) {
779             HDF_LOGE("%{public}s: get interface failed", __func__);
780             return HDF_FAILURE;
781         }
782 
783         if (fnIface->info.subclass == USB_DDK_CDC_SUBCLASS_ETHERNET) {
784             (void)EcmParseEcmIface(ecm, fnIface);
785             fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i + 1);
786             if (fnIface == NULL) {
787                 HDF_LOGE("%{public}s: get interface failed", __func__);
788                 return HDF_FAILURE;
789             }
790             (void)EcmParseEcmIface(ecm, fnIface);
791             return HDF_SUCCESS;
792         }
793     }
794 
795     return HDF_FAILURE;
796 }
797 
EcmCreateFuncDevice(struct UsbEcmDevice * ecm,struct DeviceResourceIface * iface)798 static int32_t EcmCreateFuncDevice(struct UsbEcmDevice *ecm, struct DeviceResourceIface *iface)
799 {
800     struct UsbFnDevice *fnDev = NULL;
801     int32_t ret;
802 
803     if (iface->GetString(ecm->device->property, "udc_name", (const char **)&ecm->udcName, UDC_NAME) != HDF_SUCCESS) {
804         HDF_LOGE("%{public}s: read udc_name failed, use default", __func__);
805         return HDF_FAILURE;
806     }
807 
808     fnDev = (struct UsbFnDevice *)UsbFnGetDevice(ecm->udcName);
809     if (fnDev == NULL) {
810         HDF_LOGE("%{public}s: create usb function device failed", __func__);
811         return HDF_FAILURE;
812     }
813 
814     ret = EcmParseEachIface(ecm, fnDev);
815     if (ret != HDF_SUCCESS) {
816         HDF_LOGE("%{public}s: get pipes failed", __func__);
817         goto ERR;
818     }
819 
820     ecm->fnDev = fnDev;
821     return HDF_SUCCESS;
822 
823 ERR:
824     return ret;
825 }
826 
EcmFreeNotifyRequest(struct UsbEcmDevice * ecm)827 static void EcmFreeNotifyRequest(struct UsbEcmDevice *ecm)
828 {
829     int32_t ret;
830 
831     /* free notification request */
832     ret = UsbFnFreeRequest(ecm->notifyReq);
833     if (ret != HDF_SUCCESS) {
834         HDF_LOGE("%{public}s: free notify request failed", __func__);
835         return;
836     }
837     ecm->notifyReq = NULL;
838 }
839 
EcmReleaseFuncDevice(struct UsbEcmDevice * ecm)840 static int32_t EcmReleaseFuncDevice(struct UsbEcmDevice *ecm)
841 {
842     int32_t ret = HDF_SUCCESS;
843     if (ecm->fnDev == NULL) {
844         HDF_LOGE("%{public}s: fnDev is null", __func__);
845         return HDF_FAILURE;
846     }
847     (void)UsbFnFreeRequest(ecm->ep0Req);
848     (void)EcmFreeNotifyRequest(ecm);
849     UsbFnCloseInterface(ecm->ctrlIface.handle);
850     (void)UsbFnCloseInterface(ecm->dataIface.handle);
851     (void)UsbFnStopRecvInterfaceEvent(ecm->ctrlIface.fn);
852     HDF_LOGD("%{public}s: ecn was released heres", __func__);
853     return ret;
854 }
855 
UsbEcmAlloc(struct UsbEcmDevice * ecm)856 static int32_t UsbEcmAlloc(struct UsbEcmDevice *ecm)
857 {
858     struct UsbEcm *port = NULL;
859 
860     port = (struct UsbEcm *)OsalMemCalloc(sizeof(*port));
861     if (port == NULL) {
862         HDF_LOGE("%{public}s: Alloc usb serial port failed", __func__);
863         return HDF_FAILURE;
864     }
865 
866     if (OsalMutexInit(&port->lock) != HDF_SUCCESS) {
867         HDF_LOGE("%{public}s: init lock fail!", __func__);
868         OsalMemFree(port);
869         return HDF_FAILURE;
870     }
871 
872     if (OsalMutexInit(&port->lockRW) != HDF_SUCCESS) {
873         HDF_LOGE("%{public}s: init lock fail!", __func__);
874         OsalMutexDestroy(&port->lock);
875         OsalMemFree(port);
876         return HDF_FAILURE;
877     }
878 
879     if (OsalMutexInit(&port->lockReadFifo) != HDF_SUCCESS) {
880         HDF_LOGE("%{public}s: init lock fail!", __func__);
881         OsalMutexDestroy(&port->lock);
882         OsalMutexDestroy(&port->lockRW);
883         OsalMemFree(port);
884         return HDF_FAILURE;
885     }
886 
887     if (OsalMutexInit(&port->lockWriteFifo) != HDF_SUCCESS) {
888         HDF_LOGE("%{public}s: init lock fail!", __func__);
889         OsalMutexDestroy(&port->lock);
890         OsalMutexDestroy(&port->lockRW);
891         OsalMutexDestroy(&port->lockReadFifo);
892         OsalMemFree(port);
893         return HDF_FAILURE;
894     }
895     DListHeadInit(&port->readPool);
896     DListHeadInit(&port->readQueue);
897     DListHeadInit(&port->writePool);
898 
899     ecm->port = port;
900     return HDF_SUCCESS;
901 }
902 
UsbEcmFree(struct UsbEcmDevice * ecm)903 static void UsbEcmFree(struct UsbEcmDevice *ecm)
904 {
905     if (ecm != NULL && ecm->port != NULL) {
906         OsalMutexDestroy(&ecm->port->lock);
907         OsalMutexDestroy(&ecm->port->lockRW);
908         OsalMutexDestroy(&ecm->port->lockReadFifo);
909         OsalMutexDestroy(&ecm->port->lockWriteFifo);
910         OsalMemFree(ecm->port);
911         ecm->port = NULL;
912     }
913 }
914 
915 /* HdfDriverEntry implementations */
EcmDriverBind(struct HdfDeviceObject * device)916 static int32_t EcmDriverBind(struct HdfDeviceObject *device)
917 {
918     HDF_LOGD("%{public}s: enter", __func__);
919     struct UsbEcmDevice *ecm = NULL;
920 
921     if (device == NULL) {
922         HDF_LOGE("%{public}s: device is null", __func__);
923         return HDF_ERR_INVALID_OBJECT;
924     }
925 
926     ecm = (struct UsbEcmDevice *)OsalMemCalloc(sizeof(*ecm));
927     if (ecm == NULL) {
928         HDF_LOGE("%{public}s: Alloc usb ecm device failed", __func__);
929         return HDF_FAILURE;
930     }
931     ecm->ctrlId = 0;
932     ecm->dataId = 1;
933     if (OsalMutexInit(&ecm->lock) != HDF_SUCCESS) {
934         HDF_LOGE("%{public}s: init lock fail!", __func__);
935         OsalMemFree(ecm);
936         return HDF_FAILURE;
937     }
938 
939     if (HdfDeviceObjectSetInterfaceDesc(device, "hdf.usb.usbfn") != HDF_SUCCESS) {
940         HDF_LOGE(" Set Desc fail!");
941         OsalMemFree(ecm);
942         return HDF_FAILURE;
943     }
944 
945     ecm->device = device;
946     device->service = &(ecm->service);
947     if (ecm->device->service) {
948         ecm->device->service->Dispatch = EcmDeviceDispatch;
949     }
950     HDF_LOGD("%{public}s: exit", __func__);
951     return HDF_SUCCESS;
952 }
953 
EcmInit(struct HdfDeviceObject * device)954 static int32_t EcmInit(struct HdfDeviceObject *device)
955 {
956     struct UsbEcmDevice *ecm = NULL;
957     struct DeviceResourceIface *iface = NULL;
958     int32_t ret;
959 
960     if (device == NULL) {
961         HDF_LOGE("%{public}s: device is null", __func__);
962         return HDF_ERR_INVALID_OBJECT;
963     }
964 
965     ecm = (struct UsbEcmDevice *)device->service;
966     if (ecm == NULL || ecm->initFlag) {
967         HDF_LOGE("%{public}s: ecm is null", __func__);
968         return HDF_FAILURE;
969     }
970 
971     iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
972     if (iface == NULL || iface->GetUint32 == NULL) {
973         HDF_LOGE("%{public}s: face is invalid", __func__);
974         return HDF_FAILURE;
975     }
976 
977     ret = EcmCreateFuncDevice(ecm, iface);
978     if (ret != HDF_SUCCESS) {
979         HDF_LOGE("%{public}s: EcmCreateFuncDevice failed", __func__);
980         return ret;
981     }
982 
983     ret = UsbEcmAlloc(ecm);
984     if (ret != HDF_SUCCESS) {
985         HDF_LOGE("%{public}s: UsbEcmAlloc failed", __func__);
986         return ret;
987     }
988 
989     ret = EcmAllocEp0Request(ecm);
990     if (ret != HDF_SUCCESS) {
991         HDF_LOGE("%{public}s: EcmAllocEp0Request failed", __func__);
992         goto ERR;
993     }
994 
995     ret = EcmAllocNotifyRequest(ecm);
996     if (ret != HDF_SUCCESS) {
997         HDF_LOGE("%{public}s: EcmAllocNotifyRequest failed", __func__);
998         goto ERR;
999     }
1000 
1001     ret = UsbFnStartRecvInterfaceEvent(ecm->ctrlIface.fn, RECEIVE_ALL_EVENTS, UsbEcmEventCallback, ecm);
1002     if (ret != HDF_SUCCESS) {
1003         HDF_LOGE("%{public}s: register event callback failed", __func__);
1004         goto ERR;
1005     }
1006     ecm->initFlag = true;
1007     return ret;
1008 ERR:
1009     UsbEcmFree(ecm);
1010     (void)EcmReleaseFuncDevice(ecm);
1011     return ret;
1012 }
1013 
EcmRelease(struct HdfDeviceObject * device)1014 static int32_t EcmRelease(struct HdfDeviceObject *device)
1015 {
1016     HDF_LOGD("%{public}s: enter", __func__);
1017     struct UsbEcmDevice *ecm = NULL;
1018 
1019     if (device == NULL) {
1020         HDF_LOGE("%{public}s: device is NULL", __func__);
1021         return HDF_FAILURE;
1022     }
1023 
1024     ecm = (struct UsbEcmDevice *)device->service;
1025     if (ecm == NULL) {
1026         HDF_LOGE("%{public}s: ecm is null", __func__);
1027         return HDF_FAILURE;
1028     }
1029     if (ecm->initFlag == false) {
1030         HDF_LOGE("%{public}s: ecm not init!", __func__);
1031         return HDF_FAILURE;
1032     }
1033     UsbEcmFree(ecm);
1034     (void)EcmReleaseFuncDevice(ecm);
1035     ecm->initFlag = false;
1036     HDF_LOGD("%{public}s: exit", __func__);
1037     return HDF_SUCCESS;
1038 }
1039 
EcmDriverInit(struct HdfDeviceObject * device)1040 static int32_t EcmDriverInit(struct HdfDeviceObject *device)
1041 {
1042     (void)device;
1043     HDF_LOGE("%{public}s: usbfn do nothing...", __func__);
1044     return 0;
1045 }
1046 
EcmDriverRelease(struct HdfDeviceObject * device)1047 static void EcmDriverRelease(struct HdfDeviceObject *device)
1048 {
1049     struct UsbEcmDevice *ecm = NULL;
1050     if (device == NULL) {
1051         HDF_LOGE("%{public}s: device is NULL", __func__);
1052         return;
1053     }
1054 
1055     ecm = (struct UsbEcmDevice *)device->service;
1056     if (ecm == NULL) {
1057         HDF_LOGE("%{public}s: ecm is null", __func__);
1058         return;
1059     }
1060 
1061     (void)OsalMutexDestroy(&ecm->lock);
1062     OsalMemFree(ecm);
1063     device->service = NULL;
1064 }
1065 
1066 struct HdfDriverEntry g_ecmDriverEntry = {
1067     .moduleVersion = 1,
1068     .moduleName = "usbfn_cdcecm",
1069     .Bind = EcmDriverBind,
1070     .Init = EcmDriverInit,
1071     .Release = EcmDriverRelease,
1072 };
1073 
1074 HDF_INIT(g_ecmDriverEntry);
1075