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

📄 pdd.c

📁 Windows CE 6.0 BSP for VOIPAC Board (PXA270) Version 2b.
💻 C
📖 第 1 页 / 共 3 页
字号:
//
//  This function is called by MDD to move device to pre-registred state.
//  On OMAP730 we simply disable all end points.
//
DWORD WINAPI UfnPdd_DeregisterDevice(VOID *pPddContext)
{
    USBFN_PDD *pPdd = pPddContext;
    OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
    DWORD ep;

    // Disable all RX, TX EPs
    OUTREG32(&pUSBDRegs->EP0, 0);
    for (ep = 1; ep < USBD_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;
    OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;

    OALMSG(OAL_ETHER&&OAL_FUNC, (L"UfnPdd_Stop\r\n"));

    // Deattach device
    CLRREG32(&pUSBDRegs->SYSCON1, USBD_SYSCON1_PULLUP_EN);
    DisconnectHardware();

    // Disable USB device PLL clock
    // ClkRelease(pPdd->hClk, 1); @todo

    // Done
    return ERROR_SUCCESS;
}

//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_DeinitEndpoint
//
//  This function is called when pipe to endpoit is closed. For OMAP730 we
//  will stop points in UfnPdd_DeregisterDevice.
//
DWORD WINAPI UfnPdd_DeinitEndpoint(VOID *pPddContext, DWORD endPoint)
{
    USBFN_PDD *pPdd = pPddContext;
    OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
    DWORD epNum;

    OALMSG(OAL_ETHER&&OAL_FUNC, (L"UfnPdd_DeinitEndpoint: %d\r\n", endPoint));

    // Select EP
    epNum = USBD_EP_NUM & endPoint;
    OUTREG32(&pUSBDRegs->EP_NUM, USBD_EP_NUM_SEL | epNum);

    // Clear EP
    OUTREG32(&pUSBDRegs->CTRL, USBD_CTRL_CLR_EP);

    // Deselect EP
    OUTREG32(&pUSBDRegs->EP_NUM, epNum);

    // Done
    return ERROR_SUCCESS;
}


//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_InitEndpoint
//
//  This function is called when pipe to endpoint is created. For OMAP730
//  all initialization must be done in UfnPdd_RegisterDevice.
//
DWORD WINAPI UfnPdd_InitEndpoint(
    VOID *pContext, DWORD endPoint, UFN_BUS_SPEED speed,
    USB_ENDPOINT_DESCRIPTOR *pEPDesc, VOID *pReserved, UCHAR configValue,
    UCHAR interfaceNumber, UCHAR alternateSetting
) {
    OALMSG(OAL_ETHER&&OAL_FUNC, (
        L"UfnPdd_InitEndpoint: %d\r\n", endPoint
    ));
    return ERROR_SUCCESS;
}

//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_SetAddress
//
//  This function is called by MDD when configuration process assigned address
//  to device. For OMAP730 this is managed by hardware.
//
DWORD WINAPI UfnPdd_SetAddress(VOID *pPddContext, UCHAR address)
{
    OALMSG(OAL_ETHER&&OAL_FUNC, (
        L"UfnPdd_SetAddress: %d\r\n", address
    ));
    return ERROR_SUCCESS;
}

//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_Start
//
//  This function is called after UfnPdd_RegisterDevice. It should attach
//  device to USB bus.
//
DWORD WINAPI UfnPdd_Start(VOID *pPddContext)
{
    USBFN_PDD *pPdd = pPddContext;
    OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;

    // Disconnect hardware
    DisconnectHardware();

    // Wait for while
    OALStall(10000);

    // Enable interrupts
    OUTREG32(&pUSBDRegs->IRQ_EN, USBD_IRQ_MASK);

    // Attach device to bus (it has no effect when OTG controller is used)
    SETREG32(&pUSBDRegs->SYSCON1, USBD_SYSCON1_PULLUP_EN);
    ConnectHardware();

    // Set fake device change flag which on first interrupt force
    // device state change handler even if it isn't indicated by hardware
    pPdd->fakeDsChange = TRUE;

    // Done
    return ERROR_SUCCESS;
}

//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_RegisterDevice
//
//  This function is called by MDD after device configuration was sucessfully
//  verified by UfnPdd_IsEndpointSupportable and
//  UfnPdd_IsConfigurationSupportable. It should initialize hardware for given
//  configuration. Depending on hardware endpoints can be initialized later in
//  UfnPdd_InitEndpoint. For OMAP730 it isn't a case, so we should do all
//  initialization there.
//
DWORD WINAPI UfnPdd_RegisterDevice(
    VOID *pPddContext, const USB_DEVICE_DESCRIPTOR *pHighSpeedDeviceDesc,
    const UFN_CONFIGURATION *pHighSpeedConfig,
    const USB_CONFIGURATION_DESCRIPTOR *pHighSpeedConfigDesc,
    const USB_DEVICE_DESCRIPTOR *pFullSpeedDeviceDesc,
    const UFN_CONFIGURATION *pFullSpeedConfig,
    const USB_CONFIGURATION_DESCRIPTOR *pFullSpeedConfigDesc,
    const UFN_STRING_SET *pStringSets, DWORD stringSets
) {
    DWORD rc = ERROR_INVALID_PARAMETER;
    USBFN_PDD *pPdd = pPddContext;
    OMAP730_USBD_REGS *pUSBDRegs = pPdd->pUSBDRegs;
    UFN_INTERFACE *pIFC;
    UFN_ENDPOINT *pEP;
    DWORD offset, ep, cfg;
    DWORD ifc, epx;


    // Remember self powered flag
    pPdd->selfPowered = (pFullSpeedConfig->Descriptor.bmAttributes & 0x20) != 0;

    // Unlock configuration
    CLRREG32(&pUSBDRegs->SYSCON1, USBD_SYSCON1_CFG_LOCK);

    // Configure EP0
    offset = 8;
    cfg  = Log2(pFullSpeedDeviceDesc->bMaxPacketSize0 >> 3) << 12;
    cfg |= offset >> 3;
    OUTREG32(&pUSBDRegs->EP0, cfg);
    pPdd->ep[0].maxPacketSize = pFullSpeedDeviceDesc->bMaxPacketSize0;
    offset += pFullSpeedDeviceDesc->bMaxPacketSize0;

    // Configure Rx EPs
    for (ifc = 0; ifc < pFullSpeedConfig->Descriptor.bNumInterfaces; ifc++) {
        // For each endpoint in interface
        pIFC = &pFullSpeedConfig->pInterfaces[ifc];
        for (epx = 0; epx < pIFC->Descriptor.bNumEndpoints; epx++) {
            pEP = &pIFC->pEndpoints[epx];
            // If it is Tx EP skip it
            if ((pEP->Descriptor.bEndpointAddress & 0x80) != 0) continue;
            // Get EP address
            ep = pEP->Descriptor.bEndpointAddress & 0x0F;
            // Save max packet size & direction
            pPdd->ep[ep].maxPacketSize = pEP->Descriptor.wMaxPacketSize;
            pPdd->ep[ep].dirRx = TRUE;
            // Create EP config
            cfg  = USBD_EP_VALID;
            cfg |= Log2(pEP->Descriptor.wMaxPacketSize >> 3) << 12;
            if ((pEP->Descriptor.bmAttributes & 0x03) == 0x01) {
                cfg |= USBD_EP_ISO;
            }
            cfg |= offset >> 3;
            OUTREG32(&pUSBDRegs->EP_RX[ep - 1], cfg);
            // Update offset
            offset += pEP->Descriptor.wMaxPacketSize;
        }
    }

    // Configure Tx EPs
    for (ifc = 0; ifc < pFullSpeedConfig->Descriptor.bNumInterfaces; ifc++) {
        // For each endpoint in interface
        pIFC = &pFullSpeedConfig->pInterfaces[ifc];
        for (epx = 0; epx < pIFC->Descriptor.bNumEndpoints; epx++) {
            pEP = &pIFC->pEndpoints[epx];
            // If it is Rx EP skip it
            if ((pEP->Descriptor.bEndpointAddress & 0x80) == 0) continue;
            // Get EP address
            ep = pEP->Descriptor.bEndpointAddress & 0x0F;
            // Save max packet size & direction
            pPdd->ep[ep].maxPacketSize = pEP->Descriptor.wMaxPacketSize;
            pPdd->ep[ep].dirRx = FALSE;
            // Create EP config
            cfg  = USBD_EP_VALID;
            cfg |= Log2(pEP->Descriptor.wMaxPacketSize >> 3) << 12;
            if ((pEP->Descriptor.bmAttributes & 0x03) == 0x01) {
                cfg |= USBD_EP_ISO;
            }
            cfg |= offset >> 3;
            OUTREG32(&pUSBDRegs->EP_TX[ep - 1], cfg);
            // Update offset
            offset += pEP->Descriptor.wMaxPacketSize;
        }
    }

    // Lock configuration
    SETREG32(&pUSBDRegs->SYSCON1, USBD_SYSCON1_CFG_LOCK);

    // Done
    return ERROR_SUCCESS;
}

//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_IsEndpointSupportable
//
//  This function is called by MDD to verify if EP can be supported on
//  hardware. It is called after UfnPdd_IsConfigurationSupportable. We must
//  verify configuration in this function, so we already know that EPs
//  are valid. Only information we can update there is maximal packet
//  size for EP0.
//
DWORD WINAPI UfnPdd_IsEndpointSupportable(
    VOID *pPddContext, DWORD endPoint, UFN_BUS_SPEED speed,
    USB_ENDPOINT_DESCRIPTOR *pEPDesc, UCHAR configurationValue,
    UCHAR interfaceNumber, UCHAR alternateSetting
) {
    USBFN_PDD *pPdd = pPddContext;

    // Update maximal packet size for EP0
    if (endPoint == 0) {
        DEBUGCHK(pEPDesc->wMaxPacketSize <= 64);
        DEBUGCHK(pEPDesc->bmAttributes == USB_ENDPOINT_TYPE_CONTROL);
        pEPDesc->wMaxPacketSize = 64;

    }

    // Done
    return ERROR_SUCCESS;
}

//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_IsConfigurationSupportable
//
//  This function is called before UfnPdd_RegisterDevice. It should verify
//  that USB device configuration can be supported on hardware. Function can
//  modify EP size and/or EP address.
//
//  For OMAP730 we should check if total descriptor size is smaller
/// than 2040 bytes and round EP sizes. Unfortunately we don't get information
//  about EP0 max packet size. So we will assume maximal 64 byte size.
//
DWORD WINAPI UfnPdd_IsConfigurationSupportable(
    VOID *pPddContext, UFN_BUS_SPEED speed, UFN_CONFIGURATION *pConfig
) {
    DWORD rc = ERROR_INVALID_PARAMETER;
    USBFN_PDD *pPdd = pPddContext;
    UFN_INTERFACE *pIFC;
    UFN_ENDPOINT *pEP;
    WORD ifc, epx, count;
    WORD offset, size;


    // TODO: Update self power bit & maxPower

    // We must start with offset 8 + 64 (config plus EP0 size)
    offset = 8 + 64;
    // Clear number of end points
    count = 0;

    // For each interface in configuration
    for (ifc = 0; ifc < pConfig->Descriptor.bNumInterfaces; ifc++) {
        // For each endpoint in interface
        pIFC = &pConfig->pInterfaces[ifc];
        for (epx = 0; epx < pIFC->Descriptor.bNumEndpoints; epx++) {
            pEP = &pIFC->pEndpoints[epx];
            // We support maximal sizes 8, 16, 32 and 64 bytes for non-ISO
            size = pEP->Descriptor.wMaxPacketSize;
            // First round size to supported sizes
            size = 1 << Log2(size);
            // Is it ISO end point?
            if ((pEP->Descriptor.bmAttributes & 0x03) != 0x01) {
                // Non-ISO, max size is 64 bytes
                if (size > 64) size = 64;
            } else {
                // ISO edpoint, maximal size is 512 bytes
                if (size > 512) size = 512;
            }
            // Update EP size
            pEP->Descriptor.wMaxPacketSize = size;
            // Calculate total buffer size
            offset += size;
        }
        // Add number of end points to total count
        count += pIFC->Descriptor.bNumEndpoints;
    }

    // Can we support this configuration?
    if (count < USBD_EP_COUNT && offset <= 2048) rc = ERROR_SUCCESS;

    // Done
    return rc;
}

//------------------------------------------------------------------------------
//
//  Function:  UfnPdd_Init
//
//  This function is called by MDD on driver load. It should reset driver,
//  fill PDD interface structure. It can also get SYSINTR, initialize interrupt
//  thread and start interrupt thread. It must not attach device to USB bus.
//
DWORD WINAPI UfnPdd_Init(
    LPCTSTR szActiveKey, VOID *pMddContext, UFN_MDD_INTERFACE_INFO *pMddIfc,
    UFN_PDD_INTERFACE_INFO *pPddIfc
) {
    DWORD rc = ERROR_INVALID_PARAMETER;
    USBFN_PDD *pPdd;
    OMAP730_USBD_REGS *pUSBDRegs;
    DWORD ep;

    // Allocate and initialize the OHCD object.
    pPdd = &g_usbfnpdd;
    if (pPdd == NULL) goto clean;

    // Clear the allocated object.
    memset(pPdd, 0, sizeof(USBFN_PDD));

    // Map the USB OHCI registers
    pUSBDRegs = (OMAP730_USBD_REGS*)OALPAtoUA( OMAP730_USBD_REGS_PA );

    if (pUSBDRegs == NULL) {
        OALMSG(OAL_ERROR, (
            L"ERROR: UfnPdd_Init: Controller registers mapping failed\r\n"
        ));
        goto clean;
    }
    pPdd->pUSBDRegs = pUSBDRegs;

    // Clear USB Interrupt enable registers
    OUTREG32(&pUSBDRegs->IRQ_EN, 0);
    OUTREG32(&pUSBDRegs->DMA_IRQ_EN, 0);

    // Reset all interrupts
    OUTREG32(&pUSBDRegs->IRQ_SRC, 0xFFFFFFFF);

    // Disable all RX, TX EPs
    OUTREG32(&pUSBDRegs->EP0, 0);
    for (ep = 1; ep < USBD_EP_COUNT; ep++) {
        OUTREG32(&pUSBDRegs->EP_RX[ep], 0);
        OUTREG32(&pUSBDRegs->EP_TX[ep], 0);
    }

    //OUTREG32(&pUSBDRegs->SYSCON1, 0);

    // Set PDD interface
    pPddIfc->dwVersion = UFN_PDD_INTERFACE_VERSION;
    pPddIfc->dwCapabilities = UFN_PDD_CAPS_SUPPORTS_FULL_SPEED;
    pPddIfc->dwEndpointCount = USBD_EP_COUNT;
    pPddIfc->pvPddContext = pPdd;
    pPddIfc->pfnDeinit = UfnPdd_Deinit;
    pPddIfc->pfnIsConfigurationSupportable = UfnPdd_IsConfigurationSupportable;
    pPddIfc->pfnIsEndpointSupportable = UfnPdd_IsEndpointSupportable;
    pPddIfc->pfnInitEndpoint = UfnPdd_InitEndpoint;
    pPddIfc->pfnRegisterDevice = UfnPdd_RegisterDevice;
    pPddIfc->pfnDeregisterDevice = UfnPdd_DeregisterDevice;
    pPddIfc->pfnStart = UfnPdd_Start;
    pPddIfc->pfnStop = UfnPdd_Stop;
    pPddIfc->pfnIssueTransfer = UfnPdd_IssueTransfer;
    pPddIfc->pfnAbortTransfer = UfnPdd_AbortTransfer;
    pPddIfc->pfnDeinitEndpoint = UfnPdd_DeinitEndpoint;
    pPddIfc->pfnStallEndpoint = UfnPdd_StallEndpoint;
    pPddIfc->pfnClearEndpointStall = UfnPdd_ClearEndpointStall;
    pPddIfc->pfnSendControlStatusHandshake = UfnPdd_SendControlStatusHandshake;
    pPddIfc->pfnSetAddress = UfnPdd_SetAddress;
    pPddIfc->pfnIsEndpointHalted = UfnPdd_IsEndpointHalted;
    pPddIfc->pfnInitiateRemoteWakeup = UfnPdd_InitiateRemoteWakeup;
    pPddIfc->pfnPowerDown = UfnPdd_PowerDown;
    pPddIfc->pfnPowerUp = UfnPdd_PowerUp;
    pPddIfc->pfnIOControl = UfnPdd_IOControl;

    // Save MDD context & notify function
    pPdd->pMddContext = pMddContext;
    pPdd->pfnNotify = pMddIfc->pfnNotify;

    // Done
    rc = ERROR_SUCCESS;

clean:
    return rc;
}

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

extern BOOL UfnPdd_DllEntry(
    HANDLE hDllHandle, DWORD reason, VOID *pReserved
) {
    return TRUE;
}

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

#pragma optimize ( "", on )

⌨️ 快捷键说明

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