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

📄 ezusbsys.c

📁 usb 驱动程序源码
💻 C
📖 第 1 页 / 共 5 页
字号:
   do
   {
      ntStatus = Ezusb_CreateDeviceObject(DriverObject, &deviceObject, instance);
      instance++;
   } while (!NT_SUCCESS(ntStatus) && (instance < MAX_EZUSB_DEVICES));

   if (NT_SUCCESS(ntStatus))
   {
      pdx = deviceObject->DeviceExtension;

      //
      // Non plug and play drivers usually create the device object in
      // driver entry, and the I/O manager autimatically clears this flag.
      // Since we are creating the device object ourselves in response to 
      // a PnP START_DEVICE IRP, we need to clear this flag ourselves.
      //
      deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

      //
      // This driver uses direct I/O for read/write requests
      //
      deviceObject->Flags |= DO_DIRECT_IO;

      deviceObject->Flags |= DO_POWER_PAGABLE;

      //
      //
      // store away the Physical device Object
      //
      pdx->PhysicalDeviceObject=PhysicalDeviceObject;

      //
      // Attach to the StackDeviceObject.  This is the device object that what we 
      // use to send Irps and Urbs down the USB software stack
      //
      pdx->StackDeviceObject =
         IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject);

      ASSERT (pdx->StackDeviceObject != NULL);

      pdx->LastFailedUrbStatus = 0;

	   pdx->usage = 1;				// locked until RemoveDevice
	   KeInitializeEvent(&pdx->evRemove,
                        NotificationEvent,
                        FALSE);              // set when use count drops to zero
   }

   Ezusb_KdPrint(("exit Ezusb_PnPAddDevice (%x)\n", ntStatus));

   return ntStatus;
}


NTSTATUS
Ezusb_CreateDeviceObject(
    IN PDRIVER_OBJECT DriverObject,
    IN PDEVICE_OBJECT *DeviceObject,
    LONG Instance
    )
/*++

Routine Description:
    Creates a Functional DeviceObject

Arguments:
    DriverObject - pointer to the driver object for device
    DeviceObject - pointer to DeviceObject pointer to return
                   created device object.
    Instance - instnace of the device create.

Return Value:
    STATUS_SUCCESS if successful,
    STATUS_UNSUCCESSFUL otherwise
--*/
{
   NTSTATUS ntStatus;
   WCHAR deviceLinkBuffer[]  = L"\\DosDevices\\Ezusb-0";
   UNICODE_STRING deviceLinkUnicodeString;
   WCHAR deviceNameBuffer[]  = L"\\Device\\Ezusb-0";
   UNICODE_STRING deviceNameUnicodeString;
   PDEVICE_EXTENSION pdx;
   STRING deviceName;

   Ezusb_KdPrint(("enter Ezusb_CreateDeviceObject instance = %d\n", Instance));

   //
   // fix up device names based on Instance
   //
   deviceLinkBuffer[18] = (USHORT) ('0' + Instance);
   deviceNameBuffer[14] = (USHORT) ('0' + Instance);

   Ezusb_KdPrint(("Create Device name (%ws)\n", deviceNameBuffer));

   RtlInitUnicodeString (&deviceNameUnicodeString,
                         deviceNameBuffer);

   //
   //Print out the unicode string
   //NOTE:  We must first convert the string to Unicode due to a bug in the Debugger that does not allow
   //       Unicode Strings to be printed to the debug device.
   //
   deviceName.Buffer = NULL;

   ntStatus = RtlUnicodeStringToAnsiString (&deviceName,
                                          &deviceNameUnicodeString, 
                                          TRUE);


   if (NT_SUCCESS(ntStatus))
   {
      Ezusb_KdPrint(("Create Device Name (%s)\n", deviceName.Buffer));
      RtlFreeAnsiString (&deviceName);
   }
   else
   {
      Ezusb_KdPrint(("Unicode to Ansi str failed w/ ntStatus: 0x%x\n",ntStatus));
   }

   ntStatus = IoCreateDevice (DriverObject,
                              sizeof (DEVICE_EXTENSION),
                              &deviceNameUnicodeString,
                              FILE_DEVICE_UNKNOWN,
                              0,
                              FALSE,
                              DeviceObject);


   if (NT_SUCCESS(ntStatus))
   {

      // Initialize our device extension
      pdx = (PDEVICE_EXTENSION) ((*DeviceObject)->DeviceExtension);

      RtlCopyMemory(pdx->DeviceLinkNameBuffer,
                   deviceLinkBuffer,
                   sizeof(deviceLinkBuffer));

      pdx->OpenHandles = 0;
      pdx->ConfigurationHandle = NULL;
      pdx->DeviceDescriptor = NULL;
      pdx->NeedCleanup = FALSE;
      pdx->DataRingBuffer = NULL;
      pdx->DescriptorRingBuffer = NULL;
      pdx->Started = FALSE;

      // Initialize our interface
      pdx->Interface = NULL;

      RtlInitUnicodeString (&deviceLinkUnicodeString,
                           deviceLinkBuffer);

      Ezusb_KdPrint(("Create DosDevice name (%ws)\n", deviceLinkBuffer));

      ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
                                      &deviceNameUnicodeString);

   }

   Ezusb_KdPrint(("exit Ezusb_CreateDeviceObject (%x)\n", ntStatus));

   return ntStatus;
}

NTSTATUS
Ezusb_CallUSBD(
    IN PDEVICE_OBJECT fdo,
    IN PURB Urb
    )
/*++

Routine Description:
   Passes a Usb Request Block (URB) to the USB class driver (USBD)

   Note that we create our own IRP here and use it to send the request to
   the USB software subsystem.  This means that this routine is essentially
   independent of the IRP that caused this driver to be called in the first
   place.  The IRP for this transfer is created, used, and then destroyed
   in this routine.

   However, note that this routine uses the Usb Request Block (urb) passed
   in by the caller as the request block for the USB software stack.

   Implementation of this routine may be changed depending on the specific
   requirements of your driver.  For example, while this routine issues a
   synchronous request to the USB stack, you may wish to implement this as an
   asynchronous request in which you set an IoCompletionRoutine to be called
   when the request is complete.

Arguments:
   fdo - pointer to the device object for this instance of an Ezusb Device
   Urb          - pointer to Urb request block

Return Value:
   STATUS_SUCCESS if successful,
   STATUS_UNSUCCESSFUL otherwise

--*/
{
   NTSTATUS ntStatus, status = STATUS_SUCCESS;
   PDEVICE_EXTENSION pdx;
   PIRP irp;
   KEVENT event;
   IO_STATUS_BLOCK ioStatus;
   PIO_STACK_LOCATION nextStack;

   Ezusb_KdPrint (("enter Ezusb_CallUSBD\n"));

   pdx = fdo->DeviceExtension;

   // issue a synchronous request (see notes above)
   KeInitializeEvent(&event, NotificationEvent, FALSE);

   irp = IoBuildDeviceIoControlRequest(
             IOCTL_INTERNAL_USB_SUBMIT_URB,
             pdx->StackDeviceObject,
             NULL,
             0,
             NULL,
             0,
             TRUE, /* INTERNAL */
             &event,
             &ioStatus);

   // Prepare for calling the USB driver stack
   nextStack = IoGetNextIrpStackLocation(irp);
   ASSERT(nextStack != NULL);

   // Set up the URB ptr to pass to the USB driver stack
   nextStack->Parameters.Others.Argument1 = Urb;

   Ezusb_KdPrint (("Calling USB Driver Stack\n"));

   //
   // Call the USB class driver to perform the operation.  If the returned status
   // is PENDING, wait for the request to complete.
   //
   ntStatus = IoCallDriver(pdx->StackDeviceObject,
                         irp);

   Ezusb_KdPrint (("return from IoCallDriver USBD %x\n", ntStatus));

   if (ntStatus == STATUS_PENDING)
   {
      Ezusb_KdPrint (("Wait for single object\n"));

      status = KeWaitForSingleObject(
                    &event,
                    Suspended,
                    KernelMode,
                    FALSE,
                    NULL);

      Ezusb_KdPrint (("Wait for single object, returned %x\n", status));
   }
   else
   {
      ioStatus.Status = ntStatus;
   }

   Ezusb_KdPrint (("URB status = %x status = %x irp status %x\n",
     Urb->UrbHeader.Status, status, ioStatus.Status));

   //
   // USBD maps the error code for us.  USBD uses error codes in its URB
   // structure that are more insightful into USB behavior. In order to
   // match the NT Status codes, USBD maps its error codes into more general NT
   // error categories so higher level drivers can decipher the error codes
   // based on standard NT error code definitions.
   //
   ntStatus = ioStatus.Status;

   //
   // If the URB status was not USBD_STATUS_SUCCESS, we save a copy of the
   // URB status in the device extension.  After a failure, another IOCTL,
   // IOCTL_EZUSB_GET_LAST_ERROR can be used to retrieve the URB status
   // for the most recently failed URB.  Of course, this status gets
   // overwritten by subsequent failures, but it's better than nothing.
   //
   if (!(USBD_SUCCESS(Urb->UrbHeader.Status)))
      pdx->LastFailedUrbStatus = Urb->UrbHeader.Status;

   //
   // if ioStatus.Status indicates an error (ie. the IRP failed) then return that.
   // If ioStatus.Status indicates success, it is still possible that what we were
   // trying to do failed.  For example, if the IRP is cancelled, the status returned
   // by the I/O manager for the IRP will not indicate an error.  In that case, we
   // should check the URB status.  If it indicates anything other than
   // USBD_SUCCESS, then we should return STATUS_UNSUCCESSFUL.
   //
   if (NT_SUCCESS(ntStatus))
   {
      if (!(USBD_SUCCESS(Urb->UrbHeader.Status)))
         ntStatus = STATUS_UNSUCCESSFUL;
   }

   Ezusb_KdPrint(("exit Ezusb_CallUSBD (%x)\n", ntStatus));

   return ntStatus;
}

NTSTATUS
Ezusb_ConfigureDevice(
    IN  PDEVICE_OBJECT fdo
    )
/*++
Routine Description:
   Configures the USB device via USB-specific device requests and interaction
   with the USB software subsystem.

Arguments:
   fdo - pointer to the device object for this instance of the Ezusb Device

Return Value:
   NT status code
--*/
{
   PDEVICE_EXTENSION pdx;
   NTSTATUS ntStatus;
   PURB urb = NULL;
   ULONG siz;
   PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor = NULL;

   Ezusb_KdPrint (("enter Ezusb_ConfigureDevice\n"));

   pdx = fdo->DeviceExtension;

   //
   // Get memory for the USB Request Block (urb).
   //
   urb = ExAllocatePool(NonPagedPool,
                      sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));

   if (urb != NULL)
   {
      //
      // Set size of the data buffer.  Note we add padding to cover hardware faults
      // that may cause the device to go past the end of the data buffer
      //
        siz = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 16;

        // Get the nonpaged pool memory for the data buffer
        configurationDescriptor = ExAllocatePool(NonPagedPool, siz);

        if (configurationDescriptor != NULL) {

            UsbBuildGetDescriptorRequest(urb,
                                         (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                                         USB_CONFIGURATION_DESCRIPTOR_TYPE,
                                         0,
                                         0,
                                         configurationDescriptor,
                                         NULL,
                                         sizeof (USB_CONFIGURATION_DESCRIPTOR),/* Get only the configuration descriptor */
                                         NULL);

            ntStatus = Ezusb_CallUSBD(fdo, urb);

            if (NT_SUCCESS(ntStatus)) {
                Ezusb_KdPrint (("Configuration Descriptor is at %x, bytes txferred: %d\n\
                                  Configuration Descriptor Actual Length: %d\n",
                                  configurationDescriptor,
                                  urb->UrbControlDescriptorRequest.TransferBufferLength,
                                  configurationDescriptor->wTotalLength));
            }//if

        } else {
            ntStatus = STATUS_NO_MEMORY;
            goto Exit_EzusbConfigureDevice;
        }//if-else

        // Determine how much data is in the entire configuration descriptor
        // and add extra room to protect against accidental overrun
        siz = configurationDescriptor->wTotalLength + 16;

        //  Free up the data buffer memory just used
        ExFreePool(configurationDescriptor);
        configurationDescriptor = NULL;

        // Get nonpaged pool memory for the data buffer
        configurationDescriptor = ExAllocatePool(NonPagedPool, siz);

        // Now get the entire Configuration Descriptor
        if (configurationDescriptor != NULL) {
            UsbBuildGetDescriptorRequest(urb,
                                         (USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                                         USB_CONFIGURATION_DESCRIPTOR_TYPE,
                                         0,
                                         0,
                                         configurationDescriptor,
                                         NULL,
                                         siz,  // Get all the descriptor data
                                         NULL);

            ntStatus = Ezusb_CallUSBD(fdo, urb);

            if (NT_SUCCESS(ntStatus)) {
                Ezusb_KdPrint (("Entire Configuration Descriptor is at %x, bytes txferred: %d\n",
                                  configurationDescriptor,
                                  urb->UrbControlDescriptorRequest.TransferBufferLength));
            } else {
                //Error in getting configuration descriptor
                goto Exit_EzusbConfigureDevice;
            }//else

⌨️ 快捷键说明

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