Ejemplo n.º 1
0
NTSTATUS PPJoyBus_PnP_Joy (IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
 NTSTATUS			ntStatus;
 PIO_STACK_LOCATION	IrpStack;
 PJOY_DEVICE_DATA	JoyDeviceData;

 WCHAR				LinkNameBuffer[128];
 UNICODE_STRING		LinkName;

 PAGED_CODE();

 PPJOY_DBGPRINT (FILE_PNP|PPJOY_FENTRY,("PPJoyBus_PnP_Joy(DeviceObject=0x%p,Irp=0x%p)",DeviceObject,Irp) );

 IrpStack = IoGetCurrentIrpStackLocation (Irp);
 JoyDeviceData= (PJOY_DEVICE_DATA)DeviceObject->DeviceExtension;

 switch(IrpStack->MinorFunction)
 {
  case IRP_MN_START_DEVICE:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_START_DEVICE") );

	    ntStatus= PPJoyBus_JoyStartDevice (JoyDeviceData,Irp);
		goto CompleteIRP;

  case IRP_MN_STOP_DEVICE:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_STOP_DEVICE") );

	    PPJoyBus_JoyStopDevice (JoyDeviceData,Irp);
		/* This routine must always return success. */
		ntStatus= STATUS_SUCCESS;
		goto CompleteIRP;

  case IRP_MN_QUERY_STOP_DEVICE:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_QUERY_STOP_DEVICE") );

		/* Always accept stop device request */
		ntStatus= STATUS_SUCCESS;
		goto CompleteIRP;

  case IRP_MN_CANCEL_STOP_DEVICE:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_CANCEL_STOP_DEVICE") );

		/* Canceling stop requests always successful */
		ntStatus= STATUS_SUCCESS;
		goto CompleteIRP;

  case IRP_MN_QUERY_REMOVE_DEVICE:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_QUERY_REMOVE_DEVICE") );

		/* Always accept remove requests */
		ntStatus= STATUS_SUCCESS;
		goto CompleteIRP;

  case IRP_MN_CANCEL_REMOVE_DEVICE:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_CANCEL_REMOVE_DEVICE") );

		/* Cancelling remove requests always successful */
		ntStatus= STATUS_SUCCESS;
		goto CompleteIRP;


  case IRP_MN_QUERY_CAPABILITIES:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_QUERY_CAPABILITIES") );
 
		ntStatus= PPJoyBus_JoyQueryCaps (JoyDeviceData,Irp);
		goto CompleteIRP;
 
  case IRP_MN_QUERY_DEVICE_RELATIONS:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_QUERY_DEVICE_RELATIONS type %s",DbgDeviceRelationString(IrpStack->Parameters.QueryDeviceRelations.Type)) );
 
		ntStatus= PPJoyBus_JoyDevRelations (JoyDeviceData,Irp);
		goto CompleteIRP;

  case IRP_MN_QUERY_RESOURCES:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_QUERY_RESOURCES") );

		/* Simply copy the status of the incoming IRP to return back */
		ntStatus= Irp->IoStatus.Status;
		goto CompleteIRP;
	
#if 0
  case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_QUERY_RESOURCE_REQUIREMENTS") );

		ntStatus= PPJoyBus_JoyQueryResourceRequirements (JoyDeviceData,Irp);
		goto CompleteIRP;
#endif

  case IRP_MN_DEVICE_USAGE_NOTIFICATION:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_DEVICE_USAGE_NOTIFICATION") );
		ntStatus= STATUS_UNSUCCESSFUL;
		goto CompleteIRP;

  case IRP_MN_SURPRISE_REMOVAL:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_SURPRISE_REMOVAL") );

		/* Simply say request was successful */
		ntStatus= STATUS_SUCCESS;
		goto CompleteIRP;

  case IRP_MN_REMOVE_DEVICE:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_REMOVE_DEVICE") );

		/* We stop the device if it wasn't done before the remove */
		if (JoyDeviceData->Flags&PPJFLAGS_STARTED)
		 PPJoyBus_JoyStopDevice (JoyDeviceData,Irp);

		/* Set the DeviceExtension flag to say that our device is removed */
		JoyDeviceData->Flags|= PPJFLAGS_REMOVED;

		/* Leave request to decrease requests counter. Event should be */
		/* signaled when last request leaves. Then we will return a    */
		/* successful status.                                          */
		PPJoyBus_LeaveRequest((PCOMMON_DATA)JoyDeviceData);

        KeWaitForSingleObject (&JoyDeviceData->RemoveEvent,Executive,KernelMode,FALSE,NULL);
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE2, ("KeWaitForSingleObject on RemoveEvent completed.") );

		/* If our Joystick is unplugged (via control panel applet) then we */
		/* delete the device object for it as well. Else we only mark it   */
		/* as being removed. (Can later be AddDevice and START'ed again)   */
		if (JoyDeviceData->Flags&PPJFLAGS_UNPLUGGED)
		{
		 /* Remove the PDO from joystick list. */
		 ExAcquireFastMutex (&Globals.Mutex);
		 RemoveEntryList (&JoyDeviceData->ListEntry);
		 ExReleaseFastMutex (&Globals.Mutex);

 		 PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE2, ("Device unplugged so we will delete the PDO.") );

		 /* Then nuke the PDO out of existance */
		 IoDeleteDevice (JoyDeviceData->Self);
		}

		/* The hardware is still physically present. We are ready to be */
		/* started again - so clear the REMOVED flag. Should work.      */
		JoyDeviceData->Flags&= ~PPJFLAGS_REMOVED;

		/* After all that indicate that the request was successful */
		ntStatus= STATUS_SUCCESS;
		goto CompleteIRP;

  case IRP_MN_QUERY_ID:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_QUERY_ID type %s",DbgDeviceIDString(IrpStack->Parameters.QueryId.IdType)) );
	
		ntStatus= PPJoyBus_JoyQueryIDs (JoyDeviceData,Irp);
		goto CompleteIRP;

  case IRP_MN_QUERY_DEVICE_TEXT:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_BABBLE, ("PPJoyBus_PnP_Joy: IRP_MN_QUERY_DEVICE_TEXT") );
	
		ntStatus= PPJoyBus_JoyQueryDevText (JoyDeviceData,Irp);
		goto CompleteIRP;

  default:
		PPJOY_DBGPRINT (FILE_PNP|PPJOY_WARN,("PPJoyBus_PnP_Joy: IrpStack->MinorFunction Not handled %s (0x%x)",PnPMinorFunctionString (IrpStack->MinorFunction),IrpStack->MinorFunction) );

		/* Simply copy the status of the incoming IRP to return back */
		ntStatus= Irp->IoStatus.Status;
		goto CompleteIRP;
 }

CompleteIRP:
 Irp->IoStatus.Status = ntStatus;
 IoCompleteRequest (Irp, IO_NO_INCREMENT);
 goto Exit;

Exit:
 PPJOY_EXITPROC (FILE_PNP|PPJOY_FEXIT, "PPJoyBus_PnP_Joy",ntStatus );
 return ntStatus;
}
Ejemplo n.º 2
0
NTSTATUS
Bus_PDO_PnP (
    __in PDEVICE_OBJECT       DeviceObject,
    __in PIRP                 Irp,
    __in PIO_STACK_LOCATION   IrpStack,
    __in PPDO_DEVICE_DATA     DeviceData
    )
/*++
Routine Description:
    Handle requests from the Plug & Play system for the devices on the BUS

--*/
{
    NTSTATUS                status;

    PAGED_CODE ();


    //
    // NB: Because we are a bus enumerator, we have no one to whom we could
    // defer these irps.  Therefore we do not pass them down but merely
    // return them.
    //

    switch (IrpStack->MinorFunction) {

    case IRP_MN_START_DEVICE:

        //
        // Here we do what ever initialization and ``turning on'' that is
        // required to allow others to access this device.
        // Power up the device.
        //
        DeviceData->DevicePowerState = PowerDeviceD0;
        SET_NEW_PNP_STATE(DeviceData, Started);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_STOP_DEVICE:

        //
        // Here we shut down the device and give up and unmap any resources
        // we acquired for the device.
        //

        SET_NEW_PNP_STATE(DeviceData, Stopped);
        status = STATUS_SUCCESS;
        break;


    case IRP_MN_QUERY_STOP_DEVICE:

        //
        // No reason here why we can't stop the device.
        // If there were a reason we should speak now, because answering success
        // here may result in a stop device irp.
        //

        SET_NEW_PNP_STATE(DeviceData, StopPending);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_STOP_DEVICE:

        //
        // The stop was canceled.  Whatever state we set, or resources we put
        // on hold in anticipation of the forthcoming STOP device IRP should be
        // put back to normal.  Someone, in the long list of concerned parties,
        // has failed the stop device query.
        //

        //
        // First check to see whether you have received cancel-stop
        // without first receiving a query-stop. This could happen if someone
        // above us fails a query-stop and passes down the subsequent
        // cancel-stop.
        //

        if (StopPending == DeviceData->DevicePnPState)
        {
            //
            // We did receive a query-stop, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
        }
        status = STATUS_SUCCESS;// We must not fail this IRP.
        break;

    case IRP_MN_QUERY_REMOVE_DEVICE:

        //
        // Check to see whether the device can be removed safely.
        // If not fail this request. This is the last opportunity
        // to do so.
        //
        if (DeviceData->ToasterInterfaceRefCount){
            //
            // Somebody is still using our interface.
            // We must fail remove.
            //
            status = STATUS_UNSUCCESSFUL;
            break;
        }

        SET_NEW_PNP_STATE(DeviceData, RemovePending);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_CANCEL_REMOVE_DEVICE:

        //
        // Clean up a remove that did not go through.
        //

        //
        // First check to see whether you have received cancel-remove
        // without first receiving a query-remove. This could happen if
        // someone above us fails a query-remove and passes down the
        // subsequent cancel-remove.
        //

        if (RemovePending == DeviceData->DevicePnPState)
        {
            //
            // We did receive a query-remove, so restore.
            //
            RESTORE_PREVIOUS_PNP_STATE(DeviceData);
        }
        status = STATUS_SUCCESS; // We must not fail this IRP.
        break;

    case IRP_MN_SURPRISE_REMOVAL:

        //
        // We should stop all access to the device and relinquish all the
        // resources. Let's just mark that it happened and we will do
        // the cleanup later in IRP_MN_REMOVE_DEVICE.
        //

        SET_NEW_PNP_STATE(DeviceData, SurpriseRemovePending);
        status = STATUS_SUCCESS;
        break;

    case IRP_MN_REMOVE_DEVICE:

        //
        // Present is set to true when the pdo is exposed via PlugIn IOCTL.
        // It is set to FALSE when a UnPlug IOCTL is received.
        // We will delete the PDO only after we have reported to the
        // Plug and Play manager that it's missing.
        //

        if (DeviceData->ReportedMissing) {
            PFDO_DEVICE_DATA fdoData;

            SET_NEW_PNP_STATE(DeviceData, Deleted);

            //
            // Remove the PDO from the list and decrement the count of PDO.
            // Don't forget to synchronize access to the FDO data.
            // If the parent FDO is deleted before child PDOs, the ParentFdo
            // pointer will be NULL. This could happen if the child PDO
            // is in a SurpriseRemovePending state when the parent FDO
            // is removed.
            //

            if (DeviceData->ParentFdo) {
                fdoData = FDO_FROM_PDO(DeviceData);
                ExAcquireFastMutex (&fdoData->Mutex);
                RemoveEntryList (&DeviceData->Link);
                fdoData->NumPDOs--;
                ExReleaseFastMutex (&fdoData->Mutex);
            }
            //
            // Free up resources associated with PDO and delete it.
            //
            status = Bus_DestroyPdo(DeviceObject, DeviceData);
            break;

        }
        if (DeviceData->Present) {
            //
            // When the device is disabled, the PDO transitions from
            // RemovePending to NotStarted. We shouldn't delete
            // the PDO because a) the device is still present on the bus,
            // b) we haven't reported missing to the PnP manager.
            //

            SET_NEW_PNP_STATE(DeviceData, NotStarted);
            status = STATUS_SUCCESS;
        } else {
            ASSERT(DeviceData->Present);
            status = STATUS_SUCCESS;
        }
        break;

    case IRP_MN_QUERY_CAPABILITIES:

        //
        // Return the capabilities of a device, such as whether the device
        // can be locked or ejected..etc
        //

        status = Bus_PDO_QueryDeviceCaps(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_ID:

        // Query the IDs of the device

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
                ("\tQueryId Type: %s\n",
                DbgDeviceIDString(IrpStack->Parameters.QueryId.IdType)));

        status = Bus_PDO_QueryDeviceId(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_DEVICE_RELATIONS:

        Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,
            ("\tQueryDeviceRelation Type: %s\n",DbgDeviceRelationString(\
                    IrpStack->Parameters.QueryDeviceRelations.Type)));

        status = Bus_PDO_QueryDeviceRelations(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_DEVICE_TEXT:

        status = Bus_PDO_QueryDeviceText(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_RESOURCES:

        status = Bus_PDO_QueryResources(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:

        status = Bus_PDO_QueryResourceRequirements(DeviceData, Irp);

        break;

    case IRP_MN_QUERY_BUS_INFORMATION:

        status = Bus_PDO_QueryBusInformation(DeviceData, Irp);

        break;

    case IRP_MN_DEVICE_USAGE_NOTIFICATION:

        //
        // OPTIONAL for bus drivers.
        // This bus drivers any of the bus's descendants
        // (child device, child of a child device, etc.) do not
        // contain a memory file namely paging file, dump file,
        // or hibernation file. So we  fail this Irp.
        //

        status = STATUS_UNSUCCESSFUL;
        break;

    case IRP_MN_EJECT:

        //
        // For the device to be ejected, the device must be in the D3
        // device power state (off) and must be unlocked
        // (if the device supports locking). Any driver that returns success
        // for this IRP must wait until the device has been ejected before
        // completing the IRP.
        //
        DeviceData->Present = FALSE;

        status = STATUS_SUCCESS;
        break;

    case IRP_MN_QUERY_INTERFACE:
        //
        // This request enables a driver to export a direct-call
        // interface to other drivers. A bus driver that exports
        // an interface must handle this request for its child
        // devices (child PDOs).
        //
        status = Bus_PDO_QueryInterface(DeviceData, Irp);
        break;

    case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:

        //
        // OPTIONAL for bus drivers.
        // The PnP Manager sends this IRP to a device
        // stack so filter and function drivers can adjust the
        // resources required by the device, if appropriate.
        //

        //break;

    //case IRP_MN_QUERY_PNP_DEVICE_STATE:

        //
        // OPTIONAL for bus drivers.
        // The PnP Manager sends this IRP after the drivers for
        // a device return success from the IRP_MN_START_DEVICE
        // request. The PnP Manager also sends this IRP when a
        // driver for the device calls IoInvalidateDeviceState.
        //

        // break;

    //case IRP_MN_READ_CONFIG:
    //case IRP_MN_WRITE_CONFIG:

        //
        // Bus drivers for buses with configuration space must handle
        // this request for their child devices. Our devices don't
        // have a config space.
        //

        // break;

    //case IRP_MN_SET_LOCK:

        //
        // Our device is not a lockable device
        // so we don't support this Irp.
        //

        // break;

    default:

        //
        //Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE,("\t Not handled\n"));
        // For PnP requests to the PDO that we do not understand we should
        // return the IRP WITHOUT setting the status or information fields.
        // These fields may have already been set by a filter (eg acpi).
        status = Irp->IoStatus.Status;

        break;
    }

    Irp->IoStatus.Status = status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);

    return status;
}