?? s3c6410otgdevice.cpp
字號:
pContext->Ep0State = EP0_STATE_OUT_DATA_PHASE;
}
pContext->sendDataEnd = FALSE;
}
else
{ // UDR.wLength == 0
// ClientDriver will issue a SendControlStatusHandshake to
// complete the transaction.
pContext->sendDataEnd = TRUE;
// Nothing left to do... stay in IDLE.
DEBUGCHK(pContext->Ep0State == EP0_STATE_IDLE);
}
fSendUDR = TRUE;
}
}
}
else if (pContext->Ep0State == EP0_STATE_OUT_DATA_PHASE)
{
DEBUGMSG(ZONE_TRANSFER, (_T("EP0_OUT_PHASE\r\n")));
DWORD dwCountBytes = ReadReg(DOEPTSIZ0) & 0x7f;
dwCountBytes = pContext->dwEp0MaxPktSize - dwCountBytes;
peps->pTransfer->cbTransferred += dwCountBytes;
DWORD dwRemainBytes = peps->pTransfer->cbBuffer - peps->pTransfer->cbTransferred;
if (dwRemainBytes == 0)
{
pContext->Ep0State = EP0_STATE_IDLE;
pContext->sendDataEnd = TRUE;
memcpy(peps->pTransfer->pvBuffer, pContext->pVAddrEP[0][OUT_EP] , peps->pTransfer->cbBuffer);
dwStatus = UFN_NO_ERROR;
fCompleted = TRUE;
pContext->Ep0State = EP0_STATE_IDLE;
}
else
{
WriteReg(DOEPDMA0, pContext->pPAddrEP[0][OUT_EP] + peps->pTransfer->cbTransferred);
WriteReg(DOEPTSIZ0, 1<<PACKET_COUTNT_IDX | pContext->dwEp0MaxPktSize);
WriteReg(DOEPCTL0, EP_ENABLE | CLEAR_NAK | EP0_MAX_PK_SIZ);
}
}
else
{
DEBUGMSG(ZONE_TRANSFER, (_T("EP0_IN_PHASE\r\n")));
if(peps->pTransfer->cbBuffer >= (pContext->dwEp0MaxPktSize + peps->pTransfer->cbTransferred))
peps->pTransfer->cbTransferred += pContext->dwEp0MaxPktSize;
else
peps->pTransfer->cbTransferred = peps->pTransfer->cbBuffer;
DWORD dwRemainBytes = peps->pTransfer->cbBuffer - peps->pTransfer->cbTransferred;
if (dwRemainBytes == 0)
{
dwStatus = UFN_NO_ERROR;
fCompleted = TRUE;
pContext->Ep0State = EP0_STATE_IDLE;
}
else
{
WatiForTxFIFOEmpty(100);
WriteReg(DIEPDMA0, pContext->pPAddrEP[0][IN_EP] + peps->pTransfer->cbTransferred);
if (dwRemainBytes >= pContext->dwEp0MaxPktSize)
WriteReg(DIEPTSIZ0, 1<<PACKET_COUTNT_IDX | pContext->dwEp0MaxPktSize);
else
WriteReg(DIEPTSIZ0, 1<<PACKET_COUTNT_IDX | dwRemainBytes);
WriteReg(DIEPCTL0, EP_ENABLE | CLEAR_NAK | 1<<NEXT_EP_IDX | EP0_MAX_PK_SIZ);
}
}
if (fCompleted)
{
CompleteTransfer(pContext, peps, dwStatus);
}
if (fSendUDR)
{
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &pContext->UDR);
}
FUNCTION_LEAVE_MSG();
UNLOCK_ENDPOINT(peps);
}
// Process an endpoint interrupt except endpoint0
static
VOID
HandleOutEvent(
PCTRLR_PDD_CONTEXT pContext,
DWORD dwEndpoint
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
ValidateContext(pContext);
DEBUGCHK(pContext->fRunning);
DEBUGCHK(dwEndpoint != 0);
EP_STATUS *peps = GetEpStatus(pContext, dwEndpoint);
PREFAST_DEBUGCHK(peps);
LOCK_ENDPOINT(peps);
PSTransfer pTransfer = peps->pTransfer;
DWORD dwCountBytes = ReadEPSpecificReg(dwEndpoint, DOEPTSIZ) & 0x7FFFF;
pContext->dwPipelinedXfered[dwEndpoint][pContext->dwPipelinedStrIdx] = pContext->dwPipelinedXferSize - dwCountBytes;
if(pContext->dwPipelinedXfered[dwEndpoint][pContext->dwPipelinedStrIdx] > pContext->dwPipelinedXferSize)
pContext->dwPipelinedXfered[dwEndpoint][pContext->dwPipelinedStrIdx] = pContext->dwPipelinedXferSize;
//For MSC compliance test : one of cases, A host send the data which is bigger than a device expect to get
pContext->dwPipelinedStrIdx = GET_NEXT_PF_IDX(pContext->dwPipelinedStrIdx);
if(pContext->dwUSBClassInfo != USB_MSF)
{
if(pContext->dwPipelinedXfered[dwEndpoint][pContext->dwPipelinedStrIdx] == 0)
{
WriteEPSpecificReg(dwEndpoint, DOEPDMA, pContext->pPAddrEP[dwEndpoint][pContext->dwPipelinedStrIdx]);
WriteEPSpecificReg(dwEndpoint, DOEPTSIZ, pContext->dwPipelinedPktCnt<<PACKET_COUTNT_IDX | pContext->dwPipelinedXferSize);
WriteEPSpecificReg(dwEndpoint, DOEPCTL, EP_ENABLE | CLEAR_NAK | SET_TYPE_BULK | USB_ACT_EP | peps->dwPacketSizeAssigned);
}
else
{
RETAILMSG(UFN_ZONE_WARNING,(TEXT("RING BUFFER STATE : FULL\r\n")));
DisableEndpointInterrupt(pContext, peps->dwEndpointNumber, peps->dwDirectionAssigned);
pContext->bRingBufferFull = TRUE;
}
}
if(pContext->dwPipelinedEP != 0)
{
memcpy(pTransfer->pvBuffer, \
pContext->pVAddrEP[dwEndpoint][pContext->dwPipelinedEndIdx] , \
pContext->dwPipelinedXfered[dwEndpoint][pContext->dwPipelinedEndIdx]);
pTransfer->cbTransferred += pContext->dwPipelinedXfered[dwEndpoint][pContext->dwPipelinedEndIdx];
pContext->dwPipelinedXfered[dwEndpoint][pContext->dwPipelinedEndIdx] = 0;
pContext->dwPipelinedEndIdx = GET_NEXT_PF_IDX(pContext->dwPipelinedEndIdx);
pContext->dwPipelinedEP = 0;
DisableEndpointInterrupt(pContext, peps->dwEndpointNumber, peps->dwDirectionAssigned);
CompleteTransfer(pContext, peps, UFN_NO_ERROR);
}
UNLOCK_ENDPOINT(peps);
FUNCTION_LEAVE_MSG();
}
static
VOID
HandleInEvent(
PCTRLR_PDD_CONTEXT pContext,
DWORD dwEndpoint
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
ValidateContext(pContext);
DEBUGCHK(pContext->fRunning);
DEBUGCHK(dwEndpoint != 0);
EP_STATUS *peps = GetEpStatus(pContext, dwEndpoint);
PREFAST_DEBUGCHK(peps);
LOCK_ENDPOINT(peps);
if(pContext->dwInEPRunning[dwEndpoint])
{
pContext->dwInEPRunning[dwEndpoint] = 0;
pContext->dwXmitReadyCnt--;
pContext->dwXmittingEP |= (1<<dwEndpoint);
if (pContext->dwXmitReadyCnt == 0)
{
WriteReg(DIEPMSK, TIMEOUT_CONDITION | XFER_COMPLETE);
}
PSTransfer pTransfer = peps->pTransfer;
DWORD dwPktcnt, dwBytes;
if (pTransfer->cbBuffer == 0)
{
dwPktcnt = 1;
}
else
{
dwPktcnt = pTransfer->cbBuffer / peps->dwPacketSizeAssigned;
dwBytes = pTransfer->cbBuffer % peps->dwPacketSizeAssigned;
if (dwBytes) dwPktcnt++;
}
WatiForTxFIFOEmpty(100);
WriteEPSpecificReg(dwEndpoint, DIEPDMA, pContext->pPAddrEP[dwEndpoint][IN_EP]);
WriteEPSpecificReg(dwEndpoint, DIEPTSIZ, dwPktcnt<<PACKET_COUTNT_IDX | pTransfer->cbBuffer);
if (pContext->dwUSBClassInfo == USB_RNDIS)
{
if (dwEndpoint == 1)
WriteEPSpecificReg(dwEndpoint, DIEPCTL, EP_ENABLE | CLEAR_NAK | SET_TYPE_BULK | USB_ACT_EP | 2<<NEXT_EP_IDX | peps->dwPacketSizeAssigned);
else
WriteEPSpecificReg(dwEndpoint, DIEPCTL, EP_ENABLE | CLEAR_NAK | SET_TYPE_BULK | USB_ACT_EP | 0<<NEXT_EP_IDX | peps->dwPacketSizeAssigned);
}
else
{
WriteEPSpecificReg(dwEndpoint, DIEPCTL, EP_ENABLE | CLEAR_NAK | SET_TYPE_BULK | USB_ACT_EP | 0<<NEXT_EP_IDX | peps->dwPacketSizeAssigned);
}
}
UNLOCK_ENDPOINT(peps);
FUNCTION_LEAVE_MSG();
}
static
VOID
SetEndpoint(
PCTRLR_PDD_CONTEXT pContext
)
{
DWORD dwEndpoint;
// Clear all device endpoint interrupt
for(dwEndpoint=0; dwEndpoint<ENDPOINT_COUNT; dwEndpoint++)
{
WriteEPSpecificReg(dwEndpoint, DIEPINT, 0x3f);
WriteEPSpecificReg(dwEndpoint, DOEPINT, 0x3f);
}
}
inline
static
VOID
SetAllOutEpNak()
{
DWORD dwEndpoint;
for(dwEndpoint=0; dwEndpoint<ENDPOINT_COUNT; dwEndpoint++)
{
SetClearEPSpecificReg(dwEndpoint, DOEPCTL, SET_NAK, SET);
}
}
inline
static
VOID
ClearAllOutEpNak()
{
DWORD dwEndpoint;
for(dwEndpoint=0; dwEndpoint<ENDPOINT_COUNT; dwEndpoint++)
{
SetClearEPSpecificReg(dwEndpoint, DOEPCTL, CLEAR_NAK, SET);
}
}
static
VOID
HandleReset(
PCTRLR_PDD_CONTEXT pContext
)
{
DWORD dwGOTGCTL = ReadReg(GOTGCTL);
if (pContext->attachedState == UFN_DETACH)
{
if(dwGOTGCTL & (B_SESSION_VALID|A_SESSION_VALID))
{
if (pContext->IsFirstReset == TRUE)
{
Sleep(2000); // For Sleep Wake Up Connection issue.
}
pContext->IsFirstReset = FALSE;
SetAllOutEpNak();
// Below function(ResetDevice) make USB compliance Test(chir timimg) fail.
// So If your usb H/W have usb plug detect signal, This function should be moved to Plug thread fucntion.
ResetDevice(pContext);
ClearAllOutEpNak();
pContext->fSpeedReported = FALSE;
pContext->Ep0State = EP0_STATE_IDLE;
pContext->attachedState = UFN_ATTACH;
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_ATTACH);
RETAILMSG(UFN_ZONE_USB_EVENTS,(_T("[UFNPDD] OTG Cable Attached\r\n")));
}
else
{
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_DETACH);
pContext->attachedState = UFN_DETACH;
RETAILMSG(UFN_ZONE_USB_EVENTS,(_T("[UFNPDD] RESET Exeption \r\n")));
}
}
else
{
if(!(dwGOTGCTL & (B_SESSION_VALID|A_SESSION_VALID)))
{
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_DETACH);
pContext->attachedState = UFN_DETACH;
}
else
{
// USB Device Address field should be cleared per every reset time.
// If not, USB Compliance Frame work test(EnumerationTest) make a fail.
volatile DWORD wDCFG = ReadReg(DCFG);
WriteReg(DCFG, (wDCFG & ~(DEVICE_ADDRESS_MSK)));
InitDevice(pContext);
InitPDDContext(pContext);
// Initialize EP0 Out DMA to get a SetUp packet
WriteReg(DOEPDMA0, pContext->pPAddrEP[0][OUT_EP]);
WriteReg(DOEPTSIZ0, 1<<SETUP_PKT_CNT_IDX | 1<<PACKET_COUTNT_IDX | 8);
WriteReg(DOEPCTL0, EP_ENABLE | CLEAR_NAK | EP0_MAX_PK_SIZ);
RETAILMSG(UFN_ZONE_USB_EVENTS,(_T("[UFNPDD] RESET Again \r\n")));
}
}
}
// Process USB Bus interrupt
static
VOID
HandleUSBBusIrq(
PCTRLR_PDD_CONTEXT pContext,
DWORD bUSBBusIrqStat
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
ValidateContext(pContext);
if (bUSBBusIrqStat & INT_RESET)
{
HandleReset(pContext);
WriteReg(GINTSTS, INT_RESET);
DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Reset\r\n"), pszFname));
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_RESET);
}
// for Transmit data holding issue in RNDIS ++ //
if (bUSBBusIrqStat & INT_EPMIS)
{
WriteReg(GINTSTS, INT_EPMIS);
ClearAllOutEpNak();
SetClearReg(DCTL, CLEAR_GOUTNAK, SET);
}
// for Transmit data holding issue in RNDIS -- //
if (bUSBBusIrqStat & INT_SDE)
{
WriteReg(GINTSTS, INT_SDE);
DWORD dwDSTS = ReadReg(DSTS);
if (((dwDSTS & ENUM_SPEED_MSK)>>1) == USB_HIGH)
{
pContext->dwDetectedSpeed = USB_HIGH;
pContext->dwEp0MaxPktSize = EP_0_PACKET_SIZE;
}
else if(((dwDSTS & ENUM_SPEED_MSK)>>1) == USB_FULL)
{
pContext->dwDetectedSpeed = USB_FULL;
pContext->dwEp0MaxPktSize = EP_0_PACKET_SIZE;
}
else
{
RETAILMSG(UFN_ZONE_ERROR,(_T("[UFNPDD] INT_SDE_EXEPTION Occured! \r\n")));
}
SetEndpoint(pContext);
}
if (bUSBBusIrqStat & INT_RESUME)
{
WriteReg(GINTSTS, INT_RESUME);
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_RESUME);
}
if (bUSBBusIrqStat & INT_SUSPEND)
{
WriteReg(GINTSTS, INT_SUSPEND);
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_SUSPEND);
}
if (bUSBBusIrqStat & INT_OTG)
{
DWORD dwGotgint = ReadReg(GOTGINT);
if (dwGotgint & SesEndDet)
{
RETAILMSG(UFN_ZONE_USB_EVENTS,(_T("[UFNPDD] OTG Cable Detached\r\n")));
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_DETACH);
pContext->attachedState = UFN_DETACH;
pContext->IsFirstReset = TRUE;
pContext->bOutEPDMAStartFlag = FALSE;
}
else
{
DEBUGMSG(ZONE_ERROR,(_T("[UFNPDD] OTG Interrupt Exeption %x\r\n"),dwGotgint));
}
WriteReg(GOTGINT, dwGotgint);
}
FUNCTION_LEAVE_MSG();
}
static
VOID
HandleUSBEvent(
PCTRLR_PDD_CONTEXT pContext
)
{
SETFNAME();
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -