阅读:1037回复:6
救命,一定给分
小弟是一绝对菜鸟,各位老大一定要帮忙。
小弟最近在做一USB驱动,win2000,DS生成。在进行读操作时,象实现异步读,当没有数据返回应用程序。读一次时,没有问题,应程序可以正常结束。当再执行一边应用程序时,退出应用程序死机,显示locked page。。。。,记不准了, NTSTATUS IPCDevice::Read(KIrp I) { t << "Entering IPCDevice::Read, " << I << EOL; // TODO: Check the incoming request. Replace "FALSE" in the following // line with a check that returns TRUE if the request is not valid. if (FALSE) // If (Request is invalid) { // Invalid parameter in the Read request I.Information() = 0; return I.PnpComplete(this, STATUS_INVALID_PARAMETER); } // Always ok to read 0 elements. if (I.ReadSize() == 0) { I.Information() = 0; return I.PnpComplete(this, STATUS_SUCCESS); } // Declare a memory object KMemory Mem(I.Mdl()); ULONG dwTotalSize = I.ReadSize(CURRENT); ULONG dwMaxSize = m_IPC_In.MaximumTransferSize(); // If the total requested read size is greater than the Maximum Transfer // Size for the Pipe, request to read only the Maximum Transfer Size since // the bus driver will fail an URB with a TransferBufferLength of greater // than the Maximum Transfer Size. if (dwTotalSize > dwMaxSize) { ASSERT(dwMaxSize); dwTotalSize = dwMaxSize; } t << "dwTotalSize=" << dwTotalSize << EOL; // Allocate a new context structure for Irp completion USB_COMPLETION_INFO* pCompInfo = new (NonPagedPool) USB_COMPLETION_INFO; if (pCompInfo == NULL) { I.Information() = 0; return I.PnpComplete(this, STATUS_INSUFFICIENT_RESOURCES); } // TODO: Select the correct pipe to read from // Create an URB to do actual Bulk read from the pipe PURB pUrb = m_IPC_In.BuildBulkTransfer( Mem, // Where is data coming from? dwTotalSize, // How much data to read? TRUE, // direction (TRUE = IN) NULL, // Link to next URB TRUE // Allow a short transfer ); t << "Already Build the URB." << EOL; if (pUrb == NULL) { t << "Already Build the URB but insufficient resources" << EOL; delete pCompInfo; I.Information() = 0; return I.PnpComplete(this, STATUS_INSUFFICIENT_RESOURCES); } // Initialize context structure pCompInfo->m_pClass = this; pCompInfo->m_pUrb = pUrb; // Set Cancel routine t << "Begin to set the cancel routine." << EOL; PVOID CI = InterlockedCompareExchangePointer( (PVOID*)&CurrentIrp(), PVOID( PIRP(I)), NULL); // Allow only one request at a time if ( CI != NULL ) return STATUS_DEVICE_BUSY; CancelSpinLock::Acquire(); if(I.WasCanceled()) { CancelSpinLock::Release(); delete pUrb; delete pCompInfo; return STATUS_CANCELLED; } I.SetCancelRoutine(LinkTo(Cancel)); CancelSpinLock::Release(); I.MarkPending(); // Submit the URB to our USB device m_IPC_In.SubmitUrb(I, pUrb, LinkTo(ReadComplete), pCompInfo, 0); return STATUS_PENDING; } NTSTATUS IPCDevice::ReadComplete(KIrp I, USB_COMPLETION_INFO* pContext) { // Normal completion routine code to propagate pending flag t << "Enter in ReadComplete routine" << EOL; /* Just handle the cases of ReadComplete routine in asyn way */ KIrp Current = CurrentIrp(); if (Current == NULL) { DecrementOutstandingRequestCount(); return STATUS_MORE_PROCESSING_REQUIRED; } CancelSpinLock::Acquire(); if (Current.WasCanceled()) { CancelSpinLock::Release(); // Deallocate Urb and context structure PURB pUrb = pContext->m_pUrb; delete pUrb; delete pContext; I.Information() = 0; DecrementOutstandingRequestCount(); return STATUS_CANCELLED; //return STATUS_MORE_PROCESSING_REQUIRED; } else { Current.SetCancelRoutine(NULL); CancelSpinLock::Release(); CurrentIrp() = NULL; } if (I.Status() != STATUS_SUCCESS) { NTSTATUS status = I.Status(); // Deallocate Urb and context structure PURB pUrb = pContext->m_pUrb; delete pUrb; delete pContext; Current.PnpComplete(this, status); DecrementOutstandingRequestCount(); return STATUS_MORE_PROCESSING_REQUIRED; } NTSTATUS status = I.Status(); PURB pUrb = pContext->m_pUrb; ULONG nBytesRead = 0; if ( NT_SUCCESS(status) ) { nBytesRead = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength; if (nBytesRead > 0) t << "Read() got " << nBytesRead<< " bytes from USB\n"; } // Deallocate Urb and context structure delete pUrb; delete pContext; // set returned count I.Information() = nBytesRead; // Plug and Play accounting DecrementOutstandingRequestCount(); // allow IRP completion processing return STATUS_SUCCESS; } 应用程序 OVERLAPPED overlp; ::memset(&overlp,0,sizeof(OVERLAPPED)); HANDLE hWait; hWait= ::CreateEvent(NULL,true,false,NULL); overlp.hEvent = hWait; buf = (char *) malloc(n); if (buf == NULL) { printf("Failed to allocate buffer for read"); Exit(1); } // Read data from driver printf("Reading from device - "); if(ReadFile(hDevice,buf,n,&nRead,&overlp) == false) { if(WaitForSingleObject(hWait,100) == WAIT_TIMEOUT) { CancelIo(hDevice); //AfxMessageBox("Wrong when reading data"); printf("Wrong when reading data\n"); } else { if(GetOverlappedResult(hDevice,&overlp,&nRead,FALSE)) { //handlling //ReadFile(hDevice, buf, n, &nRead, &overlp); printf("%d bytes read from device (%d requested).\n", nRead, n); // Print what was read i = 0; while(i < n) { j = min((i+26),n); for(; i < j; i++) { printf("%c, ", buf); } printf("\n"); } } } } 各位老大一定要帮忙,一定给分 |
|
沙发#
发布于:2004-03-04 13:58
try KIrp::SetCancelRoutine & KIrp::QueryIrp
如果你不清楚固件的协议,driver是无法写好的。 |
|
|
板凳#
发布于:2004-03-04 10:36
zmwk老兄,
我是希望在没有数据时,驱动会返回应用程序,进行其他的工作,并在超时后可以Cancel掉IRP或用其它的方法Complete掉IRP。固件应该没有问题,我手里有驱动可以完成对他的驱动,但只有.sys和.inf而没有源代码,而这个驱动的配置与我现在用的配置不一致,如果我想测试还需每次改变固件上的代码,很麻烦,因此想再写一个driver。 |
|
地板#
发布于:2004-03-04 10:13
看起来,不象是driver的问题。应该看看固件是否上发数据。否则会Pending的。看你写的application,应该说软件水平不错,但100ms的超时是否小了点?
另外,按一般习惯,读URB之前,应该发送一个Vendor Request什么的,通知设备上传数据。否则,下边怎么知道什么时候上传呢? 希望能帮到你。 |
|
|
地下室#
发布于:2004-03-03 16:41
认错人了,我刚开始做,且只是临时任务,所以没办法花太多精力。简直是没有功底,共同学习吧
|
|
5楼#
发布于:2004-03-03 16:33
bihaizhou大哥,我毕业设计(本科)的题目是“USB驱动程序设计”,我看你功底深厚,不知你能否帮我指条路,我该怎么学,我万分感激啊!
谢谢!谢谢! |
|
6楼#
发布于:2004-03-03 16:14
又试了一遍,是process has locked pages的错误
|
|