📄 cpipe.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Module Name:
// CPipe.cpp
// Abstract:
// Implements the Pipe class for managing open pipes for UHCI
//
// CPipe (ADT)
// / \
// CQueuedPipe (ADT) CIsochronousPipe
// / | \
// / | \
// CControlPipe CInterruptPipe CBulkPipe
//
//
// Notes:
//
//
#include <windows.h>
#include "trans.h"
#include "Cpipe.h"
#include "chw.h"
#include "CEhcd.h"
#ifndef _PREFAST_
#pragma warning(disable: 4068) // Disable pragma warnings
#endif
// ******************************************************************
// Scope: public
CPipe::CPipe( IN const LPCUSB_ENDPOINT_DESCRIPTOR lpEndpointDescriptor,
IN const BOOL fIsLowSpeed,IN const BOOL fIsHighSpeed,
IN const UCHAR bDeviceAddress,
IN const UCHAR bHubAddress,IN const UCHAR bHubPort,
IN CEhcd *const pCEhcd)
//
// Purpose: constructor for CPipe
//
// Parameters: lpEndpointDescriptor - pointer to endpoint descriptor for
// this pipe (assumed non-NULL)
//
// fIsLowSpeed - indicates if this pipe is low speed
//
// Returns: Nothing.
//
// Notes: Most of the work associated with setting up the pipe
// should be done via OpenPipe. The constructor actually
// does very minimal work.
//
// Do not modify static variables here!!!!!!!!!!!
// ******************************************************************
: CPipeAbs(lpEndpointDescriptor->bEndpointAddress )
, m_usbEndpointDescriptor( *lpEndpointDescriptor )
, m_bDeviceAddress(bDeviceAddress)
, m_pCEhcd(pCEhcd)
, m_fIsLowSpeed( !!fIsLowSpeed ) // want to ensure m_fIsLowSpeed is 0 or 1
, m_fIsHighSpeed( !!fIsHighSpeed)
, m_fIsHalted( FALSE )
, m_bHubAddress (bHubAddress)
, m_bHubPort (bHubPort)
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CPipe::CPipe\n")) );
// CPipe::Initialize should already have been called by now
// to set up the schedule and init static variables
//DEBUGCHK( pUHCIFrame->m_debug_fInitializeAlreadyCalled );
InitializeCriticalSection( &m_csPipeLock );
m_fIsHalted = FALSE;
// Assume it is Async. If it is not It should be ovewrited.
m_bFrameSMask = 0;
m_bFrameCMask = 0;
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CPipe::CPipe\n")) );
}
// ******************************************************************
// Scope: public virtual
CPipe::~CPipe( )
//
// Purpose: Destructor for CPipe
//
// Parameters: None
//
// Returns: Nothing.
//
// Notes: Most of the work associated with destroying the Pipe
// should be done via ClosePipe
//
// Do not delete static variables here!!!!!!!!!!!
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CPipe::~CPipe\n")) );
// transfers should be aborted or closed before deleting object
DeleteCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CPipe::~CPipe\n")) );
}
CPhysMem *CPipe::GetCPhysMem()
{
return m_pCEhcd->GetPhysMem();
}
// ******************************************************************
// Scope: public
HCD_REQUEST_STATUS CPipe::IsPipeHalted( OUT LPBOOL const lpbHalted )
//
// Purpose: Return whether or not this pipe is halted (stalled)
//
// Parameters: lpbHalted - pointer to BOOL which receives
// TRUE if pipe halted, else FALSE
//
// Returns: requestOK
//
// Notes: Caller should check for lpbHalted to be non-NULL
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CPipe(%s)::IsPipeHalted\n"), GetPipeType()) );
DEBUGCHK( lpbHalted ); // should be checked by CUhcd
EnterCriticalSection( &m_csPipeLock );
if (lpbHalted)
*lpbHalted = m_fIsHalted;
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CPipe(%s)::IsPipeHalted, *lpbHalted = %d, returning HCD_REQUEST_STATUS %d\n"), GetPipeType(), *lpbHalted, requestOK) );
return requestOK;
}
// ******************************************************************
// Scope: public
void CPipe::ClearHaltedFlag( void )
//
// Purpose: Clears the pipe is halted flag
//
// Parameters: None
//
// Returns: Nothing
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CPipe(%s)::ClearHaltedFlag\n"), GetPipeType() ) );
EnterCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_WARNING && !m_fIsHalted, (TEXT("CPipe(%s)::ClearHaltedFlag - warning! Called on non-stalled pipe\n"), GetPipeType()) );
m_fIsHalted = FALSE;
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CPipe(%s)::ClearHaltedFlag\n"), GetPipeType()) );
}
// ******************************************************************
// Scope: public
CQueuedPipe::CQueuedPipe( IN const LPCUSB_ENDPOINT_DESCRIPTOR lpEndpointDescriptor,
IN const BOOL fIsLowSpeed,IN const BOOL fIsHighSpeed,
IN const UCHAR bDeviceAddress,
IN const UCHAR bHubAddress,IN const UCHAR bHubPort,
IN CEhcd *const pCEhcd)
//
// Purpose: Constructor for CQueuedPipe
//
// Parameters: See CPipe::CPipe
//
// Returns: Nothing
//
// Notes: Do not modify static variables here!!
// ******************************************************************
: CPipe( lpEndpointDescriptor, fIsLowSpeed,fIsHighSpeed, bDeviceAddress,bHubAddress,bHubPort, pCEhcd ) // constructor for base class
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CQueuedPipe::CQueuedPipe\n")) );
m_pPipeQHead = NULL;
m_pUnQueuedTransfer=NULL; // ptr to last transfer in queue
m_pQueuedTransfer=NULL;
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CQueuedPipe::CQueuedPipe\n")) );
}
// ******************************************************************
// Scope: public virtual
CQueuedPipe::~CQueuedPipe( )
//
// Purpose: Destructor for CQueuedPipe
//
// Parameters: None
//
// Returns: Nothing
//
// Notes: Do not modify static variables here!!
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CQueuedPipe::~CQueuedPipe\n")) );
// queue should be freed via ClosePipe before calling destructor
EnterCriticalSection( &m_csPipeLock );
ASSERT(m_pPipeQHead == NULL);
ASSERT(m_pUnQueuedTransfer==NULL); // ptr to last transfer in queue
ASSERT(m_pQueuedTransfer==NULL);
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CQueuedPipe::~CQueuedPipe\n")) );
}
// ******************************************************************
// Scope: public (implements CPipe::AbortTransfer = 0)
HCD_REQUEST_STATUS CQueuedPipe::AbortTransfer(
IN const LPTRANSFER_NOTIFY_ROUTINE lpCancelAddress,
IN const LPVOID lpvNotifyParameter,
IN LPCVOID lpvCancelId )
//
// Purpose: Abort any transfer on this pipe if its cancel ID matches
// that which is passed in.
//
// Parameters: lpCancelAddress - routine to callback after aborting transfer
//
// lpvNotifyParameter - parameter for lpCancelAddress callback
//
// lpvCancelId - identifier for transfer to abort
//
// Returns: requestOK if transfer aborted
// requestFailed if lpvCancelId doesn't match currently executing
// transfer, or if there is no transfer in progress
//
// Notes:
// ******************************************************************
{
DEBUGMSG( ZONE_TRANSFER, (TEXT("+CQueuedPipe(%s)::AbortTransfer - lpvCancelId = 0x%x\n"), GetPipeType(), lpvCancelId) );
HCD_REQUEST_STATUS status = requestFailed;
EnterCriticalSection( &m_csPipeLock );
CQTransfer * pCurTransfer = m_pUnQueuedTransfer;
CQTransfer * pPrevTransfer= NULL;
while (pCurTransfer && pCurTransfer->GetSTransfer().lpvCancelId != lpvCancelId ) {
pPrevTransfer = pCurTransfer;
pCurTransfer= ( CQTransfer *)pCurTransfer->GetNextTransfer();
};
if (pCurTransfer) { // Found Transfer that not queue yet.
pCurTransfer->AbortTransfer();
if (pPrevTransfer)
pPrevTransfer->SetNextTransfer(pCurTransfer->GetNextTransfer());
else
m_pUnQueuedTransfer = ( CQTransfer *)pCurTransfer->GetNextTransfer();
}
else {
if (m_pQueuedTransfer!=NULL && m_pQueuedTransfer->GetSTransfer().lpvCancelId == lpvCancelId ) {
// This is one in the schdeule
RemoveQHeadFromQueue();;
m_pQueuedTransfer->AbortTransfer();
GetQHead()->InvalidNextTD();
Sleep(2);// this sleep is for Interrupt Pipe;
pCurTransfer = m_pQueuedTransfer;
m_pQueuedTransfer = NULL;
InsertQHeadToQueue() ;
}
else
ASSERT(FALSE);
};
if (pCurTransfer) {
pCurTransfer->DoneTransfer();
if ( lpCancelAddress ) {
__try { // calling the Cancel function
( *lpCancelAddress )( lpvNotifyParameter );
} __except( EXCEPTION_EXECUTE_HANDLER ) {
DEBUGMSG( ZONE_ERROR, (TEXT("CQueuedPipe::AbortTransfer - exception executing cancellation callback function\n")) );
}
}
status = requestOK;
delete pCurTransfer;
if (m_pQueuedTransfer == NULL ) { // This queue is no longer active. re-activate it.
ScheduleTransfer();
}
}
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_TRANSFER, (TEXT("-CQueuedPipe(%s)::AbortTransfer - lpvCancelId = 0x%x, returning HCD_REQUEST_STATUS %d\n"), GetPipeType(), lpvCancelId, status) );
return status;
}
// ******************************************************************
// Scope: public
void CQueuedPipe::ClearHaltedFlag( void )
//
// Purpose: Clears the pipe is halted flag
//
// Parameters: None
//
// Returns: Nothing
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CQueuedPipe(%s)::ClearHaltedFlag\n"), GetPipeType() ) );
EnterCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_WARNING && !m_fIsHalted, (TEXT("CQueuedPipe(%s)::ClearHaltedFlag - warning! Called on non-stalled pipe\n"), GetPipeType()) );
m_fIsHalted = FALSE;
m_pPipeQHead->ResetOverlayDataToggle();
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CQueuedPipe(%s)::ClearHaltedFlag\n"), GetPipeType()) );
}
// ******************************************************************
// Scope: private
void CQueuedPipe::AbortQueue( void )
//
// Purpose: Abort the current transfer (i.e., queue of TDs).
//
// Parameters: pQH - pointer to Queue Head for transfer to abort
//
// Returns: Nothing
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -