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

📄 pnp.c

📁 usbhostDriver, 设计USB的目标就是使不同厂家所生产的设备可以在一个开放的体系下广泛的使用。该规范改进了便携商务或家用电脑的现有体系结构
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
**********************************************************************
*                          Micrium, Inc.
*                      949 Crestview Circle
*                     Weston,  FL 33327-1848
*
*                           uC/USB-Bulk
*
*             (c) Copyright 2003 - 2004, Micrium, Inc.
*                      All rights reserved.
*
***********************************************************************

----------------------------------------------------------------------
File        : pnp.c
Purpose     : Part of the USB bulk driver
---------------------------END-OF-HEADER------------------------------
*/

#include "Main.h"

/*********************************************************************
*
*       _DeleteDevice
*/
static NTSTATUS _DeleteDevice(PDEVICE_OBJECT DeviceObject) {
  NTSTATUS ntS;
  UNICODE_STRING uDevUsrPath;
  RtlInitUnicodeString(&uDevUsrPath, DOS_DEVICE_NAME);
  ntS = IoDeleteSymbolicLink(&uDevUsrPath);
  IoDeleteDevice(DeviceObject);
  return(ntS);
}


/*********************************************************************
*
*       _CanStopDevice
*/
static NTSTATUS _CanStopDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  return STATUS_SUCCESS;
}

/*********************************************************************
*
*       _CanRemoveDevice
*/
static NTSTATUS _CanRemoveDevice(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  return(STATUS_SUCCESS);
}

/*********************************************************************
*
*       ReleaseMemory
*/
static NTSTATUS ReleaseMemory(IN PDEVICE_OBJECT DeviceObject) {    
  DEVICE_EXTENSION * DevExt;
  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  if (DevExt->UsbConfigurationDescriptor) {
    ExFreePool(DevExt->UsbConfigurationDescriptor);
    DevExt->UsbConfigurationDescriptor = NULL;
  }
  if (DevExt->UsbInterface) { 
    ExFreePool(DevExt->UsbInterface);
    DevExt->UsbInterface = NULL;
  }
  if (DevExt->PipeContext) {
    ExFreePool(DevExt->PipeContext);
    DevExt->PipeContext = NULL;
  }
  return(STATUS_SUCCESS);
}

/*********************************************************************
*
*       IrpCompletionRoutine
*
* Routine Description:
*   This routine is a completion routine.
*   In this routine we set an event.
*   Since the completion routine returns 
*   STATUS_MORE_PROCESSING_REQUIRED, the Irps,
*   which set this routine as the completion routine,
*   should be marked pending.
*
* Arguments:
*   DeviceObject - pointer to device object
*   Irp - I/O request packet
*   Context - 
*
* Return Value:
*   NT status value
*/
static NTSTATUS IrpCompletionRoutine( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID          Context) {
  KEVENT * pEvent = Context;
  KeSetEvent(pEvent, 0, FALSE);
  return STATUS_MORE_PROCESSING_REQUIRED;
}


/*********************************************************************
*
*       ReadandSelectDescriptors
*
* Function description
*   Config USB device (get device+config descriptor)
*/
NTSTATUS ReadandSelectDescriptors(IN PDEVICE_OBJECT DeviceObject) {
  URB *                  urb;
  ULONG                  siz;
  NTSTATUS               ntS;
  PUSB_DEVICE_DESCRIPTOR deviceDescriptor;
 
  urb = NULL;
  deviceDescriptor = NULL;

  urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  if (urb) {
    siz = sizeof(USB_DEVICE_DESCRIPTOR);
    deviceDescriptor = ExAllocatePool(NonPagedPool, siz);
    if (deviceDescriptor) {
      UsbBuildGetDescriptorRequest(urb,  (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                                   USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, 
                                   deviceDescriptor, NULL, siz, NULL);
      ntS = CallUSBD(DeviceObject, urb);
      if (NT_SUCCESS(ntS)) {
          ASSERT(deviceDescriptor->bNumConfigurations);
          ntS = ConfigureDevice(DeviceObject);    
      }
      ExFreePool(urb);                
      ExFreePool(deviceDescriptor);
    } else {
      DPRINT(("<usb> error: allocating deviceDescriptor"));
      ExFreePool(urb);
      ntS = STATUS_INSUFFICIENT_RESOURCES;
    }
  } else {
    DPRINT(("<usb> error: allocating urb"));
    ntS = STATUS_INSUFFICIENT_RESOURCES;
  }
  return(ntS);
}


/*********************************************************************
*
*       SelectInterfaces
*
* Routine Description:
*   This helper routine selects the configuration
* Arguments:
*   DeviceObject - pointer to device object
*   ConfigurationDescriptor - pointer to the configuration descriptor for the device
* Return Value:
*   NT status value
*/
NTSTATUS SelectInterfaces(IN PDEVICE_OBJECT                DeviceObject,
                          IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
{
  LONG                        numberOfInterfaces, 
                              interfaceNumber, 
                              interfaceindex;
  ULONG                       i;
  PURB                        urb;
  NTSTATUS                    ntS;
  DEVICE_EXTENSION *           DevExt;
  PUSB_INTERFACE_DESCRIPTOR   interfaceDescriptor;
  PUSBD_INTERFACE_LIST_ENTRY  interfaceList, 
                              tmp;
  PUSBD_INTERFACE_INFORMATION Interface;

  //
  // initialize the variables
  //
  urb = NULL;
  Interface = NULL;
  interfaceDescriptor = NULL;
  DevExt = DeviceObject->DeviceExtension;
  numberOfInterfaces = ConfigurationDescriptor->bNumInterfaces;
  interfaceindex = interfaceNumber = 0;
  //
  // Parse the configuration descriptor for the interface;
  //
  tmp = interfaceList =  ExAllocatePool(NonPagedPool, sizeof(USBD_INTERFACE_LIST_ENTRY) * (numberOfInterfaces + 1));
  if(!tmp) {
    DPRINT(("Failed to allocate mem for interfaceList\n"));
    return STATUS_INSUFFICIENT_RESOURCES;
  }
  while(interfaceNumber < numberOfInterfaces) {
    interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, 
                                                              ConfigurationDescriptor,
                                                              interfaceindex,
                                                              0, -1, -1, -1);
    if(interfaceDescriptor) {
      interfaceList->InterfaceDescriptor = interfaceDescriptor;
      interfaceList->Interface = NULL;
      interfaceList++;
      interfaceNumber++;
    }
    interfaceindex++;
  }
  interfaceList->InterfaceDescriptor = NULL;
  interfaceList->Interface = NULL;
  urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor, tmp);
  if(urb) {
    Interface = &urb->UrbSelectConfiguration.Interface;
    for(i=0; i<Interface->NumberOfPipes; i++) {
      //
      // perform pipe initialization here
      // set the transfer size and any pipe flags we use
      // USBD sets the rest of the Interface struct members
      //
      Interface->Pipes[i].MaximumTransferSize =  USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
    }
    ntS = CallUSBD(DeviceObject, urb);
    if(NT_SUCCESS(ntS)) {
      //
      // save a copy of interface information in the device extension.
      //
      DevExt->UsbInterface = ExAllocatePool(NonPagedPool, Interface->Length);
      if(DevExt->UsbInterface) {
        RtlCopyMemory(DevExt->UsbInterface, Interface, Interface->Length);
      } else {
        ntS = STATUS_INSUFFICIENT_RESOURCES;
        DPRINT(("memory alloc for UsbInterface failed\n"));
      }

      //
      // Dump the interface to the debugger
      //

      Interface = &urb->UrbSelectConfiguration.Interface;
      /*
        DPRINT(("<usb>    *********************** Interface info\n"));
        DPRINT(("<usb>    NumberOfPipes 0x%x\n",    Interface->NumberOfPipes));
        DPRINT(("<usb>    Length 0x%x\n",           Interface->Length));
        DPRINT(("<usb>    Alt Setting 0x%x\n",      Interface->AlternateSetting));
        DPRINT(("<usb>    Interface Number 0x%x\n", Interface->InterfaceNumber));
        DPRINT(("<usb>    Class, subclass, protocol 0x%x 0x%x 0x%x\n",
                             Interface->Class,
                             Interface->SubClass,
                             Interface->Protocol));
      */
      //
      // Initialize the PipeContext
      // Dump the pipe info
      //
      DevExt->PipeContext = ExAllocatePool( NonPagedPool, Interface->NumberOfPipes * sizeof(USB_PIPE_CONTEXT));
      if(DevExt->PipeContext) {
        for(i=0; i<Interface->NumberOfPipes; i++) {
          DevExt->PipeContext[i].PipeOpen = FALSE;
        }
      } else {
        ntS = STATUS_INSUFFICIENT_RESOURCES;
        DPRINT(("memory alloc for UsbInterface failed\n"));
      }
      /*
      for (i = 0; i < Interface->NumberOfPipes; i++) {
        DPRINT(("<usb>    *********************** Pipe info %d\n", i));
        DPRINT(("<usb>    PipeType 0x%x\n",            Interface->Pipes[i].PipeType));
        DPRINT(("<usb>    EndpointAddress 0x%x\n",     Interface->Pipes[i].EndpointAddress));
        DPRINT(("<usb>    MaxPacketSize 0x%x\n",       Interface->Pipes[i].MaximumPacketSize));
        DPRINT(("<usb>    Interval 0x%x\n",            Interface->Pipes[i].Interval));
        DPRINT(("<usb>    Handle 0x%x\n",              Interface->Pipes[i].PipeHandle));
        DPRINT(("<usb>    MaximumTransferSize 0x%x\n", Interface->Pipes[i].MaximumTransferSize));
      }
      */
    } else {
      DPRINT(("Failed to select an interface\n"));
    }
  } else {
    DPRINT(("USBD_CreateConfigurationRequestEx failed\n"));
    ntS = STATUS_INSUFFICIENT_RESOURCES;
  }
  if(tmp) {
    ExFreePool(tmp);
  }
  if(urb) {
    ExFreePool(urb);
  }
  return(ntS);
}

/*********************************************************************
*
*       IssueWaitWake
*
* Routine Description:
*   This routine will PoRequest a WAIT WAKE irp for the device
*
* Arguments:
*   DeviceExtension - pointer to device extension
*
* Return Value:
*   NT status value.
*/
NTSTATUS IssueWaitWake(IN DEVICE_EXTENSION * DeviceExtension ) {
  POWER_STATE poState;
  NTSTATUS    ntS;

  DPRINT(("IssueWaitWake - begins\n"));
  if(InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 1)) {
    return STATUS_DEVICE_BUSY;
  }
  InterlockedExchange(&DeviceExtension->FlagWWCancel, 0);
  //
  // lowest state from which this Irp will wake the system
  //
  poState.SystemState = DeviceExtension->DeviceCapabilities.SystemWake;
  ntS = PoRequestPowerIrp(DeviceExtension->PhysicalDeviceObject, 
                          IRP_MN_WAIT_WAKE,
                          poState, 
                          (PREQUEST_POWER_COMPLETE) WaitWakeCallback,
                          DeviceExtension, 
                          &DeviceExtension->WaitWakeIrp);
  if(!NT_SUCCESS(ntS)) {
    InterlockedExchange(&DeviceExtension->FlagWWOutstanding, 0);
  }
  DPRINT(("IssueWaitWake - ends\n"));
  return ntS;
}


NTSTATUS HandleStartDevice(IN	PDEVICE_OBJECT	DeviceObject, IN	PIRP	Irp) {
  KIRQL              oldIrql;
  KEVENT             startDeviceEvent;
  NTSTATUS           ntS;
  DEVICE_EXTENSION * DevExt;

  DPRINT(("<usb> -> HandleStartDevice\n"));

  DevExt = (DEVICE_EXTENSION *)DeviceObject->DeviceExtension;
  DevExt->UsbConfigurationDescriptor = NULL;
  DevExt->UsbInterface               = NULL;
  DevExt->PipeContext                = NULL;
  // we must start driver that are below us before sending any non-PNP IRP
  KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);
  IoCopyCurrentIrpStackLocationToNext(Irp);
  IoSetCompletionRoutine(Irp, IrpCompletionRoutine, (PVOID)&startDeviceEvent, TRUE, TRUE, TRUE);

  // wake up lower driver
  ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, Irp);
  if (ntS == STATUS_PENDING) {
    KeWaitForSingleObject(&startDeviceEvent, Executive, KernelMode, FALSE, NULL);
    ntS = Irp->IoStatus.Status;
  }
  
  if (NT_SUCCESS(ntS)) {
      // read device/config/interface descriptors
      ntS = ReadandSelectDescriptors(DeviceObject);
      if (NT_SUCCESS(ntS)) {
        // enable symbolic link for system components    
        ntS = IoSetDeviceInterfaceState(&DevExt->InterfaceName, TRUE);
        if(NT_SUCCESS(ntS)) {
          KeAcquireSpinLock(&DevExt->DevStateLock,	&oldIrql);
          SET_NEW_PNP_STATE(DevExt,	Working);
          DevExt->QueueState	=	AllowRequests;
          KeReleaseSpinLock(&DevExt->DevStateLock,	oldIrql);
          // initialize wait wake outstanding flag to false and issue a wait wake.
          DevExt->FlagWWOutstanding = 0;
          DevExt->FlagWWCancel = 0;
          DevExt->WaitWakeIrp = NULL;
          if (DevExt->WaitWakeEnable) {
              IssueWaitWake(DevExt);
          }
          ProcessQueuedRequests(DevExt);
        } else {
          DPRINT(("<usb> error: HandleStartDevice::IoSetDeviceInterfaceState %x\n", ntS));
        }
      } else {
        DPRINT(("<usb> error: HandleStartDevice::ReadandSelectDescriptors %x\n", ntS));
      }
  } else {
    DPRINT(("<usb> error: HandleStartDevice::IoCallDriver %x\n", ntS));
  }
  return(ntS);
}


NTSTATUS ConfigureDevice(IN PDEVICE_OBJECT DeviceObject) {
  PURB                          urb;
  ULONG                         siz;
  NTSTATUS                      ntS;
  DEVICE_EXTENSION *            DevExt;
  PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
  DPRINT(("<usb> -> ConfigureDevice\n"));

  urb = NULL;
  configurationDescriptor = NULL;
  DevExt = DeviceObject->DeviceExtension;
  urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
  if(urb) {
    siz = sizeof(USB_CONFIGURATION_DESCRIPTOR);
    configurationDescriptor = ExAllocatePool(NonPagedPool, siz);
    if(configurationDescriptor) {
      UsbBuildGetDescriptorRequest(urb, (USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                                   USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, 
                                   configurationDescriptor, NULL,  sizeof(USB_CONFIGURATION_DESCRIPTOR), NULL);
      ntS = CallUSBD(DeviceObject, urb);
      if(!NT_SUCCESS(ntS)) {
        DPRINT(("<usb> error: CallUSBD %x\n", ntS));
        goto ConfigureDevice_Exit;
      }
    } else {
      DPRINT(("<usb> error: allocating configDescriptor\n"));
      ntS = STATUS_INSUFFICIENT_RESOURCES;
      goto ConfigureDevice_Exit;
    }
    siz = configurationDescriptor->wTotalLength;
    ExFreePool(configurationDescriptor);
    configurationDescriptor = ExAllocatePool(NonPagedPool, siz);
    if (configurationDescriptor) {
      UsbBuildGetDescriptorRequest(urb, (USHORT)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                                  USB_CONFIGURATION_DESCRIPTOR_TYPE, 0, 0, configurationDescriptor,
                                  NULL, siz, NULL);
      ntS = CallUSBD(DeviceObject, urb);
      if (!NT_SUCCESS(ntS)) {
        DPRINT(("<usb> error: CallUSBD %x\n", ntS));
        goto ConfigureDevice_Exit;
      }
    } else {
      DPRINT(("<usb> error: allocating configDescriptor\n"));
      ntS = STATUS_INSUFFICIENT_RESOURCES;
      goto ConfigureDevice_Exit;
    }
  } else {
    DPRINT(("<usb> error: allocating urb\n"));
    ntS = STATUS_INSUFFICIENT_RESOURCES;
    goto ConfigureDevice_Exit;
  }
  if (configurationDescriptor) {
    // keep copy of config descriptor
    DevExt->UsbConfigurationDescriptor = configurationDescriptor;
    if(configurationDescriptor->bmAttributes & REMOTE_WAKEUP_MASK) {
      DPRINT(("<usb>    WaitWake enable\n"));
      DevExt->WaitWakeEnable = 1;
    } else {
      DPRINT(("<usb>    WaitWake disable\n"));
      DevExt->WaitWakeEnable = 0;
    }

⌨️ 快捷键说明

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