?? rwusb.c
字號:
0 );
ASSERT( pRcvBuf->Irp == NULL);
}
} // if pending
} // for
DEBUGMSG( DBG_FUNC, (" -CancelPendingReadIo()\n"));
return (BOOLEAN) cRes;
}
BOOLEAN
CancelPendingWriteIo(
IN PUSB_DEVICE DeviceExt
)
/*++
Return Value:
TRUE if cancelled any, else FALSE
--*/
{
PUSB_DEVICE device = DeviceExt;
BOOLEAN cRes = FALSE;
NTSTATUS timeStat;
PUSB_CONTEXT pCont;
ULONGLONG thisContext; //make ptr arithmetic 64-bit compatible
int i;
DEBUGMSG( DBG_FUNC, (" +CancelPendingWriteIo()\n"));
ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
//
// Free all resources for the SEND buffer queue.
//
thisContext = (ULONGLONG) device->pSendContexts;
for ( i= 0; i < NUM_SEND_CONTEXTS; i++ ) {
pCont = (PUSB_CONTEXT)thisContext;
if( TRUE == pCont->fInUse ) {
// Get the USB_CONTEXT and cancel it's IRP; the completion routine will itself
// remove it from the HeadPendingSendList and NULL out HeadPendingSendList
// when the last IRP on the list has been cancelled; that's how we exit this loop
//
ASSERT( NULL != pCont->Irp );
DEBUGMSG( DBG_WARN, (" CancelPendingWriteIo() about to CANCEL a write IRP!\n"));
// Completion routine ( USBCompleteWrite() )will free irps, mdls, buffers, etc as well
cRes = IoCancelIrp( pCont->Irp );
DEBUGCOND( DBG_ERR, !cRes, (" CancelPendingWriteIo() COULDN'T CANCEL IRP! 0x%x\n", pCont->Irp ));
DEBUGCOND( DBG_FUNC, cRes, (" CancelPendingWriteIo() CANCELLED IRP SUCCESS! 0x%x\n\n", pCont->Irp));
//
// Sleep 200 microsecs to give cancellation time to work
//
NdisMSleep(200);
}
thisContext += sizeof( USB_CONTEXT );
} // for
DEBUGMSG( DBG_FUNC, (" -CancelPendingWriteIo()\n"));
return (BOOLEAN) cRes;
}
BOOLEAN
CancelPendingControlIo(
IN PUSB_DEVICE DeviceExt,
IN PIRP IrpToCancel,
IN PKEVENT EventToClear
)
/*++
Return Value:
TRUE if cancelled any, else FALSE
--*/
{
PUSB_DEVICE device = DeviceExt;
BOOLEAN cRes = FALSE;
NTSTATUS timeStat;
DEBUGMSG( DBG_FUNC, (" +CancelPendingControlIo()\n"));
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL );
//置于非信號態(tài)
KeClearEvent( EventToClear );
if(IrpToCancel)
cRes = IoCancelIrp( IrpToCancel ); //CancelPendingControlIo()
DEBUGCOND( DBG_ERR, !cRes, (" CancelPendingControlIo() COULDN'T CANCEL IRP!\n"));
DEBUGCOND( DBG_FUNC, cRes, (" CancelPendingControlIo() CANCELLED IRP SUCCESS!\n"));
if ( cRes ) {
timeStat = MyKeWaitForSingleObject(
device,
EventToClear,
NULL, // irp to cancel; we did it above already, so pass NULL
0 );
}
DEBUGMSG( DBG_FUNC, (" -CancelPendingControlIo()\n"));
return (BOOLEAN) cRes;
}
NTSTATUS
CallUSBD(
IN PUSB_DEVICE Device,
IN PURB Urb
)
/*++
Routine Description:
Passes a URB to the USBD class driver
The client device driver passes USB request block (URB) structures
to the class driver as a parameter in an IRP with Irp->MajorFunction
set to IRP_MJ_INTERNAL_DEVICE_CONTROL and the next IRP stack location
Parameters.DeviceIoControl.IoControlCode field set to
IOCTL_INTERNAL_USB_SUBMIT_URB.
Arguments:
DeviceExt - pointer to the dev ext
Urb - pointer to an already-formatted Urb request block
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus;
PDEVICE_OBJECT urbTargetDev;
PIO_STACK_LOCATION nextStack;
PMDL mdl;
DEBUGMSG( DBG_FUNC,(" +CallUSBD\n"));
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL );
ASSERT( Device );
ASSERT( NULL == ((PUSB_INFO) Device->pUsbInfo)->IrpSubmitUrb ); //shouldn't be multiple control calls pending
//
// issue a synchronous request (we'll wait )
urbTargetDev = Device->pUsbDevObj;
ASSERT( urbTargetDev );
// make an irp sending to usbhub?用IoAllocateIrp來創(chuàng)建Irp其StackSize均要+1
((PUSB_INFO) Device->pUsbInfo)->IrpSubmitUrb =
IoAllocateIrp( (CCHAR)(Device->pUsbDevObj->StackSize +1), FALSE );
if ( NULL == ((PUSB_INFO) Device->pUsbInfo)->IrpSubmitUrb )
{
DEBUGMSG(DBG_ERR, (" CallUsbd failed to alloc IRP\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
//STATUS_NOT_SUPPORTED:
// The miniclass driver cannot distinguish the target condition
((PUSB_INFO) Device->pUsbInfo)->IrpSubmitUrb->IoStatus.Status = STATUS_NOT_SUPPORTED;
((PUSB_INFO) Device->pUsbInfo)->IrpSubmitUrb->IoStatus.Information = 0;
//
// Call the class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
nextStack = IoGetNextIrpStackLocation(((PUSB_INFO) Device->pUsbInfo)->IrpSubmitUrb);
ASSERT(nextStack != NULL);
//
// pass the URB to the USB driver stack
//
nextStack->Parameters.Others.Argument1 = Urb;
//
// pass the URB to the USB driver stack
//
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.Others.Argument1 = Urb;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
IoSetCompletionRoutine(
((PUSB_INFO) Device->pUsbInfo)->IrpSubmitUrb, // irp to use
UsbIoCompleteControl, // routine to call when irp is done
DEV_TO_CONTEXT(Device), // context to pass routine
TRUE, // call on success
TRUE, // call on error
TRUE); // call on cancel
KeClearEvent(&Device->EventUrb);
UsbIncIoCount( Device );
ntStatus = IoCallDriver( urbTargetDev, ((PUSB_INFO) Device->pUsbInfo)->IrpSubmitUrb );
DEBUGMSG( DBG_OUT,("CallUSBD () return from IoCallDriver USBD %x\n", ntStatus));
if ((ntStatus == STATUS_PENDING) || (ntStatus == STATUS_SUCCESS))
{ //wait for STATUS_PENDING
// wait, but dump out on timeout
if (ntStatus == STATUS_PENDING)
{
ntStatus = MyKeWaitForSingleObject( Device, &Device->EventUrb, NULL, 0 );
if ( ntStatus == STATUS_TIMEOUT )
{
DEBUGMSG( DBG_ERR,("CallUSBD () TIMED OUT! return from IoCallDriver USBD %x\n", ntStatus));
CancelPendingControlIo( Device, ((PUSB_INFO) Device->pUsbInfo)->IrpSubmitUrb, &Device->EventUrb );
}
}
}
else
{
DEBUGMSG( DBG_ERR, ("CallUSBD IoCallDriver FAILED(%x)\n",ntStatus));
}
DEBUGMSG( DBG_OUT,("CallUSBD () URB status = %x IRP status = %x\n",
Urb->UrbHeader.Status, ntStatus ));
done:
((PUSB_INFO) Device->pUsbInfo)->IrpSubmitUrb = NULL;
DEBUGCOND( DBG_ERR, !NT_SUCCESS( ntStatus ), ("exit CallUSBD FAILED (%x)\n", ntStatus));
DEBUGMSG( DBG_FUNC,(" -CallUSBD\n"));
return ntStatus;
}
/*****************************************************************************
*
* Function: UsbIoCompleteControl
*
* Synopsis: General completetion routine just to insure cancel-ability of control calls
* and keep track of pending irp count
*
* Arguments: pUsbDevObj - pointer to the device object which
* completed the irp
* pIrp - the irp which was completed by the device
* object
* Context - dev ext
*
* Returns: STATUS_MORE_PROCESSING_REQUIRED - allows the completion routine
* (IofCompleteRequest) to stop working on the irp.
*
* This routine is called (by the io manager) in IRQL DISPATCH_LEVEL.
*
*****************************************************************************/
NTSTATUS
UsbIoCompleteControl(
IN PDEVICE_OBJECT pUsbDevObj,
IN PIRP pIrp,
IN PVOID Context
)
{
PUSB_DEVICE device;
NTSTATUS status;
DEBUGMSG(DBG_FUNC, ("+UsbIoCompleteControl\n"));
//
// The context given to IoSetCompletionRoutine is simply the the ir
// device object pointer.
//
device = CONTEXT_TO_DEV(Context);
status = pIrp->IoStatus.Status;
switch (status)
{
case STATUS_SUCCESS:
DEBUGMSG(DBG_OUT, (" UsbIoCompleteControl STATUS_SUCCESS\n"));
break; // STATUS_SUCCESS
case STATUS_TIMEOUT:
DEBUGMSG(DBG_ERR, (" UsbIoCompleteControl STATUS_TIMEOUT\n"));
break;
case STATUS_PENDING:
DEBUGMSG(DBG_ERR, (" UsbIoCompleteControl STATUS_PENDING\n"));
break;
case STATUS_DEVICE_DATA_ERROR:
// can get during shutdown
DEBUGMSG(DBG_ERR, (" UsbIoCompleteControl STATUS_DEVICE_DATA_ERROR\n"));
break;
case STATUS_UNSUCCESSFUL:
DEBUGMSG(DBG_ERR, (" UsbIoCompleteControl STATUS_UNSUCCESSFUL\n"));
break;
case STATUS_INSUFFICIENT_RESOURCES:
DEBUGMSG(DBG_ERR, (" UsbIoCompleteControl STATUS_INSUFFICIENT_RESOURCES\n"));
break;
case STATUS_INVALID_PARAMETER:
DEBUGMSG(DBG_ERR, (" UsbIoCompleteControl STATUS_INVALID_PARAMETER\n"));
break;
case STATUS_CANCELLED:
DEBUGMSG(DBG_ERR, (" UsbIoCompleteControl STATUS_CANCELLED\n"));
break;
case STATUS_DEVICE_NOT_CONNECTED:
// can get during shutdown
DEBUGMSG(DBG_ERR, (" UsbIoCompleteControl STATUS_DEVICE_NOT_CONNECTED\n"));
break;
case STATUS_DEVICE_POWER_FAILURE:
// can get during shutdown
DEBUGMSG(DBG_ERR, (" UsbIoCompleteControl STATUS_DEVICE_POWER_FAILURE\n"));
break;
default:
DEBUGMSG(DBG_ERR, (" UsbIoCompleteControl UNKNOWN WEIRD STATUS = 0x%x, dec %d\n",status,status ));
//ASSERT( 0 );
break;
}
UsbDecIoCount( device ); //we track pending irp count
if ( pIrp == ((PUSB_INFO) device->pUsbInfo)->IrpSubmitUrb )
{
ASSERT( NULL != ((PUSB_INFO) device->pUsbInfo)->IrpSubmitUrb );
IoFreeIrp( ((PUSB_INFO) device->pUsbInfo)->IrpSubmitUrb );
device->StatusControl = status; // save status because can't use irp after completion routine is hit!
KeSetEvent(&device->EventUrb, 0, FALSE); //signal we're done
}
else
{
DEBUGMSG( DBG_ERR, (" UsbIoCompleteControl UNKNOWN IRP\n"));
ASSERT( 0 );
}
DEBUGCOND(DBG_ERR, !( NT_SUCCESS( status ) ), ("UsbIoCompleteControl BAD status = 0x%x\n", status));
DEBUGMSG(DBG_FUNC, ("-UsbIoCompleteControl\n"));
// We return STATUS_MORE_PROCESSING_REQUIRED so that the completion
// routine (IofCompleteRequest) will stop working on the irp.
//
status = STATUS_MORE_PROCESSING_REQUIRED;
return status;
}
//******************************************************************************
//
// ResetPipe()
//
// This will reset the host pipe to Data0 and should also reset the device
// endpoint to Data0 for Bulk and Interrupt pipes by issuing a Clear_Feature
// Endpoint_Stall to the device endpoint.
//
// Must be called at IRQL PASSIVE_LEVEL
//
//******************************************************************************
NTSTATUS
ResetPipe (
IN PUSB_DEVICE Device,
IN HANDLE Pipe
)
{
PURB urb;
NTSTATUS ntStatus;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -