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

📄 pnp.c

📁 usbhostDriver, 设计USB的目标就是使不同厂家所生产的设备可以在一个开放的体系下广泛的使用。该规范改进了便携商务或家用电脑的现有体系结构
💻 C
📖 第 1 页 / 共 3 页
字号:
  DPRINT(("HandleQueryCapabilities - begins\n"));
  //
  // initialize variables
  //
  irpStack = IoGetCurrentIrpStackLocation(Irp);
  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  pdc = irpStack->Parameters.DeviceCapabilities.Capabilities;
  //
  // We will provide here an example of an IRP that is processed
  // both on its way down and on its way up: there might be no need for
  // a function driver process this Irp (the bus driver will do that).
  // The driver will wait for the lower drivers (the bus driver among 
  // them) to process this IRP, then it processes it again.
  //
  if(pdc->Version < 1 || pdc->Size < sizeof(DEVICE_CAPABILITIES)) {
    DPRINT(("HandleQueryCapabilities::request failed\n"));
    ntS = STATUS_UNSUCCESSFUL;
    return ntS;
  }
  //
  // Add in the SurpriseRemovalOK bit before passing it down.
  //
  pdc->SurpriseRemovalOK = TRUE;
  Irp->IoStatus.Status = STATUS_SUCCESS;
  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;
  }
  //
  // initialize PowerDownLevel to disabled
  //
  DevExt->PowerDownLevel = PowerDeviceUnspecified;
  if(NT_SUCCESS(ntS)) {
    DevExt->DeviceCapabilities = *pdc;
    for (i = PowerSystemSleeping1; i <= PowerSystemSleeping3; i++) {
      if(DevExt->DeviceCapabilities.DeviceState[i] < PowerDeviceD3) {
        DevExt->PowerDownLevel = DevExt->DeviceCapabilities.DeviceState[i];
      }
    }
    //
    // since its safe to surprise-remove this device, we shall
    // set the SurpriseRemoveOK flag to supress any dialog to 
    // user.
    //
    pdc->SurpriseRemovalOK = 1;
  }
  if (DevExt->PowerDownLevel == PowerDeviceUnspecified ||
      DevExt->PowerDownLevel <= PowerDeviceD0)
  {
    DevExt->PowerDownLevel = PowerDeviceD2;
  }
  DPRINT(("HandleQueryCapabilities - ends\n"));
  return ntS;
}

/*********************************************************************
* 
*       ProcessQueuedRequests
*
* Routine Description:
*    Remove and process the entries in the queue. If this routine is called
*    when processing IRP_MN_CANCEL_STOP_DEVICE, IRP_MN_CANCEL_REMOVE_DEVICE
*    or IRP_MN_START_DEVICE, the requests are passed to the next lower driver.
*    If the routine is called when IRP_MN_REMOVE_DEVICE is received, the IRPs
*    are complete with STATUS_DELETE_PENDING
*
* Arguments:
*    DeviceExtension - pointer to device extension
*/
VOID ProcessQueuedRequests( IN OUT DEVICE_EXTENSION * DeviceExtension) {
  KIRQL       oldIrql;
  IRP         * nextIrp,
              * cancelledIrp;
  VOID        * cancelRoutine;
  LIST_ENTRY  cancelledIrpList;
  PLIST_ENTRY listEntry;

  DPRINT(("<usb> -> ProcessQueuedRequests\n"));
  //
  // initialize variables
  //
  cancelRoutine = NULL;
  InitializeListHead(&cancelledIrpList);
  //
  // 1.  dequeue the entries in the queue
  // 2.  reset the cancel routine
  // 3.  process them
  // 3a. if the device is active, send them down
  // 3b. else complete with STATUS_DELETE_PENDING
  //
  while(1) {
    KeAcquireSpinLock(&DeviceExtension->QueueLock, &oldIrql);
    if(IsListEmpty(&DeviceExtension->NewRequestsQueue)) {
      KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
      break;
    }
    //
    // Remove a request from the queue
    //
    listEntry = RemoveHeadList(&DeviceExtension->NewRequestsQueue);
    nextIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
    //
    // set the cancel routine to NULL
    //
    cancelRoutine = IoSetCancelRoutine(nextIrp, NULL);
    //
    // check if its already cancelled
    //
    if (nextIrp->Cancel) {
      if (cancelRoutine) {
        //
        // the cancel routine for this IRP hasnt been called yet
        // so queue the IRP in the cancelledIrp list and complete
        // after releasing the lock
        //
        InsertTailList(&cancelledIrpList, listEntry);
      } else {
        //
        // the cancel routine has run
        // it must be waiting to hold the queue lock
        // so initialize the IRPs listEntry
        //
        InitializeListHead(listEntry);
      }
      KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
    } else {
      KeReleaseSpinLock(&DeviceExtension->QueueLock, oldIrql);
      if(FailRequests == DeviceExtension->QueueState) {
        nextIrp->IoStatus.Information = 0;
        nextIrp->IoStatus.Status = STATUS_DELETE_PENDING;
        IoCompleteRequest(nextIrp, IO_NO_INCREMENT);
      } else {
        DPRINT(("ProcessQueuedRequests::"));
        DevIoIncrement(DeviceExtension);
        IoSkipCurrentIrpStackLocation(nextIrp);
        IoCallDriver(DeviceExtension->TopOfStackDeviceObject, nextIrp);
        DPRINT(("ProcessQueuedRequests::"));
        DevIoDecrement(DeviceExtension);
      }
    }
  } // while loop
  //
  // walk through the cancelledIrp list and cancel them
  //
  while(!IsListEmpty(&cancelledIrpList)) {
    PLIST_ENTRY listEntry = RemoveHeadList(&cancelledIrpList);
    cancelledIrp = CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
    cancelledIrp->IoStatus.Status = STATUS_CANCELLED;
    cancelledIrp->IoStatus.Information = 0;
    IoCompleteRequest(cancelledIrp, IO_NO_INCREMENT);
  }
  DPRINT(("<usb> <- ProcessQueuedRequests\n"));
  return;
}

/*********************************************************************
*
*       BulkUsb_GetRegistryDword
*
* Routine Description:
*
*    This routine reads the specified reqistry value.
*
* Arguments:
*
*    RegPath - registry path
*    ValueName - property to be fetched from the registry
*    Value - corresponding value read from the registry.
*
* Return Value:
*
*    NT status value
*/
NTSTATUS BulkUsb_GetRegistryDword(IN     PWCHAR RegPath, IN     PWCHAR ValueName, IN OUT PULONG Value ) {
  ULONG                    defaultData;
  WCHAR                    buffer[MAXIMUM_FILENAME_LENGTH];
  NTSTATUS                 ntS;
  UNICODE_STRING           regPath;
  RTL_QUERY_REGISTRY_TABLE paramTable[2];

  DPRINT(("BulkUsb_GetRegistryDword - begins\n"));

  regPath.Length = 0;
  regPath.MaximumLength = MAXIMUM_FILENAME_LENGTH * sizeof(WCHAR);
  regPath.Buffer = buffer;

  RtlZeroMemory(regPath.Buffer, regPath.MaximumLength);
  RtlMoveMemory(regPath.Buffer, RegPath, wcslen(RegPath) * sizeof(WCHAR));
  RtlZeroMemory(paramTable, sizeof(paramTable));

  paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  paramTable[0].Name = ValueName;
  paramTable[0].EntryContext = Value;
  paramTable[0].DefaultType = REG_DWORD;
  paramTable[0].DefaultData = &defaultData;
  paramTable[0].DefaultLength = sizeof(ULONG);
  ntS = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL, regPath.Buffer, paramTable, NULL,NULL);
  if(NT_SUCCESS(ntS)) {
    DPRINT(("success Value = %X\n", *Value));
    return STATUS_SUCCESS;
  } else {
    *Value = 0;
    return STATUS_UNSUCCESSFUL;
  }
}


/*********************************************************************
*
*       _CanDeviceSuspend
*
* Routine Description:
*
*    This is the routine where we check if the device
*    can selectively suspend. 
*
* Arguments:
*    DeviceExtension - pointer to device extension
*
* Return Value:
*    TRUE - if the device can suspend
*    FALSE - otherwise.
*
*/
#if 0
static BOOLEAN _CanDeviceSuspend(IN DEVICE_EXTENSION * DeviceExtension ) {
  DPRINT(("CanDeviceSuspend\n"));
  if((DeviceExtension->OpenHandleCount == 0) && (DeviceExtension->OutStandingIO == 1)) {
    return TRUE;
  } else {
    return FALSE;
  }
}
#endif

/*********************************************************************
*
* Routine Description
*    sends an abort pipe request for open pipes.
*
* Arguments:
*    DeviceObject - pointer to device object
*
* Return Value:
*    NT status value
*
*/
NTSTATUS BulkUsb_AbortPipes(IN PDEVICE_OBJECT DeviceObject) {
  PURB                        urb;
  ULONG                       i;
  NTSTATUS                    ntS;
  DEVICE_EXTENSION *          DevExt;
  PUSB_PIPE_CONTEXT           pipeContext;
  PUSBD_INTERFACE_INFORMATION interfaceInfo;

  //
  // initialize variables
  //
  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  pipeContext = DevExt->PipeContext;
  interfaceInfo = DevExt->UsbInterface;
  DPRINT(("BulkUsb_AbortPipes - begins\n"));
  if(interfaceInfo == NULL || pipeContext == NULL) {
      return STATUS_SUCCESS;
  }
  for(i=0; i<interfaceInfo->NumberOfPipes; i++) {
    if(pipeContext[i].PipeOpen) {
      DPRINT(("Aborting open pipe %d\n", i));
      urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
      if(urb) {
        urb->UrbHeader.Length = sizeof(struct _URB_PIPE_REQUEST);
        urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
        urb->UrbPipeRequest.PipeHandle = interfaceInfo->Pipes[i].PipeHandle;
        ntS = CallUSBD(DeviceObject, urb);
        ExFreePool(urb);
      } else {
        DPRINT(("Failed to alloc memory for urb\n"));
        ntS = STATUS_INSUFFICIENT_RESOURCES;
        return ntS;
      }
      if(NT_SUCCESS(ntS)) {
        pipeContext[i].PipeOpen = FALSE;
      }
    }
  }
  DPRINT(("BulkUsb_AbortPipes - ends\n"));
  return STATUS_SUCCESS;
}



/*********************************************************************
* 
* Routine Description:

    This routine bumps up the I/O count.
    This routine is typically invoked when any of the
    dispatch routines handle new irps for the driver.

Arguments:

    DeviceExtension - pointer to device extension

Return Value:

    new value

--*/
LONG DevIoIncrement(IN OUT DEVICE_EXTENSION * DeviceExtension) {
  LONG  result = 0;
  KIRQL oldIrql;
  KeAcquireSpinLock(&DeviceExtension->IOCountLock, &oldIrql);
  result = InterlockedIncrement(&DeviceExtension->OutStandingIO);
  //
  // when OutStandingIO bumps from 1 to 2, clear the StopEvent
  //
  if(result == 2) {
    KeClearEvent(&DeviceExtension->StopEvent);
  }
  KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
  //DPRINT(("DevIoIncrement::%d\n", result));
  return result;
}

/*********************************************************************
*
*       DevIoDecrement
* 
* Routine Description:
*
*   This routine decrements the outstanding I/O count
*   This is typically invoked after the dispatch routine
*   has finished processing the irp.
*
* Arguments:
*   DeviceExtension - pointer to device extension
*
* Return Value:
*   new value
*
*/
LONG DevIoDecrement(IN OUT DEVICE_EXTENSION * pDeviceExtension) {
  LONG  result = 0;
  KIRQL oldIrql;
  KeAcquireSpinLock(&pDeviceExtension->IOCountLock, &oldIrql);
  result = InterlockedDecrement(&pDeviceExtension->OutStandingIO);
  if(result == 1) {
    KeSetEvent(&pDeviceExtension->StopEvent, IO_NO_INCREMENT, FALSE);
  }
  if(result == 0) {
    ASSERT(Removed == pDeviceExtension->DeviceState);
    KeSetEvent(&pDeviceExtension->RemoveEvent, IO_NO_INCREMENT, FALSE);
  }
  KeReleaseSpinLock(&pDeviceExtension->IOCountLock, oldIrql);
  //DPRINT(("DevIoDecrement::%d\n", result));
  return result;
}


NTSTATUS BulkUsb_DispatchPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  PIO_STACK_LOCATION irpStack;
  DEVICE_EXTENSION *  DevExt;
  NTSTATUS           ntS;

  DPRINT(("<usb> -> BulkUsb_DispatchPnP\n"));
  irpStack = IoGetCurrentIrpStackLocation(Irp);
  DevExt = DeviceObject->DeviceExtension;
  if (Removed == DevExt->DeviceState) {
    DPRINT(("<usb> <- BulkUsb_DispatchPnP (aerly out ... Device is removed)\n"));
    return(CompleteRequest(Irp, STATUS_DELETE_PENDING, 0));
  }
  DevIoIncrement(DevExt);
  switch(irpStack->MinorFunction) {
  case IRP_MN_START_DEVICE:
    DPRINT(("<usb>    IRP_MN_START_DEVICE\n"));
    ntS = HandleStartDevice(DeviceObject, Irp);
    break;
  case IRP_MN_QUERY_STOP_DEVICE:
    DPRINT(("<usb>    IRP_MN_QUERY_STOP_DEVICE\n"));
    ntS = _CanStopDevice(DeviceObject, Irp);
    if(NT_SUCCESS(ntS)) {
      ntS = HandleQueryStopDevice(DeviceObject, Irp);
      DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
      return(ntS);
    }
    break;
  case IRP_MN_CANCEL_STOP_DEVICE:
    DPRINT(("<usb>    IRP_MN_CANCEL_STOP_DEVICE\n"));
    ntS = HandleCancelStopDevice(DeviceObject, Irp);
    break;
  case IRP_MN_STOP_DEVICE:
    DPRINT(("<usb>    IRP_MN_STOP_DEVICE\n"));
    ntS = HandleStopDevice(DeviceObject, Irp);
    DevIoDecrement(DevExt);
    DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
    return(ntS);
  case IRP_MN_QUERY_REMOVE_DEVICE:
    DPRINT(("<usb>    IRP_MN_QUERY_REMOVE_DEVICE\n"));
    ntS = HandleQueryRemoveDevice(DeviceObject, Irp);
    DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
    return(ntS);
  case IRP_MN_CANCEL_REMOVE_DEVICE:
    DPRINT(("<usb>    IRP_MN_CANCEL_REMOVE_DEVICE\n"));
    ntS = HandleCancelRemoveDevice(DeviceObject, Irp);
    break;
  case IRP_MN_SURPRISE_REMOVAL:
    DPRINT(("<usb>    IRP_MN_SURPRISE_REMOVAL\n"));
    ntS = HandleSurpriseRemoval(DeviceObject, Irp);
    DevIoDecrement(DevExt);
    DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
    return(ntS);
  case IRP_MN_REMOVE_DEVICE:
    DPRINT(("<usb>    IRP_MN_REMOVE_DEVICE\n"));
    ntS = HandleRemoveDevice(DeviceObject, Irp);
    DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
    return(ntS);
  case IRP_MN_QUERY_CAPABILITIES:
    DPRINT(("<usb>    IRP_MN_QUERY_CAPABILITIES\n"));
    ntS = HandleQueryCapabilities(DeviceObject, Irp);
    break;
  default:
    DPRINT(("<usb>    Dispatching unhandled PNP func: 0x%x", irpStack->MinorFunction));
    IoSkipCurrentIrpStackLocation(Irp);
    ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
    DevIoDecrement(DevExt);
    DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
    return(ntS);
  }
  CompleteRequest(Irp, ntS, 0);
  DevIoDecrement(DevExt);
  DPRINT(("<usb> <- BulkUsb_DispatchPnP\n"));
  return(ntS);
}

⌨️ 快捷键说明

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