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

📄 dev.c

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

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

#include "Main.h"

/*********************************************************************
*
*       CompleteRequest
*
* Function description
*   Generic IRP complete routine
*/
NTSTATUS CompleteRequest(IN PIRP Irp, IN NTSTATUS ntS, IN ULONG_PTR Info) {
  Irp->IoStatus.Status = ntS;
  Irp->IoStatus.Information = Info;
  IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  return ntS;
}

/*********************************************************************
*
*       PipeWithName
*
* Function description
*   ??? (RS)
*/
PUSB_PIPE_CONTEXT PipeWithName(IN PDEVICE_OBJECT  DeviceObject, IN PUNICODE_STRING FileName) {
  LONG                  ix;
  ULONG                 uval; 
  ULONG                 nameLength;
  ULONG                 umultiplier;
  DEVICE_EXTENSION *     DevExt;
  PUSB_PIPE_CONTEXT pipeContext;

  pipeContext = NULL;
  nameLength = (FileName->Length / sizeof(WCHAR));
  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  if (nameLength != 0) {    
    DPRINT(("<usb> using pipe %ws\n", FileName->Buffer));
    ix = nameLength - 1;
    while ((ix > -1) && ((FileName->Buffer[ix] < (WCHAR) '0')  || (FileName->Buffer[ix] > (WCHAR) '9'))) {
      ix--;
    }
    if (ix > -1) {
      uval = 0;
      umultiplier = 1;
      while ((ix > -1) && (FileName->Buffer[ix] >= (WCHAR) '0') && (FileName->Buffer[ix] <= (WCHAR) '9')) {
        uval += (umultiplier * (ULONG) (FileName->Buffer[ix] - (WCHAR) '0'));
        ix--;
        umultiplier *= 10;
      }
      if (uval < 6 && DevExt->PipeContext) {
        pipeContext = &DevExt->PipeContext[uval];
      }
    } else {
      DPRINT(("<usb> error: invalid pipe name format\n"));
    }
  }

  return pipeContext;
}


/*********************************************************************
*
*       ResetParentPort
*
* Function description
*   ??? (RS)
*/
NTSTATUS ResetParentPort(IN PDEVICE_OBJECT DeviceObject) {
  NTSTATUS           ntS;
  KEVENT             event;
  PIRP               irp;
  IO_STATUS_BLOCK    ioStatus;
  PIO_STACK_LOCATION nextStack;
  DEVICE_EXTENSION *  DevExt;

  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  KeInitializeEvent(&event, NotificationEvent, FALSE);

  irp = IoBuildDeviceIoControlRequest(
                  IOCTL_INTERNAL_USB_RESET_PORT,
                  DevExt->TopOfStackDeviceObject,
                  NULL,
                  0,
                  NULL,
                  0,
                  TRUE,
                  &event,
                  &ioStatus);
  if (irp == NULL) {
    DPRINT(("<usb> error: allocating IRP\n"));
    ntS = STATUS_INSUFFICIENT_RESOURCES;
  } else {
    nextStack = IoGetNextIrpStackLocation(irp);
    ASSERT(nextStack != NULL);
    ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, irp);
    if (STATUS_PENDING == ntS) {
      KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
    } else {
      ioStatus.Status = ntS;
    }
    ntS = ioStatus.Status;
  }
  return ntS;
}



/*********************************************************************
*
*       DispatchCreate
*
* Function description
*   Callback for IRP_MJ_CREATE
*/

NTSTATUS DispatchCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  ULONG                        i;
  NTSTATUS                     ntS;
  FILE_OBJECT *                fileObject;
  DEVICE_EXTENSION *           DevExt;
  IO_STACK_LOCATION *          irpStack;
  USB_PIPE_CONTEXT *           pipeContext;
  USBD_INTERFACE_INFORMATION * interface;

  PAGED_CODE();
  DPRINT(("<usb> IRP_MJ_CREATE\n"));
  irpStack = IoGetCurrentIrpStackLocation(Irp);
  fileObject = irpStack->FileObject;
  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  // test device state
  if (DevExt->DeviceState == Working) {
    // test USB interface
    interface = DevExt->UsbInterface;
    if (interface) {
      if (fileObject) {
        fileObject->FsContext = NULL;
        // opening a device
        if (fileObject->FileName.Length == 0) {
          DPRINT(("<usb> opening device"));                  
          ntS = STATUS_SUCCESS;
          InterlockedIncrement(&DevExt->OpenHandleCount);
        // opening a pipe
        } else {
          DPRINT(("<usb> opening pipe"));
          pipeContext = PipeWithName(DeviceObject, &fileObject->FileName);
          if (pipeContext) {
            for (i=0; i<interface->NumberOfPipes; i++) {
              if (pipeContext == &DevExt->PipeContext[i]) {
                // got a match
                DPRINT(("<usb> open pipe %d\n", i));
                fileObject->FsContext = &interface->Pipes[i];
                ASSERT(fileObject->FsContext);
                pipeContext->PipeOpen = TRUE;
                InterlockedIncrement(&DevExt->OpenHandleCount);
                ntS = STATUS_SUCCESS;
              }
            }
          } else {
              ntS = STATUS_INVALID_PARAMETER;
          }
        }
      } else {
        ntS = STATUS_INVALID_PARAMETER;
      }
    } else {
      DPRINT(("<usb> USB interface not found\n"));
      ntS = STATUS_INVALID_DEVICE_STATE;
    }
  } else {
      ntS = STATUS_INVALID_DEVICE_STATE;
  }

  return(CompleteRequest(Irp, ntS, 0));
}


/*********************************************************************
*
*       DispatchClose
*
* Function description
*   Callback for IRP_MJ_CLOSE
*/
NTSTATUS DispatchClose(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp) {
  NTSTATUS               ntS;
  PFILE_OBJECT           pFileObject;
  DEVICE_EXTENSION *     pDevExt;
  PIO_STACK_LOCATION     pIrpStack;
  PUSB_PIPE_CONTEXT      pPipeContext;
  PUSBD_PIPE_INFORMATION pPipeInformation;

  PAGED_CODE();
  pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  pFileObject = pIrpStack->FileObject;
  pPipeContext = NULL;
  pPipeInformation = NULL;
  pDevExt = (DEVICE_EXTENSION *) pDeviceObject->DeviceExtension;
  if (pFileObject && pFileObject->FsContext) {
    pPipeInformation = pFileObject->FsContext;
    if (pFileObject->FileName.Length != 0) {
      pPipeContext = PipeWithName(pDeviceObject, &pFileObject->FileName);
    }
    if(pPipeContext && pPipeContext->PipeOpen) {
      pPipeContext->PipeOpen = FALSE;
    }
  }
  ntS = STATUS_SUCCESS;
  CompleteRequest(pIrp, ntS, 0);
  InterlockedDecrement(&pDevExt->OpenHandleCount);
  return(ntS);
}

/*********************************************************************
*
*       DispatchClean
*
* Function description
*   Callback for IRP_MJ_CLEAN
*/
NTSTATUS DispatchClean(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  DEVICE_EXTENSION *  DevExt;
  KIRQL              oldIrql;
  LIST_ENTRY         cleanupList;
  PLIST_ENTRY        thisEntry, 
                     nextEntry, 
                     listHead;
  PIRP               pendingIrp;
  PIO_STACK_LOCATION pendingIrpStack, 
                     irpStack;
  NTSTATUS           ntS;

  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  irpStack = IoGetCurrentIrpStackLocation(Irp);
  InitializeListHead(&cleanupList);
  DPRINT(("<usb> IRP_MJ_CLEAN\n"));
  DevIoIncrement(DevExt);
  KeAcquireSpinLock(&DevExt->QueueLock, &oldIrql);
  // delete all fileobject related IRPs
  listHead = &DevExt->NewRequestsQueue;
  for (thisEntry=listHead->Flink, nextEntry=thisEntry->Flink;
       thisEntry != listHead;
       thisEntry=nextEntry, nextEntry=thisEntry->Flink) {
    pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);
    pendingIrpStack = IoGetCurrentIrpStackLocation(pendingIrp);
    if (irpStack->FileObject == pendingIrpStack->FileObject) {
        RemoveEntryList(thisEntry);
        // NULL cancel routine
        if (IoSetCancelRoutine(pendingIrp, NULL) == NULL) {
            InitializeListHead(thisEntry);
        } else {
            InsertTailList(&cleanupList, thisEntry);
        }
    }
  }
  KeReleaseSpinLock(&DevExt->QueueLock, oldIrql);
  // walk thru the cleanup list and cancel all IRP
  while (!IsListEmpty(&cleanupList)) {
    // complete the Irp
    thisEntry = RemoveHeadList(&cleanupList);
    pendingIrp = CONTAINING_RECORD(thisEntry, IRP, Tail.Overlay.ListEntry);
    CompleteRequest(pendingIrp, STATUS_CANCELLED, 0);
  }
  ntS = CompleteRequest(Irp, STATUS_SUCCESS, 0);
  DevIoDecrement(DevExt);
  return(ntS);
}

/*********************************************************************
*
*       DispatchIoctl
*
* Function description
*   Callback for IRP_MJ_DEVICE_CONTROL
*/
NTSTATUS DispatchIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
  ULONG              code;
  PVOID              ioBuffer;
  ULONG              inputBufferLength;
  ULONG              outputBufferLength;
  ULONG              info;
  NTSTATUS           ntS;
  DEVICE_EXTENSION *  DevExt;
  PIO_STACK_LOCATION irpStack;

  info = 0;
  irpStack = IoGetCurrentIrpStackLocation(Irp);
  code = irpStack->Parameters.DeviceIoControl.IoControlCode;
  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;

  ioBuffer           = Irp->AssociatedIrp.SystemBuffer;
  inputBufferLength  = irpStack->Parameters.DeviceIoControl.InputBufferLength;
  outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;

  if (DevExt->DeviceState != Working) {
    DPRINT(("<usb> error: invalid device state\n"));
    return(CompleteRequest(Irp, STATUS_INVALID_DEVICE_STATE, 0));
  }

  DevIoIncrement(DevExt);

  switch (code) {
  case IOCTL_USB_BULK_RESET_PIPE:     // reset pipe
  {
    PFILE_OBJECT           fileObject;
    PUSBD_PIPE_INFORMATION pipe;

    DPRINT(("<usb> IOCTL_USB_BULK_RESET_PIPE"));
    fileObject = irpStack->FileObject;
    if (fileObject == NULL) {
      ntS = STATUS_INVALID_PARAMETER;
      break;
    }

    pipe = (PUSBD_PIPE_INFORMATION) fileObject->FsContext;
    if (pipe) {
      ntS = ResetPipe(DeviceObject, pipe);
    } else {  
      ntS = STATUS_INVALID_PARAMETER;
    }
    break;
  }
  // get config descriptor
  case IOCTL_USB_BULK_GET_CONFIG_DESCRIPTOR:
  {
    ULONG length;

    DPRINT(("<usb> IOCTL_USB_BULK_GET_CONFIG_DESCRIPTOR"));
    if (DevExt->UsbConfigurationDescriptor) {
      length = DevExt->UsbConfigurationDescriptor->wTotalLength;
      if (outputBufferLength >= length) {
        RtlCopyMemory(ioBuffer, DevExt->UsbConfigurationDescriptor, length);
        info = length;
        ntS = STATUS_SUCCESS;
      } else {      
        ntS = STATUS_BUFFER_TOO_SMALL;
      }
    } else {
      ntS = STATUS_UNSUCCESSFUL;
    }
    break;
  }

  // reset device
  case IOCTL_USB_BULK_RESET_DEVICE:
  {
    DPRINT(("<usb> IOCTL_USB_BULK_RESET_DEVICE"));
    ntS = ResetDevice(DeviceObject);
    break;
  }
  
  default:
    ntS = STATUS_INVALID_DEVICE_REQUEST;
    break;
  }

  CompleteRequest(Irp, ntS, info);
  DevIoDecrement(DevExt);

  return(ntS);
}

/*********************************************************************
*
*       ResetPipe
*
* Function description
*   // reset pipe by handle  
*/
NTSTATUS ResetPipe(IN PDEVICE_OBJECT DeviceObject, IN PUSBD_PIPE_INFORMATION PipeInfo) {
  PURB              urb;
  NTSTATUS          ntS;
  DEVICE_EXTENSION * DevExt;

  urb = NULL;
  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;

  urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
  if (urb) {
    urb->UrbHeader.Length = (USHORT) sizeof(struct _URB_PIPE_REQUEST);
    urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
    urb->UrbPipeRequest.PipeHandle = PipeInfo->PipeHandle;
    ntS = CallUSBD(DeviceObject, urb);
    if (!NT_SUCCESS(ntS)) {
      DPRINT(("<usb> error: ResetPipe::CallUSBD %x"));
    } else {
      DPRINT(("<usb> pipe reseted\n"));
      ntS = STATUS_SUCCESS;
    }
    
    ExFreePool(urb);
  } else {
    DPRINT(("<usb> error: allocating urb"));
    ntS = STATUS_INSUFFICIENT_RESOURCES;
  }

  return(ntS);
}

/*********************************************************************
*
*       GetPortStatus
*
* Function description
*   ???
*/
static NTSTATUS _GetPortStatus(IN PDEVICE_OBJECT DeviceObject, IN OUT PULONG PortStatus) {
  NTSTATUS           ntS;
  KEVENT             event;
  PIRP               irp;
  IO_STATUS_BLOCK    ioStatus;
  PIO_STACK_LOCATION nextStack;
  DEVICE_EXTENSION *  DevExt;

  DevExt = (DEVICE_EXTENSION *) DeviceObject->DeviceExtension;
  *PortStatus = 0;

  KeInitializeEvent(&event, NotificationEvent, FALSE);

  irp = IoBuildDeviceIoControlRequest(
                  IOCTL_INTERNAL_USB_GET_PORT_STATUS,
                  DevExt->TopOfStackDeviceObject,
                  NULL,
                  0,
                  NULL,
                  0,
                  TRUE,
                  &event,
                  &ioStatus);

  if (irp == NULL) {
      DPRINT(("<usb> error: allocating IRP\n"));
      ntS = STATUS_INSUFFICIENT_RESOURCES;
  } else {
    nextStack = IoGetNextIrpStackLocation(irp);
    ASSERT(nextStack != NULL);
    nextStack->Parameters.Others.Argument1 = PortStatus;

    ntS = IoCallDriver(DevExt->TopOfStackDeviceObject, irp);

    if (ntS == STATUS_PENDING) {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
    } else {
        ioStatus.Status = ntS;
    }
    ntS = ioStatus.Status;
  }

  return(ntS);
}

/*********************************************************************
*
*       ResetDevice
*
* Function description
*   reset device ???
*/
NTSTATUS ResetDevice(IN PDEVICE_OBJECT DeviceObject) {
  NTSTATUS ntS;
  ULONG    portStatus;

  ntS = _GetPortStatus(DeviceObject, &portStatus);
  if((NT_SUCCESS(ntS))  && (!(portStatus & USBD_PORT_ENABLED)) && (portStatus & USBD_PORT_CONNECTED)) {
    ntS = ResetParentPort(DeviceObject);
  }

  return(ntS);
}





⌨️ 快捷键说明

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