📄 uscrusb.c
字号:
NT status code
--*/
{
NTSTATUS ntStatus;
PURB urb;
PDEVICE_EXTENSION deviceExtension;
deviceExtension = DeviceObject->DeviceExtension;
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetPipe() Reset Pipe %x\n", PipeInfo));
urb = USCR_ExAllocatePool(NonPagedPool,
sizeof(struct _URB_PIPE_REQUEST));
if (urb) {
urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
urb->UrbPipeRequest.PipeHandle =
PipeInfo->PipeHandle;
ntStatus = USCR_CallUSBD(DeviceObject, urb);
USCR_ExFreePool(urb);
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
if (!(NT_SUCCESS(ntStatus))) {
#if DBG
if ( gpDbg )
gpDbg->PipeErrorCount++;
#endif
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetPipe() FAILED, ntStatus =0x%x\n", ntStatus ));
}
else {
#if DBG
if ( gpDbg )
gpDbg->ResetPipeCount++;
#endif
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetPipe() SUCCESS, ntStatus =0x%x\n", ntStatus ));
}
return ntStatus;
}
LONG
USCR_DecrementIoCount(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
We keep a pending IO count ( extension->PendingIoCount ) in the device extension.
The first increment of this count is done on adding the device.
Subsequently, the count is incremented for each new IRP received and
decremented when each IRP is completed or passed on.
Transition to 'one' therefore indicates no IO is pending and signals
deviceExtension->NoPendingIoEvent. This is needed for processing
IRP_MN_QUERY_REMOVE_DEVICE
Transition to 'zero' signals an event ( deviceExtension->RemoveEvent )
to enable device removal. This is used in processing for IRP_MN_REMOVE_DEVICE
Arguments:
DeviceObject -- ptr to our FDO
Return Value:
deviceExtension->PendingIoCount
--*/
{
PDEVICE_EXTENSION deviceExtension;
LONG ioCount;
KIRQL oldIrql;
deviceExtension = DeviceObject->DeviceExtension;
KeAcquireSpinLock (&deviceExtension->IoCountSpinLock, &oldIrql);
ioCount = InterlockedDecrement(&deviceExtension->PendingIoCount);
#if DBG
InterlockedDecrement(&gpDbg->PendingIoCount);
#endif
USCR_TrapCond( DBGLVL_HIGH,( 0 > ioCount ) );
if (ioCount==1) {
// trigger no pending io
KeSetEvent(&deviceExtension->NoPendingIoEvent,
1,
FALSE);
//USCR_KdPrint( DBGLVL_DEFAULT,("Set NoPendingIoEvent\n"));
}
if (ioCount==0) {
// trigger remove-device event
KeSetEvent(&deviceExtension->RemoveEvent,
1,
FALSE);
}
KeReleaseSpinLock (&deviceExtension->IoCountSpinLock, oldIrql);
//USCR_KdPrint( DBGLVL_HIGH,("Exit USCR_DecrementIoCount() Pending io count = %x\n", ioCount));
return ioCount;
}
VOID
USCR_IncrementIoCount(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
We keep a pending IO count ( extension->PendingIoCount ) in the device extension.
The first increment of this count is done on adding the device.
Subsequently, the count is incremented for each new IRP received and
decremented when each IRP is completed or passed on.
Arguments:
DeviceObject -- ptr to our FDO
Return Value:
None
--*/
{
PDEVICE_EXTENSION deviceExtension;
KIRQL oldIrql;
LONG ioCount;
deviceExtension = DeviceObject->DeviceExtension;
//USCR_KdPrint( DBGLVL_MAXIMUM,("Enter USCR_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount));
KeAcquireSpinLock (&deviceExtension->IoCountSpinLock, &oldIrql);
ioCount = InterlockedIncrement(&deviceExtension->PendingIoCount);
//************************************************************
//see uscrpnp.c line 273. yanglq 2005-6-25
if(ioCount > 1)
{
KeClearEvent(&deviceExtension->NoPendingIoEvent);
//USCR_KdPrint( DBGLVL_DEFAULT,("Clear NoPendingIoEvent\n"));
}
//************************************************************
#if DBG
InterlockedIncrement(&gpDbg->PendingIoCount);
#endif
KeReleaseSpinLock (&deviceExtension->IoCountSpinLock, oldIrql);
//USCR_KdPrint( DBGLVL_HIGH,("Exit USCR_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount));
}
NTSTATUS
USCR_AbortPipes(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Called as part of sudden device removal handling.
Cancels any pending transfers for all open pipes.
If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
Also marks the pipe 'closed' in our saved configuration info.
Arguments:
Ptrs to our FDO
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PURB urb;
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
ULONG i;
PUSBD_INTERFACE_INFORMATION interface;
interface = deviceExtension->UsbInterface;
if(deviceExtension->OpenPipeCount)
{
for (i=0; i<interface->NumberOfPipes; i++) {
USCR_KdPrint( DBGLVL_HIGH,("USCR_AbortPipes() Aborting open Pipe %d\n", i));
urb = USCR_ExAllocatePool(NonPagedPool,
sizeof(struct _URB_PIPE_REQUEST));
if (urb) {
urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
urb->UrbPipeRequest.PipeHandle =
interface->Pipes[i].PipeHandle;
ntStatus = USCR_CallUSBD(DeviceObject, urb);
USCR_ExFreePool(urb);
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
USCR_KdPrint( DBGLVL_HIGH,("USCR_AbortPipes() FAILED urb alloc\n" ));
break;
}
if (!(NT_SUCCESS(ntStatus))) {
// if we failed, dump out
#if DBG
if ( gpDbg )
gpDbg->PipeErrorCount++;
#endif
break;
}
else {
deviceExtension->OpenPipeCount--;
#if DBG
if ( gpDbg )
gpDbg->AbortPipeCount++;
#endif
}
} // end, for all pipes
}
return ntStatus;
}
BOOLEAN
USCR_CanAcceptIoRequests(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Check device extension status flags;
Can't accept a new io request if device:
1) is removed,
2) has never been started,
3) is stopped,
4) has a remove request pending, or
5) has a stop device pending
Arguments:
DeviceObject - pointer to the device object for this instance of the 82930
device.
Return Value:
return TRUE if can accept new io requests, else FALSE
--*/
{
PDEVICE_EXTENSION deviceExtension;
BOOLEAN fCan = FALSE;
deviceExtension = DeviceObject->DeviceExtension;
//flag set when processing IRP_MN_REMOVE_DEVICE
if ( !deviceExtension->DeviceRemoved &&
// device must be started( enabled )
deviceExtension->DeviceStarted &&
// flag set when driver has answered success to IRP_MN_QUERY_REMOVE_DEVICE
!deviceExtension->RemoveDeviceRequested &&
// flag set when driver has answered success to IRP_MN_QUERY_STOP_DEVICE
!deviceExtension->StopDeviceRequested ){
fCan = TRUE;
}
USCR_KdPrintCond( DBGLVL_MAXIMUM, !fCan, ("**** FALSE return from USCR_CanAcceptIoRequests()!\n"));
return fCan;
}
NTSTATUS
USCR_ResetDevice(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Checks port status; if OK, return success and do no more;
If bad, attempt reset
Arguments:
DeviceObject - pointer to the device object for this instance of the 82930
device.
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus;
ULONG portStatus;
USCR_KdPrint(5,("Enter USCR_ResetDevice()\n"));
//
// Check the port state, if it is disabled we will need
// to re-enable it
//
ntStatus = USCR_GetPortStatus(DeviceObject, &portStatus);
if (NT_SUCCESS(ntStatus) && !(portStatus & USBD_PORT_ENABLED) &&
portStatus & USBD_PORT_CONNECTED) {
//
// port is disabled, attempt reset
//
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetDevice() will reset\n"));
ntStatus = USCR_ResetParentPort(DeviceObject);
}
return ntStatus;
}
NTSTATUS
USCR_GetPortStatus(
IN PDEVICE_OBJECT DeviceObject,
IN PULONG PortStatus
)
/*++
Routine Description:
returns the port status for our device
Arguments:
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
PDEVICE_EXTENSION deviceExtension;
USCR_KdPrint( DBGLVL_DEFAULT,("enter USCR_GetPortStatus\n"));
deviceExtension = DeviceObject->DeviceExtension;
*PortStatus = 0;
//
// issue a synchronous request
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
// IoBuildDeviceIoControlRequest allocates and sets up an IRP for a device control request
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_GET_PORT_STATUS,
deviceExtension->TopOfStackDeviceObject, //next-lower driver's device object, representing the target device.
NULL, // no input or output buffers
0,
NULL,
0,
TRUE, // internal ( use IRP_MJ_INTERNAL_DEVICE_CONTROL )
&event, // event to be signalled on completion ( we wait for it below )
&ioStatus);
//
// Call the class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
// IoGetNextIrpStackLocation gives a higher level driver access to the next-lower
// driver's I/O stack location in an IRP so the caller can set it up for the lower driver.
nextStack = IoGetNextIrpStackLocation(irp);
USCR_ASSERT(nextStack != NULL);
nextStack->Parameters.Others.Argument1 = PortStatus;
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_GetPortStatus() calling USBD port status api\n"));
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_GetPortStatus() return from IoCallDriver USBD %x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
USCR_KdPrint( DBGLVL_DEFAULT,("Wait for single object\n"));
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_GetPortStatus() Wait for single object, returned %x\n", status));
} else {
ioStatus.Status = ntStatus;
}
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_GetPortStatus() Port status = %x\n", *PortStatus));
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
USCR_KdPrint( DBGLVL_DEFAULT,("Exit USCR_GetPortStatus (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
USCR_ResetParentPort(
IN IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Reset the our parent port
Arguments:
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -