1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2024 Archermind Technology (Nanjing) Co. Ltd. All rights reserved.
3094332d3Sopenharmony_ci *
4094332d3Sopenharmony_ci * Redistribution and use in source and binary forms, with or without modification,
5094332d3Sopenharmony_ci * are permitted provided that the following conditions are met:
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, this list of
8094332d3Sopenharmony_ci *    conditions and the following disclaimer.
9094332d3Sopenharmony_ci *
10094332d3Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11094332d3Sopenharmony_ci *    of conditions and the following disclaimer in the documentation and/or other materials
12094332d3Sopenharmony_ci *    provided with the distribution.
13094332d3Sopenharmony_ci *
14094332d3Sopenharmony_ci * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15094332d3Sopenharmony_ci *    to endorse or promote products derived from this software without specific prior written
16094332d3Sopenharmony_ci *    permission.
17094332d3Sopenharmony_ci *
18094332d3Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19094332d3Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20094332d3Sopenharmony_ci * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21094332d3Sopenharmony_ci * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22094332d3Sopenharmony_ci * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23094332d3Sopenharmony_ci * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24094332d3Sopenharmony_ci * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25094332d3Sopenharmony_ci * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26094332d3Sopenharmony_ci * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27094332d3Sopenharmony_ci * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28094332d3Sopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29094332d3Sopenharmony_ci */
30094332d3Sopenharmony_ci
31094332d3Sopenharmony_ci#include <unistd.h>
32094332d3Sopenharmony_ci#include "securec.h"
33094332d3Sopenharmony_ci#include "osal_mem.h"
34094332d3Sopenharmony_ci#include "osal_time.h"
35094332d3Sopenharmony_ci
36094332d3Sopenharmony_ci#include "hdf_base.h"
37094332d3Sopenharmony_ci#include "hdf_log.h"
38094332d3Sopenharmony_ci
39094332d3Sopenharmony_ci#include "usb_ddk_pnp_loader.h"
40094332d3Sopenharmony_ci#include "usb_ddk_interface.h"
41094332d3Sopenharmony_ci#include "usb_net_host.h"
42094332d3Sopenharmony_ci#include "rndis_rawapi.h"
43094332d3Sopenharmony_ci
44094332d3Sopenharmony_ci#define HDF_LOG_TAG USB_HOST_RNDIS_RAW_API
45094332d3Sopenharmony_ci#define URB_LEGAL_ACTUAL_LENGTH 8
46094332d3Sopenharmony_ci#define ZERO_INDEX  0
47094332d3Sopenharmony_ci#define ONE_INDEX   1
48094332d3Sopenharmony_ci#define TWO_INDEX   2
49094332d3Sopenharmony_ci#define THREE_INDEX 3
50094332d3Sopenharmony_ci#define FOUR_INDEX  4
51094332d3Sopenharmony_ci#define FIVE_INDEX  5
52094332d3Sopenharmony_ci
53094332d3Sopenharmony_ci#define MSG_HEAD_LENGTH         4
54094332d3Sopenharmony_ci#define UNION_OFFSET_LENGTH     8
55094332d3Sopenharmony_ci#define COMMAND_COUNT_MAX       10
56094332d3Sopenharmony_ci#define UNION_GETOFFSET_NUMBER  20
57094332d3Sopenharmony_ci#define RNDIS_COMMAND_SLEEPTIME 40
58094332d3Sopenharmony_ci#define RNDIS_QUERY_INPUT_LENGTH 48
59094332d3Sopenharmony_ci
60094332d3Sopenharmony_ci/* define rndis union */
61094332d3Sopenharmony_ciunion {
62094332d3Sopenharmony_ci    void *buf;
63094332d3Sopenharmony_ci    struct RndisMsgHdr *header;
64094332d3Sopenharmony_ci    struct RndisInit *init;
65094332d3Sopenharmony_ci    struct RndisInitC *initC;
66094332d3Sopenharmony_ci    struct RndisQuery *get;
67094332d3Sopenharmony_ci    struct RndisQueryC *getC;
68094332d3Sopenharmony_ci    struct RndisSet *set;
69094332d3Sopenharmony_ci    struct RndisSetC *setC;
70094332d3Sopenharmony_ci    struct RndisHalt *halt;
71094332d3Sopenharmony_ci} g_u;
72094332d3Sopenharmony_ci
73094332d3Sopenharmony_cistatic int32_t UsbGetBulkEndpoint(struct UsbnetHost **ppUsbNet, const struct UsbRawEndpointDescriptor *endPoint)
74094332d3Sopenharmony_ci{
75094332d3Sopenharmony_ci    if ((endPoint->endpointDescriptor.bEndpointAddress & USB_DDK_ENDPOINT_DIR_MASK) == USB_DDK_DIR_IN) {
76094332d3Sopenharmony_ci        /* get bulk in endpoint */
77094332d3Sopenharmony_ci        (*ppUsbNet)->dataInEp = OsalMemAlloc(sizeof(struct UsbEndpoint));
78094332d3Sopenharmony_ci        if ((*ppUsbNet)->dataInEp == NULL) {
79094332d3Sopenharmony_ci            HDF_LOGE("%{public}s:%{public}d allocate dataInEp failed", __func__, __LINE__);
80094332d3Sopenharmony_ci            return HDF_FAILURE;
81094332d3Sopenharmony_ci        }
82094332d3Sopenharmony_ci        (*ppUsbNet)->dataInEp->addr = endPoint->endpointDescriptor.bEndpointAddress;
83094332d3Sopenharmony_ci        (*ppUsbNet)->dataInEp->interval = endPoint->endpointDescriptor.bInterval;
84094332d3Sopenharmony_ci        (*ppUsbNet)->dataInEp->maxPacketSize = endPoint->endpointDescriptor.wMaxPacketSize;
85094332d3Sopenharmony_ci        HARCH_INFO_PRINT("usbNet->dataInEp=[addr:%{public}#x, interval:%{public}d, maxPacketSize:%{public}hu]",
86094332d3Sopenharmony_ci            (*ppUsbNet)->dataInEp->addr, (*ppUsbNet)->dataInEp->interval, (*ppUsbNet)->dataInEp->maxPacketSize);
87094332d3Sopenharmony_ci    } else {
88094332d3Sopenharmony_ci        /* get bulk out endpoint */
89094332d3Sopenharmony_ci        (*ppUsbNet)->dataOutEp = OsalMemAlloc(sizeof(struct UsbEndpoint));
90094332d3Sopenharmony_ci        if ((*ppUsbNet)->dataOutEp == NULL) {
91094332d3Sopenharmony_ci            HDF_LOGE("%{public}s:%{public}d allocate dataOutEp failed", __func__, __LINE__);
92094332d3Sopenharmony_ci            return HDF_FAILURE;
93094332d3Sopenharmony_ci        }
94094332d3Sopenharmony_ci        (*ppUsbNet)->dataOutEp->addr = endPoint->endpointDescriptor.bEndpointAddress;
95094332d3Sopenharmony_ci        (*ppUsbNet)->dataOutEp->interval = endPoint->endpointDescriptor.bInterval;
96094332d3Sopenharmony_ci        (*ppUsbNet)->dataOutEp->maxPacketSize = endPoint->endpointDescriptor.wMaxPacketSize;
97094332d3Sopenharmony_ci        HARCH_INFO_PRINT("usbNet->dataOutEp=[addr:%{public}#x, interval:%{public}d, maxPacketSize:%{public}hu]",
98094332d3Sopenharmony_ci            (*ppUsbNet)->dataOutEp->addr, (*ppUsbNet)->dataOutEp->interval, (*ppUsbNet)->dataOutEp->maxPacketSize);
99094332d3Sopenharmony_ci    }
100094332d3Sopenharmony_ci    return HDF_SUCCESS;
101094332d3Sopenharmony_ci}
102094332d3Sopenharmony_ci
103094332d3Sopenharmony_cistatic void UsbParseConfigDescriptorProcess(struct UsbnetHost **ppUsbNet,
104094332d3Sopenharmony_ci    const struct UsbRawInterface *interface, uint8_t interfaceIndex)
105094332d3Sopenharmony_ci{
106094332d3Sopenharmony_ci    uint8_t ifaceClass   = interface->altsetting->interfaceDescriptor.bInterfaceClass;
107094332d3Sopenharmony_ci    uint8_t numEndpoints = interface->altsetting->interfaceDescriptor.bNumEndpoints;
108094332d3Sopenharmony_ci    HARCH_INFO_PRINT("ifaceClass=%{public}d, numEndpoints=%{public}d", ifaceClass, numEndpoints);
109094332d3Sopenharmony_ci    switch (ifaceClass) {
110094332d3Sopenharmony_ci        case USB_DDK_CLASS_WIRELESS_CONTROLLER: //USB_DDK_CLASS_COMM:
111094332d3Sopenharmony_ci            (*ppUsbNet)->ctrlIface = interfaceIndex;
112094332d3Sopenharmony_ci            HARCH_INFO_PRINT("ctrlInface:%{public}d", interfaceIndex);
113094332d3Sopenharmony_ci            (*ppUsbNet)->statusEp = OsalMemAlloc(sizeof(struct UsbEndpoint));
114094332d3Sopenharmony_ci            if ((*ppUsbNet)->statusEp == NULL) {
115094332d3Sopenharmony_ci                HDF_LOGE("%{public}s:%{public}d allocate endpoint failed", __func__, __LINE__);
116094332d3Sopenharmony_ci                break;
117094332d3Sopenharmony_ci            }
118094332d3Sopenharmony_ci            /* get the first endpoint by default */
119094332d3Sopenharmony_ci            (*ppUsbNet)->statusEp->addr = interface->altsetting->endPoint[0].endpointDescriptor.bEndpointAddress;
120094332d3Sopenharmony_ci            (*ppUsbNet)->statusEp->interval = interface->altsetting->endPoint[0].endpointDescriptor.bInterval;
121094332d3Sopenharmony_ci            (*ppUsbNet)->statusEp->maxPacketSize = interface->altsetting->endPoint[0].endpointDescriptor.wMaxPacketSize;
122094332d3Sopenharmony_ci
123094332d3Sopenharmony_ci            HARCH_INFO_PRINT("usbNet->statusEp=[addr:%{public}#x, interval:%{public}d, maxPacketSize:%{public}hu]",
124094332d3Sopenharmony_ci                (*ppUsbNet)->statusEp->addr, (*ppUsbNet)->statusEp->interval, (*ppUsbNet)->statusEp->maxPacketSize);
125094332d3Sopenharmony_ci            break;
126094332d3Sopenharmony_ci        case USB_DDK_CLASS_CDC_DATA:
127094332d3Sopenharmony_ci            (*ppUsbNet)->dataIface = interfaceIndex;
128094332d3Sopenharmony_ci            HARCH_INFO_PRINT("dataIface:%{public}d", interfaceIndex);
129094332d3Sopenharmony_ci            for (uint8_t j = 0; j < numEndpoints; j++) {
130094332d3Sopenharmony_ci                const struct UsbRawEndpointDescriptor *endPoint = &interface->altsetting->endPoint[j];
131094332d3Sopenharmony_ci                if (UsbGetBulkEndpoint(ppUsbNet, endPoint) != HDF_SUCCESS) {
132094332d3Sopenharmony_ci                    HARCH_INFO_PRINT("");
133094332d3Sopenharmony_ci                    break;
134094332d3Sopenharmony_ci                }
135094332d3Sopenharmony_ci                HARCH_INFO_PRINT("");
136094332d3Sopenharmony_ci            }
137094332d3Sopenharmony_ci            break;
138094332d3Sopenharmony_ci        default:
139094332d3Sopenharmony_ci            HARCH_INFO_PRINT("wrong descriptor type");
140094332d3Sopenharmony_ci            break;
141094332d3Sopenharmony_ci    }
142094332d3Sopenharmony_ci}
143094332d3Sopenharmony_ci
144094332d3Sopenharmony_cistatic int32_t UsbParseConfigDescriptor(struct UsbnetHost **ppUsbNet)
145094332d3Sopenharmony_ci{
146094332d3Sopenharmony_ci    const struct UsbRawInterface *interface = (*ppUsbNet)->config->interface[0];
147094332d3Sopenharmony_ci    //set 0 interface and 1 interface data endpoint and ctrl endpoint
148094332d3Sopenharmony_ci    int32_t ret = UsbRawClaimInterface((*ppUsbNet)->devHandle, 0);
149094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
150094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d claim interface failed", __func__, __LINE__);
151094332d3Sopenharmony_ci        return HDF_FAILURE;
152094332d3Sopenharmony_ci    }
153094332d3Sopenharmony_ci    HARCH_INFO_PRINT("");
154094332d3Sopenharmony_ci    UsbParseConfigDescriptorProcess(ppUsbNet, interface, 0);
155094332d3Sopenharmony_ci
156094332d3Sopenharmony_ci    const struct UsbRawInterface *interface1 = (*ppUsbNet)->config->interface[1];
157094332d3Sopenharmony_ci    ret = UsbRawClaimInterface((*ppUsbNet)->devHandle, 1);
158094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
159094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d claim interface failed", __func__, __LINE__);
160094332d3Sopenharmony_ci        return HDF_FAILURE;
161094332d3Sopenharmony_ci    }
162094332d3Sopenharmony_ci    HARCH_INFO_PRINT("");
163094332d3Sopenharmony_ci    UsbParseConfigDescriptorProcess(ppUsbNet, interface1, 1);
164094332d3Sopenharmony_ci    return HDF_SUCCESS;
165094332d3Sopenharmony_ci}
166094332d3Sopenharmony_ci
167094332d3Sopenharmony_ci/*
168094332d3Sopenharmony_ci * RNDIS indicate messages.
169094332d3Sopenharmony_ci */
170094332d3Sopenharmony_cistatic void HostRndisMsgIndicate(struct UsbnetHost *usbNet, struct RndisIndicate *msg, int buflen)
171094332d3Sopenharmony_ci{
172094332d3Sopenharmony_ci    HARCH_INFO_PRINT("begin");
173094332d3Sopenharmony_ci    uint32_t status = CPU_TO_LE32(msg->status);
174094332d3Sopenharmony_ci    switch (status) {
175094332d3Sopenharmony_ci        case RNDIS_STATUS_MEDIA_CONNECT:
176094332d3Sopenharmony_ci            HARCH_INFO_PRINT("rndis media connect");
177094332d3Sopenharmony_ci            break;
178094332d3Sopenharmony_ci        case RNDIS_STATUS_MEDIA_DISCONNECT:
179094332d3Sopenharmony_ci            HARCH_INFO_PRINT("rndis media disconnect");
180094332d3Sopenharmony_ci            break;
181094332d3Sopenharmony_ci        default:
182094332d3Sopenharmony_ci            HARCH_INFO_PRINT("rndis indication: 0x%{public}08x\n", status);
183094332d3Sopenharmony_ci            /* fall-through */
184094332d3Sopenharmony_ci    }
185094332d3Sopenharmony_ci}
186094332d3Sopenharmony_ci
187094332d3Sopenharmony_cistatic void UsbnetHostHandleNonRsp(struct UsbnetHost *usbNet,
188094332d3Sopenharmony_ci    struct RndisMsgHdr *buf, int buflen, uint32_t msgType)
189094332d3Sopenharmony_ci{
190094332d3Sopenharmony_ci    switch (msgType) {
191094332d3Sopenharmony_ci        /* fault/event */
192094332d3Sopenharmony_ci        case RNDIS_MSG_INDICATE:
193094332d3Sopenharmony_ci            HostRndisMsgIndicate(usbNet, (void *)buf, buflen);
194094332d3Sopenharmony_ci            break;
195094332d3Sopenharmony_ci        case RNDIS_MSG_KEEPALIVE: {
196094332d3Sopenharmony_ci                /* ping */
197094332d3Sopenharmony_ci                struct RndisKeepaliveC *msg = (void *)buf;
198094332d3Sopenharmony_ci                msg->msgType = CPU_TO_LE32(RNDIS_MSG_KEEPALIVE_C);
199094332d3Sopenharmony_ci                msg->msgLen = CPU_TO_LE32(sizeof(struct RndisKeepaliveC));
200094332d3Sopenharmony_ci                msg->status = CPU_TO_LE32(RNDIS_STATUS_SUCCESS);
201094332d3Sopenharmony_ci
202094332d3Sopenharmony_ci                struct UsbnetHostCmdParam cmdParam = {};
203094332d3Sopenharmony_ci                cmdParam.cmd = USB_DDK_CDC_SEND_ENCAPSULATED_COMMAND;
204094332d3Sopenharmony_ci                cmdParam.reqtype = USB_DDK_DIR_OUT|USB_DDK_TYPE_CLASS|USB_DDK_RECIP_INTERFACE;
205094332d3Sopenharmony_ci                cmdParam.value = 0;
206094332d3Sopenharmony_ci                cmdParam.index = usbNet->curInterfaceNumber;
207094332d3Sopenharmony_ci                cmdParam.data = msg;
208094332d3Sopenharmony_ci                cmdParam.size = sizeof(struct RndisKeepaliveC);
209094332d3Sopenharmony_ci                int32_t retval = UsbnetHostWriteCmdSync(usbNet, cmdParam);
210094332d3Sopenharmony_ci                HARCH_INFO_PRINT("retval = %{public}d", retval);
211094332d3Sopenharmony_ci                if (retval < 0) {
212094332d3Sopenharmony_ci                    HARCH_INFO_PRINT("rndis keepalive err %{public}d\n", retval);
213094332d3Sopenharmony_ci                }
214094332d3Sopenharmony_ci            }
215094332d3Sopenharmony_ci            break;
216094332d3Sopenharmony_ci        default:
217094332d3Sopenharmony_ci            HARCH_INFO_PRINT("unexpected rndis msg %{public}08x len %{public}d\n",
218094332d3Sopenharmony_ci                CPU_TO_LE32(buf->msgType), CPU_TO_LE32(buf->msgLen));
219094332d3Sopenharmony_ci            break;
220094332d3Sopenharmony_ci    }
221094332d3Sopenharmony_ci}
222094332d3Sopenharmony_ci
223094332d3Sopenharmony_cistatic int32_t UsbnetHostHandleMsg(struct UsbnetHost *usbNet, struct RndisMsgHdr *buf, int buflen, uint32_t xid)
224094332d3Sopenharmony_ci{
225094332d3Sopenharmony_ci    uint32_t msgType = CPU_TO_LE32(buf->msgType);
226094332d3Sopenharmony_ci    uint32_t msgLen = CPU_TO_LE32(buf->msgLen);
227094332d3Sopenharmony_ci    uint32_t status = CPU_TO_LE32(buf->status);
228094332d3Sopenharmony_ci    uint32_t requestId =  (uint32_t)buf->requestId;
229094332d3Sopenharmony_ci    uint32_t rsp = CPU_TO_LE32(buf->msgType) | RNDIS_MSG_COMPLETION;
230094332d3Sopenharmony_ci    HARCH_INFO_PRINT("rndis reply msgType = %{public}x, msgLen = %{public}x,"
231094332d3Sopenharmony_ci        "status = %{public}x, requestId = %{public}x",
232094332d3Sopenharmony_ci        msgType, msgLen, status, requestId);
233094332d3Sopenharmony_ci
234094332d3Sopenharmony_ci    if (msgType == rsp) {
235094332d3Sopenharmony_ci        if (requestId == xid) {
236094332d3Sopenharmony_ci            HARCH_INFO_PRINT("rndis reply status %{public}08x\n", status);
237094332d3Sopenharmony_ci            HARCH_INFO_PRINT("rndis reply rsp %{public}08x\n", rsp);
238094332d3Sopenharmony_ci            if (rsp == RNDIS_MSG_RESET_C) {
239094332d3Sopenharmony_ci                return HDF_SUCCESS;
240094332d3Sopenharmony_ci            }
241094332d3Sopenharmony_ci
242094332d3Sopenharmony_ci            if (RNDIS_STATUS_SUCCESS == status) {
243094332d3Sopenharmony_ci                return HDF_SUCCESS;
244094332d3Sopenharmony_ci            }
245094332d3Sopenharmony_ci
246094332d3Sopenharmony_ci            HARCH_INFO_PRINT("rndis reply status %{public}08x\n", status);
247094332d3Sopenharmony_ci            return -EL3RST;
248094332d3Sopenharmony_ci        }
249094332d3Sopenharmony_ci        /* then likely retry */
250094332d3Sopenharmony_ci    } else {
251094332d3Sopenharmony_ci        HARCH_INFO_PRINT("unexpected rndis msg %{public}08x len %{public}d\n", CPU_TO_LE32(buf->msgType), msgLen);
252094332d3Sopenharmony_ci        UsbnetHostHandleNonRsp(usbNet, buf, buflen, msgType);
253094332d3Sopenharmony_ci    }
254094332d3Sopenharmony_ci    return HDF_SUCCESS;
255094332d3Sopenharmony_ci}
256094332d3Sopenharmony_ci
257094332d3Sopenharmony_ci/*
258094332d3Sopenharmony_ci * RPC done RNDIS-style.  Caller guarantees:
259094332d3Sopenharmony_ci * - message is properly byteswapped
260094332d3Sopenharmony_ci * - there's no other request pending
261094332d3Sopenharmony_ci * - buf can hold up to 1KB response (required by RNDIS spec)
262094332d3Sopenharmony_ci * On return, the first few entries are already byteswapped.
263094332d3Sopenharmony_ci *
264094332d3Sopenharmony_ci * Call context is likely probe(), before interface name is known,
265094332d3Sopenharmony_ci * which is why we won't try to use it in the diagnostics.
266094332d3Sopenharmony_ci */
267094332d3Sopenharmony_cistatic int32_t HostRndisCommand(struct UsbnetHost *usbNet, struct RndisMsgHdr *buf, int buflen)
268094332d3Sopenharmony_ci{
269094332d3Sopenharmony_ci    HARCH_INFO_PRINT("begin");
270094332d3Sopenharmony_ci    uint32_t msgType = CPU_TO_LE32(buf->msgType);
271094332d3Sopenharmony_ci    uint32_t xid = 0;
272094332d3Sopenharmony_ci
273094332d3Sopenharmony_ci    /* Issue the request; xid is unique, don't bother byteswapping it */
274094332d3Sopenharmony_ci    if (msgType != RNDIS_MSG_HALT && msgType != RNDIS_MSG_RESET) {
275094332d3Sopenharmony_ci        xid = usbNet->xid++;
276094332d3Sopenharmony_ci        if (!xid) {
277094332d3Sopenharmony_ci            xid = usbNet->xid++;
278094332d3Sopenharmony_ci        }
279094332d3Sopenharmony_ci        buf->requestId = (__le32) xid;
280094332d3Sopenharmony_ci    }
281094332d3Sopenharmony_ci    HARCH_INFO_PRINT("msgType= %{public}d, xid = %{public}d", msgType, xid);
282094332d3Sopenharmony_ci    struct UsbnetHostCmdParam cmdParam = {};
283094332d3Sopenharmony_ci    cmdParam.cmd = USB_DDK_CDC_SEND_ENCAPSULATED_COMMAND;
284094332d3Sopenharmony_ci    cmdParam.reqtype = USB_DDK_DIR_OUT|USB_DDK_TYPE_CLASS|USB_DDK_RECIP_INTERFACE;
285094332d3Sopenharmony_ci    cmdParam.value = 0;
286094332d3Sopenharmony_ci    cmdParam.index = usbNet->curInterfaceNumber;
287094332d3Sopenharmony_ci    cmdParam.data = buf;
288094332d3Sopenharmony_ci    cmdParam.size = CPU_TO_LE32(buf->msgLen);
289094332d3Sopenharmony_ci
290094332d3Sopenharmony_ci    int retval = UsbnetHostWriteCmdSync(usbNet, cmdParam);
291094332d3Sopenharmony_ci    HARCH_INFO_PRINT("retval = %{public}d", retval);
292094332d3Sopenharmony_ci    if (retval < 0 || xid == 0) {
293094332d3Sopenharmony_ci        return retval;
294094332d3Sopenharmony_ci    }
295094332d3Sopenharmony_ci    UsbnetWriteLog((char *)buf, CPU_TO_LE32(buf->msgLen), 0);
296094332d3Sopenharmony_ci    HARCH_INFO_PRINT("rndis xid %{public}d\n", xid);
297094332d3Sopenharmony_ci    uint32_t count = 0;
298094332d3Sopenharmony_ci    /* Poll the control channel; the request probably completed immediately */
299094332d3Sopenharmony_ci    for (count = 0; count < COMMAND_COUNT_MAX; count++) {
300094332d3Sopenharmony_ci        HARCH_INFO_PRINT("count = %{public}d, buflen = %{public}d", count, buflen);
301094332d3Sopenharmony_ci        memset_s(buf, CONTROL_BUFFER_SIZE, 0, CONTROL_BUFFER_SIZE);
302094332d3Sopenharmony_ci        cmdParam.cmd = USB_DDK_CDC_GET_ENCAPSULATED_RESPONSE;
303094332d3Sopenharmony_ci        cmdParam.reqtype = USB_DDK_DIR_IN|USB_DDK_TYPE_CLASS|USB_DDK_RECIP_INTERFACE;
304094332d3Sopenharmony_ci        cmdParam.value = 0;
305094332d3Sopenharmony_ci        cmdParam.index = usbNet->curInterfaceNumber;
306094332d3Sopenharmony_ci        cmdParam.data = buf;
307094332d3Sopenharmony_ci        cmdParam.size = buflen;
308094332d3Sopenharmony_ci        retval= UsbnetHostWriteCmdSync(usbNet, cmdParam);
309094332d3Sopenharmony_ci        HARCH_INFO_PRINT("retval = %{public}d", retval);
310094332d3Sopenharmony_ci        UsbnetWriteLog((char *)buf, buflen, 0);
311094332d3Sopenharmony_ci
312094332d3Sopenharmony_ci        if (retval > URB_LEGAL_ACTUAL_LENGTH) {
313094332d3Sopenharmony_ci            return UsbnetHostHandleMsg(usbNet, buf, buflen, xid);
314094332d3Sopenharmony_ci        } else {
315094332d3Sopenharmony_ci            /* device probably issued a protocol stall; ignore */
316094332d3Sopenharmony_ci            HARCH_INFO_PRINT("rndis response error = %{public}d", retval);
317094332d3Sopenharmony_ci        }
318094332d3Sopenharmony_ci        OsalMSleep(RNDIS_COMMAND_SLEEPTIME);
319094332d3Sopenharmony_ci    }
320094332d3Sopenharmony_ci    HARCH_INFO_PRINT("rndis response timeout");
321094332d3Sopenharmony_ci    return HDF_ERR_TIMEOUT;
322094332d3Sopenharmony_ci}
323094332d3Sopenharmony_ci
324094332d3Sopenharmony_ci/* Performs a query for @oid along with 0 or more bytes of payload as
325094332d3Sopenharmony_ci * specified by @in_len. If @replyLen is not set to -1 then the reply
326094332d3Sopenharmony_ci * length is checked against this value, resulting in an error if it
327094332d3Sopenharmony_ci * doesn't match.
328094332d3Sopenharmony_ci *
329094332d3Sopenharmony_ci * NOTE: Adding a payload exactly or greater than the size of the expected
330094332d3Sopenharmony_ci * response payload is an evident requirement MSFT added for ActiveSync.
331094332d3Sopenharmony_ci *
332094332d3Sopenharmony_ci * The only exception is for OIDs that return a variably sized response,
333094332d3Sopenharmony_ci * in which case no payload should be added.  This undocumented (and
334094332d3Sopenharmony_ci * nonsensical!) issue was found by sniffing protocol requests from the
335094332d3Sopenharmony_ci * ActiveSync 4.1 Windows driver.
336094332d3Sopenharmony_ci */
337094332d3Sopenharmony_cistatic int32_t HostRndisQuery(struct UsbnetHost *usbNet, struct RndisQueryParam queryParam, void **reply, int *replyLen)
338094332d3Sopenharmony_ci{
339094332d3Sopenharmony_ci    HARCH_INFO_PRINT("begin");
340094332d3Sopenharmony_ci    int retval;
341094332d3Sopenharmony_ci    union {
342094332d3Sopenharmony_ci        void *buf;
343094332d3Sopenharmony_ci        struct RndisMsgHdr *header;
344094332d3Sopenharmony_ci        struct RndisQuery *get;
345094332d3Sopenharmony_ci        struct RndisQueryC *getC;
346094332d3Sopenharmony_ci    } uq;
347094332d3Sopenharmony_ci
348094332d3Sopenharmony_ci    uq.buf = queryParam.buf;
349094332d3Sopenharmony_ci    memset_s(uq.get, sizeof(struct RndisQuery) + queryParam.in_len, 0, sizeof(struct RndisQuery) + queryParam.in_len);
350094332d3Sopenharmony_ci    uq.get->msgType = CPU_TO_LE32(RNDIS_MSG_QUERY);
351094332d3Sopenharmony_ci    uq.get->msgLen  = CPU_TO_LE32(sizeof(struct RndisQuery) + queryParam.in_len);
352094332d3Sopenharmony_ci    uq.get->oid = CPU_TO_LE32(queryParam.oid);
353094332d3Sopenharmony_ci    uq.get->len = CPU_TO_LE32(queryParam.in_len);
354094332d3Sopenharmony_ci    uq.get->offset = CPU_TO_LE32(UNION_GETOFFSET_NUMBER);
355094332d3Sopenharmony_ci
356094332d3Sopenharmony_ci    retval = HostRndisCommand(usbNet, uq.header, CONTROL_BUFFER_SIZE);
357094332d3Sopenharmony_ci    HARCH_INFO_PRINT("retval = %{public}d", retval);
358094332d3Sopenharmony_ci    HARCH_INFO_PRINT("RNDIS_MSG_QUERY(0x%{public}08x) %{public}d\n", queryParam.oid, retval);
359094332d3Sopenharmony_ci    if (retval < 0) {
360094332d3Sopenharmony_ci        HDF_LOGE("RNDIS_MSG_QUERY(0x%{public}08x) failed, %{public}d", queryParam.oid, retval);
361094332d3Sopenharmony_ci        return retval;
362094332d3Sopenharmony_ci    }
363094332d3Sopenharmony_ci
364094332d3Sopenharmony_ci    uint32_t off = CPU_TO_LE32(uq.getC->offset);
365094332d3Sopenharmony_ci    uint32_t len = CPU_TO_LE32(uq.getC->len);
366094332d3Sopenharmony_ci
367094332d3Sopenharmony_ci    HARCH_INFO_PRINT("off = %{public}d, len = %{public}d, retval = %{public}d", off, len, retval);
368094332d3Sopenharmony_ci    // CONTROL_BUFFER_SIZE_-UNION_OFFSET_LENGTH is valid memory range
369094332d3Sopenharmony_ci    if ((off > CONTROL_BUFFER_SIZE - UNION_OFFSET_LENGTH) || (len > CONTROL_BUFFER_SIZE - UNION_OFFSET_LENGTH - off)) {
370094332d3Sopenharmony_ci        goto response_error;
371094332d3Sopenharmony_ci    }
372094332d3Sopenharmony_ci
373094332d3Sopenharmony_ci    if (*replyLen != -1 && len != *replyLen) {
374094332d3Sopenharmony_ci        goto response_error;
375094332d3Sopenharmony_ci    }
376094332d3Sopenharmony_ci
377094332d3Sopenharmony_ci    *reply = (unsigned char *) &uq.getC->requestId + off;
378094332d3Sopenharmony_ci    *replyLen = len;
379094332d3Sopenharmony_ci
380094332d3Sopenharmony_ci    HARCH_INFO_PRINT("*replyLen = %{public}d, retval = %{public}d", len, retval);
381094332d3Sopenharmony_ci    return retval;
382094332d3Sopenharmony_ci
383094332d3Sopenharmony_ciresponse_error:
384094332d3Sopenharmony_ci    HDF_LOGE("RNDIS_MSG_QUERY(0x%{public}08x) invalid response - off %{public}d len %{public}d",
385094332d3Sopenharmony_ci        queryParam.oid, off, len);
386094332d3Sopenharmony_ci
387094332d3Sopenharmony_ci    return -EDOM;
388094332d3Sopenharmony_ci}
389094332d3Sopenharmony_ci
390094332d3Sopenharmony_cistatic void HostRndisInitUsbnet(struct UsbnetHost **ppUsbNet, int32_t *retval)
391094332d3Sopenharmony_ci{
392094332d3Sopenharmony_ci    /* max transfer (in spec) is 0x4000 at full speed, but for
393094332d3Sopenharmony_ci     * TX we'll stick to one Ethernet packet plus RNDIS framing.
394094332d3Sopenharmony_ci     * For RX we handle drivers that zero-pad to end-of-packet.
395094332d3Sopenharmony_ci     * Don't let userspace change these settings.
396094332d3Sopenharmony_ci     *
397094332d3Sopenharmony_ci     * NOTE: there still seems to be wierdness here, as if we need
398094332d3Sopenharmony_ci     * to do some more things to make sure WinCE targets accept this.
399094332d3Sopenharmony_ci     * They default to jumbograms of 8KB or 16KB, which is absurd
400094332d3Sopenharmony_ci     * for such low data rates and which is also more than Linux
401094332d3Sopenharmony_ci     * can usually expect to allocate for SKB data...
402094332d3Sopenharmony_ci     */
403094332d3Sopenharmony_ci    (*ppUsbNet)->net.hardHeaderLen += sizeof(struct RndisDataHdr);
404094332d3Sopenharmony_ci    (*ppUsbNet)->net.hardMtu = (*ppUsbNet)->net.mtu + (*ppUsbNet)->net.hardHeaderLen;
405094332d3Sopenharmony_ci    HARCH_INFO_PRINT("hardHeaderLen = %{public}d, hardMtu = %{public}d\n",
406094332d3Sopenharmony_ci        (*ppUsbNet)->net.hardHeaderLen, (*ppUsbNet)->net.hardMtu);
407094332d3Sopenharmony_ci    (*ppUsbNet)->net.maxpacket = (*ppUsbNet)->dataOutEp->maxPacketSize;
408094332d3Sopenharmony_ci
409094332d3Sopenharmony_ci    HARCH_INFO_PRINT("maxpacket = %{public}d\n", (*ppUsbNet)->net.maxpacket);
410094332d3Sopenharmony_ci    if ((*ppUsbNet)->net.maxpacket == 0) {
411094332d3Sopenharmony_ci        HDF_LOGE("usbNet->maxpacket can't be 0");
412094332d3Sopenharmony_ci        *retval = HDF_ERR_INVALID_PARAM;
413094332d3Sopenharmony_ci        return;
414094332d3Sopenharmony_ci    }
415094332d3Sopenharmony_ci
416094332d3Sopenharmony_ci    (*ppUsbNet)->net.rxUrbSize = (*ppUsbNet)->net.hardMtu + ((*ppUsbNet)->net.maxpacket + 1);
417094332d3Sopenharmony_ci    (*ppUsbNet)->net.rxUrbSize &= ~((*ppUsbNet)->net.maxpacket - 1);
418094332d3Sopenharmony_ci    HARCH_INFO_PRINT("rxUrbSize = %{public}d\n", (*ppUsbNet)->net.rxUrbSize);
419094332d3Sopenharmony_ci}
420094332d3Sopenharmony_ci
421094332d3Sopenharmony_cistatic void HostRndisUpdateMtu(struct UsbnetHost **ppUsbNet, int32_t *retval)
422094332d3Sopenharmony_ci{
423094332d3Sopenharmony_ci    uint32_t tmp = CPU_TO_LE32(g_u.initC->maxTransferSize);
424094332d3Sopenharmony_ci    if (tmp < (*ppUsbNet)->net.hardMtu) {
425094332d3Sopenharmony_ci        if (tmp <= (*ppUsbNet)->net.hardHeaderLen) {
426094332d3Sopenharmony_ci            HARCH_INFO_PRINT("RNDIS init failed, %{public}d", *retval);
427094332d3Sopenharmony_ci            HDF_LOGE("usbNet can't take %{public}u byte packets (max %{public}u)", (*ppUsbNet)->net.hardMtu, tmp);
428094332d3Sopenharmony_ci            *retval = HDF_ERR_INVALID_PARAM;
429094332d3Sopenharmony_ci        }
430094332d3Sopenharmony_ci        HARCH_INFO_PRINT("usbNet can't take %{public}u byte packets (max %{public}u) adjusting MTU to %{public}u\n",
431094332d3Sopenharmony_ci            (*ppUsbNet)->net.hardMtu, tmp, tmp - (*ppUsbNet)->net.hardHeaderLen);
432094332d3Sopenharmony_ci        HDF_LOGW("usbNet can't take %{public}u byte packets (max %{public}u) adjusting MTU to %{public}u",
433094332d3Sopenharmony_ci            (*ppUsbNet)->net.hardMtu, tmp, tmp - (*ppUsbNet)->net.hardHeaderLen);
434094332d3Sopenharmony_ci        (*ppUsbNet)->net.hardMtu = tmp;
435094332d3Sopenharmony_ci        (*ppUsbNet)->net.mtu = (*ppUsbNet)->net.hardMtu - (*ppUsbNet)->net.hardHeaderLen;
436094332d3Sopenharmony_ci    }
437094332d3Sopenharmony_ci    HARCH_INFO_PRINT("hard mtu %{public}u (%{public}u from usbNet), rx buflen %{public}u, align %{public}d\n",
438094332d3Sopenharmony_ci        (*ppUsbNet)->net.hardMtu, tmp, (*ppUsbNet)->net.rxUrbSize, 1 << CPU_TO_LE32(g_u.initC->packetAlignment));
439094332d3Sopenharmony_ci}
440094332d3Sopenharmony_ci
441094332d3Sopenharmony_cistatic void HostRndisSetmacAddrByBp(struct UsbnetHost **ppUsbNet, int32_t *retval)
442094332d3Sopenharmony_ci{
443094332d3Sopenharmony_ci    int replyLen = MAC_ADDR_SIZE;
444094332d3Sopenharmony_ci    unsigned char *bp;
445094332d3Sopenharmony_ci    struct RndisQueryParam queryParam = {g_u.buf, RNDIS_OID_802_3_PERMANENT_ADDRESS, RNDIS_QUERY_INPUT_LENGTH};
446094332d3Sopenharmony_ci    *retval = HostRndisQuery(*ppUsbNet, queryParam, (void **)&bp, &replyLen);
447094332d3Sopenharmony_ci    if (*retval < 0) {
448094332d3Sopenharmony_ci        HDF_LOGE("rndis get ethaddr, %{public}d", *retval);
449094332d3Sopenharmony_ci        *retval = HDF_ERR_NOPERM;
450094332d3Sopenharmony_ci    }
451094332d3Sopenharmony_ci
452094332d3Sopenharmony_ci    HARCH_INFO_PRINT("bp 1= %{public}x", bp[ZERO_INDEX]);
453094332d3Sopenharmony_ci    HARCH_INFO_PRINT("bp 2= %{public}x", bp[ONE_INDEX]);
454094332d3Sopenharmony_ci    HARCH_INFO_PRINT("bp 3= %{public}x", bp[TWO_INDEX]);
455094332d3Sopenharmony_ci    HARCH_INFO_PRINT("bp 4= %{public}x", bp[THREE_INDEX]);
456094332d3Sopenharmony_ci    HARCH_INFO_PRINT("bp 5= %{public}x", bp[FOUR_INDEX]);
457094332d3Sopenharmony_ci    HARCH_INFO_PRINT("bp 6= %{public}x", bp[FIVE_INDEX]);
458094332d3Sopenharmony_ci
459094332d3Sopenharmony_ci    if (bp[0] & 0x02) {
460094332d3Sopenharmony_ci        HARCH_INFO_PRINT("not GetmacAddr");
461094332d3Sopenharmony_ci        (*ppUsbNet)->net.isGetmacAddr = 0;
462094332d3Sopenharmony_ci        size_t macAddrLen = sizeof((*ppUsbNet)->net.macAddr) / sizeof((*ppUsbNet)->net.macAddr[0]);
463094332d3Sopenharmony_ci        if (memset_s((*ppUsbNet)->net.macAddr, macAddrLen, 0, macAddrLen) !=EOK) {
464094332d3Sopenharmony_ci            HARCH_INFO_PRINT("HostRndisSetmacAddrByBp memset_s fail!");
465094332d3Sopenharmony_ci            return;
466094332d3Sopenharmony_ci        }
467094332d3Sopenharmony_ci    } else {
468094332d3Sopenharmony_ci        HARCH_INFO_PRINT("GetmacAddr");
469094332d3Sopenharmony_ci        (*ppUsbNet)->net.isGetmacAddr = 1;
470094332d3Sopenharmony_ci        etherAddrCopy((*ppUsbNet)->net.macAddr, bp);
471094332d3Sopenharmony_ci    }
472094332d3Sopenharmony_ci}
473094332d3Sopenharmony_ci
474094332d3Sopenharmony_cistatic void HostRndisSetmacAddr(struct UsbnetHost **ppUsbNet, int32_t *retval)
475094332d3Sopenharmony_ci{
476094332d3Sopenharmony_ci    __le32 *phym = NULL;
477094332d3Sopenharmony_ci    __le32 phym_unspec;
478094332d3Sopenharmony_ci    int replyLen = sizeof(__le32);
479094332d3Sopenharmony_ci    /* Check physical medium */
480094332d3Sopenharmony_ci    struct RndisQueryParam queryParam = {g_u.buf, RNDIS_OID_GEN_PHYSICAL_MEDIUM, replyLen};
481094332d3Sopenharmony_ci    *retval = HostRndisQuery(*ppUsbNet, queryParam, (void **)&phym, &replyLen);
482094332d3Sopenharmony_ci    if ((retval != NULL && *retval != 0) || !phym) {
483094332d3Sopenharmony_ci        /* OID is optional so don't fail here. */
484094332d3Sopenharmony_ci        phym_unspec = CPU_TO_LE32(RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED);
485094332d3Sopenharmony_ci        phym = &phym_unspec;
486094332d3Sopenharmony_ci    }
487094332d3Sopenharmony_ci
488094332d3Sopenharmony_ci    if (((*ppUsbNet)->flags & FLAG_RNDIS_PHYM_WIRELESS) &&
489094332d3Sopenharmony_ci        CPU_TO_LE32(*phym) != RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) {
490094332d3Sopenharmony_ci        HDF_LOGE("driver requires wireless physical medium, but device is not");
491094332d3Sopenharmony_ci        *retval = HDF_ERR_NOPERM;
492094332d3Sopenharmony_ci    }
493094332d3Sopenharmony_ci
494094332d3Sopenharmony_ci    if (((*ppUsbNet)->flags & FLAG_RNDIS_PHYM_NOT_WIRELESS) &&
495094332d3Sopenharmony_ci        CPU_TO_LE32(*phym) == RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) {
496094332d3Sopenharmony_ci        HDF_LOGE("driver requires non-wireless physical medium, but device is wireless");
497094332d3Sopenharmony_ci        *retval = HDF_ERR_NOPERM;
498094332d3Sopenharmony_ci    }
499094332d3Sopenharmony_ci
500094332d3Sopenharmony_ci    /* Get designated host ethernet address */
501094332d3Sopenharmony_ci    HostRndisSetmacAddrByBp(ppUsbNet, retval);
502094332d3Sopenharmony_ci}
503094332d3Sopenharmony_ci
504094332d3Sopenharmony_cistatic int32_t HostRndisInitUnion(struct UsbnetHost *usbNet, int32_t *retval)
505094332d3Sopenharmony_ci{
506094332d3Sopenharmony_ci    int32_t ret = HDF_SUCCESS;
507094332d3Sopenharmony_ci    g_u.buf = OsalMemAlloc(CONTROL_BUFFER_SIZE);
508094332d3Sopenharmony_ci    if (!g_u.buf) {
509094332d3Sopenharmony_ci        HDF_LOGE("g_u.buf can't be 0");
510094332d3Sopenharmony_ci        ret = HDF_ERR_MALLOC_FAIL;
511094332d3Sopenharmony_ci    }
512094332d3Sopenharmony_ci
513094332d3Sopenharmony_ci    g_u.init->msgType = CPU_TO_LE32(RNDIS_MSG_INIT);
514094332d3Sopenharmony_ci    g_u.init->msgLen  = CPU_TO_LE32(sizeof(struct RndisInit));
515094332d3Sopenharmony_ci    g_u.init->majorVersion = CPU_TO_LE32(1);
516094332d3Sopenharmony_ci    g_u.init->minorVersion = CPU_TO_LE32(0);
517094332d3Sopenharmony_ci
518094332d3Sopenharmony_ci    g_u.init->maxTransferSize = CPU_TO_LE32((usbNet)->net.rxUrbSize);
519094332d3Sopenharmony_ci    *retval = HostRndisCommand(usbNet, g_u.header, CONTROL_BUFFER_SIZE);
520094332d3Sopenharmony_ci    if (*retval < 0) {
521094332d3Sopenharmony_ci        /* it might not even be an RNDIS device!! */
522094332d3Sopenharmony_ci        HARCH_INFO_PRINT("RNDIS init failed, %{public}d", *retval);
523094332d3Sopenharmony_ci        HDF_LOGE("RNDIS init failed, %{public}d", *retval);
524094332d3Sopenharmony_ci        ret = HDF_DEV_ERR_OP;
525094332d3Sopenharmony_ci    }
526094332d3Sopenharmony_ci    return ret;
527094332d3Sopenharmony_ci}
528094332d3Sopenharmony_ci
529094332d3Sopenharmony_cistatic int32_t HostRndisEnableDataTransfers(struct UsbnetHost *usbNet)
530094332d3Sopenharmony_ci{
531094332d3Sopenharmony_ci    int32_t ret = HDF_SUCCESS;
532094332d3Sopenharmony_ci    /* set a nonzero filter to enable data transfers */
533094332d3Sopenharmony_ci    memset_s(g_u.set, sizeof(struct RndisSet), 0, sizeof(struct RndisSet));
534094332d3Sopenharmony_ci    g_u.set->msgType = CPU_TO_LE32(RNDIS_MSG_SET);
535094332d3Sopenharmony_ci    g_u.set->msgLen = CPU_TO_LE32(MSG_HEAD_LENGTH + sizeof(struct RndisSet));
536094332d3Sopenharmony_ci    g_u.set->oid = CPU_TO_LE32(RNDIS_OID_GEN_CURRENT_PACKET_FILTER);
537094332d3Sopenharmony_ci    g_u.set->len = CPU_TO_LE32(MSG_HEAD_LENGTH);
538094332d3Sopenharmony_ci    g_u.set->offset = CPU_TO_LE32(sizeof(struct RndisSet) - UNION_OFFSET_LENGTH);
539094332d3Sopenharmony_ci    *(__le32 *)(g_u.buf + sizeof(struct RndisSet)) = CPU_TO_LE32(RNDIS_DEFAULT_FILTER);
540094332d3Sopenharmony_ci    int32_t retval = HostRndisCommand(usbNet, g_u.header, CONTROL_BUFFER_SIZE);
541094332d3Sopenharmony_ci    if (retval < 0) {
542094332d3Sopenharmony_ci        HDF_LOGE("rndis set packet filter, %{public}d", retval);
543094332d3Sopenharmony_ci        ret = HDF_FAILURE;
544094332d3Sopenharmony_ci    }
545094332d3Sopenharmony_ci    OsalMemFree(g_u.buf);
546094332d3Sopenharmony_ci    g_u.buf = NULL;
547094332d3Sopenharmony_ci    return ret;
548094332d3Sopenharmony_ci}
549094332d3Sopenharmony_ci
550094332d3Sopenharmony_ci/* function
551094332d3Sopenharmony_ci    1.get usb endpoints info
552094332d3Sopenharmony_ci    2.init usb device
553094332d3Sopenharmony_ci    3.get usb device adrress and status
554094332d3Sopenharmony_ci    4.set usb device work
555094332d3Sopenharmony_ci*/
556094332d3Sopenharmony_cistatic int32_t HostRndisBind(struct UsbnetHost *usbNet)
557094332d3Sopenharmony_ci{
558094332d3Sopenharmony_ci    int32_t retval = 0;
559094332d3Sopenharmony_ci    int32_t ret = UsbParseConfigDescriptor(&usbNet);
560094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
561094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d UsbParseConfigDescriptor failed", __func__, __LINE__);
562094332d3Sopenharmony_ci        UsbRawFreeConfigDescriptor(usbNet->config);
563094332d3Sopenharmony_ci        usbNet->config = NULL;
564094332d3Sopenharmony_ci        return ret;
565094332d3Sopenharmony_ci    }
566094332d3Sopenharmony_ci
567094332d3Sopenharmony_ci    HostRndisInitUsbnet(&usbNet, &retval);
568094332d3Sopenharmony_ci    if (retval == HDF_ERR_INVALID_PARAM) {
569094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d HostRndisInitUsbnet failed", __func__, __LINE__);
570094332d3Sopenharmony_ci        return retval;
571094332d3Sopenharmony_ci    }
572094332d3Sopenharmony_ci
573094332d3Sopenharmony_ci    ret = HostRndisInitUnion(usbNet, &retval);
574094332d3Sopenharmony_ci    if (ret == HDF_ERR_MALLOC_FAIL) {
575094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d HostRndisInitUnion failed", __func__, __LINE__);
576094332d3Sopenharmony_ci        return ret;
577094332d3Sopenharmony_ci    } else if (ret == HDF_DEV_ERR_OP) {
578094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d HostRndisInitUnion failed", __func__, __LINE__);
579094332d3Sopenharmony_ci        OsalMemFree(g_u.buf);
580094332d3Sopenharmony_ci        g_u.buf = NULL;
581094332d3Sopenharmony_ci        return ret;
582094332d3Sopenharmony_ci    }
583094332d3Sopenharmony_ci
584094332d3Sopenharmony_ci    HostRndisUpdateMtu(&usbNet, &retval);
585094332d3Sopenharmony_ci    if (retval == HDF_ERR_INVALID_PARAM) {
586094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d HostRndisUpdateMtu failed", __func__, __LINE__);
587094332d3Sopenharmony_ci        goto ERR_HALT_FAILED_AND_RELEASE;
588094332d3Sopenharmony_ci        return retval;
589094332d3Sopenharmony_ci    }
590094332d3Sopenharmony_ci
591094332d3Sopenharmony_ci    HostRndisSetmacAddr(&usbNet, &retval);
592094332d3Sopenharmony_ci    if (retval == HDF_ERR_NOPERM) {
593094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d HostRndisSetmacAddr failed", __func__, __LINE__);
594094332d3Sopenharmony_ci        goto ERR_HALT_FAILED_AND_RELEASE;
595094332d3Sopenharmony_ci        return retval;
596094332d3Sopenharmony_ci    }
597094332d3Sopenharmony_ci
598094332d3Sopenharmony_ci    ret = HostRndisEnableDataTransfers(usbNet);
599094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
600094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d HostRndisEnableDataTransfers failed", __func__, __LINE__);
601094332d3Sopenharmony_ci        goto ERR_HALT_FAILED_AND_RELEASE;
602094332d3Sopenharmony_ci    }
603094332d3Sopenharmony_ci    return ret;
604094332d3Sopenharmony_ciERR_HALT_FAILED_AND_RELEASE:
605094332d3Sopenharmony_ci    memset_s(g_u.halt, sizeof(struct RndisHalt), 0, sizeof(struct RndisHalt));
606094332d3Sopenharmony_ci    g_u.halt->msgType = CPU_TO_LE32(RNDIS_MSG_HALT);
607094332d3Sopenharmony_ci    g_u.halt->msgLen = CPU_TO_LE32(sizeof(struct RndisHalt));
608094332d3Sopenharmony_ci    (void)HostRndisCommand(usbNet, (void *)g_u.halt, CONTROL_BUFFER_SIZE);
609094332d3Sopenharmony_ci    return HDF_FAILURE;
610094332d3Sopenharmony_ci}
611094332d3Sopenharmony_ci
612094332d3Sopenharmony_cistatic void HostRndisUnbind(struct UsbnetHost *usbNet)
613094332d3Sopenharmony_ci{
614094332d3Sopenharmony_ci    HARCH_INFO_PRINT();
615094332d3Sopenharmony_ci    struct RndisHalt *halt = OsalMemAlloc(sizeof(struct RndisHalt));
616094332d3Sopenharmony_ci
617094332d3Sopenharmony_ci    memset_s(halt, sizeof(struct RndisHalt), 0, sizeof(struct RndisHalt));
618094332d3Sopenharmony_ci    halt->msgType = CPU_TO_LE32(RNDIS_MSG_HALT);
619094332d3Sopenharmony_ci    halt->msgLen  = CPU_TO_LE32(sizeof(struct RndisHalt));
620094332d3Sopenharmony_ci    (void) HostRndisCommand(usbNet, (void *)halt, CONTROL_BUFFER_SIZE);
621094332d3Sopenharmony_ci    OsalMemFree(halt);
622094332d3Sopenharmony_ci}
623094332d3Sopenharmony_ci
624094332d3Sopenharmony_cistatic struct UsbnetHostDriverInfo g_hostRndisInfo = {
625094332d3Sopenharmony_ci    .description    =    "rndis device",
626094332d3Sopenharmony_ci    .bind           =    HostRndisBind,
627094332d3Sopenharmony_ci    .unbind         =    HostRndisUnbind,
628094332d3Sopenharmony_ci};
629094332d3Sopenharmony_ci
630094332d3Sopenharmony_cistatic int32_t HostRndisDriverDeviceDispatch(
631094332d3Sopenharmony_ci    struct HdfDeviceIoClient *client, int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
632094332d3Sopenharmony_ci{
633094332d3Sopenharmony_ci    return HDF_SUCCESS;
634094332d3Sopenharmony_ci}
635094332d3Sopenharmony_ci
636094332d3Sopenharmony_ci/* HdfDriverEntry implementations */
637094332d3Sopenharmony_cistatic int32_t HostRndisDriverBind(struct HdfDeviceObject *device)
638094332d3Sopenharmony_ci{
639094332d3Sopenharmony_ci    HARCH_INFO_PRINT("[-cbs-] HostRndisDriverBind begin !");
640094332d3Sopenharmony_ci    if (device == NULL) {
641094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: device is null", __func__);
642094332d3Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
643094332d3Sopenharmony_ci    }
644094332d3Sopenharmony_ci
645094332d3Sopenharmony_ci    struct UsbnetHost *usbNet = (struct UsbnetHost *)OsalMemCalloc(sizeof(*usbNet));
646094332d3Sopenharmony_ci    if (usbNet == NULL) {
647094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: Alloc  UsbnetHost memory failed", __func__);
648094332d3Sopenharmony_ci        return HDF_FAILURE;
649094332d3Sopenharmony_ci    }
650094332d3Sopenharmony_ci
651094332d3Sopenharmony_ci    struct UsbPnpNotifyServiceInfo *info = NULL;
652094332d3Sopenharmony_ci    info = (struct UsbPnpNotifyServiceInfo *)device->priv;
653094332d3Sopenharmony_ci    if (info != NULL) {
654094332d3Sopenharmony_ci        HARCH_INFO_PRINT("[-cbs-]bus:%{public}d+dev:%{public}d", info->busNum, info->devNum);
655094332d3Sopenharmony_ci        HARCH_INFO_PRINT("[-cbs-]interfaceLength:%{public}d", info->interfaceLength);
656094332d3Sopenharmony_ci        HARCH_INFO_PRINT("[-cbs-]curInterfaceNum:%{public}d", info->curInterfaceNumber);
657094332d3Sopenharmony_ci
658094332d3Sopenharmony_ci        usbNet->busNum = info->busNum;
659094332d3Sopenharmony_ci        usbNet->devAddr = info->devNum;
660094332d3Sopenharmony_ci        usbNet->curInterfaceNumber = info->curInterfaceNumber;
661094332d3Sopenharmony_ci    } else {
662094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d info is NULL!", __func__, __LINE__);
663094332d3Sopenharmony_ci        goto ERROR;
664094332d3Sopenharmony_ci    }
665094332d3Sopenharmony_ci
666094332d3Sopenharmony_ci    HDF_LOGE("%{public}s:%{public}d", __func__, __LINE__);
667094332d3Sopenharmony_ci    device->service = &(usbNet->service);
668094332d3Sopenharmony_ci    if (device->service == NULL) {
669094332d3Sopenharmony_ci        HDF_LOGE("%{public}s:%{public}d", __func__, __LINE__);
670094332d3Sopenharmony_ci    }
671094332d3Sopenharmony_ci
672094332d3Sopenharmony_ci    device->service->Dispatch = HostRndisDriverDeviceDispatch;
673094332d3Sopenharmony_ci    usbNet->deviceObject = device;
674094332d3Sopenharmony_ci
675094332d3Sopenharmony_ci    /* here need to choose device driver */
676094332d3Sopenharmony_ci    struct  UsbnetHostDriverInfo *driver = &g_hostRndisInfo;
677094332d3Sopenharmony_ci    //function
678094332d3Sopenharmony_ci    usbNet->driverInfo = driver;
679094332d3Sopenharmony_ci
680094332d3Sopenharmony_ci    HARCH_INFO_PRINT("bind ok");
681094332d3Sopenharmony_ci    return HDF_SUCCESS;
682094332d3Sopenharmony_ciERROR:
683094332d3Sopenharmony_ci    OsalMemFree(usbNet);
684094332d3Sopenharmony_ci    return HDF_SUCCESS;
685094332d3Sopenharmony_ci}
686094332d3Sopenharmony_ci
687094332d3Sopenharmony_cistatic int32_t HostRndisDriverInit(struct HdfDeviceObject *device)
688094332d3Sopenharmony_ci{
689094332d3Sopenharmony_ci    HARCH_INFO_PRINT("[-cbs-] HostRndisDriverInit begin !");
690094332d3Sopenharmony_ci    if (device == NULL) {
691094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: device is null", __func__);
692094332d3Sopenharmony_ci        return HDF_ERR_INVALID_OBJECT;
693094332d3Sopenharmony_ci    }
694094332d3Sopenharmony_ci    int32_t ret = HDF_SUCCESS;
695094332d3Sopenharmony_ci
696094332d3Sopenharmony_ci    struct UsbnetHost *usbNet = (struct UsbnetHost *)device->service;
697094332d3Sopenharmony_ci    //net init
698094332d3Sopenharmony_ci    ret = UsbnetHostProbe(usbNet);
699094332d3Sopenharmony_ci    if (ret != HDF_SUCCESS) {
700094332d3Sopenharmony_ci        HARCH_INFO_PRINT("[-cbs-] UsbnetHostProbe error !");
701094332d3Sopenharmony_ci    }
702094332d3Sopenharmony_ci    //usb init
703094332d3Sopenharmony_ci    return ret;
704094332d3Sopenharmony_ci}
705094332d3Sopenharmony_ci
706094332d3Sopenharmony_cistatic void HostRndisDriverRelease(struct HdfDeviceObject *device)
707094332d3Sopenharmony_ci{
708094332d3Sopenharmony_ci    HARCH_INFO_PRINT();
709094332d3Sopenharmony_ci    struct UsbPnpNotifyServiceInfo *info = NULL;
710094332d3Sopenharmony_ci    info = (struct UsbPnpNotifyServiceInfo *)device->priv;
711094332d3Sopenharmony_ci    if (info != NULL) {
712094332d3Sopenharmony_ci        HARCH_INFO_PRINT("bus:%{public}d+dev:%{public}d", info->busNum, info->devNum);
713094332d3Sopenharmony_ci        HARCH_INFO_PRINT("interfaceLength:%{public}d", info->interfaceLength);
714094332d3Sopenharmony_ci    }
715094332d3Sopenharmony_ci    struct UsbnetHost *usbNet = (struct UsbnetHost *)device->service;
716094332d3Sopenharmony_ci    if (usbNet == NULL) {
717094332d3Sopenharmony_ci        HDF_LOGE("%{public}s: Alloc  UsbnetHost memory failed", __func__);
718094332d3Sopenharmony_ci        return;
719094332d3Sopenharmony_ci    }
720094332d3Sopenharmony_ci
721094332d3Sopenharmony_ci    UsbnetHostRelease(usbNet);
722094332d3Sopenharmony_ci    usbNet->driverInfo->unbind(usbNet);
723094332d3Sopenharmony_ci
724094332d3Sopenharmony_ci    //free momory
725094332d3Sopenharmony_ci    OsalMemFree(usbNet);
726094332d3Sopenharmony_ci    return;
727094332d3Sopenharmony_ci}
728094332d3Sopenharmony_ci
729094332d3Sopenharmony_cistruct HdfDriverEntry g_hostRndisRawDriverEntry = {
730094332d3Sopenharmony_ci    .moduleVersion = 1,
731094332d3Sopenharmony_ci    .moduleName = "usbhost_rndis_rawapi",
732094332d3Sopenharmony_ci    .Bind = HostRndisDriverBind,
733094332d3Sopenharmony_ci    .Init = HostRndisDriverInit,
734094332d3Sopenharmony_ci    .Release = HostRndisDriverRelease,
735094332d3Sopenharmony_ci};
736094332d3Sopenharmony_ciHDF_INIT(g_hostRndisRawDriverEntry);
737