mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
373 lines
9.6 KiB
373 lines
9.6 KiB
/*
|
|
*************************************************************************
|
|
* File: PNP.C
|
|
*
|
|
* Module: HID1394.SYS
|
|
* HID (Human Input Device) minidriver for IEEE 1394 devices.
|
|
*
|
|
* Copyright (c) 1998 Microsoft Corporation
|
|
*
|
|
*
|
|
* Author: ervinp
|
|
*
|
|
*************************************************************************
|
|
*/
|
|
|
|
#include <wdm.h>
|
|
#include <hidport.h>
|
|
#include <1394.h>
|
|
|
|
#include "hid1394.h"
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, HIDT_PnP)
|
|
#pragma alloc_text(PAGE, HIDT_StartDevice)
|
|
#pragma alloc_text(PAGE, HIDT_StopDevice)
|
|
#pragma alloc_text(PAGE, HIDT_RemoveDevice)
|
|
#pragma alloc_text(PAGE, HIDT_AbortPendingRequests)
|
|
#endif
|
|
|
|
|
|
/*
|
|
************************************************************
|
|
* HIDT_PnP
|
|
************************************************************
|
|
*
|
|
* Process PnP IRPs sent to this device.
|
|
*
|
|
*/
|
|
NTSTATUS HIDT_PnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PIO_STACK_LOCATION irpSp;
|
|
PDEVICE_EXTENSION DeviceExtension;
|
|
|
|
PAGED_CODE();
|
|
|
|
DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
|
|
irpSp = IoGetCurrentIrpStackLocation (Irp);
|
|
|
|
switch(irpSp->MinorFunction){
|
|
|
|
case IRP_MN_START_DEVICE:
|
|
ntStatus = HIDT_StartDevice(DeviceObject);
|
|
break;
|
|
|
|
case IRP_MN_STOP_DEVICE:
|
|
ntStatus = HIDT_StopDevice(DeviceObject);
|
|
break;
|
|
|
|
case IRP_MN_REMOVE_DEVICE:
|
|
ntStatus = HIDT_RemoveDevice(DeviceObject);
|
|
break;
|
|
}
|
|
|
|
|
|
if (NT_SUCCESS(ntStatus)){
|
|
/*
|
|
* Our processing has succeeded.
|
|
* So pass this IRP down to the next driver.
|
|
*/
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
IoSetCompletionRoutine(Irp,
|
|
HIDT_PnpCompletion,
|
|
DeviceExtension, // context
|
|
TRUE,
|
|
TRUE,
|
|
TRUE );
|
|
ntStatus = IoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
|
|
}
|
|
else {
|
|
ASSERT(NT_SUCCESS(ntStatus));
|
|
Irp->IoStatus.Status = ntStatus;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
************************************************************
|
|
* HIDT_Power
|
|
************************************************************
|
|
*
|
|
* Process Power IRPs sent to this device.
|
|
*
|
|
*/
|
|
NTSTATUS HIDT_Power(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|
{
|
|
NTSTATUS status;
|
|
|
|
IoCopyCurrentIrpStackLocationToNext(Irp);
|
|
status = PoCallDriver(GET_NEXT_DEVICE_OBJECT(DeviceObject), Irp);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
************************************************************
|
|
* HIDT_StartDevice
|
|
************************************************************
|
|
*
|
|
*
|
|
*/
|
|
NTSTATUS HIDT_StartDevice(IN PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PDEVICE_EXTENSION DeviceExtension;
|
|
|
|
PAGED_CODE();
|
|
|
|
DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
|
|
DeviceExtension->DeviceState = DEVICE_STATE_STARTING;
|
|
DeviceExtension->NumPendingRequests = 0;
|
|
|
|
KeInitializeEvent( &DeviceExtension->AllRequestsCompleteEvent,
|
|
NotificationEvent,
|
|
FALSE);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
************************************************************
|
|
* HIDT_InitDevice
|
|
************************************************************
|
|
*
|
|
* Get the device information and attempt to initialize a configuration
|
|
* for a device. If we cannot identify this as a valid HID device or
|
|
* configure the device, our start device function is failed.
|
|
*
|
|
* Note: This function is called from the PnP completion routine,
|
|
* so it cannot be pageable.
|
|
*/
|
|
NTSTATUS HIDT_InitDevice(IN PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
|
|
|
|
// BUGBUG FINISH
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
/*
|
|
************************************************************
|
|
* HIDT_StopDevice
|
|
************************************************************
|
|
*
|
|
*
|
|
*/
|
|
NTSTATUS HIDT_StopDevice(IN PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
ULONG Size;
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PDEVICE_EXTENSION DeviceExtension;
|
|
|
|
PAGED_CODE();
|
|
|
|
DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
|
|
DeviceExtension->DeviceState = DEVICE_STATE_STOPPING;
|
|
|
|
/*
|
|
* Abort all pending IO on the device.
|
|
* We do an extra decrement here, which causes the
|
|
* NumPendingRequests to eventually go to -1, which causes
|
|
* AllRequestsCompleteEvent to get set.
|
|
* NumPendingRequests will get reset to 0 when we re-start.
|
|
*/
|
|
HIDT_AbortPendingRequests(DeviceObject);
|
|
HIDT_DecrementPendingRequestCount(DeviceExtension);
|
|
KeWaitForSingleObject( &DeviceExtension->AllRequestsCompleteEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL );
|
|
|
|
|
|
// BUGBUG FINISH - select NULL configuration
|
|
|
|
|
|
if (!NT_SUCCESS(ntStatus)){
|
|
/*
|
|
* We will not pass this IRP down,
|
|
* so our completion routine will not set the device's
|
|
* state to DEVICE_STATE_STOPPED; so set it here.
|
|
*/
|
|
ASSERT(NT_SUCCESS(ntStatus));
|
|
DeviceExtension->DeviceState = DEVICE_STATE_STOPPED;
|
|
}
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
************************************************************
|
|
* HIDT_AbortPendingRequests
|
|
************************************************************
|
|
*
|
|
*
|
|
*/
|
|
NTSTATUS HIDT_AbortPendingRequests(IN PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
|
|
PAGED_CODE();
|
|
|
|
// BUGBUG FINISH
|
|
|
|
ASSERT(NT_SUCCESS(status));
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
************************************************************
|
|
* HIDT_PnpCompletion
|
|
************************************************************
|
|
*
|
|
*/
|
|
NTSTATUS HIDT_PnpCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
|
|
{
|
|
PDEVICE_EXTENSION DeviceExtension;
|
|
PIO_STACK_LOCATION irpSp;
|
|
NTSTATUS status;
|
|
|
|
DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
|
|
irpSp = IoGetCurrentIrpStackLocation (Irp);
|
|
status = Irp->IoStatus.Status;
|
|
|
|
switch(irpSp->MinorFunction){
|
|
|
|
case IRP_MN_START_DEVICE:
|
|
if (NT_SUCCESS(status)) {
|
|
DeviceExtension->DeviceState = DEVICE_STATE_RUNNING;
|
|
|
|
status = HIDT_InitDevice(DeviceObject);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
DBGWARN(("HIDT_InitDevice failed; failing IRP_MN_START_DEVICE."));
|
|
DeviceExtension->DeviceState = DEVICE_STATE_START_FAILED;
|
|
Irp->IoStatus.Status = status;
|
|
}
|
|
}
|
|
else {
|
|
ASSERT(NT_SUCCESS(status));
|
|
DeviceExtension->DeviceState = DEVICE_STATE_START_FAILED;
|
|
}
|
|
break;
|
|
|
|
case IRP_MN_STOP_DEVICE:
|
|
|
|
DeviceExtension->DeviceState = DEVICE_STATE_STOPPED;
|
|
|
|
/*
|
|
* Release resources
|
|
*/
|
|
// BUGBUG FINISH
|
|
break;
|
|
|
|
case IRP_MN_QUERY_CAPABILITIES:
|
|
/*
|
|
* The lower driver set the capabilities flags for this device.
|
|
* Since all 1394 devices are hot-unpluggable,
|
|
* add the SurpriseRemovalOK bit.
|
|
*/
|
|
if (NT_SUCCESS(status)){
|
|
irpSp->Parameters.DeviceCapabilities.Capabilities->SurpriseRemovalOK = TRUE;
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
/*
|
|
* If the lower driver returned PENDING, mark our stack location as
|
|
* pending also. This prevents the IRP's thread from being freed if
|
|
* the client's call returns pending.
|
|
*/
|
|
if (Irp->PendingReturned){
|
|
IoMarkIrpPending(Irp);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
************************************************************
|
|
* HIDT_RemoveDevice
|
|
************************************************************
|
|
*
|
|
*
|
|
*/
|
|
NTSTATUS HIDT_RemoveDevice(IN PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
NTSTATUS ntStatus = STATUS_SUCCESS;
|
|
PDEVICE_EXTENSION DeviceExtension;
|
|
ULONG oldDeviceState;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Get a pointer to the device extension
|
|
//
|
|
|
|
DeviceExtension = GET_MINIDRIVER_DEVICE_EXTENSION(DeviceObject);
|
|
|
|
//
|
|
// Set device state, this prevents new IOs from starting
|
|
//
|
|
|
|
oldDeviceState = DeviceExtension->DeviceState;
|
|
DeviceExtension->DeviceState = DEVICE_STATE_REMOVING;
|
|
|
|
//
|
|
// Cancel any outstanding IRPs if the device was running
|
|
//
|
|
|
|
if (oldDeviceState == DEVICE_STATE_RUNNING){
|
|
ntStatus = HIDT_AbortPendingRequests( DeviceObject );
|
|
|
|
|
|
/*
|
|
* Note: RemoveDevice does an extra decrement, so we complete
|
|
* the REMOVE IRP on the transition to -1, whether this
|
|
* happens in RemoveDevice itself or subsequently while
|
|
* RemoveDevice is waiting for this event to fire.
|
|
*/
|
|
HIDT_DecrementPendingRequestCount(DeviceExtension);
|
|
KeWaitForSingleObject( &DeviceExtension->AllRequestsCompleteEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL );
|
|
}
|
|
else if (oldDeviceState == DEVICE_STATE_STOPPING){
|
|
ASSERT(!(PVOID)"PnP IRPs are not synchronized! -- got REMOVE_DEVICE before STOP_DEVICE completed!");
|
|
}
|
|
else {
|
|
ASSERT(DeviceExtension->NumPendingRequests == -1);
|
|
}
|
|
|
|
//
|
|
// Release any resources
|
|
//
|
|
|
|
// BUGBUG FINISH
|
|
|
|
ntStatus = STATUS_SUCCESS;
|
|
|
|
return ntStatus;
|
|
}
|
|
|
|
|