📄 pxa25xpdd.cpp
字号:
// There is no error status for this. Will Assume it success.
if (pTransfer) {
if (pTransfer->cbTransferred >= pTransfer->cbBuffer || (ulUdccs &USB_UDCCS_RSP )!= 0 ) { // Complete.
*(peps->lpulUDCCSx) = ulUdccs ;
CompleteTransfer(pContext, peps, UFN_NO_ERROR);
continue;
}
}
else { // No transfer. Keep Naking. do not interrupt us anymore
ulUdccs &= ~USB_UDCCS_RPC;
}
}
if((ulUdccs & (USB_UDCCS_SST|USB_UDCCS_FST))== (USB_UDCCS_SST|USB_UDCCS_FST)) {
USB_DEVICE_REQUEST udr;
udr.bmRequestType = USB_REQUEST_FOR_ENDPOINT;
udr.bRequest =USB_REQUEST_CLEAR_FEATURE;
udr.wValue = USB_FEATURE_ENDPOINT_STALL;
udr.wIndex = (BYTE) peps->dwEndPointNumber ;
udr.wLength =0;
DEBUGMSG(ZONE_USB_EVENTS || ZONE_PIPE, (_T("%s Got SST EP%u \r\n"), pszFname, peps->dwEndPointNumber ));
ulUdccs &= ~(USB_UDCCS_SST | USB_UDCCS_FST);
*(peps->lpulUDCCSx) = ulUdccs;
bContinue = TRUE;
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_PREPROCESSED_SETUP_PACKET,(DWORD) &udr);
continue;
}
*(peps->lpulUDCCSx) = ulUdccs ;
}
if (peps->pTransfer == NULL )
DisableEndpointInterrupt(pContext, peps->dwEndPointNumber );
FUNCTION_LEAVE_MSG();
}
// Write data to an endpoint.
static VOID
HandleTx(
PCTRLR_PDD_CONTEXT pContext,
PEP_STATUS peps
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DEBUGCHK(pContext);
PREFAST_DEBUGCHK(peps);
BOOL fCompleted = FALSE;
// This routine can be entered from both ISTMain and MDD/Client threads so
// need critical section.
BOOL bContinue = TRUE;
while (bContinue) {
ULONG ulUdccs = *(peps->lpulUDCCSx);
bContinue = FALSE;
PSTransfer pTransfer = peps->pTransfer;
DEBUGMSG(ZONE_USB_EVENTS || ZONE_PIPE, (_T("%s ulUdccs = %u \r\n"), pszFname, ulUdccs));
ulUdccs &= ~USB_UDCCS_TSP ;
if ( ulUdccs & USB_UDCCS_TPC ) { // The status is valid here.
if (pTransfer && !peps->fZeroPacketNeeded && pTransfer->cbTransferred >= pTransfer->cbBuffer) {
*(peps->lpulUDCCSx) = ulUdccs ;
CompleteTransfer(pContext,peps, UFN_NO_ERROR);
continue;
}
}
if (pTransfer && ( ulUdccs & USB_UDCCS_TFS )!= 0 &&
(pTransfer->cbTransferred < pTransfer->cbBuffer || peps->fZeroPacketNeeded )) {
DEBUGCHK(peps->fInitialized);
ValidateTransferDirection(pContext, peps, pTransfer);
DWORD dwSize = (pTransfer->cbTransferred< pTransfer->cbBuffer? pTransfer->cbBuffer-pTransfer->cbTransferred: 0);
dwSize = min(dwSize, peps->dwPacketSizeSupported );
DWORD dwReturnSize = 0;
DWORD dwError = UFN_NO_ERROR ;
DWORD dwCurrentPermissions = GetCurrentPermissions();
SetProcPermissions(pTransfer->dwCallerPermissions);
__try {
dwReturnSize = XmitData(peps,(PBYTE)pTransfer->pvBuffer + pTransfer->cbTransferred,dwSize);
}
__except(EXCEPTION_EXECUTE_HANDLER) {
dwReturnSize = 0;
dwError =UFN_CLIENT_BUFFER_ERROR;
}
SetProcPermissions(dwCurrentPermissions);
pTransfer->cbTransferred += dwReturnSize;
if (dwReturnSize < peps->dwPacketSizeSupported) {
ulUdccs |= USB_UDCCS_TSP ;
}
peps->fZeroPacketNeeded = FALSE;
DEBUGMSG(ZONE_USB_EVENTS || ZONE_PIPE, (_T("%s Transfer dwReturnSize = 0x%x ulUdccs = 0x%x, fZeroPacket =%d \r\n"), pszFname, dwReturnSize ,ulUdccs));
}
if((ulUdccs & (USB_UDCCS_SST|USB_UDCCS_FST))== (USB_UDCCS_SST|USB_UDCCS_FST)) {
USB_DEVICE_REQUEST udr;
udr.bmRequestType = USB_REQUEST_FOR_ENDPOINT;
udr.bRequest =USB_REQUEST_CLEAR_FEATURE;
udr.wValue = USB_FEATURE_ENDPOINT_STALL;
udr.wIndex = (BYTE) peps->dwEndPointNumber ;
udr.wLength =0;
DEBUGMSG(ZONE_USB_EVENTS || ZONE_PIPE, (_T("%s Got SST EP%u \r\n"), pszFname, peps->dwEndPointNumber ));
ulUdccs &= ~USB_UDCCS_FST;
*(peps->lpulUDCCSx) = ulUdccs;
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_PREPROCESSED_SETUP_PACKET,(DWORD) &udr);
continue;
}
*(peps->lpulUDCCSx) = ulUdccs ;
}
if (peps->pTransfer == NULL )
DisableEndpointInterrupt(pContext, peps->dwEndPointNumber );
FUNCTION_LEAVE_MSG();
}
// Process an endpoint interrupt. Call interrupt-specific handler.
static
VOID
HandleEndpointEvent(
PCTRLR_PDD_CONTEXT pContext,
DWORD dwEndpoint
)
{
BOOL fNotifyMddClearFeature = FALSE;
SETFNAME();
DEBUGCHK(dwEndpoint != 0);
ValidateContext(pContext);
DEBUGCHK(pContext->fRunning);
PEP_STATUS peps = GetEpStatus(pContext, dwEndpoint);
LOCK_ENDPOINT(peps);
FUNCTION_ENTER_MSG();
volatile ULONG *lpulIrqStat = peps->lpulUDCCSx;
PREFAST_DEBUGCHK(lpulIrqStat != NULL);
DWORD dwPendingEvents = 0;
peps->fInIST = TRUE;
// setup active && out packet ready -> setup token event
if (peps->dwDirectionSupported == USB_IN_TRANSFER){
HandleTx(pContext, peps);
DEBUGMSG(ZONE_FUNCTION, (_T("%s End EPIn Status = %x \r\n"), pszFname, *lpulIrqStat));
}
else if (peps->dwDirectionSupported == USB_OUT_TRANSFER){
//
// receive packet complete && receive fifo not empty -> out token + data rx event
//
HandleRx(pContext, peps);
DEBUGMSG(ZONE_FUNCTION, (_T("%s End EPOut Status = %x \r\n"),
pszFname, *lpulIrqStat));
}
peps->fInIST = FALSE;
FUNCTION_LEAVE_MSG();
UNLOCK_ENDPOINT(peps);
}
static void SetRequestInfo(EP0_REQUEST *pRequest, EP0_DIR eDir)
{
pRequest->eDir = eDir;
pRequest->dwExpectedSize = 0;
pRequest->fCompleted = FALSE;
if (eDir == EP0Setup ) {
pRequest->fBackupNext = FALSE;
}
}
static BOOL GetSetupPkt(PUSB_DEVICE_REQUEST pUdr, BOOL fForce)
{
SETFNAME();
DWORD dwRead = 0;
UCHAR *pucBuffer = (UCHAR *) pUdr;
while( (dwRead < sizeof(USB_DEVICE_REQUEST)) &&
(fForce || g_pUDCBase->udccs0 & USB_UDCCS0_RNE) ) {
*pucBuffer++ = (UCHAR) g_pUDCBase->uddr0;
dwRead++;
}
if (dwRead != sizeof(USB_DEVICE_REQUEST)) {
DEBUGMSG(ZONE_WARNING, (_T("%s Only %d bytes read for SetupPacket\r\n"),
pszFname, dwRead));
return FALSE;
}
return TRUE;
}
#define UDCCS0_MWRITEREG( x, y ) ((x) = ((x) & (~UDCCS0_MASK)) | (y))
#define UISR_IR0_CLR(pUISR0) (pUISR0 = USB_UISR0_IR0)
#if defined(CHECK_UISR_IR0_CLR)
#define PRECHECK_IR0(p) do { if (((p) & 1) == 0) DEBUGMSG(ZONE_WARNING, (_T("%s %d IR0 not set\r\n"), pszFname, __LINE__)); } while (0)
#define CHECK_IR0(p) do { if ((p) & 1) DEBUGMSG(ZONE_WARNING, (_T("%s %d IR0 still set\r\n", pszFname, __LINE__)); } while (0)
#define UISR_IR0_CLR_CHK(p) do { PRECHECK_IR0((p)); UISR_IR0_CLR((p)); CHECK_IR0((p)); } while (0)
#else
#define UISR_IR0_CLR_CHK(p) UISR_IR0_CLR((p))
#endif
static VOID ServiceSetup(PCTRLR_PDD_CONTEXT pContext , PEP_STATUS peps)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DEBUGCHK(pContext);
BOOL bContinue = TRUE;
while (bContinue) {
bContinue = FALSE;
USB_DEVICE_REQUEST udr;
DWORD dwUdrMsg = 0;
ULONG ulStatusReg = *(peps->lpulUDCCSx);
DEBUGMSG(ZONE_TRANSFER, (_T("%s EP0 Status Reg = %x \r\n"), pszFname, ulStatusReg));
PEP0_REQUEST pRequest = &pContext->ep0Request;
PSTransfer pTransfer = peps->pTransfer;
// Check for stall sent
if ((ulStatusReg & USB_UDCCS0_SST)!=0) { // Stall on endpoint zero, It is auto clear, So we do not need to do anything here.
ulStatusReg &= ~(USB_UDCCS0_FST);
SetRequestInfo(pRequest, EP0Setup);
}
// Continue processing the other.
if (ulStatusReg & USB_UDCCS0_OPR) {
// check for missing status interrupt
if ((ulStatusReg & USB_UDCCS0_SA)!=0 ) {
if (pContext->fSpeedReported == FALSE) {
pContext->fSpeedReported = TRUE;
// After Every Reset Notify MDD of Speed setting.
// This device can only support FULL Speed.
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_SPEED, BS_FULL_SPEED);
// The HW Filters the Set Address ... Fake it here
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SET_ADDRESS, 0xFF);
// Setup Configuration.
udr.bmRequestType = USB_REQUEST_FOR_DEVICE;
udr.bRequest = USB_REQUEST_SET_CONFIGURATION;
udr.wValue = pContext->wConfigurationValue ;
udr.wIndex = 0;
udr.wLength =0;
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET,(DWORD) &udr);
}
if (!GetSetupPkt(&udr,TRUE)) { // No matter what, Read Packet First.
// fail to properly get setup packet from FIFO
// force a STALL condition
ulStatusReg |=USB_UDCCS0_FST;
DEBUGMSG(ZONE_WARNING, (_T("%s **** ERROR: Get setup packet failed\r\n"), pszFname));
ASSERT(FALSE);
}
if (pTransfer) {
CompleteTransfer(pContext, peps, UFN_NO_ERROR);
}
if (pContext->fEndpoint0AckNeeded) { // Wait for Ack from Application. Do not clean anything.
DisableEndpointInterrupt(pContext, 0 );
pRequest->fBackupNext = TRUE;
pRequest->udr = udr;
*(peps->lpulUDCCSx)= ulStatusReg ;
}
else {
SetRequestInfo(pRequest, EP0Setup);
pRequest->fCompleted = FALSE;
pRequest->dwExpectedSize = udr.wLength;
// Set data direction
if (udr.wLength != 0) {
if (udr.bmRequestType & USB_REQUEST_DEVICE_TO_HOST) {
pRequest->eDir = EP0In;
}
else {
pRequest->eDir = EP0Out;
}
}
else {
pRequest->eDir = EP0Out;
}
pRequest->fBackupNext = FALSE ;
pContext->fEndpoint0AckNeeded = TRUE;
*(peps->lpulUDCCSx)= ulStatusReg ;
pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &udr);
}
continue;
}
else { // Out Data.
if ((ulStatusReg & USB_UDCCS0_RNE)== 0 ) { // This is ack from Host.
if (pRequest->eDir == EP0In) {
if (pTransfer) {
*(peps->lpulUDCCSx)= ulStatusReg ;
CompleteTransfer(pContext, peps, UFN_NO_ERROR);
continue;
}
}
else {
DEBUGMSG(ZONE_ERROR,(_T("%s **** ERROR: Get Zero Packet on EP0 Out Transfer,UDCCS0@INT = 0x%x,UDCCS0@Now = 0x%x, Try it again\r\n"), pszFname,ulStatusReg,*(peps->lpulUDCCSx)));
bContinue = TRUE;
continue;
}
}
else { // Data Available.
if (pTransfer ) {
if ( pRequest->eDir == EP0Out) {
DWORD dwCurrentPermissions = GetCurrentPermissions();
DWORD dwSize = (pTransfer->cbTransferred< pTransfer->cbBuffer? pTransfer->cbBuffer-pTransfer->cbTransferred: 0);
dwSize = min(dwSize, peps->dwPacketSizeSupported );
DWORD dwReturnSize = 0;
DWORD dwError = UFN_NO_ERROR ;
SetProcPermissions(pTransfer->dwCallerPermissions);
__try {
dwReturnSize = ReceiveData(peps,(PBYTE)pTransfer->pvBuffer + pTransfer->cbTransferred , dwSize);
}
__except(EXCEPTION_EXECUTE_HANDLER) {
dwReturnSize = 0;
dwError =UFN_CLIENT_BUFFER_ERROR ;
}
SetProcPermissions(dwCurrentPermissions);
pTransfer->cbTransferred += dwReturnSize;
if (pTransfer->cbTransferred >= pTransfer->cbBuffer || dwReturnSize < dwSize) { // Complete or shourt packet.
*(peps->lpulUDCCSx)= ulStatusReg ;
CompleteTransfer(pContext, peps, dwError);
continue;
}
}
else
ulStatusReg |=USB_UDCCS0_FST;
}
else {
DEBUGMSG(ZONE_ERROR, (_T("%s EP0 Out Packet without Transfer, Packet Dropped!!! \r\n"), pszFname));
}
}
}
}
else
if ((ulStatusReg & USB_UDCCS0_IPR) == 0) { // Received One Packet.
if (pRequest->eDir == EP0In) {
if (pTransfer) {
DWORD dwCurrentPermissions = GetCurrentPermissions();
DWORD dwSize = (pTransfer->cbTransferred< pTransfer->cbBuffer? pTransfer->cbBuffer-pTransfer->cbTransferred: 0);
dwSize = min(dwSize, peps->dwPacketSizeSupported );
DWORD dwReturnSize = 0;
DWORD dwError = UFN_NO_ERROR ;
SetProcPermissions(pTransfer->dwCallerPermissions);
__try {
dwReturnSize = XmitData(peps, (PBYTE)pTransfer->pvBuffer + pTransfer->cbTransferred,dwSize);
}
__except(EXCEPTION_EXECUTE_HANDLER) {
dwReturnSize = 0;
dwError =UFN_CLIENT_BUFFER_ERROR ;
}
SetProcPermissions(dwCurrentPermissions);
pTransfer->cbTransferred += dwReturnSize;
if (dwReturnSize < peps->dwPacketSizeSupported) {
ulStatusReg |= USB_UDCCS0_IPR;
peps->fZeroPacketNeeded = FALSE; // Short packet already.
}
else
peps->fZeroPacketNeeded = TRUE;
if (pTransfer->cbTransferred >= pTransfer->cbBuffer && !peps->fZeroPacketNeeded) { // We are complete.
*(peps->lpulUDCCSx) = ulStatusReg ;
CompleteTransfer(pContext, peps, UFN_NO_ERROR);
continue;
}
}
}
}
else
ulStatusReg &= ~USB_UDCCS0_IPR;
*(peps->lpulUDCCSx) = ulStatusReg ;
}
FUNCTION_LEAVE_MSG();
}
static
VOID
ServiceEP0(
PCTRLR_PDD_CONTEXT pContext
)
{
SETFNAME();
FUNCTION_ENTER_MSG();
DEBUGCHK(pContext);
PEP_STATUS peps = GetEpStatus(pContext, 0);
LOCK_ENDPOINT(peps);
peps->fInIST = TRUE;
ServiceSetup(pContext, peps);
peps->fInIST = FALSE;
UNLOCK_ENDPOINT(peps);
FUNCTION_LEAVE_MSG();
}
// Process an interrupt.
static
VOID
HandleUSBEvent(
PCTRLR_PDD_CONTEXT pContext
)
{
DWORD interruptsToClear = 0;
DWORD ulI;
SETFNAME();
FUNCTION_ENTER_MSG();
ValidateContext(pContext);
// GetDevice Interrupt Flag.
BOOL bContinue = TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -