📄 umss.c
字号:
#if DBG
if ( gpDbg )
gpDbg->ResetPipeCount++;
#endif
UMSS_KdPrint( DBGLVL_DEFAULT,("UMSS_ResetPipe() SUCCESS, ntStatus =0x%x\n", ntStatus ));
}
RETURN(ntStatus, UMSS_ResetPipe);
}
LONG
UMSS_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
UMSS_TrapCond( DBGLVL_HIGH,( 0 > ioCount ) );
if (ioCount==1)
{
// trigger no pending io
KeSetEvent(
&deviceExtension->NoPendingIoEvent,
1,
FALSE
);
}
if (ioCount==0)
{
// trigger remove-device event
KeSetEvent(
&deviceExtension->RemoveEvent,
1,
FALSE
);
}
KeReleaseSpinLock (&deviceExtension->IoCountSpinLock, oldIrql);
UMSS_KdPrint( DBGLVL_HIGH,("Exit UMSS_DecrementIoCount() Pending io count = %x\n", ioCount));
return ioCount;
}
VOID
UMSS_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;
deviceExtension = DeviceObject->DeviceExtension;
UMSS_KdPrint( DBGLVL_HIGH,("Enter UMSS_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount));
KeAcquireSpinLock (&deviceExtension->IoCountSpinLock, &oldIrql);
InterlockedIncrement(&deviceExtension->PendingIoCount);
#if DBG
InterlockedIncrement(&gpDbg->PendingIoCount);
#endif
KeReleaseSpinLock (&deviceExtension->IoCountSpinLock, oldIrql);
UMSS_KdPrint( DBGLVL_HIGH,("Exit UMSS_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount));
}
BOOLEAN UMSS_GetDeviceProtocolFromRegistry(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Retrieves the device protocol to be used for the USB mass storage
device from the device's registry section.
Arguments:
DeviceObject - Device object for USB mass storage device.
Return Value:
TRUE if device protocol found in registry.
FALSE if device protocol not found in registry.
--*/
{
HANDLE RegistryHandle;
UCHAR DeviceProtocol;
RTL_QUERY_REGISTRY_TABLE paramTable[2];
PDEVICE_EXTENSION DeviceExtension;
ENTER(UMSS_GetDeviceProtocolFromRegistry);
DeviceExtension = DeviceObject->DeviceExtension;
if (NT_SUCCESS(IoOpenDeviceRegistryKey(
DeviceExtension->PhysicalDeviceObject,
PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_ALL,
&RegistryHandle) ) )
{
RtlZeroMemory (¶mTable[0], sizeof(paramTable));
paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[0].Name = L"DeviceProtocol";
paramTable[0].EntryContext = &DeviceProtocol;
paramTable[0].DefaultType = REG_BINARY;
paramTable[0].DefaultData = &DeviceProtocol;
paramTable[0].DefaultLength = sizeof(DeviceProtocol);
RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
(PCWSTR)RegistryHandle,
¶mTable[0],
NULL, // Context
NULL); // Environment
ZwClose(RegistryHandle);
DeviceExtension->DeviceProtocol = DeviceProtocol;
switch (DeviceProtocol)
{
case PROTOCOL_BULKONLY:
UMSS_KdPrint( DBGLVL_DEFAULT,("Protocol from registry - BULK ONLY\n"));
return TRUE;
case PROTOCOL_CBI:
UMSS_KdPrint( DBGLVL_DEFAULT,("Protocol from registry - CONTROL/BULK/INTERRUPT\n"));
return TRUE;
case PROTOCOL_CB:
UMSS_KdPrint( DBGLVL_DEFAULT,("Protocol from registry - CONTROL/BULK\n"));
return TRUE;
}
}
DeviceExtension->DeviceProtocol = PROTOCOL_UNDEFINED;
RETURN(FALSE, UMSS_GetDeviceProtocolFromRegistry);
}
BOOLEAN
UMSS_GetDeviceProtocolFromDescriptor(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Retrieves the device protocol to be used for the USB mass storage
device from the device's interface descriptor.
Arguments:
DeviceObject - Device object for USB mass storage device.
Return Value:
TRUE if valid device protocol found in descriptor.
FALSE if valid device protocol not found in descriptor.
--*/
{
ULONG DeviceProtocol;
PDEVICE_EXTENSION DeviceExtension;
ENTER(UMSS_GetDeviceProtocolFromDescriptor);
DeviceExtension = DeviceObject->DeviceExtension;
if (DeviceExtension->UsbInterface->Class == CLASS_MASS_STORAGE)
{
DeviceExtension->DeviceProtocol = DeviceExtension->UsbInterface->Protocol;
switch (DeviceExtension->DeviceProtocol)
{
case PROTOCOL_BULKONLY:
UMSS_KdPrint( DBGLVL_DEFAULT,("Protocol from descriptor - BULK ONLY\n"));
return TRUE;
case PROTOCOL_CBI:
UMSS_KdPrint( DBGLVL_DEFAULT,("Protocol from descriptor - CONTROL/BULK/INTERRUPT\n"));
return TRUE;
case PROTOCOL_CB:
UMSS_KdPrint( DBGLVL_DEFAULT,("Protocol from descriptor - CONTROL/BULK\n"));
return TRUE;
}
}
UMSS_KdPrint( DBGLVL_DEFAULT,("No protocol found in descriptor!\n"));
DeviceExtension->DeviceProtocol = PROTOCOL_UNDEFINED;
RETURN(FALSE, UMSS_GetDeviceProtocolFromDescriptor);
}
NTSTATUS
UMSS_GetPortStatus(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PULONG PortStatus
)
/*++
Routine Description:
Returns the status of the USB port that the device is plugged into.
Used to determine if the device is still attached.
Arguments:
DeviceObject - pointer to the physical device object (PDO)
PortStatus - pointer to ULONG that receives the port status
Return Value:
Result of the request for the port status.
--*/
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
ENTER(UMSS_GetPortStatus);
deviceExtension = DeviceObject->DeviceExtension;
//
// issue a synchronous request
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_GET_PORT_STATUS,
deviceExtension->TopOfStackDeviceObject, //Points to the next-lower driver's device object
NULL, // optional input bufer; none needed here
0, // input buffer len if used
NULL, // optional output bufer; none needed here
0, // output buffer len if used
TRUE, // If InternalDeviceControl is TRUE the target driver's Dispatch
// outine for IRP_MJ_INTERNAL_DEVICE_CONTROL or IRP_MJ_SCSI
// is called; otherwise, the Dispatch routine for
// IRP_MJ_DEVICE_CONTROL is called.
&event, // event to be signalled on completion
&ioStatus); // Specifies an I/O status block to be set when the request is completed the lower driver.
//
// Call the class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
nextStack = IoGetNextIrpStackLocation(irp);
UMSS_ASSERT(nextStack != NULL);
//
// pass the URB to the USB driver stack
//
nextStack->Parameters.Others.Argument1 = PortStatus;
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
UMSS_KdPrint( DBGLVL_MAXIMUM,("UMSS_GetPortStatus() return from IoCallDriver USBD %x\n", ntStatus));
if (ntStatus == STATUS_PENDING)
{
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
} else
{
ioStatus.Status = ntStatus;
}
UMSS_KdPrint( DBGLVL_MAXIMUM,("UMSS_GetPortStatus() status = %x irp status %x\n",
status, ioStatus.Status));
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
RETURN(ntStatus, UMSS_GetPortStatus);
}
NTSTATUS
UMSS_ResetParentPort(
IN IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Reset our parent port
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;
ENTER(UMSS_ResetParentPort);
deviceExtension = DeviceObject->DeviceExtension;
//
// issue a synchronous request
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_RESET_PORT,
deviceExtension->TopOfStackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, // internal ( use IRP_MJ_INTERNAL_DEVICE_CONTROL )
&event,
&ioStatus);
//
// Call the class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
nextStack = IoGetNextIrpStackLocation(irp);
UMSS_ASSERT(nextStack != NULL);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
UMSS_KdPrint( DBGLVL_DEFAULT,("UMSS_ResetParentPort() return from IoCallDriver USBD %x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
UMSS_KdPrint( DBGLVL_DEFAULT,("UMSS_ResetParentPort() Wait for single object\n"));
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
UMSS_KdPrint( DBGLVL_DEFAULT,("UMSS_ResetParentPort() Wait for single object, returned %x\n", status));
} else {
ioStatus.Status = ntStatus;
}
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
RETURN(ntStatus, UMSS_ResetParentPort);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -