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