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

📄 ufnmdd.cpp

📁 freescale i.mx31 BSP CE5.0全部源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//

/*****************************************************************************
* Copyright (C) 2005-2006, Freescale Semiconductor, Inc. All Rights Reserved.
* THIS SOURCE CODE IS CONFIDENTIAL AND PROPRIETARY AND MAY NOT
* BE USED OR DISTRIBUTED WITHOUT THE WRITTEN PERMISSION OF
* Freescale Semiconductor, Inc.
*******************************************************************************/
/*++

THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name: 

        UFNMDD.CPP

Abstract:

        USB Function Controller Model Device Driver Implementation.
        
--*/

#include "mx31_ufnmdd.h"
#include <devload.h>
#include <creg.hxx>



#define VERIFY_RUNNING() \
    if (!pContext->fRunning) { \
        DEBUGMSG(ZONE_ERROR, (_T("%s Device is not running\r\n"), pszFname)); \
        dwRet = ERROR_INVALID_HANDLE; \
        goto EXIT; \
    }


#ifdef DEBUG

// Validate a context object.
VOID
ValidateContext(
    PUFN_MDD_CONTEXT pContext
    )
{
    PREFAST_DEBUGCHK(pContext);
    DEBUGCHK(pContext->dwSig == UFN_MDD_SIG);

    
    if (pContext->Speed != BS_UNKNOWN_SPEED) {
        DEBUGCHK(pContext->Speed & pContext->PddInfo.dwCapabilities);
    }

    if (!pContext->fClientIsBeingAddedOrRemoved) {
        if (pContext->pUfnBus->IsClientActive()) {
            DEBUGCHK(pContext->pPipes != NULL);
            DEBUGCHK(pContext->pFreeTransferList);
        }
        else {
            DEBUGCHK(pContext->pPipes == NULL);
            DEBUGCHK(pContext->pFreeTransferList == NULL);
        }
    }
    else {
        DEBUGCHK(pContext->pPipes);
        DEBUGCHK(pContext->pFreeTransferList);
    }
}

#endif

#ifndef SHIP_BUILD

static
LPCTSTR
GetSpeedString(
    UFN_BUS_SPEED Speed
    )
{
    LPCTSTR pszSpeed = _T("unknown");

    if (Speed == BS_FULL_SPEED) {
        pszSpeed = _T("full");
    }
    else if (Speed == BS_HIGH_SPEED) {
        pszSpeed = _T("high");
    }

    return pszSpeed;
}

#endif


// Reset the pipe status table to its default state.
static
VOID
ResetPipeStatusTable(
    PUFN_MDD_CONTEXT pContext
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    PREFAST_DEBUGCHK(pContext);
    DEBUGCHK(pContext->pPipes);

    // the default endpoint is always endpoint 0
    for (DWORD dwEp = 0; dwEp < pContext->PddInfo.dwEndpointCount; ++dwEp) {
        PCPipe pPipe = &pContext->pPipes[dwEp];
        pPipe->Reset();
    }

    FUNCTION_LEAVE_MSG();
}


static
VOID
InitializeEndpointZeroDescriptor(
    PUFN_MDD_CONTEXT pContext,
    BYTE bMaxPacketSize,
    PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc
    )
{
    DEBUGCHK(pContext);
    PREFAST_DEBUGCHK(pEndpointDesc);
    
    pEndpointDesc->bEndpointAddress = 0;
    pEndpointDesc->bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
    pEndpointDesc->wMaxPacketSize = bMaxPacketSize;
}


// Search for the target endpoint address. The endpoint address is
// stored in the endpoint descriptor.
PCPipe
FindPipe(
    PUFN_MDD_CONTEXT pContext,
    DWORD dwEndpointAddress
    )
{
    PCPipe pPipe = NULL;
    PREFAST_DEBUGCHK(pContext);
    PREFAST_DEBUGCHK(pContext->pPipes);
    DEBUGCHK(dwEndpointAddress != -1);
    
    for (DWORD dwPipe = 0; dwPipe < pContext->PddInfo.dwEndpointCount; ++dwPipe) {
        if (pContext->pPipes[dwPipe].GetEndpointAddress() == dwEndpointAddress) {
            pPipe = &pContext->pPipes[dwPipe];
            break;
        }
    }

    return pPipe;
}


static
DWORD
ReadRegDword(
    HKEY hKey,
    LPCTSTR pszKey,
    BOOL fMustSucceed,
    PDWORD pdwValue
    )
{
    SETFNAME();
    
    PREFAST_DEBUGCHK(hKey);
    DEBUGCHK(pszKey);
    DEBUGCHK(pdwValue);

    DWORD dwType;
    DWORD cbData = sizeof(DWORD);
    DWORD dwErr = RegQueryValueEx(hKey, pszKey, NULL, 
        &dwType, (PBYTE) pdwValue, &cbData);
    
    if ( (dwErr == ERROR_SUCCESS) && (dwType != REG_DWORD) ) {
        dwErr = ERROR_INVALID_DATA;
    }

    if ( fMustSucceed && (dwErr != ERROR_SUCCESS) ) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Failed to read %s. Error: %d\r\n"),
            pszFname, pszKey, dwErr));
    }

    return dwErr;
}


// See if the packet size adheres to the USB standard for the speed and type.
static
BOOL
ValidatePacketSize(
    UFN_BUS_SPEED Speed,
    PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc
    )
{
    PREFAST_DEBUGCHK(pEndpointDesc);
    
    BOOL fRet = TRUE;

    WORD wPacketSize = 
        (pEndpointDesc->wMaxPacketSize & USB_ENDPOINT_MAX_PACKET_SIZE_MASK);
    
    switch (pEndpointDesc->bmAttributes & USB_ENDPOINT_TYPE_MASK) {
    case USB_ENDPOINT_TYPE_CONTROL:
        if ( (wPacketSize != 8) && (wPacketSize != 16) &&
             (wPacketSize != 32) && (wPacketSize != 64) ) {
            fRet = FALSE;
        }
        break;
        
    case USB_ENDPOINT_TYPE_BULK:
        if ( (wPacketSize != 8) && (wPacketSize != 16) &&
             (wPacketSize != 32) && (wPacketSize != 64) &&
             (wPacketSize != 512) ) {
            fRet = FALSE;
        }
        else if ( (wPacketSize == 512) && (Speed != BS_HIGH_SPEED) ) {
            fRet = FALSE;
        }
        break;
        
    case USB_ENDPOINT_TYPE_INTERRUPT:
        if ( (Speed == BS_FULL_SPEED) && (wPacketSize > 64) ) {
            fRet = FALSE;
        }
        else if (wPacketSize > 1024) {
            DEBUGCHK(Speed == BS_HIGH_SPEED);
            fRet = FALSE;
        }
        break;
        
    case USB_ENDPOINT_TYPE_ISOCHRONOUS:
        if ( (Speed == BS_FULL_SPEED) && (wPacketSize > 1023) ) {
            fRet = FALSE;
        }
        else if (wPacketSize > 1024) {
            DEBUGCHK(Speed == BS_HIGH_SPEED);
            fRet = FALSE;
        }
        break;

    default:
        // We should net get here.
        fRet = FALSE;
        break;
    }

    return fRet;
}


// Append data to the config descriptor and advance pointers.
static
DWORD
FillConfigDescBuffer(
    PBYTE  *ppbDest,
    PDWORD  pcbDest,
    PVOID   pvSource,
    DWORD   cbSource
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();
    
    PREFAST_DEBUGCHK(ppbDest);
    DEBUGCHK(*ppbDest);
    PREFAST_DEBUGCHK(pcbDest);
    PREFAST_DEBUGCHK(pvSource);
    DEBUGCHK(cbSource);
    
    DWORD dwRet = ERROR_SUCCESS;
    
    if (cbSource > *pcbDest) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Config descriptor length is too short\r\n"), pszFname));
        dwRet = ERROR_INVALID_PARAMETER;
    }
    else {    
        memcpy(*ppbDest, pvSource, cbSource);
        *ppbDest += cbSource;
        *pcbDest -= cbSource;
    }

    FUNCTION_LEAVE_MSG();

    return dwRet;
}
    
    
// Creates the config descriptor from the descriptor tree.
static
DWORD
CreateConfigDesc(
    PUSB_CONFIGURATION_DESCRIPTOR *ppConfigDesc,
    PUFN_CONFIGURATION pConfig
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();
    
    PREFAST_DEBUGCHK(pConfig);
    PREFAST_DEBUGCHK(ppConfigDesc);

    DWORD dwRet;

    DWORD cbConfig = pConfig->Descriptor.wTotalLength;
    PBYTE pbBuffer = (PBYTE) LocalAlloc(0, cbConfig);
    if (pbBuffer == NULL) {
        dwRet = GetLastError();
        DEBUGMSG(ZONE_ERROR, (_T("%s LocalAlloc failed. Error: %d\r\n"), pszFname, 
            dwRet));
        goto EXIT;
    }
    
    PUSB_CONFIGURATION_DESCRIPTOR pConfigDesc = (PUSB_CONFIGURATION_DESCRIPTOR) pbBuffer;
    DWORD cbBuffer = cbConfig;

    // Copy configuration descriptor
    dwRet = FillConfigDescBuffer(&pbBuffer, &cbBuffer, &pConfig->Descriptor, 
        sizeof(USB_CONFIGURATION_DESCRIPTOR));
    if (dwRet != ERROR_SUCCESS) {
        goto EXIT;
    }

    if (pConfig->pvExtended) {
        dwRet = FillConfigDescBuffer(&pbBuffer, &cbBuffer, pConfig->pvExtended,
            pConfig->cbExtended);
        if (dwRet != ERROR_SUCCESS) {
            goto EXIT;
        }        
    }

    for (DWORD dwInterface = 0; dwInterface < pConfigDesc->bNumInterfaces; ++dwInterface) {
        // Copy interface descriptor
        PUFN_INTERFACE pInterface = &pConfig->pInterfaces[dwInterface];
        PREFAST_DEBUGCHK(pInterface);
        dwRet = FillConfigDescBuffer(&pbBuffer, &cbBuffer, &pInterface->Descriptor,
            sizeof(USB_INTERFACE_DESCRIPTOR));
        if (dwRet != ERROR_SUCCESS) {
            goto EXIT;
        }

        if (pInterface->pvExtended) {
            dwRet = FillConfigDescBuffer(&pbBuffer, &cbBuffer, pInterface->pvExtended,
                pInterface->cbExtended);
            if (dwRet != ERROR_SUCCESS) {
                goto EXIT;
            }        
        }

        DEBUGCHK( (pInterface->pEndpoints && pInterface->Descriptor.bNumEndpoints > 0) ||
                  (pInterface->pEndpoints == NULL && pInterface->Descriptor.bNumEndpoints == 0) );

        // Copy endpoint descriptors        
        for (DWORD dwEndpoint = 0; dwEndpoint < pInterface->Descriptor.bNumEndpoints; ++dwEndpoint) {
            PUFN_ENDPOINT pEndpoint = &pInterface->pEndpoints[dwEndpoint];

            dwRet = FillConfigDescBuffer(&pbBuffer, &cbBuffer, 
                &pEndpoint->Descriptor, sizeof(USB_ENDPOINT_DESCRIPTOR));
            if (dwRet != ERROR_SUCCESS) {
                goto EXIT;
            }

            if (pEndpoint->pvExtended) {
                dwRet = FillConfigDescBuffer(&pbBuffer, &cbBuffer, pEndpoint->pvExtended,
                    pEndpoint->cbExtended);
                if (dwRet != ERROR_SUCCESS) {
                    goto EXIT;
                }        
            }
        }
    }

    if (cbBuffer != 0) {
        DEBUGMSG(ZONE_ERROR, (_T("%s Config descriptor length is too long\r\n"), pszFname));
        dwRet = ERROR_INVALID_PARAMETER;
        goto EXIT;
    }

    *ppConfigDesc = pConfigDesc;
    dwRet = ERROR_SUCCESS;

EXIT:
    if (dwRet != ERROR_SUCCESS) {
        if (pConfigDesc) LocalFree(pConfigDesc);
    }
    
    FUNCTION_LEAVE_MSG();

    return dwRet;
}


// Allocates room and copies an extended descriptor if it exists.
static
DWORD
CopyExtendedDesc(
    PVOID *ppvDest,
    PDWORD pcbDest,
    PVOID  pvSource,
    DWORD  cbSource
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    PREFAST_DEBUGCHK(ppvDest);
    PREFAST_DEBUGCHK(pcbDest);
    
    DWORD dwRet = ERROR_SUCCESS;

    if (pvSource) {
        *ppvDest = LocalAlloc(0, cbSource);
        if (*ppvDest == NULL) {
            dwRet = GetLastError();
            DEBUGMSG(ZONE_ERROR, (_T("%s LocalAlloc failed. Error: %d\r\n"), pszFname, 
                dwRet));
            goto EXIT;
        }

        memcpy(*ppvDest, pvSource, cbSource);
        *pcbDest = cbSource;
        DEBUGMSG(ZONE_FUNCTION, (_T("%s Copied %d bytes of extended descriptor(s)\r\n"),
            pszFname, cbSource));
    }

EXIT:
    FUNCTION_LEAVE_MSG();

    return dwRet;
}


// Copies a config tree structure.
static
DWORD
CopyConfig(
    PUFN_CONFIGURATION pConfigDest,
    PUFN_CONFIGURATION pConfigSource
    )
{
    SETFNAME();
    FUNCTION_ENTER_MSG();

    DWORD dwRet;

    memcpy(pConfigDest, pConfigSource, sizeof(UFN_CONFIGURATION));

    // Clear out the configuration's pointers
    pConfigDest->pInterfaces = NULL;
    pConfigDest->pvExtended = NULL;
    
    // Copy the config's extended descriptor    
    dwRet = CopyExtendedDesc(&pConfigDest->pvExtended, &pConfigDest->cbExtended,
        pConfigSource->pvExtended, pConfigSource->cbExtended);
    if (dwRet != ERROR_SUCCESS) {
        goto EXIT;
    }

    // Copy the interface structure
    DEBUGCHK(pConfigSource->Descriptor.bNumInterfaces);
    PREFAST_DEBUGCHK(pConfigSource->pInterfaces);
    DWORD cbInterfaces = 
        pConfigDest->Descriptor.bNumInterfaces * sizeof(UFN_INTERFACE);
    pConfigDest->pInterfaces = (PUFN_INTERFACE) LocalAlloc(0, cbInterfaces);
    if (pConfigDest->pInterfaces == NULL) {

⌨️ 快捷键说明

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