📄 pdd.c
字号:
//
// 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 + -