📄 pnp.c
字号:
break;
case IRP_MN_STOP_DEVICE:
//
// After the start IRP has been sent to the lower driver object, the
// bus may NOT send any more IRPS down ``touch'' until another START
// has occured.
// What ever access is required must be done before the Irp is passed
// on.
//
if (deviceExtension->Started) {
Print(deviceExtension, DBG_PNP_INFO,
("Cancelling and stopping detection for stop\n"));
deviceExtension->Started = FALSE;
//
// Cancel the read and stop detection
//
IoCancelIrp(deviceExtension->ReadIrp);
SerialMouseStopDetection(deviceExtension);
}
//
// We don't need a completion routine so fire and forget.
//
skipIt = TRUE;
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_SURPRISE_REMOVAL:
SerialGGemoveDevice(deviceExtension, Irp);
skipIt = TRUE;
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_REMOVE_DEVICE:
//
// The PlugPlay system has dictacted the removal of this device. We
// have no choise but to detach and delete the device objecct.
// (If we wanted to express and interest in preventing this removal,
// we should have filtered the query remove and query stop routines.)
//
// Note! we might receive a remove WITHOUT first receiving a stop.
//
Print(deviceExtension, DBG_PNP_TRACE, ("enter RemoveDevice \n"));
deviceExtension->Removed = TRUE;
SerialGGemoveDevice(deviceExtension, Irp);
//
// Send on the remove IRP
//
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(deviceExtension->TopOfStack, Irp);
//
// Wait for the remove lock to free.
//
IoReleaseRemoveLockAndWait(&deviceExtension->RemoveLock, Irp);
//
// Free the associated memory.
//
IoFreeIrp(deviceExtension->ReadIrp);
deviceExtension->ReadIrp = NULL;
if (deviceExtension->DetectionIrp) {
IoFreeIrp(deviceExtension->DetectionIrp);
deviceExtension->DetectionIrp = NULL;
}
Print(deviceExtension, DBG_PNP_NOISE, ("remove and wait done\n"));
IoDetachDevice(deviceExtension->TopOfStack);
IoDeleteDevice(deviceExtension->Self);
return status;
case IRP_MN_QUERY_CAPABILITIES:
status = SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
Irp,
TRUE);
if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
stack->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK
= TRUE;
}
//
// status, Irp->IoStatus.Status set above
//
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_QUERY_PNP_DEVICE_STATE:
status = SerialMouseSendIrpSynchronously(deviceExtension->TopOfStack,
Irp,
TRUE);
//
// If the lower filter does not support this Irp, this is
// OK, we can ignore this error
//
if (status == STATUS_NOT_SUPPORTED ||
status == STATUS_INVALID_DEVICE_REQUEST) {
status = STATUS_SUCCESS;
}
if (NT_SUCCESS(status) && deviceExtension->RemovalDremoved) {
(PNP_DEVICE_STATE) Irp->IoStatus.Information |= PNP_DEVICE_REMOVED;
}
if (!NT_SUCCESS(status)) {
Print(deviceExtension, DBG_PNP_ERROR,
("error pending query pnp device state event (0x%x)\n",
status
));
}
//
// Irp->IoStatus.Information will contain the new i/o resource
// requirements list so leave it alone
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
case IRP_MN_QUERY_DEVICE_RELATIONS:
case IRP_MN_QUERY_INTERFACE:
case IRP_MN_QUERY_RESOURCES:
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
case IRP_MN_READ_CONFIG:
case IRP_MN_WRITE_CONFIG:
case IRP_MN_EJECT:
case IRP_MN_SET_LOCK:
case IRP_MN_QUERY_ID:
default:
skipIt = TRUE;
break;
}
if (skipIt) {
//
// Don't touch the irp...
//
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(deviceExtension->TopOfStack, Irp);
}
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
Print(deviceExtension, DBG_PNP_TRACE, ("PnP exit (%x)\n", status));
return status;
}
NTSTATUS
SerialMousePower (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
The power dispatch routine.
All we care about is the transition from a low D state to D0.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION stack;
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
POWER_STATE powerState;
POWER_STATE_TYPE powerType;
KEVENT event;
IO_STATUS_BLOCK iosb;
LARGE_INTEGER li;
PAGED_CODE();
Print(deviceExtension, DBG_POWER_TRACE, ("Power Enter.\n"));
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
stack = IoGetCurrentIrpStackLocation(Irp);
powerType = stack->Parameters.Power.Type;
powerState = stack->Parameters.Power.State;
status = IoAcquireRemoveLock(&deviceExtension->RemoveLock, Irp);
if (!NT_SUCCESS(status)) {
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
switch (stack->MinorFunction) {
case IRP_MN_WAIT_WAKE:
break;
case IRP_MN_SET_POWER:
//
// Let system power irps fall through
//
if (powerType == DevicePowerState &&
powerState.DeviceState != deviceExtension->PowerState) {
switch (powerState.DeviceState) {
case PowerDeviceD0:
//
// Transitioning from a low D state to D0
//
Print(deviceExtension, DBG_POWER_INFO,
("Powering up to PowerDeviceD0\n"));
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
deviceExtension->PoweringDown = FALSE;
deviceExtension->PowerState =
stack->Parameters.Power.State.DeviceState;
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp,
SerialMouseCompletionRoutine,
&event,
TRUE, // on success
TRUE, // on error
TRUE // on cancel
);
status = PoCallDriver(deviceExtension->TopOfStack, Irp);
//
// Wait for lower drivers to be done with the Irp
//
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL
);
status = Irp->IoStatus.Status;
}
if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
PoSetPowerState(DeviceObject, powerType, powerState);
status = SerialMouseStartDevice(deviceExtension,
Irp,
FALSE);
if (!NT_SUCCESS(status)) {
Print(deviceExtension, DBG_POWER_INFO,
("mouse not found on power up, 0x%x\n", status));
//
// The device has been removed or is not detectable
// after powering back up ... have serenum do the
// removal work
//
KeClearEvent(&event);
SerialMouseIoSyncInternalIoctl(
IOCTL_INTERNAL_SERENUM_REMOVE_SELF,
deviceExtension->TopOfStack,
&event,
&iosb
);
}
}
Irp->IoStatus.Status = status;
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
PoStartNextPowerIrp(Irp);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
case PowerDeviceD1:
case PowerDeviceD2:
case PowerDeviceD3:
deviceExtension->PoweringDown = TRUE;
// If a wait wake is pending against the mouse, keep it powered
//
if (deviceExtension->WaitWakePending) {
Print(deviceExtension, DBG_POWER_INFO,
("Ignoring power down for wait wake (-> D%d)\n",
powerState.DeviceState-1
));
break;
}
Print(deviceExtension, DBG_POWER_INFO,
("Powering down to PowerDeviceD%d\n",
powerState.DeviceState-1
));
//
// Acquire another reference to the lock so that the decrement
// in the cancel section of the completion routine will not fall
// to zero (and have the remlock think we are removed)
//
// status = IoAcquireRemoveLock(&deviceExtension->RemoveLock,
// deviceExtension->ReadIrp);
ASSERT(NT_SUCCESS(status));
deviceExtension->PowerState =
stack->Parameters.Power.State.DeviceState;
//
// Cancel the read irp so that it won't conflict with power up
// initialization (which involves some reads against the port)
//
IoCancelIrp(deviceExtension->ReadIrp);
//
// We don't want the powering down of the port to be confused
// with removal
//
SerialMouseStopDetection(deviceExtension);
//
// Power down the device by clearing RTS and waiting 150 ms
//
Print(deviceExtension, DBG_POWER_INFO, ("Clearing RTS...\n"));
KeInitializeEvent(&event, NotificationEvent, FALSE);
status = SerialMouseIoSyncIoctl(IOCTL_SERIAL_CLR_RTS,
deviceExtension->TopOfStack,
&event,
&iosb
);
if (NT_SUCCESS(status)) {
Print(deviceExtension, DBG_POWER_INFO, ("150ms wait\n"));
li = RtlConvertLongToLargeInteger(-PAUSE_150_MS);
KeDelayExecutionThread(KernelMode, FALSE, &li);
}
PoSetPowerState(DeviceObject,
stack->Parameters.Power.Type,
stack->Parameters.Power.State);
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
//
// Fire and forget
//
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCopyCurrentIrpStackLocationToNext(Irp);
PoStartNextPowerIrp(Irp);
return PoCallDriver(deviceExtension->TopOfStack, Irp);
}
}
break;
case IRP_MN_QUERY_POWER:
break;
default:
Print(deviceExtension, DBG_POWER_ERROR,
("Power minor (0x%x) is not handled\n", stack->MinorFunction));
}
//
// Must call the Po versions of these functions or bad things (tm) will happen!
//
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
status = PoCallDriver(deviceExtension->TopOfStack, Irp);
IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp);
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -