1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include "cdcecm.h"
17094332d3Sopenharmony_ci#include <unistd.h>
18094332d3Sopenharmony_ci#include "device_resource_if.h"
19094332d3Sopenharmony_ci#include "hdf_base.h"
20094332d3Sopenharmony_ci#include "hdf_device_object.h"
21094332d3Sopenharmony_ci#include "hdf_log.h"
22094332d3Sopenharmony_ci#include "osal_mem.h"
23094332d3Sopenharmony_ci#include "osal_sem.h"
24094332d3Sopenharmony_ci#include "osal_time.h"
25094332d3Sopenharmony_ci#include "securec.h"
26094332d3Sopenharmony_ci#include "usbfn_device.h"
27094332d3Sopenharmony_ci#include "usbfn_interface.h"
28094332d3Sopenharmony_ci#include "usbfn_request.h"
29094332d3Sopenharmony_ci
30094332d3Sopenharmony_ci#define HDF_LOG_TAG cdc_ecm
31094332d3Sopenharmony_ci#define UDC_NAME "invalid_udc_name"
32094332d3Sopenharmony_ci
33094332d3Sopenharmony_ci#define QUEUE_SIZE           8
34094332d3Sopenharmony_ci#define WRITE_BUF_SIZE       8192
35094332d3Sopenharmony_ci#define READ_BUF_SIZE        8192
36094332d3Sopenharmony_ci#define ECM_STATUS_BYTECOUNT 16
37094332d3Sopenharmony_ci#define ECM_BIT              9728000
38094332d3Sopenharmony_ci#define USBCDC_LEN 2
39094332d3Sopenharmony_ci#define RECEIVE_ALL_EVENTS 0xff
40094332d3Sopenharmony_cistatic const int32_t WAIT_UDC_MAX_LOOP = 3;
41094332d3Sopenharmony_cistatic const uint32_t WAIT_UDC_TIME = 100000;
42094332d3Sopenharmony_ci
43094332d3Sopenharmony_cistatic int32_t EcmInit(struct HdfDeviceObject *device);
44094332d3Sopenharmony_cistatic int32_t EcmRelease(struct HdfDeviceObject *device);
45094332d3Sopenharmony_ci
46094332d3Sopenharmony_cistatic inline unsigned EcmBitrate(void)
47094332d3Sopenharmony_ci{
48094332d3Sopenharmony_ci    return ECM_BIT;
49094332d3Sopenharmony_ci}
50094332d3Sopenharmony_ci
51094332d3Sopenharmony_ci/* Usb Serial Related Functions */
52094332d3Sopenharmony_cistatic int32_t UsbEcmStartTx(struct UsbEcm *port)
53094332d3Sopenharmony_ci{
54094332d3Sopenharmony_ci    struct DListHead *pool = &port->writePool;
55094332d3Sopenharmony_ci    if (port->ecm == NULL) {
56094332d3Sopenharmony_ci        return HDF_SUCCESS;
57094332d3Sopenharmony_ci    }
58094332d3Sopenharmony_ci
59094332d3Sopenharmony_ci    while (!port->writeBusy && !DListIsEmpty(pool)) {
60094332d3Sopenharmony_ci        struct UsbFnRequest *req = NULL;
61094332d3Sopenharmony_ci        uint32_t len;
62094332d3Sopenharmony_ci        if (port->writeStarted >= QUEUE_SIZE) {
63094332d3Sopenharmony_ci            break;
64094332d3Sopenharmony_ci        }
65094332d3Sopenharmony_ci        req = DLIST_FIRST_ENTRY(pool, struct UsbFnRequest, list);
66094332d3Sopenharmony_ci        OsalMutexLock(&port->lockWriteFifo);
67094332d3Sopenharmony_ci        len = DataFifoRead(&port->writeFifo, req->buf, port->ecm->dataInPipe.maxPacketSize);
68094332d3Sopenharmony_ci        OsalMutexUnlock(&port->lockWriteFifo);
69094332d3Sopenharmony_ci        if (len == 0) {
70094332d3Sopenharmony_ci            break;
71094332d3Sopenharmony_ci        }
72094332d3Sopenharmony_ci        req->length = len;
73094332d3Sopenharmony_ci        DListRemove(&req->list);
74094332d3Sopenharmony_ci        port->writeBusy = true;
75094332d3Sopenharmony_ci        int32_t ret = UsbFnSubmitRequestAsync(req);
76094332d3Sopenharmony_ci        port->writeBusy = false;
77094332d3Sopenharmony_ci        if (ret != HDF_SUCCESS) {
78094332d3Sopenharmony_ci            HDF_LOGE("%{public}s: send request error %{public}d", __func__, ret);
79094332d3Sopenharmony_ci            DListInsertTail(&req->list, pool);
80094332d3Sopenharmony_ci            break;
81094332d3Sopenharmony_ci        }
82094332d3Sopenharmony_ci        port->writeStarted++;
83094332d3Sopenharmony_ci        /* if ecm is disconnect, abort immediately */
84094332d3Sopenharmony_ci        if (port->ecm == NULL) {
85094332d3Sopenharmony_ci            break;
86094332d3Sopenharmony_ci        }
87094332d3Sopenharmony_ci    }
88094332d3Sopenharmony_ci    return HDF_SUCCESS;
89094332d3Sopenharmony_ci}
90094332d3Sopenharmony_ci
91094332d3Sopenharmony_cistatic uint32_t UsbEcmStartRx(struct UsbEcm *port)
92094332d3Sopenharmony_ci{
93094332d3Sopenharmony_ci    struct DListHead *pool = &port->readPool;
94094332d3Sopenharmony_ci    struct UsbEcmPipe *out = &port->ecm->dataOutPipe;
95094332d3Sopenharmony_ci
96094332d3Sopenharmony_ci    while (!DListIsEmpty(pool)) {
97094332d3Sopenharmony_ci        struct UsbFnRequest *req = NULL;
98094332d3Sopenharmony_ci        int32_t ret;
99094332d3Sopenharmony_ci
100094332d3Sopenharmony_ci        if (port->readStarted >= QUEUE_SIZE) {
101094332d3Sopenharmony_ci            break;
102094332d3Sopenharmony_ci        }
103094332d3Sopenharmony_ci
104094332d3Sopenharmony_ci        req = DLIST_FIRST_ENTRY(pool, struct UsbFnRequest, list);
105094332d3Sopenharmony_ci        DListRemove(&req->list);
106094332d3Sopenharmony_ci        req->length = out->maxPacketSize;
107094332d3Sopenharmony_ci        ret = UsbFnSubmitRequestAsync(req);
108094332d3Sopenharmony_ci        if (ret != HDF_SUCCESS) {
109094332d3Sopenharmony_ci            HDF_LOGE("%{public}s: send request error %{public}d", __func__, ret);
110094332d3Sopenharmony_ci            DListInsertTail(&req->list, pool);
111094332d3Sopenharmony_ci            break;
112094332d3Sopenharmony_ci        }
113094332d3Sopenharmony_ci        port->readStarted++;
114094332d3Sopenharmony_ci        /* if ecm is disconnect, abort immediately */
115094332d3Sopenharmony_ci        if (port->ecm == NULL) {
116094332d3Sopenharmony_ci            break;
117094332d3Sopenharmony_ci        }
118094332d3Sopenharmony_ci    }
119094332d3Sopenharmony_ci    return port->readStarted;
120094332d3Sopenharmony_ci}
121094332d3Sopenharmony_ci
122094332d3Sopenharmony_cistatic void UsbEcmRxPush(struct UsbEcm *port)
123094332d3Sopenharmony_ci{
124094332d3Sopenharmony_ci    struct DListHead *queue = &port->readQueue;
125094332d3Sopenharmony_ci    bool disconnect = false;
126094332d3Sopenharmony_ci
127094332d3Sopenharmony_ci    while (!DListIsEmpty(queue)) {
128094332d3Sopenharmony_ci        struct UsbFnRequest *req;
129094332d3Sopenharmony_ci
130094332d3Sopenharmony_ci        req = DLIST_FIRST_ENTRY(queue, struct UsbFnRequest, list);
131094332d3Sopenharmony_ci        switch (req->status) {
132094332d3Sopenharmony_ci            case USB_REQUEST_NO_DEVICE:
133094332d3Sopenharmony_ci                disconnect = true;
134094332d3Sopenharmony_ci                HDF_LOGV("%{public}s: the device is disconnected", __func__);
135094332d3Sopenharmony_ci                break;
136094332d3Sopenharmony_ci            case USB_REQUEST_COMPLETED:
137094332d3Sopenharmony_ci                break;
138094332d3Sopenharmony_ci            default:
139094332d3Sopenharmony_ci                HDF_LOGV("%{public}s: unexpected status %{public}d", __func__, req->status);
140094332d3Sopenharmony_ci                break;
141094332d3Sopenharmony_ci        }
142094332d3Sopenharmony_ci        if (req->actual && req->status == 0) {
143094332d3Sopenharmony_ci            uint32_t size = req->actual;
144094332d3Sopenharmony_ci            uint8_t *data = req->buf;
145094332d3Sopenharmony_ci            OsalMutexLock(&port->lockReadFifo);
146094332d3Sopenharmony_ci            if (DataFifoIsFull(&port->readFifo)) {
147094332d3Sopenharmony_ci                DataFifoSkip(&port->readFifo, size);
148094332d3Sopenharmony_ci            }
149094332d3Sopenharmony_ci            uint32_t count = DataFifoWrite(&port->readFifo, data, size);
150094332d3Sopenharmony_ci            if (count != size) {
151094332d3Sopenharmony_ci                HDF_LOGW("%{public}s: write %{public}u less than expected %{public}u", __func__, count, size);
152094332d3Sopenharmony_ci            }
153094332d3Sopenharmony_ci            OsalMutexUnlock(&port->lockReadFifo);
154094332d3Sopenharmony_ci        }
155094332d3Sopenharmony_ci        DListRemove(&req->list);
156094332d3Sopenharmony_ci        DListInsertTail(&req->list, &port->readPool);
157094332d3Sopenharmony_ci        port->readStarted--;
158094332d3Sopenharmony_ci    }
159094332d3Sopenharmony_ci
160094332d3Sopenharmony_ci    if (!disconnect && port->ecm) {
161094332d3Sopenharmony_ci        UsbEcmStartRx(port);
162094332d3Sopenharmony_ci    }
163094332d3Sopenharmony_ci}
164094332d3Sopenharmony_ci
165094332d3Sopenharmony_cistatic void UsbEcmFreeRequests(const struct DListHead *head, int32_t *allocated)
166094332d3Sopenharmony_ci{
167094332d3Sopenharmony_ci    struct UsbFnRequest *req = NULL;
168094332d3Sopenharmony_ci    while (!DListIsEmpty(head)) {
169094332d3Sopenharmony_ci        req = DLIST_FIRST_ENTRY(head, struct UsbFnRequest, list);
170094332d3Sopenharmony_ci        DListRemove(&req->list);
171094332d3Sopenharmony_ci        (void)UsbFnFreeRequest(req);
172094332d3Sopenharmony_ci        if (allocated) {
173094332d3Sopenharmony_ci            (*allocated)--;
174094332d3Sopenharmony_ci        }
175094332d3Sopenharmony_ci    }
176094332d3Sopenharmony_ci}
177094332d3Sopenharmony_ci
178094332d3Sopenharmony_cistatic void UsbEcmReadComplete(uint8_t pipe, struct UsbFnRequest *req)
179094332d3Sopenharmony_ci{
180094332d3Sopenharmony_ci    struct UsbEcm *port = (struct UsbEcm *)req->context;
181094332d3Sopenharmony_ci    OsalMutexLock(&port->lock);
182094332d3Sopenharmony_ci    DListInsertTail(&req->list, &port->readQueue);
183094332d3Sopenharmony_ci    UsbEcmRxPush(port);
184094332d3Sopenharmony_ci    OsalMutexUnlock(&port->lock);
185094332d3Sopenharmony_ci}
186094332d3Sopenharmony_ci
187094332d3Sopenharmony_cistatic void UsbEcmWriteComplete(uint8_t pipe, struct UsbFnRequest *req)
188094332d3Sopenharmony_ci{
189094332d3Sopenharmony_ci    struct UsbEcm *port = (struct UsbEcm *)req->context;
190094332d3Sopenharmony_ci    OsalMutexLock(&port->lock);
191094332d3Sopenharmony_ci    DListInsertTail(&req->list, &port->writePool);
192094332d3Sopenharmony_ci    port->writeStarted--;
193094332d3Sopenharmony_ci
194094332d3Sopenharmony_ci    switch (req->status) {
195094332d3Sopenharmony_ci        case USB_REQUEST_COMPLETED:
196094332d3Sopenharmony_ci            UsbEcmStartTx(port);
197094332d3Sopenharmony_ci            break;
198094332d3Sopenharmony_ci        case USB_REQUEST_NO_DEVICE:
199094332d3Sopenharmony_ci            HDF_LOGV("%{public}s: ecm device was disconnected", __func__);
200094332d3Sopenharmony_ci            break;
201094332d3Sopenharmony_ci        default:
202094332d3Sopenharmony_ci            HDF_LOGV("%{public}s: unexpected status %{public}d", __func__, req->status);
203094332d3Sopenharmony_ci            break;
204094332d3Sopenharmony_ci    }
205094332d3Sopenharmony_ci    OsalMutexUnlock(&port->lock);
206094332d3Sopenharmony_ci}
207094332d3Sopenharmony_ci
208094332d3Sopenharmony_cistatic int32_t UsbEcmAllocReadRequests(struct UsbEcm *port, int32_t num)
209094332d3Sopenharmony_ci{
210094332d3Sopenharmony_ci    struct UsbEcmDevice *ecm = port->ecm;
211094332d3Sopenharmony_ci    struct DListHead *head = &port->readPool;
212094332d3Sopenharmony_ci    struct UsbFnRequest *req = NULL;
213094332d3Sopenharmony_ci    int32_t i;
214094332d3Sopenharmony_ci
215094332d3Sopenharmony_ci    for (i = 0; i < num; i++) {
216094332d3Sopenharmony_ci        req = UsbFnAllocRequest(ecm->dataIface.handle, ecm->dataOutPipe.id, ecm->dataOutPipe.maxPacketSize);
217094332d3Sopenharmony_ci        if (!req) {
218094332d3Sopenharmony_ci            return DListIsEmpty(head) ? HDF_FAILURE : HDF_SUCCESS;
219094332d3Sopenharmony_ci        }
220094332d3Sopenharmony_ci
221094332d3Sopenharmony_ci        req->complete = UsbEcmReadComplete;
222094332d3Sopenharmony_ci        req->context = port;
223094332d3Sopenharmony_ci        DListInsertTail(&req->list, head);
224094332d3Sopenharmony_ci        port->readAllocated++;
225094332d3Sopenharmony_ci    }
226094332d3Sopenharmony_ci    return HDF_SUCCESS;
227094332d3Sopenharmony_ci}
228094332d3Sopenharmony_ci
229094332d3Sopenharmony_cistatic int32_t UsbEcmAllocWriteRequests(struct UsbEcm *port, int32_t num)
230094332d3Sopenharmony_ci{
231094332d3Sopenharmony_ci    struct UsbEcmDevice *ecm = port->ecm;
232094332d3Sopenharmony_ci    struct DListHead *head = &port->writePool;
233094332d3Sopenharmony_ci    struct UsbFnRequest *req = NULL;
234094332d3Sopenharmony_ci    int32_t i;
235094332d3Sopenharmony_ci
236094332d3Sopenharmony_ci    for (i = 0; i < num; i++) {
237094332d3Sopenharmony_ci        req = UsbFnAllocRequest(ecm->dataIface.handle, ecm->dataInPipe.id, ecm->dataInPipe.maxPacketSize);
238094332d3Sopenharmony_ci        if (!req) {
239094332d3Sopenharmony_ci            return DListIsEmpty(head) ? HDF_FAILURE : HDF_SUCCESS;
240094332d3Sopenharmony_ci        }
241094332d3Sopenharmony_ci
242094332d3Sopenharmony_ci        req->complete = UsbEcmWriteComplete;
243094332d3Sopenharmony_ci        req->context = port;
244094332d3Sopenharmony_ci        DListInsertTail(&req->list, head);
245094332d3Sopenharmony_ci        port->writeAllocated++;
246094332d3Sopenharmony_ci    }
247094332d3Sopenharmony_ci    return HDF_SUCCESS;
248094332d3Sopenharmony_ci}
249094332d3Sopenharmony_ci
250094332d3Sopenharmony_cistatic int32_t UsbEcmStartIo(struct UsbEcm *port)
251094332d3Sopenharmony_ci{
252094332d3Sopenharmony_ci    struct DListHead *head = &port->readPool;
253094332d3Sopenharmony_ci    int32_t ret = HDF_SUCCESS;
254094332d3Sopenharmony_ci    uint32_t started;
255094332d3Sopenharmony_ci
256094332d3Sopenharmony_ci    /* allocate requests for read/write */
257094332d3Sopenharmony_ci    if (port->readAllocated == 0) {
258094332d3Sopenharmony_ci        ret = UsbEcmAllocReadRequests(port, QUEUE_SIZE);
259094332d3Sopenharmony_ci        if (ret != HDF_SUCCESS) {
260094332d3Sopenharmony_ci            return ret;
261094332d3Sopenharmony_ci        }
262094332d3Sopenharmony_ci    }
263094332d3Sopenharmony_ci    if (port->writeAllocated == 0) {
264094332d3Sopenharmony_ci        ret = UsbEcmAllocWriteRequests(port, QUEUE_SIZE);
265094332d3Sopenharmony_ci        if (ret != HDF_SUCCESS) {
266094332d3Sopenharmony_ci            UsbEcmFreeRequests(head, &port->readAllocated);
267094332d3Sopenharmony_ci            return ret;
268094332d3Sopenharmony_ci        }
269094332d3Sopenharmony_ci    }
270094332d3Sopenharmony_ci
271094332d3Sopenharmony_ci    started = UsbEcmStartRx(port);
272094332d3Sopenharmony_ci    if (started) {
273094332d3Sopenharmony_ci        UsbEcmStartTx(port);
274094332d3Sopenharmony_ci    } else {
275094332d3Sopenharmony_ci        UsbEcmFreeRequests(head, &port->readAllocated);
276094332d3Sopenharmony_ci        UsbEcmFreeRequests(&port->writePool, &port->writeAllocated);
277094332d3Sopenharmony_ci        ret = HDF_ERR_IO;
278094332d3Sopenharmony_ci    }
279094332d3Sopenharmony_ci
280094332d3Sopenharmony_ci    return ret;
281094332d3Sopenharmony_ci}
282094332d3Sopenharmony_ci
283094332d3Sopenharmony_ci
284094332d3Sopenharmony_cistatic int32_t UsbEcmAllocFifo(struct DataFifo *fifo, uint32_t size)
285094332d3Sopenharmony_ci{
286094332d3Sopenharmony_ci    if (!DataFifoIsInitialized(fifo)) {
287094332d3Sopenharmony_ci        void *data = OsalMemAlloc(size);
288094332d3Sopenharmony_ci        if (data == NULL) {
289094332d3Sopenharmony_ci            HDF_LOGE("%{public}s: allocate fifo data buffer failed", __func__);
290094332d3Sopenharmony_ci            return HDF_ERR_MALLOC_FAIL;
291094332d3Sopenharmony_ci        }
292094332d3Sopenharmony_ci        DataFifoInit(fifo, size, data);
293094332d3Sopenharmony_ci    }
294094332d3Sopenharmony_ci    return HDF_SUCCESS;
295094332d3Sopenharmony_ci}
296094332d3Sopenharmony_ci
297094332d3Sopenharmony_cistatic int32_t UsbEcmOpen(struct UsbEcm *port)
298094332d3Sopenharmony_ci{
299094332d3Sopenharmony_ci    int32_t ret;
300094332d3Sopenharmony_ci
301094332d3Sopenharmony_ci    if (port == NULL) {
302094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
303094332d3Sopenharmony_ci    }
304094332d3Sopenharmony_ci
305094332d3Sopenharmony_ci    OsalMutexLock(&port->lock);
306094332d3Sopenharmony_ci    ret = UsbEcmAllocFifo(&port->writeFifo, WRITE_BUF_SIZE);
307094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
308094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: UsbEcmAllocFifo failed", __func__);
309094332d3Sopenharmony_ci        goto OUT;
310094332d3Sopenharmony_ci    }
311094332d3Sopenharmony_ci    ret = UsbEcmAllocFifo(&port->readFifo, READ_BUF_SIZE);
312094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
313094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: UsbEcmAllocFifo failed", __func__);
314094332d3Sopenharmony_ci        goto OUT;
315094332d3Sopenharmony_ci    }
316094332d3Sopenharmony_ci    DataFifoReset(&port->writeFifo);
317094332d3Sopenharmony_ci    DataFifoReset(&port->readFifo);
318094332d3Sopenharmony_ci
319094332d3Sopenharmony_ci    if (port->refCount++) {
320094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: refCount failed", __func__);
321094332d3Sopenharmony_ci        goto OUT;
322094332d3Sopenharmony_ci    }
323094332d3Sopenharmony_ci
324094332d3Sopenharmony_ci    /* the ecm is enabled, start the io stream */
325094332d3Sopenharmony_ci    if (port->ecm) {
326094332d3Sopenharmony_ci        HDF_LOGD("%{public}s: start usb io", __func__);
327094332d3Sopenharmony_ci        ret = UsbEcmStartIo(port);
328094332d3Sopenharmony_ci        if (ret != HDF_SUCCESS) {
329094332d3Sopenharmony_ci            goto OUT;
330094332d3Sopenharmony_ci        }
331094332d3Sopenharmony_ci    }
332094332d3Sopenharmony_ci
333094332d3Sopenharmony_ciOUT:
334094332d3Sopenharmony_ci    OsalMutexUnlock(&port->lock);
335094332d3Sopenharmony_ci    return HDF_SUCCESS;
336094332d3Sopenharmony_ci}
337094332d3Sopenharmony_ci
338094332d3Sopenharmony_cistatic int32_t UsbEcmClose(struct UsbEcm *port)
339094332d3Sopenharmony_ci{
340094332d3Sopenharmony_ci    if (port == NULL) {
341094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
342094332d3Sopenharmony_ci    }
343094332d3Sopenharmony_ci
344094332d3Sopenharmony_ci    OsalMutexLock(&port->lock);
345094332d3Sopenharmony_ci    if (port->refCount != 1) {
346094332d3Sopenharmony_ci        --port->refCount;
347094332d3Sopenharmony_ci        goto OUT;
348094332d3Sopenharmony_ci    }
349094332d3Sopenharmony_ci
350094332d3Sopenharmony_ci    HDF_LOGD("%{public}s: close usb serial", __func__);
351094332d3Sopenharmony_ci
352094332d3Sopenharmony_ci    DataFifoReset(&port->writeFifo);
353094332d3Sopenharmony_ci    DataFifoReset(&port->readFifo);
354094332d3Sopenharmony_ci    port->refCount = 0;
355094332d3Sopenharmony_ci
356094332d3Sopenharmony_ciOUT:
357094332d3Sopenharmony_ci    OsalMutexUnlock(&port->lock);
358094332d3Sopenharmony_ci    return HDF_SUCCESS;
359094332d3Sopenharmony_ci}
360094332d3Sopenharmony_ci
361094332d3Sopenharmony_cistatic int32_t UsbEcmRead(struct UsbEcm *port, struct HdfSBuf *reply)
362094332d3Sopenharmony_ci{
363094332d3Sopenharmony_ci    uint32_t len;
364094332d3Sopenharmony_ci    int32_t ret = HDF_SUCCESS;
365094332d3Sopenharmony_ci    uint8_t *buf = NULL;
366094332d3Sopenharmony_ci    OsalMutexLock(&port->lock);
367094332d3Sopenharmony_ci    OsalMutexLock(&port->lockReadFifo);
368094332d3Sopenharmony_ci    if (DataFifoIsEmpty(&port->readFifo)) {
369094332d3Sopenharmony_ci        OsalMutexUnlock(&port->lockReadFifo);
370094332d3Sopenharmony_ci        OsalMutexUnlock(&port->lock);
371094332d3Sopenharmony_ci        return 0;
372094332d3Sopenharmony_ci    }
373094332d3Sopenharmony_ci
374094332d3Sopenharmony_ci    buf = (uint8_t *)OsalMemCalloc(DataFifoLen(&port->readFifo) + sizeof(uint32_t));
375094332d3Sopenharmony_ci    if (buf == NULL) {
376094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: OsalMemCalloc error", __func__);
377094332d3Sopenharmony_ci        OsalMutexUnlock(&port->lockReadFifo);
378094332d3Sopenharmony_ci        OsalMutexUnlock(&port->lock);
379094332d3Sopenharmony_ci        return HDF_ERR_MALLOC_FAIL;
380094332d3Sopenharmony_ci    }
381094332d3Sopenharmony_ci
382094332d3Sopenharmony_ci    len = DataFifoRead(&port->readFifo, buf, DataFifoLen(&port->readFifo));
383094332d3Sopenharmony_ci    if (len == 0) {
384094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: no data", __func__);
385094332d3Sopenharmony_ci        ret = HDF_ERR_IO;
386094332d3Sopenharmony_ci        OsalMutexUnlock(&port->lockReadFifo);
387094332d3Sopenharmony_ci        goto OUT;
388094332d3Sopenharmony_ci    }
389094332d3Sopenharmony_ci    OsalMutexUnlock(&port->lockReadFifo);
390094332d3Sopenharmony_ci
391094332d3Sopenharmony_ci    bool bufok = HdfSbufWriteBuffer(reply, (const void *)buf, len);
392094332d3Sopenharmony_ci    if (!bufok) {
393094332d3Sopenharmony_ci        HDF_LOGE("UsbEcmRead HdfSbufWriteBuffer error");
394094332d3Sopenharmony_ci        ret = HDF_ERR_IO;
395094332d3Sopenharmony_ci        goto OUT;
396094332d3Sopenharmony_ci    }
397094332d3Sopenharmony_ci
398094332d3Sopenharmony_ciOUT:
399094332d3Sopenharmony_ci    if (port->ecm) {
400094332d3Sopenharmony_ci        UsbEcmStartRx(port);
401094332d3Sopenharmony_ci    }
402094332d3Sopenharmony_ci    OsalMemFree(buf);
403094332d3Sopenharmony_ci    OsalMutexUnlock(&port->lock);
404094332d3Sopenharmony_ci    return ret;
405094332d3Sopenharmony_ci}
406094332d3Sopenharmony_ci
407094332d3Sopenharmony_cistatic int32_t UsbEcmWrite(struct UsbEcm *port, struct HdfSBuf *data)
408094332d3Sopenharmony_ci{
409094332d3Sopenharmony_ci    uint32_t size = 0;
410094332d3Sopenharmony_ci    uint8_t *buf = NULL;
411094332d3Sopenharmony_ci
412094332d3Sopenharmony_ci    if (!HdfSbufReadBuffer(data, (const void **)&buf, &size)) {
413094332d3Sopenharmony_ci        HDF_LOGE("UsbEcmWrite HdfSbufReadBuffer err");
414094332d3Sopenharmony_ci        return HDF_ERR_IO;
415094332d3Sopenharmony_ci    }
416094332d3Sopenharmony_ci
417094332d3Sopenharmony_ci    OsalMutexLock(&port->lock);
418094332d3Sopenharmony_ci    if (size > 0 && buf != NULL) {
419094332d3Sopenharmony_ci        OsalMutexLock(&port->lockWriteFifo);
420094332d3Sopenharmony_ci        size = DataFifoWrite(&port->writeFifo, buf, size);
421094332d3Sopenharmony_ci        OsalMutexUnlock(&port->lockWriteFifo);
422094332d3Sopenharmony_ci    }
423094332d3Sopenharmony_ci    if (port->ecm) {
424094332d3Sopenharmony_ci        UsbEcmStartTx(port);
425094332d3Sopenharmony_ci    }
426094332d3Sopenharmony_ci    OsalMutexUnlock(&port->lock);
427094332d3Sopenharmony_ci    return HDF_SUCCESS;
428094332d3Sopenharmony_ci}
429094332d3Sopenharmony_ci
430094332d3Sopenharmony_civoid UsbFnNotifyRequest(struct UsbFnRequest *req, struct UsbEcmDevice *ecm)
431094332d3Sopenharmony_ci{
432094332d3Sopenharmony_ci    int32_t status;
433094332d3Sopenharmony_ci    ecm->notifyReq = NULL;
434094332d3Sopenharmony_ci    status = UsbFnSubmitRequestAsync(req);
435094332d3Sopenharmony_ci    if (status < 0) {
436094332d3Sopenharmony_ci        ecm->notifyReq = req;
437094332d3Sopenharmony_ci        HDF_LOGD("notify --> %{public}d", status);
438094332d3Sopenharmony_ci    }
439094332d3Sopenharmony_ci}
440094332d3Sopenharmony_ci
441094332d3Sopenharmony_cistatic void EcmDoNotify(struct UsbEcmDevice *ecm)
442094332d3Sopenharmony_ci{
443094332d3Sopenharmony_ci    struct UsbFnRequest *req = ecm->notifyReq;
444094332d3Sopenharmony_ci    struct UsbCdcNotification *event = NULL;
445094332d3Sopenharmony_ci    uint32_t *data = NULL;
446094332d3Sopenharmony_ci
447094332d3Sopenharmony_ci    if (!req) {
448094332d3Sopenharmony_ci        return;
449094332d3Sopenharmony_ci    }
450094332d3Sopenharmony_ci    ecm->isOpen = true;
451094332d3Sopenharmony_ci    event = (struct UsbCdcNotification *)req->buf;
452094332d3Sopenharmony_ci    if (event == NULL) {
453094332d3Sopenharmony_ci        return;
454094332d3Sopenharmony_ci    }
455094332d3Sopenharmony_ci    switch (ecm->notifyState) {
456094332d3Sopenharmony_ci        case ECM_NOTIFY_NONE:
457094332d3Sopenharmony_ci            return;
458094332d3Sopenharmony_ci
459094332d3Sopenharmony_ci        case ECM_NOTIFY_CONNECT:
460094332d3Sopenharmony_ci            event->bNotificationType = USB_DDK_CDC_NOTIFY_NETWORK_CONNECTION;
461094332d3Sopenharmony_ci            if (ecm->isOpen) {
462094332d3Sopenharmony_ci                event->wValue = CPU_TO_LE16(1);
463094332d3Sopenharmony_ci            } else {
464094332d3Sopenharmony_ci                event->wValue = CPU_TO_LE16(0);
465094332d3Sopenharmony_ci            }
466094332d3Sopenharmony_ci            event->wLength = 0;
467094332d3Sopenharmony_ci            req->length = sizeof(*event);
468094332d3Sopenharmony_ci
469094332d3Sopenharmony_ci            HDF_LOGD("notify connect %{public}s", ecm->isOpen ? "true" : "false");
470094332d3Sopenharmony_ci            ecm->notifyState = ECM_NOTIFY_SPEED;
471094332d3Sopenharmony_ci            break;
472094332d3Sopenharmony_ci
473094332d3Sopenharmony_ci        case ECM_NOTIFY_SPEED:
474094332d3Sopenharmony_ci            event->bNotificationType = USB_DDK_CDC_NOTIFY_SPEED_CHANGE;
475094332d3Sopenharmony_ci            event->wValue = CPU_TO_LE16(0);
476094332d3Sopenharmony_ci            event->wLength = CPU_TO_LE16(0x08);
477094332d3Sopenharmony_ci            req->length = ECM_STATUS_BYTECOUNT;
478094332d3Sopenharmony_ci
479094332d3Sopenharmony_ci            /* SPEED_CHANGE data is up/down speeds in bits/sec */
480094332d3Sopenharmony_ci            data = (uint32_t *)((char *)req->buf + sizeof(*event));
481094332d3Sopenharmony_ci            data[0] = CPU_TO_LE32(EcmBitrate());
482094332d3Sopenharmony_ci            data[1] = data[0];
483094332d3Sopenharmony_ci
484094332d3Sopenharmony_ci            HDF_LOGD("notify speed %{public}d", EcmBitrate());
485094332d3Sopenharmony_ci            ecm->notifyState = ECM_NOTIFY_NONE;
486094332d3Sopenharmony_ci            break;
487094332d3Sopenharmony_ci
488094332d3Sopenharmony_ci        default:
489094332d3Sopenharmony_ci            break;
490094332d3Sopenharmony_ci    }
491094332d3Sopenharmony_ci    event->bmRequestType = 0xA1;
492094332d3Sopenharmony_ci    event->wIndex = CPU_TO_LE16(ecm->ctrlId);
493094332d3Sopenharmony_ci    UsbFnNotifyRequest(req, ecm);
494094332d3Sopenharmony_ci}
495094332d3Sopenharmony_ci
496094332d3Sopenharmony_cistatic void EcmNotifyComplete(uint8_t pipe, struct UsbFnRequest *req)
497094332d3Sopenharmony_ci{
498094332d3Sopenharmony_ci    struct UsbEcmDevice *ecm = req->context;
499094332d3Sopenharmony_ci    struct UsbCdcNotification *event = req->buf;
500094332d3Sopenharmony_ci    ecm->notifyReq = req;
501094332d3Sopenharmony_ci    if (req->status == 0) {
502094332d3Sopenharmony_ci        EcmDoNotify(ecm);
503094332d3Sopenharmony_ci    } else {
504094332d3Sopenharmony_ci        HDF_LOGD("event %{public}d --> %{public}d", event->bNotificationType, req->status);
505094332d3Sopenharmony_ci    }
506094332d3Sopenharmony_ci}
507094332d3Sopenharmony_ci
508094332d3Sopenharmony_cistatic int32_t EcmSetup(const struct UsbEcmDevice *ecm, const struct UsbFnCtrlRequest *ctrl)
509094332d3Sopenharmony_ci{
510094332d3Sopenharmony_ci    struct UsbFnRequest *req = ecm->ep0Req;
511094332d3Sopenharmony_ci    int32_t ret = -1;
512094332d3Sopenharmony_ci    uint16_t index = LE16_TO_CPU(ctrl->index);
513094332d3Sopenharmony_ci    uint16_t value = LE16_TO_CPU(ctrl->value);
514094332d3Sopenharmony_ci    uint16_t length = LE16_TO_CPU(ctrl->length);
515094332d3Sopenharmony_ci
516094332d3Sopenharmony_ci    switch ((ctrl->reqType << 0x08) | ctrl->request) {
517094332d3Sopenharmony_ci        case ((USB_DDK_DIR_OUT | USB_DDK_TYPE_CLASS | USB_DDK_RECIP_INTERFACE) << 0x08) |
518094332d3Sopenharmony_ci            USB_DDK_CDC_SET_ETHERNET_PACKET_FILTER:
519094332d3Sopenharmony_ci            if (length != 0 || index != ecm->ctrlId) {
520094332d3Sopenharmony_ci                break;
521094332d3Sopenharmony_ci            }
522094332d3Sopenharmony_ci            HDF_LOGD("packet filter %{public}02x", value);
523094332d3Sopenharmony_ci            ret = 0;
524094332d3Sopenharmony_ci            break;
525094332d3Sopenharmony_ci
526094332d3Sopenharmony_ci        default:
527094332d3Sopenharmony_ci            HDF_LOGW(
528094332d3Sopenharmony_ci                "invalid control req%{public}02x.%{public}02x v%{public}04x i%{public}04x l%{public}hu",
529094332d3Sopenharmony_ci                ctrl->reqType, ctrl->request, value, index, length);
530094332d3Sopenharmony_ci    }
531094332d3Sopenharmony_ci
532094332d3Sopenharmony_ci    if (ret >= 0) {
533094332d3Sopenharmony_ci        HDF_LOGD("ecm req%{public}02x.%{public}02x v%{public}04x i%{public}04x l%{public}d",
534094332d3Sopenharmony_ci            ctrl->reqType, ctrl->request, value, index, length);
535094332d3Sopenharmony_ci        req->length = (uint32_t)ret;
536094332d3Sopenharmony_ci        ret = UsbFnSubmitRequestSync(req, 0);
537094332d3Sopenharmony_ci        if (ret < 0) {
538094332d3Sopenharmony_ci            HDF_LOGD("ecm req %{public}02x.%{public}02x response err %{public}d", ctrl->reqType, ctrl->request, ret);
539094332d3Sopenharmony_ci        }
540094332d3Sopenharmony_ci    }
541094332d3Sopenharmony_ci
542094332d3Sopenharmony_ci    return value;
543094332d3Sopenharmony_ci}
544094332d3Sopenharmony_ci
545094332d3Sopenharmony_cistatic int32_t EcmDeviceDispatch(
546094332d3Sopenharmony_ci    struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
547094332d3Sopenharmony_ci{
548094332d3Sopenharmony_ci    struct UsbEcmDevice *ecm = NULL;
549094332d3Sopenharmony_ci    struct UsbEcm *port = NULL;
550094332d3Sopenharmony_ci    int32_t ret;
551094332d3Sopenharmony_ci    if (client == NULL || client->device == NULL || client->device->service == NULL) {
552094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: client is NULL", __func__);
553094332d3Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
554094332d3Sopenharmony_ci    }
555094332d3Sopenharmony_ci    if (data == NULL || reply == NULL) {
556094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: data or reply is NULL", __func__);
557094332d3Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
558094332d3Sopenharmony_ci    }
559094332d3Sopenharmony_ci
560094332d3Sopenharmony_ci    if (HdfDeviceObjectCheckInterfaceDesc(client->device, data) == false) {
561094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d check interface desc fail", __func__, __LINE__);
562094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
563094332d3Sopenharmony_ci    }
564094332d3Sopenharmony_ci
565094332d3Sopenharmony_ci    switch (cmd) {
566094332d3Sopenharmony_ci        case USB_ECM_INIT:
567094332d3Sopenharmony_ci            return EcmInit(client->device);
568094332d3Sopenharmony_ci        case USB_ECM_RELEASE:
569094332d3Sopenharmony_ci            return EcmRelease(client->device);
570094332d3Sopenharmony_ci        default:
571094332d3Sopenharmony_ci            break;
572094332d3Sopenharmony_ci    }
573094332d3Sopenharmony_ci    ecm = (struct UsbEcmDevice *)client->device->service;
574094332d3Sopenharmony_ci    port = ecm->port;
575094332d3Sopenharmony_ci    if (port == NULL) {
576094332d3Sopenharmony_ci        return HDF_ERR_IO;
577094332d3Sopenharmony_ci    }
578094332d3Sopenharmony_ci    OsalMutexLock(&port->lockRW);
579094332d3Sopenharmony_ci    switch (cmd) {
580094332d3Sopenharmony_ci        case USB_ECM_OPEN:
581094332d3Sopenharmony_ci            ret = UsbEcmOpen(port);
582094332d3Sopenharmony_ci            break;
583094332d3Sopenharmony_ci        case USB_ECM_CLOSE:
584094332d3Sopenharmony_ci            ret = UsbEcmClose(port);
585094332d3Sopenharmony_ci            break;
586094332d3Sopenharmony_ci        case USB_ECM_READ:
587094332d3Sopenharmony_ci            ret = UsbEcmRead(port, reply);
588094332d3Sopenharmony_ci            break;
589094332d3Sopenharmony_ci        case USB_ECM_WRITE:
590094332d3Sopenharmony_ci            ret = UsbEcmWrite(port, data);
591094332d3Sopenharmony_ci            break;
592094332d3Sopenharmony_ci        default:
593094332d3Sopenharmony_ci            ret = HDF_ERR_NOT_SUPPORT;
594094332d3Sopenharmony_ci            break;
595094332d3Sopenharmony_ci    }
596094332d3Sopenharmony_ci    OsalMutexUnlock(&port->lockRW);
597094332d3Sopenharmony_ci    return ret;
598094332d3Sopenharmony_ci}
599094332d3Sopenharmony_ci
600094332d3Sopenharmony_cistatic int32_t EcmEnable(struct UsbEcmDevice *ecm)
601094332d3Sopenharmony_ci{
602094332d3Sopenharmony_ci    (void)ecm;
603094332d3Sopenharmony_ci    return HDF_SUCCESS;
604094332d3Sopenharmony_ci}
605094332d3Sopenharmony_ci
606094332d3Sopenharmony_cistatic void EcmDisable(const struct UsbEcmDevice *ecm)
607094332d3Sopenharmony_ci{
608094332d3Sopenharmony_ci    (void)ecm;
609094332d3Sopenharmony_ci    return;
610094332d3Sopenharmony_ci}
611094332d3Sopenharmony_ci
612094332d3Sopenharmony_cistatic void UsbEcmEventCallback(struct UsbFnEvent *event)
613094332d3Sopenharmony_ci{
614094332d3Sopenharmony_ci    struct UsbEcmDevice *ecm = NULL;
615094332d3Sopenharmony_ci
616094332d3Sopenharmony_ci    if (event == NULL || event->context == NULL) {
617094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: event is null", __func__);
618094332d3Sopenharmony_ci        return;
619094332d3Sopenharmony_ci    }
620094332d3Sopenharmony_ci
621094332d3Sopenharmony_ci    ecm = (struct UsbEcmDevice *)event->context;
622094332d3Sopenharmony_ci    switch (event->type) {
623094332d3Sopenharmony_ci        case USBFN_STATE_BIND:
624094332d3Sopenharmony_ci            HDF_LOGI("%{public}s: receive bind event", __func__);
625094332d3Sopenharmony_ci            break;
626094332d3Sopenharmony_ci        case USBFN_STATE_UNBIND:
627094332d3Sopenharmony_ci            HDF_LOGI("%{public}s: receive unbind event", __func__);
628094332d3Sopenharmony_ci            break;
629094332d3Sopenharmony_ci        case USBFN_STATE_ENABLE:
630094332d3Sopenharmony_ci            HDF_LOGI("%{public}s: receive enable event", __func__);
631094332d3Sopenharmony_ci            EcmEnable(ecm);
632094332d3Sopenharmony_ci            break;
633094332d3Sopenharmony_ci        case USBFN_STATE_DISABLE:
634094332d3Sopenharmony_ci            HDF_LOGI("%{public}s: receive disable event", __func__);
635094332d3Sopenharmony_ci            EcmDisable(ecm);
636094332d3Sopenharmony_ci            break;
637094332d3Sopenharmony_ci        case USBFN_STATE_SETUP:
638094332d3Sopenharmony_ci            HDF_LOGI("%{public}s: receive setup event", __func__);
639094332d3Sopenharmony_ci            if (event->setup != NULL) {
640094332d3Sopenharmony_ci                EcmSetup(ecm, event->setup);
641094332d3Sopenharmony_ci            }
642094332d3Sopenharmony_ci            break;
643094332d3Sopenharmony_ci        case USBFN_STATE_SUSPEND:
644094332d3Sopenharmony_ci            HDF_LOGI("%{public}s: receive suspend event", __func__);
645094332d3Sopenharmony_ci            break;
646094332d3Sopenharmony_ci        case USBFN_STATE_RESUME:
647094332d3Sopenharmony_ci            HDF_LOGI("%{public}s: receive resume event", __func__);
648094332d3Sopenharmony_ci            break;
649094332d3Sopenharmony_ci        default:
650094332d3Sopenharmony_ci            break;
651094332d3Sopenharmony_ci    }
652094332d3Sopenharmony_ci}
653094332d3Sopenharmony_ci
654094332d3Sopenharmony_cistatic int32_t EcmAllocNotifyRequest(struct UsbEcmDevice *ecm)
655094332d3Sopenharmony_ci{
656094332d3Sopenharmony_ci    /* allocate notification request */
657094332d3Sopenharmony_ci    ecm->notifyReq =
658094332d3Sopenharmony_ci        UsbFnAllocRequest(ecm->ctrlIface.handle, ecm->notifyPipe.id, sizeof(struct UsbCdcNotification) * USBCDC_LEN);
659094332d3Sopenharmony_ci    if (ecm->notifyReq == NULL) {
660094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: allocate notify request failed", __func__);
661094332d3Sopenharmony_ci        return HDF_FAILURE;
662094332d3Sopenharmony_ci    }
663094332d3Sopenharmony_ci    ecm->notifyReq->complete = EcmNotifyComplete;
664094332d3Sopenharmony_ci    ecm->notifyReq->context = ecm;
665094332d3Sopenharmony_ci
666094332d3Sopenharmony_ci    return HDF_SUCCESS;
667094332d3Sopenharmony_ci}
668094332d3Sopenharmony_ci
669094332d3Sopenharmony_cistatic int32_t EcmAllocEp0Request(struct UsbEcmDevice *ecm)
670094332d3Sopenharmony_ci{
671094332d3Sopenharmony_ci    /* allocate notification request */
672094332d3Sopenharmony_ci    ecm->ep0Req = UsbFnAllocCtrlRequest(ecm->ctrlIface.handle, ECM_STATUS_BYTECOUNT);
673094332d3Sopenharmony_ci    if (ecm->ep0Req == NULL) {
674094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: allocate ep0Req request failed", __func__);
675094332d3Sopenharmony_ci        return HDF_FAILURE;
676094332d3Sopenharmony_ci    }
677094332d3Sopenharmony_ci    return HDF_SUCCESS;
678094332d3Sopenharmony_ci}
679094332d3Sopenharmony_ci
680094332d3Sopenharmony_cistatic int32_t EcmParseEachPipe(struct UsbEcmDevice *ecm, struct UsbEcmInterface *iface)
681094332d3Sopenharmony_ci{
682094332d3Sopenharmony_ci    struct UsbFnInterface *fnIface = iface->fn;
683094332d3Sopenharmony_ci    uint32_t repetIdx = 0;
684094332d3Sopenharmony_ci    for (int32_t i = 0; i < fnIface->info.numPipes; i++) {
685094332d3Sopenharmony_ci        struct UsbFnPipeInfo pipeInfo;
686094332d3Sopenharmony_ci        (void)memset_s(&pipeInfo, sizeof(pipeInfo), 0, sizeof(pipeInfo));
687094332d3Sopenharmony_ci        int32_t ret = UsbFnGetInterfacePipeInfo(fnIface, (uint8_t)i, &pipeInfo);
688094332d3Sopenharmony_ci        if (ret != HDF_SUCCESS) {
689094332d3Sopenharmony_ci            HDF_LOGE("%{public}s: get pipe info error", __func__);
690094332d3Sopenharmony_ci            return HDF_FAILURE;
691094332d3Sopenharmony_ci        }
692094332d3Sopenharmony_ci
693094332d3Sopenharmony_ci        switch (pipeInfo.type) {
694094332d3Sopenharmony_ci            case USB_PIPE_TYPE_INTERRUPT:
695094332d3Sopenharmony_ci                ecm->notifyPipe.id = pipeInfo.id;
696094332d3Sopenharmony_ci                ecm->notifyPipe.maxPacketSize = pipeInfo.maxPacketSize;
697094332d3Sopenharmony_ci                ecm->ctrlIface = *iface;
698094332d3Sopenharmony_ci                break;
699094332d3Sopenharmony_ci            case USB_PIPE_TYPE_BULK:
700094332d3Sopenharmony_ci                if (pipeInfo.dir == USB_PIPE_DIRECTION_IN) {
701094332d3Sopenharmony_ci                    ecm->dataInPipe.id = pipeInfo.id;
702094332d3Sopenharmony_ci                    ecm->dataInPipe.maxPacketSize = pipeInfo.maxPacketSize;
703094332d3Sopenharmony_ci                    ecm->dataIface = *iface;
704094332d3Sopenharmony_ci                } else {
705094332d3Sopenharmony_ci                    ecm->dataOutPipe.id = pipeInfo.id;
706094332d3Sopenharmony_ci                    ecm->dataOutPipe.maxPacketSize = pipeInfo.maxPacketSize;
707094332d3Sopenharmony_ci                }
708094332d3Sopenharmony_ci                break;
709094332d3Sopenharmony_ci            default:
710094332d3Sopenharmony_ci                if (repetIdx < WAIT_UDC_MAX_LOOP) {
711094332d3Sopenharmony_ci                    usleep(WAIT_UDC_TIME);
712094332d3Sopenharmony_ci                    i--;
713094332d3Sopenharmony_ci                }
714094332d3Sopenharmony_ci                repetIdx++;
715094332d3Sopenharmony_ci                HDF_LOGE("%{public}s: pipe type %{public}d don't support", __func__, pipeInfo.type);
716094332d3Sopenharmony_ci                break;
717094332d3Sopenharmony_ci        }
718094332d3Sopenharmony_ci    }
719094332d3Sopenharmony_ci
720094332d3Sopenharmony_ci    return HDF_SUCCESS;
721094332d3Sopenharmony_ci}
722094332d3Sopenharmony_ci
723094332d3Sopenharmony_cistatic int32_t EcmParseEcmIface(struct UsbEcmDevice *ecm, struct UsbFnInterface *fnIface)
724094332d3Sopenharmony_ci{
725094332d3Sopenharmony_ci    int32_t ret;
726094332d3Sopenharmony_ci    struct UsbEcmInterface iface;
727094332d3Sopenharmony_ci    UsbFnInterfaceHandle handle = UsbFnOpenInterface(fnIface);
728094332d3Sopenharmony_ci    if (handle == NULL) {
729094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: open interface failed", __func__);
730094332d3Sopenharmony_ci        return HDF_FAILURE;
731094332d3Sopenharmony_ci    }
732094332d3Sopenharmony_ci    iface.fn = fnIface;
733094332d3Sopenharmony_ci    iface.handle = handle;
734094332d3Sopenharmony_ci
735094332d3Sopenharmony_ci    ret = EcmParseEachPipe(ecm, &iface);
736094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
737094332d3Sopenharmony_ci        return HDF_FAILURE;
738094332d3Sopenharmony_ci    }
739094332d3Sopenharmony_ci    return HDF_SUCCESS;
740094332d3Sopenharmony_ci}
741094332d3Sopenharmony_ci
742094332d3Sopenharmony_cistatic int32_t EcmParseEachIface(struct UsbEcmDevice *ecm, struct UsbFnDevice *fnDev)
743094332d3Sopenharmony_ci{
744094332d3Sopenharmony_ci    struct UsbFnInterface *fnIface = NULL;
745094332d3Sopenharmony_ci    uint32_t i;
746094332d3Sopenharmony_ci
747094332d3Sopenharmony_ci    for (i = 0; i < fnDev->numInterfaces; i++) {
748094332d3Sopenharmony_ci        fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i);
749094332d3Sopenharmony_ci        if (fnIface == NULL) {
750094332d3Sopenharmony_ci            HDF_LOGE("%{public}s: get interface failed", __func__);
751094332d3Sopenharmony_ci            return HDF_FAILURE;
752094332d3Sopenharmony_ci        }
753094332d3Sopenharmony_ci
754094332d3Sopenharmony_ci        if (fnIface->info.subclass == USB_DDK_CDC_SUBCLASS_ETHERNET) {
755094332d3Sopenharmony_ci            (void)EcmParseEcmIface(ecm, fnIface);
756094332d3Sopenharmony_ci            fnIface = (struct UsbFnInterface *)UsbFnGetInterface(fnDev, i + 1);
757094332d3Sopenharmony_ci            if (fnIface == NULL) {
758094332d3Sopenharmony_ci                HDF_LOGE("%{public}s: get interface failed", __func__);
759094332d3Sopenharmony_ci                return HDF_FAILURE;
760094332d3Sopenharmony_ci            }
761094332d3Sopenharmony_ci            (void)EcmParseEcmIface(ecm, fnIface);
762094332d3Sopenharmony_ci            return HDF_SUCCESS;
763094332d3Sopenharmony_ci        }
764094332d3Sopenharmony_ci    }
765094332d3Sopenharmony_ci
766094332d3Sopenharmony_ci    return HDF_FAILURE;
767094332d3Sopenharmony_ci}
768094332d3Sopenharmony_ci
769094332d3Sopenharmony_cistatic int32_t EcmCreateFuncDevice(struct UsbEcmDevice *ecm, struct DeviceResourceIface *iface)
770094332d3Sopenharmony_ci{
771094332d3Sopenharmony_ci    struct UsbFnDevice *fnDev = NULL;
772094332d3Sopenharmony_ci    int32_t ret;
773094332d3Sopenharmony_ci
774094332d3Sopenharmony_ci    if (iface->GetString(ecm->device->property, "udc_name", (const char **)&ecm->udcName, UDC_NAME) != HDF_SUCCESS) {
775094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: read udc_name failed, use default", __func__);
776094332d3Sopenharmony_ci        return HDF_FAILURE;
777094332d3Sopenharmony_ci    }
778094332d3Sopenharmony_ci
779094332d3Sopenharmony_ci    fnDev = (struct UsbFnDevice *)UsbFnGetDevice(ecm->udcName);
780094332d3Sopenharmony_ci    if (fnDev == NULL) {
781094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: create usb function device failed", __func__);
782094332d3Sopenharmony_ci        return HDF_FAILURE;
783094332d3Sopenharmony_ci    }
784094332d3Sopenharmony_ci
785094332d3Sopenharmony_ci    ret = EcmParseEachIface(ecm, fnDev);
786094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
787094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: get pipes failed", __func__);
788094332d3Sopenharmony_ci        goto ERR;
789094332d3Sopenharmony_ci    }
790094332d3Sopenharmony_ci
791094332d3Sopenharmony_ci    ecm->fnDev = fnDev;
792094332d3Sopenharmony_ci    return HDF_SUCCESS;
793094332d3Sopenharmony_ci
794094332d3Sopenharmony_ciERR:
795094332d3Sopenharmony_ci    return ret;
796094332d3Sopenharmony_ci}
797094332d3Sopenharmony_ci
798094332d3Sopenharmony_cistatic void EcmFreeNotifyRequest(struct UsbEcmDevice *ecm)
799094332d3Sopenharmony_ci{
800094332d3Sopenharmony_ci    int32_t ret;
801094332d3Sopenharmony_ci
802094332d3Sopenharmony_ci    /* free notification request */
803094332d3Sopenharmony_ci    ret = UsbFnFreeRequest(ecm->notifyReq);
804094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
805094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: free notify request failed", __func__);
806094332d3Sopenharmony_ci        return;
807094332d3Sopenharmony_ci    }
808094332d3Sopenharmony_ci    ecm->notifyReq = NULL;
809094332d3Sopenharmony_ci}
810094332d3Sopenharmony_ci
811094332d3Sopenharmony_cistatic int32_t EcmReleaseFuncDevice(struct UsbEcmDevice *ecm)
812094332d3Sopenharmony_ci{
813094332d3Sopenharmony_ci    int32_t ret = HDF_SUCCESS;
814094332d3Sopenharmony_ci    if (ecm->fnDev == NULL) {
815094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: fnDev is null", __func__);
816094332d3Sopenharmony_ci        return HDF_FAILURE;
817094332d3Sopenharmony_ci    }
818094332d3Sopenharmony_ci    (void)UsbFnFreeRequest(ecm->ep0Req);
819094332d3Sopenharmony_ci    (void)EcmFreeNotifyRequest(ecm);
820094332d3Sopenharmony_ci    UsbFnCloseInterface(ecm->ctrlIface.handle);
821094332d3Sopenharmony_ci    (void)UsbFnCloseInterface(ecm->dataIface.handle);
822094332d3Sopenharmony_ci    (void)UsbFnStopRecvInterfaceEvent(ecm->ctrlIface.fn);
823094332d3Sopenharmony_ci    return ret;
824094332d3Sopenharmony_ci}
825094332d3Sopenharmony_ci
826094332d3Sopenharmony_cistatic int32_t UsbEcmAlloc(struct UsbEcmDevice *ecm)
827094332d3Sopenharmony_ci{
828094332d3Sopenharmony_ci    struct UsbEcm *port = NULL;
829094332d3Sopenharmony_ci
830094332d3Sopenharmony_ci    port = (struct UsbEcm *)OsalMemCalloc(sizeof(*port));
831094332d3Sopenharmony_ci    if (port == NULL) {
832094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: Alloc usb serial port failed", __func__);
833094332d3Sopenharmony_ci        return HDF_FAILURE;
834094332d3Sopenharmony_ci    }
835094332d3Sopenharmony_ci
836094332d3Sopenharmony_ci    if (OsalMutexInit(&port->lock) != HDF_SUCCESS) {
837094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: init lock fail!", __func__);
838094332d3Sopenharmony_ci        OsalMemFree(port);
839094332d3Sopenharmony_ci        return HDF_FAILURE;
840094332d3Sopenharmony_ci    }
841094332d3Sopenharmony_ci
842094332d3Sopenharmony_ci    if (OsalMutexInit(&port->lockRW) != HDF_SUCCESS) {
843094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: init lock fail!", __func__);
844094332d3Sopenharmony_ci        OsalMutexDestroy(&port->lock);
845094332d3Sopenharmony_ci        OsalMemFree(port);
846094332d3Sopenharmony_ci        return HDF_FAILURE;
847094332d3Sopenharmony_ci    }
848094332d3Sopenharmony_ci
849094332d3Sopenharmony_ci    if (OsalMutexInit(&port->lockReadFifo) != HDF_SUCCESS) {
850094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: init lock fail!", __func__);
851094332d3Sopenharmony_ci        OsalMutexDestroy(&port->lock);
852094332d3Sopenharmony_ci        OsalMutexDestroy(&port->lockRW);
853094332d3Sopenharmony_ci        OsalMemFree(port);
854094332d3Sopenharmony_ci        return HDF_FAILURE;
855094332d3Sopenharmony_ci    }
856094332d3Sopenharmony_ci
857094332d3Sopenharmony_ci    if (OsalMutexInit(&port->lockWriteFifo) != HDF_SUCCESS) {
858094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: init lock fail!", __func__);
859094332d3Sopenharmony_ci        OsalMutexDestroy(&port->lock);
860094332d3Sopenharmony_ci        OsalMutexDestroy(&port->lockRW);
861094332d3Sopenharmony_ci        OsalMutexDestroy(&port->lockReadFifo);
862094332d3Sopenharmony_ci        OsalMemFree(port);
863094332d3Sopenharmony_ci        return HDF_FAILURE;
864094332d3Sopenharmony_ci    }
865094332d3Sopenharmony_ci    DListHeadInit(&port->readPool);
866094332d3Sopenharmony_ci    DListHeadInit(&port->readQueue);
867094332d3Sopenharmony_ci    DListHeadInit(&port->writePool);
868094332d3Sopenharmony_ci
869094332d3Sopenharmony_ci    ecm->port = port;
870094332d3Sopenharmony_ci    return HDF_SUCCESS;
871094332d3Sopenharmony_ci}
872094332d3Sopenharmony_ci
873094332d3Sopenharmony_cistatic void UsbEcmFree(struct UsbEcmDevice *ecm)
874094332d3Sopenharmony_ci{
875094332d3Sopenharmony_ci    if (ecm != NULL && ecm->port != NULL) {
876094332d3Sopenharmony_ci        OsalMutexDestroy(&ecm->port->lock);
877094332d3Sopenharmony_ci        OsalMutexDestroy(&ecm->port->lockRW);
878094332d3Sopenharmony_ci        OsalMutexDestroy(&ecm->port->lockReadFifo);
879094332d3Sopenharmony_ci        OsalMutexDestroy(&ecm->port->lockWriteFifo);
880094332d3Sopenharmony_ci        OsalMemFree(ecm->port);
881094332d3Sopenharmony_ci        ecm->port = NULL;
882094332d3Sopenharmony_ci    }
883094332d3Sopenharmony_ci}
884094332d3Sopenharmony_ci
885094332d3Sopenharmony_ci/* HdfDriverEntry implementations */
886094332d3Sopenharmony_cistatic int32_t EcmDriverBind(struct HdfDeviceObject *device)
887094332d3Sopenharmony_ci{
888094332d3Sopenharmony_ci    struct UsbEcmDevice *ecm = NULL;
889094332d3Sopenharmony_ci
890094332d3Sopenharmony_ci    if (device == NULL) {
891094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: device is null", __func__);
892094332d3Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
893094332d3Sopenharmony_ci    }
894094332d3Sopenharmony_ci
895094332d3Sopenharmony_ci    ecm = (struct UsbEcmDevice *)OsalMemCalloc(sizeof(*ecm));
896094332d3Sopenharmony_ci    if (ecm == NULL) {
897094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: Alloc usb ecm device failed", __func__);
898094332d3Sopenharmony_ci        return HDF_FAILURE;
899094332d3Sopenharmony_ci    }
900094332d3Sopenharmony_ci    ecm->ctrlId = 0;
901094332d3Sopenharmony_ci    ecm->dataId = 1;
902094332d3Sopenharmony_ci    if (OsalMutexInit(&ecm->lock) != HDF_SUCCESS) {
903094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: init lock fail!", __func__);
904094332d3Sopenharmony_ci        OsalMemFree(ecm);
905094332d3Sopenharmony_ci        return HDF_FAILURE;
906094332d3Sopenharmony_ci    }
907094332d3Sopenharmony_ci
908094332d3Sopenharmony_ci    if (HdfDeviceObjectSetInterfaceDesc(device, "hdf.usb.usbfn") != HDF_SUCCESS) {
909094332d3Sopenharmony_ci        HDF_LOGE(" Set Desc fail!");
910094332d3Sopenharmony_ci        OsalMemFree(ecm);
911094332d3Sopenharmony_ci        return HDF_FAILURE;
912094332d3Sopenharmony_ci    }
913094332d3Sopenharmony_ci
914094332d3Sopenharmony_ci    ecm->device = device;
915094332d3Sopenharmony_ci    device->service = &(ecm->service);
916094332d3Sopenharmony_ci    if (ecm->device->service) {
917094332d3Sopenharmony_ci        ecm->device->service->Dispatch = EcmDeviceDispatch;
918094332d3Sopenharmony_ci    }
919094332d3Sopenharmony_ci    return HDF_SUCCESS;
920094332d3Sopenharmony_ci}
921094332d3Sopenharmony_ci
922094332d3Sopenharmony_cistatic int32_t EcmInit(struct HdfDeviceObject *device)
923094332d3Sopenharmony_ci{
924094332d3Sopenharmony_ci    struct UsbEcmDevice *ecm = NULL;
925094332d3Sopenharmony_ci    struct DeviceResourceIface *iface = NULL;
926094332d3Sopenharmony_ci    int32_t ret;
927094332d3Sopenharmony_ci
928094332d3Sopenharmony_ci    if (device == NULL) {
929094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: device is null", __func__);
930094332d3Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
931094332d3Sopenharmony_ci    }
932094332d3Sopenharmony_ci
933094332d3Sopenharmony_ci    ecm = (struct UsbEcmDevice *)device->service;
934094332d3Sopenharmony_ci    if (ecm == NULL || ecm->initFlag) {
935094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: ecm is null", __func__);
936094332d3Sopenharmony_ci        return HDF_FAILURE;
937094332d3Sopenharmony_ci    }
938094332d3Sopenharmony_ci
939094332d3Sopenharmony_ci    iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
940094332d3Sopenharmony_ci    if (iface == NULL || iface->GetUint32 == NULL) {
941094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: face is invalid", __func__);
942094332d3Sopenharmony_ci        return HDF_FAILURE;
943094332d3Sopenharmony_ci    }
944094332d3Sopenharmony_ci
945094332d3Sopenharmony_ci    ret = EcmCreateFuncDevice(ecm, iface);
946094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
947094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: EcmCreateFuncDevice failed", __func__);
948094332d3Sopenharmony_ci        return ret;
949094332d3Sopenharmony_ci    }
950094332d3Sopenharmony_ci
951094332d3Sopenharmony_ci    ret = UsbEcmAlloc(ecm);
952094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
953094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: UsbEcmAlloc failed", __func__);
954094332d3Sopenharmony_ci        return ret;
955094332d3Sopenharmony_ci    }
956094332d3Sopenharmony_ci
957094332d3Sopenharmony_ci    ret = EcmAllocEp0Request(ecm);
958094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
959094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: EcmAllocEp0Request failed", __func__);
960094332d3Sopenharmony_ci        goto ERR;
961094332d3Sopenharmony_ci    }
962094332d3Sopenharmony_ci
963094332d3Sopenharmony_ci    ret = EcmAllocNotifyRequest(ecm);
964094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
965094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: EcmAllocNotifyRequest failed", __func__);
966094332d3Sopenharmony_ci        goto ERR;
967094332d3Sopenharmony_ci    }
968094332d3Sopenharmony_ci
969094332d3Sopenharmony_ci    ret = UsbFnStartRecvInterfaceEvent(ecm->ctrlIface.fn, RECEIVE_ALL_EVENTS, UsbEcmEventCallback, ecm);
970094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
971094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: register event callback failed", __func__);
972094332d3Sopenharmony_ci        goto ERR;
973094332d3Sopenharmony_ci    }
974094332d3Sopenharmony_ci    ecm->initFlag = true;
975094332d3Sopenharmony_ci    return ret;
976094332d3Sopenharmony_ciERR:
977094332d3Sopenharmony_ci    UsbEcmFree(ecm);
978094332d3Sopenharmony_ci    (void)EcmReleaseFuncDevice(ecm);
979094332d3Sopenharmony_ci    return ret;
980094332d3Sopenharmony_ci}
981094332d3Sopenharmony_ci
982094332d3Sopenharmony_cistatic int32_t EcmRelease(struct HdfDeviceObject *device)
983094332d3Sopenharmony_ci{
984094332d3Sopenharmony_ci    struct UsbEcmDevice *ecm = NULL;
985094332d3Sopenharmony_ci
986094332d3Sopenharmony_ci    if (device == NULL) {
987094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: device is NULL", __func__);
988094332d3Sopenharmony_ci        return HDF_FAILURE;
989094332d3Sopenharmony_ci    }
990094332d3Sopenharmony_ci
991094332d3Sopenharmony_ci    ecm = (struct UsbEcmDevice *)device->service;
992094332d3Sopenharmony_ci    if (ecm == NULL) {
993094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: ecm is null", __func__);
994094332d3Sopenharmony_ci        return HDF_FAILURE;
995094332d3Sopenharmony_ci    }
996094332d3Sopenharmony_ci    if (ecm->initFlag == false) {
997094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: ecm not init!", __func__);
998094332d3Sopenharmony_ci        return HDF_FAILURE;
999094332d3Sopenharmony_ci    }
1000094332d3Sopenharmony_ci    UsbEcmFree(ecm);
1001094332d3Sopenharmony_ci    (void)EcmReleaseFuncDevice(ecm);
1002094332d3Sopenharmony_ci    ecm->initFlag = false;
1003094332d3Sopenharmony_ci    return HDF_SUCCESS;
1004094332d3Sopenharmony_ci}
1005094332d3Sopenharmony_ci
1006094332d3Sopenharmony_cistatic int32_t EcmDriverInit(struct HdfDeviceObject *device)
1007094332d3Sopenharmony_ci{
1008094332d3Sopenharmony_ci    (void)device;
1009094332d3Sopenharmony_ci    HDF_LOGE("%{public}s: usbfn do nothing...", __func__);
1010094332d3Sopenharmony_ci    return 0;
1011094332d3Sopenharmony_ci}
1012094332d3Sopenharmony_ci
1013094332d3Sopenharmony_cistatic void EcmDriverRelease(struct HdfDeviceObject *device)
1014094332d3Sopenharmony_ci{
1015094332d3Sopenharmony_ci    struct UsbEcmDevice *ecm = NULL;
1016094332d3Sopenharmony_ci    if (device == NULL) {
1017094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: device is NULL", __func__);
1018094332d3Sopenharmony_ci        return;
1019094332d3Sopenharmony_ci    }
1020094332d3Sopenharmony_ci
1021094332d3Sopenharmony_ci    ecm = (struct UsbEcmDevice *)device->service;
1022094332d3Sopenharmony_ci    if (ecm == NULL) {
1023094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: ecm is null", __func__);
1024094332d3Sopenharmony_ci        return;
1025094332d3Sopenharmony_ci    }
1026094332d3Sopenharmony_ci
1027094332d3Sopenharmony_ci    (void)OsalMutexDestroy(&ecm->lock);
1028094332d3Sopenharmony_ci    OsalMemFree(ecm);
1029094332d3Sopenharmony_ci    device->service = NULL;
1030094332d3Sopenharmony_ci}
1031094332d3Sopenharmony_ci
1032094332d3Sopenharmony_cistruct HdfDriverEntry g_ecmDriverEntry = {
1033094332d3Sopenharmony_ci    .moduleVersion = 1,
1034094332d3Sopenharmony_ci    .moduleName = "usbfn_cdcecm",
1035094332d3Sopenharmony_ci    .Bind = EcmDriverBind,
1036094332d3Sopenharmony_ci    .Init = EcmDriverInit,
1037094332d3Sopenharmony_ci    .Release = EcmDriverRelease,
1038094332d3Sopenharmony_ci};
1039094332d3Sopenharmony_ci
1040094332d3Sopenharmony_ciHDF_INIT(g_ecmDriverEntry);
1041