⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pnp.c

📁 usbhostDriver, 设计USB的目标就是使不同厂家所生产的设备可以在一个开放的体系下广泛的使用。该规范改进了便携商务或家用电脑的现有体系结构
💻 C
📖 第 1 页 / 共 3 页
字号:
    ntS = SelectInterfaces(DeviceObject, configurationDescriptor);
  } else {
    DevExt->UsbConfigurationDescriptor = NULL;
  }

ConfigureDevice_Exit:
  if (urb) {
    ExFreePool(urb);
  }
  DPRINT(("<usb> <- ConfigureDevice\n"));
  return(ntS);
}



NTSTATUS DeconfigureDevice(IN PDEVICE_OBJECT DeviceObject) {
  PURB     urb;
  ULONG    siz;
  NTSTATUS ntS;
  
  DPRINT(("<usb> DeconfigureDevice()\n"));
  siz = sizeof(struct _URB_SELECT_CONFIGURATION);
  urb = ExAllocatePool(NonPagedPool, siz);

  if (urb) {
    UsbBuildSelectConfigurationRequest(urb, (USHORT)siz, NULL);
    ntS = CallUSBD(DeviceObject, urb);
    if (!NT_SUCCESS(ntS)) {
      DPRINT(("<usb> error: CallUSBD %x (deconfig device)\n", ntS));
    }
    ExFreePool(urb);
  } else {
    DPRINT(("<usb> error: allocating urb\n"));
    ntS = STATUS_INSUFFICIENT_RESOURCES;
  }
  return(ntS);
}

/*********************************************************************
*
* Routine Description:
*   This routine synchronously submits an urb down the stack.
* Arguments:
*   DeviceObject - pointer to device object
*   Urb - USB request block
*
* Return Value:
--*/
NTSTATUS CallUSBD(IN PDEVICE_OBJECT DeviceObject, IN PURB           Urb) {
  PIRP               irp;
  KEVENT             event;
  NTSTATUS           ntS;
  IO_STATUS_BLOCK    ioStatus;
  PIO_STACK_LOCATION nextStack;
  DEVICE_EXTENSION *  DevExt;

  DPRINT(("<usb> -> CallUSBD"));
  //
  // initialize the variables
  //
  irp = NULL;
  DevExt = DeviceObject->DeviceExtension;
  KeInitializeEvent(&event, NotificationEvent, FALSE);
  irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, DevExt->TopOfStackDeviceObject,
                                      NULL, 0, NULL, 0, TRUE, &event, &ioStatus);
  if (!irp) {
    DPRINT(("IoBuildDeviceIoControlRequest failed\n"));
    ntS = STATUS_INSUFFICIENT_RESOURCES;
  } else {
    nextStack = IoGetNextIrpStackLocation(irp);
    ASSERT(nextStack != NULL);
    nextStack->Parameters.Others.Argument1 = Urb;
    DevIoIncrement(DevExt);
    ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, irp);
    if(ntS == STATUS_PENDING) {
      KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
      ntS = ioStatus.Status;
    }
    DevIoDecrement(DevExt);
  }
  DPRINT(("<usb> <- CallUSBD"));
  return ntS;
}

/*********************************************************************
*
*  Routine Description:
*    This routine services the Irps of minor type IRP_MN_QUERY_STOP_DEVICE
*  Arguments:
*    DeviceObject - pointer to device object
*    Irp - I/O request packet sent by the pnp manager.
*  Return Value:
*   NT status value
*/
NTSTATUS HandleQueryStopDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) {
  KIRQL              oldIrql;
  NTSTATUS           ntS;
  DEVICE_EXTENSION * DevExt;

  DPRINT(("HandleQueryStopDevice - begins\n"));
  //
  // initialize variables
  //
  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  //
  // If we can stop the device, we need to set the QueueState to 
  // HoldRequests so further requests will be queued.
  //
  KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
  SET_NEW_PNP_STATE(DevExt, PendingStop);
  DevExt->QueueState = HoldRequests;
  KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
  //
  // wait for the existing ones to be finished.
  // first, decrement this operation
  //
  DPRINT(("HandleQueryStopDevice::"));
  DevIoDecrement(DevExt);
  KeWaitForSingleObject(&DevExt->StopEvent, Executive, KernelMode, FALSE, NULL);
  Irp->IoStatus.Status = STATUS_SUCCESS;
  Irp->IoStatus.Information = 0;
  IoSkipCurrentIrpStackLocation(Irp);
  ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
  DPRINT(("HandleQueryStopDevice - ends\n"));
  return ntS;
}

/*********************************************************************
*
*  Routine Description:
*    This routine services Irp of minor type IRP_MN_CANCEL_STOP_DEVICE
*  Arguments:
*   DeviceObject - pointer to device object
*   Irp - I/O request packet sent by the pnp manager.
*  Return Value:
*    NT value
*
*/
NTSTATUS HandleCancelStopDevice(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) {
  KIRQL             oldIrql;    
  KEVENT            event;
  NTSTATUS          ntS;
  DEVICE_EXTENSION * DevExt;

  DPRINT(("HandleCancelStopDevice - begins\n"));
  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  //
  // Send this IRP down and wait for it to come back.
  // Set the QueueState flag to AllowRequests, 
  // and process all the previously queued up IRPs.
  //
  // 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 (PendingStop == DevExt->DeviceState) {
    KeInitializeEvent(&event, NotificationEvent, FALSE);
    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(Irp, IrpCompletionRoutine, (PVOID)&event, TRUE, TRUE, TRUE);
    ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
    if(ntS == STATUS_PENDING) {
      KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
      ntS = Irp->IoStatus.Status;
    }
    if (NT_SUCCESS(ntS)) {
      KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
      RESTORE_PREVIOUS_PNP_STATE(DevExt);
      DevExt->QueueState = AllowRequests;
      ASSERT(DevExt->DeviceState == Working);
      KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
      ProcessQueuedRequests(DevExt);
    }
  } else {
    // spurious Irp
    ntS = STATUS_SUCCESS;
  }
  DPRINT(("HandleCancelStopDevice - ends\n"));
  return ntS;
}

/*++

Routine Description:

    This routine services Irp of minor type IRP_MN_STOP_DEVICE

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet sent by the pnp manager.

Return Value:

    NT status value

--*/
NTSTATUS HandleStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP  Irp) {
  KIRQL              oldIrql;
  NTSTATUS           ntS;
  DEVICE_EXTENSION * DevExt;
  DPRINT(("HandleStopDevice - begins\n"));
  //
  // initialize variables
  //
  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  //
  // after the stop Irp is sent to the lower driver object, 
  // the driver must not send any more Irps down that touch 
  // the device until another Start has occurred.
  //
  if(DevExt->WaitWakeEnable) {
      CancelWaitWake(DevExt);
  }
  KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
  SET_NEW_PNP_STATE(DevExt, Stopped);
  KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
  //
  // This is the right place to actually give up all the resources used
  // This might include calls to IoDisconnectInterrupt, MmUnmapIoSpace, 
  // etc.
  //
  ReleaseMemory(DeviceObject);
  ntS = DeconfigureDevice(DeviceObject);
  Irp->IoStatus.Status = ntS;
  Irp->IoStatus.Information = 0;
  IoSkipCurrentIrpStackLocation(Irp);
  ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
  DPRINT(("HandleStopDevice - ends\n"));
  return ntS;
}

/*++
 
Routine Description:

    This routine services Irp of minor type IRP_MN_QUERY_REMOVE_DEVICE

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet sent by the pnp manager.

Return Value:

    NT status value

--*/
NTSTATUS HandleQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  KIRQL             oldIrql;
  NTSTATUS          ntS;
  DEVICE_EXTENSION * DevExt;
  DPRINT(("HandleQueryRemoveDevice - begins\n"));
  //
  // initialize variables
  //
  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  //
  // If we can allow removal of the device, we should set the QueueState
  // to HoldRequests so further requests will be queued. This is required
  // so that we can process queued up requests in cancel-remove just in 
  // case somebody else in the stack fails the query-remove. 
  // 
  ntS = _CanRemoveDevice(DeviceObject, Irp);
  KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
  DevExt->QueueState = HoldRequests;
  SET_NEW_PNP_STATE(DevExt, PendingRemove);
  KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
  DPRINT(("HandleQueryRemoveDevice::"));
  DevIoDecrement(DevExt);
  //
  // wait for all the requests to be completed
  //
  KeWaitForSingleObject(&DevExt->StopEvent, Executive, KernelMode, FALSE, NULL);
  Irp->IoStatus.Status = STATUS_SUCCESS;
  Irp->IoStatus.Information = 0;
  IoSkipCurrentIrpStackLocation(Irp);
  ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
  DPRINT(("HandleQueryRemoveDevice - ends\n"));
  return ntS;
}

/*********************************************************************
*
* Routine Description:
*   This routine services Irp of minor type IRP_MN_CANCEL_REMOVE_DEVICE
* Arguments:
*   DeviceObject - pointer to device object
*   Irp - I/O request packet sent by the pnp manager.
* Return Value:
*   NT status value
--*/
NTSTATUS HandleCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  KIRQL             oldIrql;
  KEVENT            event;
  NTSTATUS          ntS;
  DEVICE_EXTENSION * DevExt;

  DPRINT(("HandleCancelRemoveDevice - begins\n"));
  //
  // initialize variables
  //
  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  //
  // We need to reset the QueueState flag to ProcessRequest, 
  // since the device resume its normal activities.
  //
  //
  // 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(PendingRemove == DevExt->DeviceState) {
    KeInitializeEvent(&event, NotificationEvent, FALSE);
    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(Irp, IrpCompletionRoutine, (PVOID)&event, TRUE, TRUE, TRUE);
    ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
    if(ntS == STATUS_PENDING) {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        ntS = Irp->IoStatus.Status;
    }
    if(NT_SUCCESS(ntS)) {
      KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
      DevExt->QueueState = AllowRequests;
      RESTORE_PREVIOUS_PNP_STATE(DevExt);
      KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
      // process the queued requests that arrive between QUERY_REMOVE and CANCEL_REMOVE
      ProcessQueuedRequests(DevExt);
    }
  } else {
    // 
    // spurious cancel-remove
    //
    ntS = STATUS_SUCCESS;
  }
  DPRINT(("HandleCancelRemoveDevice - ends\n"));
  return ntS;
}

/*
 * 1. block & fail pending requests
 * 2. signal new PNP state
 * 3. call lower drivers
 */
NTSTATUS HandleSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  KIRQL             oldIrql;
  NTSTATUS          ntS;
  DEVICE_EXTENSION * DevExt;

  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  if (DevExt->WaitWakeEnable) {
    CancelWaitWake(DevExt);
  }
  KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
  DevExt->QueueState = FailRequests;
  SET_NEW_PNP_STATE(DevExt, SurpriseRemoved);
  KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
  ProcessQueuedRequests(DevExt);
  ntS = IoSetDeviceInterfaceState(&DevExt->InterfaceName, FALSE);
  if (!NT_SUCCESS(ntS)) {
    DPRINT(("<usb> error: HandleSurpriseRemoval::IoSetDeviceInterfaceState %x\n", ntS));
  }
  BulkUsb_AbortPipes(DeviceObject);
  Irp->IoStatus.Status = STATUS_SUCCESS;
  Irp->IoStatus.Information = 0;
  IoSkipCurrentIrpStackLocation(Irp);
  ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
  return(ntS);
}

NTSTATUS HandleRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  KIRQL             oldIrql;
  ULONG             requestCount;
  NTSTATUS          ntS;
  DEVICE_EXTENSION * DevExt;

  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  if(SurpriseRemoved != DevExt->DeviceState) {
    KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
    DevExt->QueueState = FailRequests;
    KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
    if(DevExt->WaitWakeEnable) {
        CancelWaitWake(DevExt);
    }
    ProcessQueuedRequests(DevExt);
    ntS = IoSetDeviceInterfaceState(&DevExt->InterfaceName, FALSE);
    if(!NT_SUCCESS(ntS)) {
        DPRINT(("<usb> error: HandleRemoveDevice::IoSetDeviceInterfaceState %x\n", ntS));
    }
    BulkUsb_AbortPipes(DeviceObject);
  }

  KeAcquireSpinLock(&DevExt->DevStateLock, &oldIrql);
  SET_NEW_PNP_STATE(DevExt, Removed);
  KeReleaseSpinLock(&DevExt->DevStateLock, oldIrql);
  DPRINT(("HandleRemoveDevice::"));
  requestCount = DevIoDecrement(DevExt);
  ASSERT(requestCount > 0);
  DPRINT(("HandleRemoveDevice::"));
  requestCount = DevIoDecrement(DevExt);
  KeWaitForSingleObject(&DevExt->RemoveEvent, Executive, KernelMode, FALSE, NULL);
  ReleaseMemory(DeviceObject);
  Irp->IoStatus.Status = STATUS_SUCCESS;
  Irp->IoStatus.Information = 0;
  IoSkipCurrentIrpStackLocation(Irp);
  ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
  //
  // Detach the FDO from the device stack
  //
  IoDetachDevice(DevExt->TopOfStackDeviceObject);
  _DeleteDevice(DeviceObject);
  return(ntS);
}

/*++
 
Routine Description:

    This routine services Irp of minor type IRP_MN_QUERY_CAPABILITIES

Arguments:

    DeviceObject - pointer to device object
    Irp - I/O request packet sent by the pnp manager.

Return Value:

    NT status value  

--*/
NTSTATUS HandleQueryCapabilities(IN PDEVICE_OBJECT DeviceObject, IN PIRP           Irp) {
  ULONG                 i;
  KEVENT                event;
  NTSTATUS              ntS;
  DEVICE_EXTENSION *    DevExt;
  PDEVICE_CAPABILITIES  pdc;
  PIO_STACK_LOCATION    irpStack;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -