⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rndis.c

📁 Windows CE 6.0 BSP for the Beagle Board.
💻 C
📖 第 1 页 / 共 4 页
字号:
        default:
            OALMSG(OAL_ERROR, (L"*** Unknown GET_DESCRIPTOR request:0x%x\r\n", HIBYTE(wType)));
            fRet = FALSE;
            break;
    }

    if (fRet) {
        pRequest->eDir = EP0In;
        pRequest->pucData = pucData;
        pRequest->dwExpectedSize = pUdr->wLength;
        pRequest->dwActualSize = min(wLength, pUdr->wLength);
        pRequest->pfnNotification = NULL;       // notification not required
        pRequest->pvUser = NULL;
    }
    return fRet;
}

// parses the setup packet to determine if it is one of the two standard RNDIS requests
// and sets up a send or receive transfer request on EP0 if necessary
static BOOL PDD_DoVendorCommand(USB_DEVICE_REQUEST *pUdr, EP0_REQUEST *pRequest)
{
    BOOL fRet = TRUE;

    //
    // RNDIS spec:: we should only be getting:
    // - SEND_ENCAPSULATED_COMMAND  or
    // - GET_ENCAPSULATED_RESPONSE.
    // So let's just look for these two, and bail out if it does
    //not match..
    //
    switch (pUdr->bRequest) {
        case SEND_ENCAPSULATED_COMMAND:
            pRequest->eDir = EP0Out;
            pRequest->pucData = (UCHAR *)(g_RndisKitlDev.EP0RxBuffer);
            pRequest->dwExpectedSize = pUdr->wLength;
            pRequest->dwActualSize = pUdr->wLength;
            pRequest->pfnNotification = PDD_RecvNotification;
            pRequest->pvUser = &(g_RndisKitlDev.EP0DataWrapper);
            break;

        case GET_ENCAPSULATED_RESPONSE:
            pRequest->eDir = EP0In;
            if (!IsListEmpty(&(g_RndisKitlDev.listTxRndisMessageQueue))) {
                PLIST_ENTRY pLink;
                PDATA_WRAPPER pDataWrapper;

                pLink = RemoveHeadList(&(g_RndisKitlDev.listTxRndisMessageQueue));
                pDataWrapper = CONTAINING_RECORD(pLink, DATA_WRAPPER, Link);
                //KITLDEBUGMSG(MDDZONE, ("<0x%X\r\n", pDataWrapper));
                pRequest->pucData = pDataWrapper->pucData;
                pRequest->dwExpectedSize = pUdr->wLength;
                pRequest->dwActualSize = pDataWrapper->dwDataSize;
                pRequest->pfnNotification = PDD_SendNotification;
                pRequest->pvUser = pDataWrapper;

                g_RndisKitlDev.pEP0DataWrapper = pDataWrapper;
            } else {
                //
                // RNDIS spec says if we have no data to send then 
                // send one byte packet set to 00 instead of stalling the 
                // pipe.
                //
                pRequest->pucData = &g_ucScratch;
                pRequest->dwActualSize = sizeof(UCHAR);
                pRequest->dwExpectedSize = pUdr->wLength;
                pRequest->pfnNotification = NULL;
                pRequest->pvUser = NULL;
            }
            break;

        default:
            fRet = FALSE;
            break;
    }
    return fRet;
}

// sets up a packet receive transfer on EP1 (BULK OUT)
VOID SetupEP1Transfer()
{
    // allocate data transfer for EP1
    if (!g_pEP1DataWrapper) {
        g_pEP1DataWrapper = MDDAllocDataWrapper();
        if (!g_pEP1DataWrapper) {
            OALMSG(OAL_ERROR, (L"No mem for RX DataWrapper\r\n"));
            return;
        }

        g_pEP1DataWrapper->pucData = MDDAllocMem();
        if (!g_pEP1DataWrapper->pucData) {
            OALMSG(OAL_ERROR, (L"No mem for RX data\r\n"));
            MDDFreeDataWrapper(g_pEP1DataWrapper);
            return;
        }
        g_pEP1DataWrapper->dwDataSize = MAX_INCOMING_BUFFER;
    }

    // g_EP1Transfer.dwCallerPermissions;
    g_EP1Transfer.pvBuffer = g_pEP1DataWrapper->pucData;
    // g_EP1Transfer.dwBufferPhysicalAddress; // not used
    g_EP1Transfer.cbBuffer = g_pEP1DataWrapper->dwDataSize;
    g_EP1Transfer.cbTransferred = 0;
    g_EP1Transfer.dwUsbError = UFN_NOT_COMPLETE_ERROR; // Possible values are in usbfntypes.h
    g_EP1Transfer.pvPddData = NULL;
    g_EP1Transfer.pvPddTransferInfo = NULL;
    g_EP1Transfer.dwFlags = 0;
    g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext, 1, &g_EP1Transfer );
}

// parses the setup packet received on EP0
BOOL HandleSetupPacket(USB_DEVICE_REQUEST *pUdr, EP0_REQUEST *pRequest)
{
    if (pUdr->bmRequestType & (USB_REQUEST_CLASS | USB_REQUEST_VENDOR)) {
        if (PDD_DoVendorCommand(pUdr, pRequest)) {
            // do nothing
        } else {
            OALMSG(OAL_ERROR, (
                L"**** Unhandled verndor command 0x%x\r\n", pUdr->bRequest
            ));
            pRequest->eDir = EP0Setup;
            pRequest->pucData = NULL;
            pRequest->dwExpectedSize = 0;
            pRequest->dwActualSize = 0;
            pRequest->pfnNotification = NULL;
            pRequest->pvUser = NULL;
        }
        return TRUE;
    }

    // standard chapter 9 commands
    pRequest->eDir = EP0Setup;
    pRequest->pucData = NULL;
    pRequest->dwExpectedSize = 0;
    pRequest->dwActualSize = 0;
    pRequest->pfnNotification = NULL;
    pRequest->pvUser = NULL;

    switch(pUdr->bRequest) {
        case USB_REQUEST_GET_STATUS:
            if (pUdr->bmRequestType == 0x82) {
                // TODO: handle this
                OALMSG(OAL_WARN, (L"***RequestType==0x82\r\n"));
                // check for the stall bit
            }
            break;

        case USB_REQUEST_CLEAR_FEATURE:
            if (pUdr->bmRequestType == 0x02) {
                // TODO: handle this
                OALMSG(OAL_WARN, (L"***RequestType==0x02\r\n"));
            }
            break;

        case USB_REQUEST_SET_FEATURE:
            if (pUdr->bmRequestType == 0x02) {
                // TODO: handle this
                OALMSG(OAL_WARN, (L"***RequestType==0x02\r\n"));
            }
            break;

        case USB_REQUEST_SET_ADDRESS:
            // TODO: handle this
            break;

        case USB_REQUEST_GET_DESCRIPTOR:
            if (PDD_GetDescriptor(pUdr, pRequest)) {
                // do nothing
            } else {
                OALMSG(OAL_ERROR, (
                    L"*** UnHandled GET_DESCRIPTOR request:0x%x\r\n",
                    pUdr->wValue
                ));
            }
            break;

        case USB_REQUEST_SET_DESCRIPTOR:
            // TODO: handle this
            break;

        case USB_REQUEST_GET_CONFIGURATION:
            // TODO: handle this
            break;

        case USB_REQUEST_SET_CONFIGURATION:
            OALStall(5000);
            // setup RX transfer on EP1
            SetupEP1Transfer();
            ////pDev->ucConfigValue = (BYTE)pUdr->wValue;
            break;

        case USB_REQUEST_GET_INTERFACE:
            // TODO: handle this
            break;

        case USB_REQUEST_SET_INTERFACE:
            // TODO: handle this
            break;

        case USB_REQUEST_SYNC_FRAME:
            // TODO: handle this
            break;

        default:
            OALMSG(OAL_WARN, (
                L"*** Unknown request 0x%x\r\n", pUdr->bRequest
            ));
    }
    return TRUE;
}

// indicates to the KITL MDD that a packet has been sent
void TxComplete(void)
{
    RNDIS_KITLDEV *pRndisKitlDev = &g_RndisKitlDev;

    OALMSG(OAL_ETHER&&OAL_FUNC, (
        L"SendPacket request completed! [%d bytes]\r\n", 
        g_EP2Transfer.cbTransferred 
    ));
    MddSendRndisPacketComplete(pRndisKitlDev->pTxDataWrapper);

    OALMSG(OAL_ETHER&&OAL_FUNC, (L"Done\r\n"));
    pRndisKitlDev->pTxDataWrapper = NULL;
}

// The USB FN PDD will call this function to notify it of various events (data sent/received, 
// setup packet received, device addressed, reset, etc.
BOOL WINAPI NotifyHandler (
    PVOID pvMddContext,
    DWORD dwMsg,
    DWORD dwParam
    )
{
    USB_DEVICE_REQUEST request;
    EP0_REQUEST EP0Request;
    STransfer *pTransfer;

    switch( dwMsg )
    {
    case UFN_MSG_SETUP_PACKET:
        request = *(USB_DEVICE_REQUEST*)(void*)dwParam;
        g_udr = request;

        if( !HandleSetupPacket( &g_udr, &EP0Request ) )
        {
            OALMSG(OAL_ERROR, (L"ERROR PARSING SETUP PACKET\r\n"));
        }

        memcpy(&g_RndisKitlDev.EP0Request, &EP0Request, sizeof(EP0Request));
        g_RndisKitlDev.EP0Request.dwProcessed = 0;
        g_RndisKitlDev.EP0Request.fCompleted = FALSE;

        if (g_RndisKitlDev.EP0Request.eDir != EP0Setup) {
            g_EP0DataWrapper.pucData = g_RndisKitlDev.EP0Request.pucData;
            g_EP0DataWrapper.dwDataSize = g_RndisKitlDev.EP0Request.dwActualSize;
            
            // g_EP2Transfer.dwCallerPermissions;
            g_EP0Transfer.pvBuffer = g_EP0DataWrapper.pucData;
            // g_EP2Transfer.dwBufferPhysicalAddress; // not used
            g_EP0Transfer.cbBuffer = g_EP0DataWrapper.dwDataSize;
            g_EP0Transfer.cbTransferred = 0;
            g_EP0Transfer.dwUsbError = UFN_NOT_COMPLETE_ERROR; // Possible values are in usbfntypes.h
            g_EP0Transfer.pvPddData = NULL;
            g_EP0Transfer.pvPddTransferInfo = NULL;

            if (g_RndisKitlDev.EP0Request.eDir == EP0In) {
                OALMSG(OAL_ETHER&&OAL_FUNC, (L"Got SETUP IN packet\r\n"));
                g_EP0Transfer.dwFlags = USB_REQUEST_DEVICE_TO_HOST;
                g_EP0TransferState = TS_SENDING_MESSAGE;
                g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext, 0, &g_EP0Transfer );
            }
            else
            {
                OALMSG(OAL_ETHER&&OAL_FUNC, (L"Got SETUP OUT packet.\r\n"));
                g_EP0Transfer.dwFlags = 0;
                g_EP0TransferState = TS_RECEIVING_MESSAGE;
                g_pddInterface.pfnIssueTransfer( g_pddInterface.pvPddContext, 0, &g_EP0Transfer );
            }
        }
        else
        {
            OALMSG(OAL_ETHER&&OAL_FUNC, (
                L"Got SETUP <NO DATA: %x %x %x %x %x> packet.\r\n",
                g_udr.bmRequestType, g_udr.bRequest, g_udr.wValue, g_udr.wIndex,
                 g_udr.wLength 
            ));

            // Send the SETUP ACK packet
            g_EP0TransferState = TS_IDLE;
            g_pddInterface.pfnSendControlStatusHandshake( g_pddInterface.pvPddContext, 0 );
        }
        break;

    case UFN_MSG_TRANSFER_COMPLETE: 
        pTransfer = (STransfer *)dwParam;
        if( pTransfer == &g_EP0Transfer )
        {
            switch( g_EP0TransferState )
            {
            case TS_RECEIVING_MESSAGE:
                g_EP0TransferState = TS_IDLE;
                OALMSG(OAL_ETHER&&OAL_FUNC, (L"Done receiving data.\r\n"));

                g_pddInterface.pfnSendControlStatusHandshake( g_pddInterface.pvPddContext, 0 );

                if (g_RndisKitlDev.EP0Request.pfnNotification) {
                    OALMSG(OAL_ETHER&&OAL_FUNC, (L"Received a message!\r\n"));
                    g_RndisKitlDev.EP0Request.pfnNotification(&g_RndisKitlDev.EP0Request, g_RndisKitlDev.EP0Request.pvUser);
                }
                memset(&g_RndisKitlDev.EP0Request, 0, sizeof (g_RndisKitlDev.EP0Request));
                break;
            case TS_SENDING_MESSAGE:
                OALMSG(OAL_ETHER&&OAL_FUNC, (L"Done sending data.\r\n"));

                g_EP0TransferState = TS_IDLE;
                g_pddInterface.pfnSendControlStatusHandshake( g_pddInterface.pvPddContext, 0 );

                if (g_RndisKitlDev.EP0Request.pfnNotification) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -