📄 cpipe.cpp
字号:
}
ASSERT(m_pArrayOfCSITD);
ASSERT(m_dwNumOfTDAvailable == NUM_OF_PRE_ALLOCATED_TD);
m_EndptBuget.period = (1<< ( bInterval-1));
}
m_EndptBuget.ep_type = isoch ;
m_EndptBuget.type= lpEndpointDescriptor->bDescriptorType;
m_EndptBuget.direction =(USB_ENDPOINT_DIRECTION_OUT(lpEndpointDescriptor->bEndpointAddress)?OUTDIR:INDIR);
m_EndptBuget.speed=(fIsHighSpeed?HSSPEED:(fIsLowSpeed?LSSPEED:FSSPEED));
m_bSuccess=pCEhcd->AllocUsb2BusTime(bHubAddress,bHubPort,&m_EndptBuget);
ASSERT(m_bSuccess);
if (m_bSuccess ) {
if (fIsHighSpeed) { // Update SMask and CMask for Slit Interrupt Endpoitt
m_bFrameSMask=pCEhcd->GetSMASK(&m_EndptBuget);
m_bFrameCMask=0;
}
else {
m_bFrameSMask=pCEhcd->GetSMASK(&m_EndptBuget);
m_bFrameCMask=pCEhcd->GetCMASK(&m_EndptBuget);
}
}
else {
ASSERT(FALSE);
}
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CIsochronousPipe::CIsochronousPipe\n")) );
}
// ******************************************************************
// Scope: public
CIsochronousPipe::~CIsochronousPipe( )
//
// Purpose: Destructor for CIsochronousPipe
//
// Parameters: None
//
// Returns: Nothing
//
// Notes: Do not modify static variables here!!
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CIsochronousPipe::~CIsochronousPipe\n")) );
// m_pWakeupTD should have been freed by the time we get here
if (m_bSuccess)
m_pCEhcd->FreeUsb2BusTime( m_bHubAddress, m_bHubPort,&m_EndptBuget);
ClosePipe();
if (m_pArrayOfCITD) {
for (m_dwNumOfTDAvailable=0;m_dwNumOfTDAvailable<NUM_OF_PRE_ALLOCATED_TD;m_dwNumOfTDAvailable++) {
if ( *(m_pArrayOfCITD + m_dwNumOfTDAvailable) !=NULL) {
(*(m_pArrayOfCITD + m_dwNumOfTDAvailable))->~CITD();
m_pCEhcd->GetPhysMem()->FreeMemory((PBYTE)*(m_pArrayOfCITD + m_dwNumOfTDAvailable),
m_pCEhcd->GetPhysMem()->VaToPa((PBYTE)*(m_pArrayOfCITD + m_dwNumOfTDAvailable)),
CPHYSMEM_FLAG_HIGHPRIORITY |CPHYSMEM_FLAG_NOBLOCK );
}
}
delete (m_pArrayOfCITD);
}
if (m_pArrayOfCSITD) {
for (m_dwNumOfTDAvailable=0;m_dwNumOfTDAvailable<NUM_OF_PRE_ALLOCATED_TD;m_dwNumOfTDAvailable++) {
if ( *(m_pArrayOfCSITD + m_dwNumOfTDAvailable) != NULL) {
(*(m_pArrayOfCSITD + m_dwNumOfTDAvailable))->~CSITD();
m_pCEhcd->GetPhysMem()->FreeMemory((PBYTE)*(m_pArrayOfCSITD + m_dwNumOfTDAvailable),
m_pCEhcd->GetPhysMem()->VaToPa((PBYTE)*(m_pArrayOfCSITD + m_dwNumOfTDAvailable)),
CPHYSMEM_FLAG_HIGHPRIORITY |CPHYSMEM_FLAG_NOBLOCK );
}
}
delete (m_pArrayOfCSITD);
}
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CIsochronousPipe::~CIsochronousPipe\n")) );
}
CITD * CIsochronousPipe::AllocateCITD( CITransfer * pTransfer)
{
EnterCriticalSection( &m_csPipeLock );
ASSERT(m_pArrayOfCITD!=NULL) ;
CITD * pReturn = NULL;
if (m_pArrayOfCITD!=NULL ) {
ASSERT(m_dwNumOfTDAvailable <= NUM_OF_PRE_ALLOCATED_TD);
for (DWORD dwIndex=m_dwNumOfTDAvailable;dwIndex!=0;dwIndex--) {
if ((pReturn = *(m_pArrayOfCITD + dwIndex -1))!=NULL) {
m_dwNumOfTDAvailable = dwIndex-1;
*(m_pArrayOfCITD + m_dwNumOfTDAvailable) = NULL;
pReturn->ReInit(pTransfer);
break;
}
}
}
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_WARNING && (pReturn==NULL) , (TEXT("CIsochronousPipe::AllocateCITD: return NULL, run out of pre-allocated ITD\r\n")) );
return pReturn;
}
CSITD * CIsochronousPipe::AllocateCSITD( CSITransfer * pTransfer,CSITD * pPrev)
{
EnterCriticalSection( &m_csPipeLock );
ASSERT(m_pArrayOfCSITD!=NULL) ;
CSITD * pReturn = NULL;
if (m_pArrayOfCSITD!=NULL ) {
ASSERT(m_dwNumOfTDAvailable <= NUM_OF_PRE_ALLOCATED_TD);
for (DWORD dwIndex=m_dwNumOfTDAvailable;dwIndex!=0;dwIndex--) {
if ((pReturn = *(m_pArrayOfCSITD + dwIndex -1))!=NULL) {
m_dwNumOfTDAvailable = dwIndex -1;
*(m_pArrayOfCSITD + m_dwNumOfTDAvailable) = NULL;
pReturn->ReInit(pTransfer,pPrev);
break;
}
}
}
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_WARNING && (pReturn==NULL) , (TEXT("CIsochronousPipe::AllocateCSITD: return NULL, run out of pre-allocated CITD\r\n")) );
return pReturn;
}
void CIsochronousPipe::FreeCITD(CITD * pITD)
{
EnterCriticalSection( &m_csPipeLock );
ASSERT(m_pArrayOfCITD!=NULL);
ASSERT(m_dwNumOfTDAvailable< NUM_OF_PRE_ALLOCATED_TD);
if (m_pArrayOfCITD && pITD && m_dwNumOfTDAvailable< NUM_OF_PRE_ALLOCATED_TD) {
ASSERT(*(m_pArrayOfCITD+m_dwNumOfTDAvailable)==NULL);
pITD->~CITD();
*(m_pArrayOfCITD+m_dwNumOfTDAvailable)= pITD;
m_dwNumOfTDAvailable ++;
}
LeaveCriticalSection( &m_csPipeLock );
}
void CIsochronousPipe::FreeCSITD(CSITD * pSITD)
{
EnterCriticalSection( &m_csPipeLock );
ASSERT(m_pArrayOfCSITD );
ASSERT(m_dwNumOfTDAvailable< NUM_OF_PRE_ALLOCATED_TD);
if (m_pArrayOfCSITD && pSITD && m_dwNumOfTDAvailable< NUM_OF_PRE_ALLOCATED_TD ) {
ASSERT(*(m_pArrayOfCSITD+m_dwNumOfTDAvailable)==NULL);
pSITD->~CSITD();
*(m_pArrayOfCSITD+m_dwNumOfTDAvailable)= pSITD;
m_dwNumOfTDAvailable ++;
}
LeaveCriticalSection( &m_csPipeLock );
}
// ******************************************************************
// Scope: public (Implements CPipe::OpenPipe = 0)
HCD_REQUEST_STATUS CIsochronousPipe::OpenPipe( void )
//
// Purpose: Inserting the necessary (empty) items into the
// schedule to permit future transfers
//
// Parameters: None
//
// Returns: requestOK if pipe opened successfuly
// requestFailed if pipe not opened
//
// Notes:
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE, (TEXT("+CIsochronousPipe::OpenPipe\n")) );
HCD_REQUEST_STATUS status = requestFailed;
m_pQueuedTransfer=NULL;
EnterCriticalSection( &m_csPipeLock );
DEBUGCHK( m_usbEndpointDescriptor.bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE &&
m_usbEndpointDescriptor.bLength >= sizeof( USB_ENDPOINT_DESCRIPTOR ) &&
(m_usbEndpointDescriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_ISOCHRONOUS );
m_dwLastValidFrame = 0;
m_pCEhcd->GetFrameNumber(&m_dwLastValidFrame);
// if this fails, someone is trying to open an already opened pipe
if ( m_pQueuedTransfer == NULL && m_bSuccess == TRUE) {
status = requestOK;
}
else
ASSERT(FALSE);
LeaveCriticalSection( &m_csPipeLock );
if (status == requestOK ) {
BOOL bReturn = m_pCEhcd->AddToBusyPipeList(this, TRUE);
ASSERT(bReturn == TRUE);
}
DEBUGMSG( ZONE_PIPE, (TEXT("-CIsochronousPipe::OpenPipe, returning HCD_REQUEST_STATUS %d\n"), status ) );
return status;
}
// ******************************************************************
// Scope: public (Implements CPipe::ClosePipe = 0)
HCD_REQUEST_STATUS CIsochronousPipe::ClosePipe( void )
//
// Purpose: Abort any transfers associated with this pipe, and
// remove its data structures from the schedule
//
// Parameters: None
//
// Returns: requestOK
//
// Notes:
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE, (TEXT("+CIsochronousPipe::ClosePipe\n")) );
m_pCEhcd->RemoveFromBusyPipeList( this );
EnterCriticalSection( &m_csPipeLock );
CIsochTransfer * pCurTransfer = m_pQueuedTransfer;
m_pQueuedTransfer = NULL;
while ( pCurTransfer ) {
pCurTransfer->AbortTransfer();
CIsochTransfer * pNext = (CIsochTransfer *)pCurTransfer ->GetNextTransfer();
delete pCurTransfer;
pCurTransfer = pNext;
}
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_PIPE, (TEXT("-CIsochronousPipe::ClosePipe\n")) );
return requestOK;
}
// ******************************************************************
// Scope: public (Implements CPipe::AbortTransfer = 0)
HCD_REQUEST_STATUS CIsochronousPipe::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("+CIsochronousPipe::AbortTransfer\n")));
HCD_REQUEST_STATUS status = requestFailed;
EnterCriticalSection( &m_csPipeLock );
// Find this transfer.
if (m_pQueuedTransfer!=NULL) {
CIsochTransfer * pCur=m_pQueuedTransfer;
CIsochTransfer * pPrev=NULL;
while (pCur!=NULL && (pCur ->GetSTransfer()).lpvCancelId != lpvCancelId) {
pPrev = pCur;
pCur =(CIsochTransfer * )pCur ->GetNextTransfer();
};
if (pCur!=NULL) { // We found it
if (pPrev!=NULL)
pPrev->SetNextTransfer(pCur->GetNextTransfer());
else // It is Locate at header
m_pQueuedTransfer = (CIsochTransfer * )m_pQueuedTransfer->GetNextTransfer();
pCur->AbortTransfer();
// Do not need call DoneTransfer here because AboutTransfer Called DoneTransfer already.
delete pCur;
if ( lpCancelAddress ) {
__try { // calling the Cancel function
( *lpCancelAddress )( lpvNotifyParameter );
} __except( EXCEPTION_EXECUTE_HANDLER ) {
DEBUGMSG( ZONE_ERROR, (TEXT("CIsochronousPipe::AbortTransfer - exception executing cancellation callback function\n")) );
}
}
status=requestOK;
}
}
LeaveCriticalSection( &m_csPipeLock );
return status;
}
// ******************************************************************
// Scope: public
HCD_REQUEST_STATUS CIsochronousPipe::IssueTransfer(
IN const UCHAR address,
IN LPTRANSFER_NOTIFY_ROUTINE const lpStartAddress,
IN LPVOID const lpvNotifyParameter,
IN const DWORD dwFlags,
IN LPCVOID const lpvControlHeader,
IN const DWORD dwStartingFrame,
IN const DWORD dwFrames,
IN LPCDWORD const aLengths,
IN const DWORD dwBufferSize,
IN_OUT LPVOID const lpvClientBuffer,
IN const ULONG paBuffer,
IN LPCVOID const lpvCancelId,
OUT LPDWORD const adwIsochErrors,
OUT LPDWORD const adwIsochLengths,
OUT LPBOOL const lpfComplete,
OUT LPDWORD const lpdwBytesTransferred,
OUT LPDWORD const lpdwError )
//
// Purpose: Issue a Transfer on this pipe
//
// Parameters: address - USB address to send transfer to
//
// OTHER PARAMS - see comment in CUhcd::IssueTransfer
//
// Returns: requestOK if transfer issued ok, else requestFailed
//
// Notes:
// ******************************************************************
{
DEBUGMSG( ZONE_TRANSFER, (TEXT("+CPipe(%s)::IssueTransfer, address = %d\n"), GetPipeType(), address) );
DWORD dwEarliestFrame=0;
m_pCEhcd->GetFrameNumber(&dwEarliestFrame);
dwEarliestFrame = max(m_dwLastValidFrame,dwEarliestFrame+MIN_ADVANCED_FRAME);
DWORD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -