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

📄 usbfx2lk_usb.cpp

📁 USBFX2LK WDM drive for OSR s USB FX2 Learning Kit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//  
//   Since the support in the DDK isn't there, we simply
//    added our own vendor specific command to determine if
//    we're running at full or high speed. If you don't have
//    this amount of flexibility with your device, you would 
//    need to cut and paste the appropriate definitions out 
//    of USBBUSIF.H in the Windows XP or Server 2003 build environment
//    with the caveat of it not being officially documented or 
//    supported
//
///////////////////////////////////////////////////////////////////////////////
VOID DetermineDeviceSpeed(PUSBFX2LK_EXT DevExt) 
{

    DevExt->RunningAtHighSpeed = FALSE;

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("DetermineDeviceSpeed: Enter\n"));

#ifdef W2K

    NTSTATUS status;
    URB urb;
    ULONG transferFlags;

    //
    // See the Notes section above, we've created
    //  a custom command to determine this while
    //  running on Win2K
    //
    RtlZeroMemory(&urb,sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST));

    //
    // Build the vendor request with the appropriate 
    //  flags and command
    //
    UsbBuildVendorRequest(&urb,
                          URB_FUNCTION_VENDOR_DEVICE,
                          sizeof(struct  _URB_CONTROL_VENDOR_OR_CLASS_REQUEST),
                          (USBD_SHORT_TRANSFER_OK | USBD_TRANSFER_DIRECTION_IN),
                          0,
                          USBFX2LK_IS_HIGH_SPEED,
                          0,
                          0,
                          &DevExt->RunningAtHighSpeed,
                          NULL,
                          sizeof(BOOLEAN),
                          NULL);

    //
    // Make the request active on the device
    //
    status = SubmitUrb(DevExt, &urb);

    if(!NT_SUCCESS(status)) {
        
        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,
            ("DetermineDeviceSpeed: Failed to query speed - 0x%x (%s)\n",
                status,OsrNtStatusToString(status)));

    } else {

        OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,
            ("DetermineDeviceSpeed: Device is running at %s speed.\n",
            DevExt->RunningAtHighSpeed ? "HIGH" : "FULL"));
    }

#else

    NTSTATUS status;
    PIRP irp;
    KEVENT event;
    PIO_STACK_LOCATION ioNextStack;
    USB_BUS_INTERFACE_USBDI_V1 usbInterface;

    //
    // The way we determine our device speed on
    //  XP and later is by sending an IRP_MJ_PNP/
    //  IRP_MN_QUERY_INTERFACE IRP for the 
    //  USB_BUS_INTERFACE_USBDI_GUID interface.
    //

    //
    // Allocate an IRP with an appropriate number
    //  of stack locations for this request
    //
    irp = IoAllocateIrp(DevExt->DeviceToSendIrpsTo->StackSize,
                        FALSE);

    if(!irp) {

        //
        // Can't allocate an IRP so we can't determine if
        //  we're at high speed.
        //
        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,
            ("DetermineDeviceSpeed: Failed to allocate an IRP. Defaulting to full speed\n"));
        return;
    }

    //
    // Assume failure.
    //
    irp->IoStatus.Status = STATUS_NOT_SUPPORTED;

    //
    // Initialize the IRP that we will be waiting on for the 
    //  IRP to complete
    //
    KeInitializeEvent(&event, NotificationEvent, FALSE);

    //
    // Get a pointer to the NEXT irp stack location. 
    //  Because we are the ones who allocated the IRP,
    //  we do not have a current IRP stack location. 
    //  Also, since we are passing the IRP down to the 
    //  next lower driver, we want to modify the next 
    //  stack location
    //
    ioNextStack = IoGetNextIrpStackLocation(irp);

    //
    // This is a PNP/QUERY_INTERFACE request
    //
    ioNextStack->MajorFunction = IRP_MJ_PNP;
    ioNextStack->MinorFunction = IRP_MN_QUERY_INTERFACE;

    //
    // Setup the QUERY_INTERFACE stack location parameters
    //

    //
    // Indicate which interface we're querying for
    //
    ioNextStack->Parameters.QueryInterface.InterfaceType = 
                                        &USB_BUS_INTERFACE_USBDI_GUID;

    //
    // Indicate which version of the interface we are querying
    //
    ioNextStack->Parameters.QueryInterface.Version = USB_BUSIF_USBDI_VERSION_1;

    //
    // Setup the buffer for the returned interface
    //
    ioNextStack->Parameters.QueryInterface.Interface = (PINTERFACE)&usbInterface;


    //
    // Set up the size of the buffer
    //
    ioNextStack->Parameters.QueryInterface.Size = 
                                    sizeof(USB_BUS_INTERFACE_USBDI_V1);


#ifdef IoForwardIrpSynchronously
    //
    // Pass the IRP down to the lower driver
    //
    if(IoForwardIrpSynchronously(DevExt->DeviceToSendIrpsTo,irp)) {
        status = Irp->IoStatus.Status;
    } else {
        status = STATUS_UNSUCCESSFUL;
    }

#else //IoForwardIrpSynchronously

    //
    // Setup a completion routine, passing the event as the 
    //  context parameter. When the completion routine runs, it
    //  will set the event and stop completion processing by 
    //  returning STATUS_MORE_PROCESSING_REQUIRED.
    //
    IoSetCompletionRoutine(irp,
                           DetermineDeviceSpeedCompletionRoutine,
                           &event,
                           TRUE,
                           TRUE,
                           TRUE);

    //
    // Pass the IRP down to the lower driver
    //
    status = IoCallDriver(DevExt->DeviceToSendIrpsTo, irp);

    if(status == STATUS_PENDING) {

        //
        // If the IRP was pended, then we must wait for the 
        //  event to be signalled by our completion routine
        //
        (VOID)OsrWaitForSingleObject(&event);

        //
        // Retrieve the real completion status from the
        //  IRP
        //
        status = irp->IoStatus.Status;
    }
#endif //IoForwardIrpSynchronously
    //
    // DId the call succeed?
    //
    if(NT_SUCCESS(status)) {

        //
        // We should have a valid IsDeviceHighSpeed routine to
        //  call through the interface
        //
        ASSERT(usbInterface.IsDeviceHighSpeed);

        //
        // Call the routine and see what we are running at
        //
        DevExt->RunningAtHighSpeed = usbInterface.IsDeviceHighSpeed(usbInterface.BusContext);


        OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_PNP_INFO,
            ("DetermineDeviceSpeed: Device is running at %s speed.\n",
            DevExt->RunningAtHighSpeed ? "HIGH" : "FULL"));

    } else {

        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,
            ("DetermineDeviceSpeed: Failed to query interface - 0x%x (%s)\n",
            status,OsrNtStatusToString(status)));

    }

    //
    // Delete the Irp that we allocated.
    //
    IoFreeIrp(irp);

#endif

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("DetermineDeviceSpeed: Exit\n"));

    return;
}

#ifndef IoForwardIrpSynchronously
///////////////////////////////////////////////////////////////////////////////
//
// DetermineDeviceSpeedCompletionRoutine
//
//  This routine is a completion routine used to signal the completion
//  of the IRP sent down by DetermineDeviceSpeed. It's only job is to 
//  set the event passed in as the context parameter and stop the processing
//  of the IRP.
//
//
//  INPUTS:
//
//      DeviceObject  -  Address of the Devices Device Extension.
//      Irp           -  Address of the QUERY_INTERFACE IRP sent down by 
//                       DetermineDeviceSpeed
//      Context       -  A pointer to a KEVENT
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      STATUS_MORE_PROCESSING_REQUIRED to stop completion processing of the IRP
//
//  IRQL:
//
//      IRQL <= DISPATCH_LEVEL
//
//  CONTEXT:
//
//      Arbitrary Context
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS DetermineDeviceSpeedCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
{    
    
    PKEVENT event = (PKEVENT)Context;

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("DetermineDeviceSpeedCompletionRoutine: Enter\n"));

    UNREFERENCED_PARAMETER(DeviceObject);
    UNREFERENCED_PARAMETER(Irp);

    //
    // Set the event
    //
    KeSetEvent(event, EVENT_INCREMENT, FALSE);

    //
    // And stop completion processing of the IRP
    // 

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("DetermineDeviceSpeedCompletionRoutine: Exit\n"));

    return STATUS_MORE_PROCESSING_REQUIRED;

}
#endif //IoForwardIrpSynchronously

///////////////////////////////////////////////////////////////////////////////
//
// SubmitUrb
//
//  This routine is called to synchronously submit the Input Urb to the USB
//  device.
//
//
//  INPUTS:
//
//      DevExt  -  Address of the Devices Device Extension.
//      Urb      -  Address of the USB to be delivered.
//
//  OUTPUTS:
//
//      None
//
//  RETURNS:
//
//      None
//
//  IRQL:
//
//      IRQL == PASSIVE_LEVEL
//
//  CONTEXT:
//
//      Arbitrary Context
//
//  NOTES:
//
///////////////////////////////////////////////////////////////////////////////
NTSTATUS SubmitUrb(PUSBFX2LK_EXT DevExt,PURB Urb)
{
    PIRP               irp = NULL;
    KEVENT             event;
    NTSTATUS           status;
    IO_STATUS_BLOCK    ioStatus;
    PIO_STACK_LOCATION nextStack;

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("SubmitUrb: Enter\n"));

    //
    // Initialize the Event that will be waited on if the underlying
    // driver returns STATUS_PENDING
    //
    KeInitializeEvent(&event, NotificationEvent, FALSE);

    //
    // Build the Irp to be used to submit the URB.
    //
    irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB, 
                                        DevExt->DeviceToSendIrpsTo,
                                        NULL, 
                                        0, 
                                        NULL, 
                                        0, 
                                        TRUE, 
                                        &event, 
                                        &ioStatus);

    if(!irp) {
        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_USB,
            ("SubmitUrb: IoBuildDeviceIoControlRequest failed\n"));
        return STATUS_INSUFFICIENT_RESOURCES;
    }


    //
    // Put the URB to be submitted into the Others part of the next stack location.
    // This urb will be passed to the USB Bus Driver for submission to our USB
    // device.
    //
    nextStack = IoGetNextIrpStackLocation(irp);
    nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
    nextStack->Parameters.Others.Argument1 = Urb;

    //
    // Increment the number of outstanding requests.
    //
    OsrIncrementOutstandingIoCount(DevExt,__FILE__,__LINE__);

    //
    // Submit the Irp to the driver.
    //
    status = IoCallDriver(DevExt->DeviceToSendIrpsTo,irp);

    //
    // Wait for a response if not already completed.
    //
    if(status == STATUS_PENDING) {
        
        (VOID)OsrWaitForSingleObject(&event);

        //
        //  Get the completion status
        //
        status = ioStatus.Status;
    }

    //
    // Decrement the number of outstanding requests.
    //
    OsrDecrementOutstandingIoCount(DevExt,__FILE__,__LINE__);

    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_USB,("SubmitUrb: Exit\n"));

    return status;
}

///////////////////////////////////////////////////////////////////////////////
//
// SubmitIrpAndUrbAsync
//
//  This routine is called to asynchronously submit the Input IRP and Urb to 
//  the USB device.
//
//
//  INPUTS:
//
//      DevExt  -  Address of the Devices Device Extension.
//      IRP     -  Address of the IRP to setup for the URB transfer

⌨️ 快捷键说明

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