阅读:1483回复:1
USB等时传输的问题(急!!!)
各位大侠
小弟遇到棘手的问题了,请大侠帮忙,万分感谢!!! 在USB驱动中做等时传输时(我以Driver Studio中的例子usbisoch做了一些小的修改),在开始一段时间里可以传输正确,但过了一段时间后,提交IRP时返回的结果是STATUS_UNSUCCESSFUL, 而且之后好像就不再继续读了。 我把代码贴在下面: 基本上都是例子中的代码。其中,StartIsocReads 在 OnStartDevice() 之后就调用。 NTSTATUS UsbDriverDevice::StartIsocReads() { NTSTATUS status; for (int i=0; i<ISOC_NUM_READ_URBS; i++) { UCHAR *p = new (NonPagedPool) UCHAR[ISOC_URB_DATA_SIZE]; ASSERT(p); if ( !p ) break; PURB pUrb = m_Endpoint2IN.BuildIsochronousTransfer( ISOC_NUM_PACKETS_PER_URB, // # packets ISOC_PACKET_SIZE, // packet size TRUE, // bIn TRUE, // bASAP USBD_ISO_START_FRAME_RANGE,// Start Frame p, // pBuffer ISOC_URB_DATA_SIZE // Length ); ASSERT(pUrb); if ( !pUrb ) { delete p; break; } // Do not get an error on short or zero length packets pUrb->UrbIsochronousTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK; PISOC_CONTEXT pContext = new (NonPagedPool) ISOC_CONTEXT; ASSERT(pContext); if ( !pContext ) { delete pUrb; delete p; break; } // Create the accompanying IRP once, since the kernel // does not like us deleting and allocating IRPs // on every completion routine. //CCHAR stackSize = m_Usb.StackRequirement() + 1; CCHAR stackSize = m_Lower.StackRequirement() + 1; PIRP pIrp = IoAllocateIrp(stackSize, FALSE); pContext->pNext = m_pReadContexts; pContext->bUsed = TRUE; pContext->pDev = this; pContext->pIrp = pIrp; pContext->pUrb = pUrb; pContext->pData = p; pContext->pMdl = NULL; m_pReadContexts = pContext; IncrementOutstandingRequestCount(); status = QueueIsocRead(pContext); if ( !NT_SUCCESS(status) ) break; } if ( i != ISOC_NUM_READ_URBS ) { t << "StartReads() allocation FAILURE!\n"; return STATUS_INSUFFICIENT_RESOURCES; } return STATUS_SUCCESS; } NTSTATUS UsbDriverDevice::QueueIsocRead(PISOC_CONTEXT pContext) { NTSTATUS status; _URB_HEADER *pUHdr = (_URB_HEADER *)pContext->pUrb; _URB_ISOCH_TRANSFER *pIsoc = &pContext->pUrb->UrbIsochronousTransfer; pUHdr->UsbdDeviceHandle = NULL; pUHdr->UsbdFlags = 0; pIsoc->TransferBufferLength = ISOC_URB_DATA_SIZE; pIsoc->TransferBufferMDL = NULL; pIsoc->StartFrame = 0; memset(&pIsoc->hca, 0, sizeof(_URB_HCD_AREA)); status = m_Endpoint2IN.SubmitUrb( pContext->pIrp, pContext->pUrb, LinkTo(UsbIsocReadComplete), pContext ); if ( !NT_SUCCESS(status) ) { t << "Submission of Isoc Read URB FAILED (status=" << (ULONG)status << ")!\n"; } return status; } NTSTATUS UsbDriverDevice::UsbIsocReadComplete(KIrp I, PISOC_CONTEXT pContext) { NTSTATUS status; if ( m_State.m_StopPending || m_State.m_RemovePending || m_State.m_Removed || m_State.m_SurpriseRemoval ) { // Do not re-submit this URB pContext->bUsed = FALSE; DecrementOutstandingRequestCount(); return STATUS_MORE_PROCESSING_REQUIRED; } if ( !NT_SUCCESS(I.Status()) ) { // URB submission FAILED! t << "Isoc Read IRP FAILED (status="<< (ULONG)I.Status() << ")!\n"; pContext->bUsed = FALSE; DecrementOutstandingRequestCount(); return STATUS_MORE_PROCESSING_REQUIRED; } // If we have nowhere to put its data, just re-cycle this buffer. if ( !m_pReadFifo ) { status = QueueIsocRead(pContext); return STATUS_MORE_PROCESSING_REQUIRED; } _URB_ISOCH_TRANSFER *pIsoc = &pContext->pUrb->UrbIsochronousTransfer; PUSBD_ISO_PACKET_DESCRIPTOR ppd; UCHAR temp[ISOC_PACKET_SIZE]; BOOLEAN bOverflow = FALSE; ULONG dwDataCount = 0; // Take data from URB completion, and copy it into our FIFO // If our FIFO fills up, then clear out enough for the new data! for (int i=0; i<ISOC_NUM_PACKETS_PER_URB; i++) { ppd = &pIsoc->IsoPacket; // We ignore zero length packets in the data stream for now. // You might want to have a zero length packet signal the // end of a large block of data. If so, then you need to // handle a zero length packet arriving at any time! if ( USBD_SUCCESS(ppd->Status) && (ppd->Length > 0) ) { PUCHAR p = ((UCHAR *)pIsoc->TransferBuffer) + ppd->Offset; m_pReadFifo->Lock(); if ( ISOC_PACKET_SIZE > m_pReadFifo->NumberOfItemsAvailableForWrite() ) { bOverflow = TRUE; // Discard oldest data from the Read FIFO m_pReadFifo->Read(temp, ppd->Length); } m_pReadFifo->Write(p, ppd->Length); m_pReadFifo->Unlock(); dwDataCount += ppd->Length; } } if ( bOverflow ) { t << "Read FIFO overflow!\n"; m_readOverflow++; } if ( (dwDataCount > 0)) t << "Isoc Read received " << dwDataCount << " bytes\n"; // Resubmit this URB. status = QueueIsocRead(pContext); return STATUS_MORE_PROCESSING_REQUIRED; } 红色部分就是我的问题所在部分。 求求大侠们了 这两天都郁闷得做不下去了。 谢谢,谢谢!! |
|
沙发#
发布于:2007-09-30 12:41
|
|