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

📄 pdd.c

📁 Windows CE 6.0 BSP for the Beagle Board.
💻 C
📖 第 1 页 / 共 5 页
字号:
//
//  Function:  UfnPdd_IsEndpointHalted
//
DWORD WINAPI UfnPdd_IsEndpointHalted(VOID *pPddContext,
                                     DWORD endPoint,
                                     BOOL *pHalted)
{
    DWORD rc = ERROR_INVALID_FUNCTION;
    USBFN_PDD *pPdd = pPddContext;
    OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
    DWORD epNum;

    DEBUGMSG(ZONE_PDD, (L"UsbFnPdd_IsEndpointHalted %d\r\n", endPoint));

    // Endpoint can't be zero
    if (endPoint != 0)
    {
        // Select EP
        epNum = USBD_EP_NUM & endPoint;

        if (!pPdd->ep[endPoint].dirRx)
        {
            epNum |= USBD_EP_NUM_DIRIN;
        }

        SelectEp(pPdd, epNum);

        // Is EP halted?
        *pHalted = ((INREG32(&pUSBDRegs->STAT_FLG) & USBD_STAT_HALTED) != 0);

        // Deselect EP
        DeselectEp(pPdd, epNum);

        // Done
        rc = ERROR_SUCCESS;
    }

    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_SendControlStatusHandshake
//
//  Send the control status handshake.
//
DWORD WINAPI UfnPdd_SendControlStatusHandshake(VOID *pPddContext,
                                               DWORD endPoint)
{
    USBFN_PDD *pPdd = pPddContext;
    OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
    DWORD epNum, stat;

    DEBUGMSG(ZONE_USB_EVENTS, (L"UfnPdd_SendControlStatusHandshake() - START\r\n"));

    // Select EP
    epNum = USBD_EP_NUM & endPoint;

    if (pPdd->setupDirRx)
    {
        epNum |= USBD_EP_NUM_DIRIN;
    }

    SelectEp(pPdd, epNum);

    // Get actual status
    stat = INREG32(&pUSBDRegs->STAT_FLG);

    DEBUGMSG(ZONE_USB_EVENTS, (L"UfnPdd_SendControlStatusHandshake() - "
        L"EndPoint %d (%s): STAT_FLG = 0x%04X\r\n", endPoint, pPdd->setupDirRx ? L"IN" : L"OUT", stat));

    // Only send the handshake when the EndPoint is not stalled.
    if ((stat & USBD_STAT_STALL) == 0)
    {
        // Clear & enable FIFO
        OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_CLR_EP);
        OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_FIFO_EN);
    }
    else
    {
        DEBUGMSG(ZONE_USB_EVENTS, (L"UfnPdd_SendControlStatusHandshake() - "
            L"Not sending handshake because Endpoint %d is stalled\r\n", epNum));
    }

    // Deselect EP
    DeselectEp(pPdd, epNum);

    DEBUGMSG(ZONE_USB_EVENTS, (L"UfnPdd_SendControlStatusHandshake() - END\r\n"));

    return ERROR_SUCCESS;
}

//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_InitiateRemoteWakeup
//
DWORD WINAPI UfnPdd_InitiateRemoteWakeup(VOID *pPddContext)
{
    USBFN_PDD *pPdd = pPddContext;
    OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;

    DEBUGMSG(ZONE_PDD, (L"UsbFnPdd_InitiateRemoteWakeup\r\n"));

    SETREG32(&pUSBDRegs->SYSCON2, USBD_SYSCON2_RMT_WKP);

    return ERROR_SUCCESS;
}


//------------------------------------------------------------------------------

#define PSZ_REG_CLIENT_DRIVER_PATH              _T("\\Drivers\\USB\\FunctionDrivers")
#define PSZ_REG_DEFAULT_DEFAULT_CLIENT_DRIVER   _T("DefaultClientDriver")
#define PSZ_REG_FRIENDLY_NAME                   _T("FriendlyName")
#define PSZ_REG_DEFAULT_CLIENT_KEY              _T("DefaultClientKey")
#define MAX_LOADSTRING                          100

static BOOL GetUfnDescription(HKEY   hkClient,
                              LPTSTR pszDescription,
                              DWORD  cchDescription)
{
    DWORD dwType;
    DWORD cbValue = sizeof(TCHAR) * cchDescription;
    DWORD dwError = RegQueryValueEx(hkClient,
                                    PSZ_REG_FRIENDLY_NAME,
                                    NULL,
                                    &dwType,
                                    (PBYTE)pszDescription,
                                    &cbValue);

    pszDescription[cchDescription - 1] = 0; // Null-terminate

    if ((dwError != ERROR_SUCCESS) || (dwType != REG_SZ))
    {
        // No description. Still return success, though.
        pszDescription[0] = 0;
    }

    return TRUE;
}


static DWORD OpenFunctionKey(HKEY *phkFunctions)
{
    // Determine which client driver to load
    return RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                        PSZ_REG_CLIENT_DRIVER_PATH,
                        0,
                        0,
                        phkFunctions);
}


static DWORD GetDefaultClientName(LPTSTR pszClientName)
{
    HKEY  hkFunctions = NULL;
    DWORD cbData      = MAX_LOADSTRING * sizeof(TCHAR);
    DWORD dwType;
    DWORD dwRet       = OpenFunctionKey(&hkFunctions);


    if (dwRet == ERROR_SUCCESS)
    {
        dwRet = RegQueryValueEx(hkFunctions,
                                PSZ_REG_DEFAULT_DEFAULT_CLIENT_DRIVER,
                                NULL,
                                &dwType,
                                (PBYTE)pszClientName,
                                &cbData);

        if ((dwRet != ERROR_SUCCESS) || (dwType != REG_SZ))
        {
            // No client name. Still return success, though.
            pszClientName[0] = 0;
        }
    }

    if (hkFunctions)
    {
        RegCloseKey(hkFunctions);
    }

    return dwRet;
}


static DWORD ChangeDefaultClient(LPTSTR pszClientName)
{
    DWORD dwRet;
    HKEY  hkFunctions = NULL;


    dwRet = OpenFunctionKey(&hkFunctions);
    if (dwRet == ERROR_SUCCESS)
    {
        dwRet = RegSetValueEx(hkFunctions,
                              PSZ_REG_DEFAULT_DEFAULT_CLIENT_DRIVER,
                              0,
                              REG_SZ,
                              (PBYTE)pszClientName,
                              (_tcslen(pszClientName) + 1) * sizeof(TCHAR));
    }

    if (hkFunctions)
    {
        RegCloseKey(hkFunctions);
    }

    return dwRet;
}


//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_IOControl
//
DWORD WINAPI UfnPdd_IOControl(VOID        *pPddContext,
                              IOCTL_SOURCE source,
                              DWORD        code,
                              UCHAR       *pInBuffer,
                              DWORD        inSize,
                              UCHAR       *pOutBuffer,
                              DWORD        outSize,
                              DWORD       *pOutSize)
{
    DWORD                rc   = ERROR_INVALID_PARAMETER;
    USBFN_PDD           *pPdd = pPddContext;
    UFN_PDD_INFO         info;
    CE_BUS_POWER_STATE  *pBusPowerState;
    CEDEVICE_POWER_STATE devicePowerState;


    switch (code)
    {
        case IOCTL_UFN_GET_PDD_INFO:
            if (source != BUS_IOCTL)
            {
                break;
            }
            if (pOutBuffer == NULL || outSize < sizeof(UFN_PDD_INFO))
            {
                break;
            }
            info.InterfaceType = Internal;
            info.BusNumber = 0;
            info.dwAlignment = sizeof(DWORD);
            if (!CeSafeCopyMemory(pOutBuffer, &info, sizeof(UFN_PDD_INFO)))
            {
                break;
            }
            rc = ERROR_SUCCESS;
            break;

        case IOCTL_BUS_GET_POWER_STATE:
            if (source != MDD_IOCTL)
            {
                break;
            }
            if (pInBuffer == NULL || inSize < sizeof(CE_BUS_POWER_STATE))
            {
                break;
            }
            pBusPowerState = (CE_BUS_POWER_STATE*)pInBuffer;
            if (!CeSafeCopyMemory(pBusPowerState->lpceDevicePowerState, &pPdd->m_CurrentPowerState, sizeof(CEDEVICE_POWER_STATE)))
            {
                break;
            }

            rc = ERROR_SUCCESS;
            break;

        case IOCTL_BUS_SET_POWER_STATE:
            if (pInBuffer == NULL || inSize < sizeof(CE_BUS_POWER_STATE))
            {
                DEBUGMSG(ZONE_WARNING, (L"UfnPdd_IOControl() "
                    L"WARNING: Bad Parameter\r\n"));
                break;
            }
            pBusPowerState = (CE_BUS_POWER_STATE*)pInBuffer;
            if (!CeSafeCopyMemory(&devicePowerState, pBusPowerState->lpceDevicePowerState, sizeof(CEDEVICE_POWER_STATE)))
            {
                break;
            }
            DEBUGMSG(ZONE_POWER, (L"UfnPdd_IOControl() - "
                L"Set Power State to D%d\r\n", (int)devicePowerState));
            pPdd->m_NewPowerState = devicePowerState;
            if (UpdateDevicePower(pPdd))
            {
                rc = ERROR_SUCCESS;
            }
            break;

        case IOCTL_UFN_CHANGE_DEFAULT_CLIENT:
            rc = ChangeDefaultClient((LPTSTR)pInBuffer);
            break;
    }

    return rc;
}


//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_Deinit
//
DWORD WINAPI UfnPdd_Deinit(VOID *pPddContext)
{
    USBFN_PDD *pPdd = pPddContext;
    OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;


    // Stop interrupt thread
    if (pPdd->hIntrThread != NULL)
    {
        pPdd->exitIntrThread = TRUE;
        SetEvent(pPdd->hIntrEvent);
        WaitForSingleObject(pPdd->hIntrThread, INFINITE);
        CloseHandle(pPdd->hIntrThread);
    }

    // Close interrupt handler
    if (pPdd->hIntrEvent != NULL)
    {
        CloseHandle(pPdd->hIntrEvent);
        pPdd->hIntrEvent = NULL;
    }

    // If parent bus is open, set hardware to D4 and close it
    if (pPdd->hParentBus != NULL)
    {
        SetDevicePowerState(pPdd->hParentBus, D4, NULL);
        CloseBusAccessHandle(pPdd->hParentBus);
        pPdd->hParentBus = NULL;
    }

    // Unmap USBD controller registers
    if (pPdd->pUSBDRegs != NULL)
    {
        MmUnmapIoSpace((VOID*)pPdd->pUSBDRegs, pPdd->memLen);
        pPdd->pUSBDRegs = NULL;
    }

    // Release interrupt
    if (pPdd->sysIntr != 0)
    {
        InterruptDisable(pPdd->sysIntr);
        KernelIoControl(IOCTL_HAL_RELEASE_SYSINTR,
                        &pPdd->sysIntr,
                        sizeof(pPdd->sysIntr),
                        NULL,
                        0,
                        NULL);

        pPdd->sysIntr = 0;
    }

    // Delete critical section
    DeleteCriticalSection(&pPdd->epCS);

    // Free PDD context
    LocalFree(pPdd);

    AdvertiseInterface((const GUID *)DMCLASS_PROTECTEDBUSNAMESPACE, L"UsbFn",FALSE);

    // Done
    return ERROR_SUCCESS;
}


//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_DeregisterDevice
//
//  This function is called by MDD to move device to pre-registred state.
//  On OMAP7xx we simply disable all end points.
//
DWORD WINAPI UfnPdd_DeregisterDevice(VOID *pPddContext)
{
    USBFN_PDD          *pPdd      = pPddContext;
    OMAP2420_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
    DWORD               ep;


    // Disable all RX, TX EPs
    OUTREG32(&pUSBDRegs->EP0, 0);

    for (ep = 0; ep < USBD_NONZERO_EP_COUNT; ep++)
    {
        OUTREG32(&pUSBDRegs->EP_RX[ep], 0);
        OUTREG32(&pUSBDRegs->EP_TX[ep], 0);
    }

    return ERROR_SUCCESS;
}


//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_Stop
//
//  This function is called before UfnPdd_DeregisterDevice. It should de-attach
//  device to USB bus (but we don't want disable interrupts because...)
//
DWORD WINAPI UfnPdd_Stop(VOID *pPddContext)
{
    USBFN_PDD           *pPdd      = pPddContext;
    OMAP2420_USBD_REGS  *pUSBDRegs = pPdd->pUSBDRegs;
    CEDEVICE_POWER_STATE prevPowerState ;


    DEBUGMSG(ZONE_PDD, (L"UfnPdd_Stop\r\n"));

    prevPowerState = pPdd->m_CurrentPowerState;

    if ((prevPowerState == D3) || (prevPowerState == D4))
    {
        pPdd->m_NewPowerState = D2;
        UpdateDevicePower(pPdd);

⌨️ 快捷键说明

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