www.pudn.com > usbfx2lk_v1.1.zip > usbfx2lk_devctrl.cpp


/////////////////////////////////////////////////////////////////////////////// 
// 
//    (C) Copyright 2005 OSR Open Systems Resources, Inc. 
//    All Rights Reserved 
// 
//    This sofware is supplied for instructional purposes only. 
// 
//    OSR Open Systems Resources, Inc. (OSR) expressly disclaims any warranty 
//    for this software.  THIS SOFTWARE IS PROVIDED  "AS IS" WITHOUT WARRANTY 
//    OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, 
//    THE IMPLIED WARRANTIES OF MECHANTABILITY OR FITNESS FOR A PARTICULAR 
//    PURPOSE.  THE ENTIRE RISK ARISING FROM THE USE OF THIS SOFTWARE REMAINS 
//    WITH YOU.  OSR's entire liability and your exclusive remedy shall not 
//    exceed the price paid for this material.  In no event shall OSR or its 
//    suppliers be liable for any damages whatsoever (including, without 
//    limitation, damages for loss of business profit, business interruption, 
//    loss of business information, or any other pecuniary loss) arising out 
//    of the use or inability to use this software, even if OSR has been 
//    advised of the possibility of such damages.  Because some states/ 
//    jurisdictions do not allow the exclusion or limitation of liability for 
//    consequential or incidental damages, the above limitation may not apply 
//    to you. 
// 
//    OSR Open Systems Resources, Inc. 
//    105 Route 101A Suite 19 
//    Amherst, NH 03031  (603) 595-6500 FAX: (603) 595-6503 
//    email bugs to: bugs@osr.com 
// 
// 
//    MODULE: 
// 
//      USBFx2LK_DevCtrl.cpp 
// 
//    ABSTRACT: 
// 
//      This file contains the routines that handle IRP_MJ_DEVICE_CONTROL processing for the  
//      OSR USB FX2 Learning Kit Device 
// 
//    AUTHOR(S): 
// 
//      OSR Open Systems Resources, Inc. 
//  
/////////////////////////////////////////////////////////////////////////////// 
#include "usbfx2lk.h" 
 
#ifdef WPP_TRACING 
// 
// Include the necessary tmh file - this is  
//  just a matter of course if you're using WPP tracing. 
// 
extern "C" { 
#include "usbfx2lk_devctrl.tmh" 
} 
#endif 
 
// 
// Forward declarations 
// 
static LPCSTR   IoctlToString(ULONG Ioctl); 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
// UsbFx2LkDeviceControl 
// 
//  This routine is called by the IO Manager to process a IRP_MJ_DEVICE_CONTROL 
//  Irp. 
// 
// 
//  INPUTS: 
// 
//      DeviceObject  -  One of our Device Objects. 
//      Irp  -  The Irp to process. 
// 
//  OUTPUTS: 
// 
//      None 
// 
//  RETURNS: 
// 
//      None 
// 
//  IRQL: 
// 
//      IRQL == PASSIVE_LEVEL 
// 
//  CONTEXT: 
// 
//      User Context 
// 
//  NOTES: 
// 
/////////////////////////////////////////////////////////////////////////////// 
NTSTATUS UsbFx2LkDeviceControl(PDEVICE_OBJECT DeviceObject,PIRP Irp) 
{ 
    PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 
    PUSBFX2LK_EXT devExt = (PUSBFX2LK_EXT)DeviceObject->DeviceExtension; 
    ULONG ioctl; 
    NTSTATUS status = STATUS_UNSUCCESSFUL; 
    ULONG inputBufferLength; 
    ULONG outputBufferLength; 
    ULONG bytesReturned; 
    KIRQL oldIrql; 
 
    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_IOCTL_INFO,("UsbFx2LkDeviceControl: Entered\n")); 
 
    // 
    // We treat this routine as pageable 
    // 
    PAGED_CODE(); 
 
    // 
    // Increment the count of outstanding IOs. 
    // 
    OsrIncrementOutstandingIoCount(devExt,__FILE__,__LINE__); 
 
    // 
    // See what sort of state we're in.  
    // 
    KeAcquireSpinLock(&devExt->IoStateLock,&oldIrql); 
    if (devExt->DevicePnPState < STATE_ALL_BELOW_FAIL) { 
 
        KeReleaseSpinLock(&devExt->IoStateLock,oldIrql); 
        OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                ("UsbFx2LkDeviceControl: Failing  request due to Pnp State! Current PnP state - %s\n", 
                  OsrPrintState(devExt))); 
 
        Irp->IoStatus.Status = STATUS_INVALID_DEVICE_STATE; 
        Irp->IoStatus.Information = 0; 
        IoCompleteRequest(Irp, IO_NO_INCREMENT); 
 
        // 
        // We're done with this request 
        // 
        OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__); 
        return STATUS_INVALID_DEVICE_STATE; 
 
    } 
    KeReleaseSpinLock(&devExt->IoStateLock,oldIrql); 
 
    // 
    // See which IOCTL the caller has sent us 
    // 
    ioctl = ioStack->Parameters.DeviceIoControl.IoControlCode; 
 
    // 
    // And get the buffer lengths. 
    // 
    inputBufferLength  = ioStack->Parameters.DeviceIoControl.InputBufferLength; 
    outputBufferLength = ioStack->Parameters.DeviceIoControl.OutputBufferLength; 
         
 
    OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_IOCTL_INFO, ("UsbFx2LkDeviceControl: Entered with IRP: 0x%p, IOCTL: 0x%x (%s)\n",  
        Irp, ioctl, IoctlToString(ioctl))); 
 
    switch (ioctl) { 
 
        case IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY: { 
 
            // 
            // This IOCTL doesn't use an input 
            //  buffer. Make sure that the caller knows that 
            //  and is playing by the rules. 
            // 
            if (inputBufferLength) { 
 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User passed an input buffer - Incorrect usage for this IOCTL\n")); 
 
                status = STATUS_INVALID_PARAMETER; 
                bytesReturned = 0; 
                break; 
 
            } 
 
            // 
            // Make sure the caller's output buffer is large enough 
            //  to hold the state of the bar graph 
            // 
            if (outputBufferLength < sizeof(BAR_GRAPH_STATE)) { 
 
                // 
                // Let the user know how big the buffer was 
                //  supposed to be 
                // 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User's output buffer is too small for this IOCTL, expecting an BAR_GRAPH_STATE\n")); 
 
                status = STATUS_BUFFER_TOO_SMALL; 
                bytesReturned = sizeof(BAR_GRAPH_STATE); 
                break; 
 
            } 
 
 
            // 
            // Post the IRP off to the get bar graph code.  
            //  This request may pend while the device powers up, 
            //  so just return whatever SubmitGetBarGraphState 
            //  returns to us and don't touch the IRP 
            // 
            status = SubmitGetBarGraphState(devExt, Irp); 
 
            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND, 
               ("UsbFx2LkDeviceControl: SubmitGetBarGraphState returned "\ 
                                                    "0x%x (%s). Exiting...\n", 
                status,OsrNtStatusToString(status))); 
 
 
            return status; 
        } 
        case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY: { 
 
            // 
            // This IOCTL doesn't use an output 
            //  buffer. Make sure that the caller knows that 
            //  and is playing by the rules. 
            // 
            if (outputBufferLength) { 
 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User passed an output buffer - Incorrect usage for this IOCTL\n")); 
 
                status = STATUS_INVALID_PARAMETER; 
                bytesReturned = 0; 
                break; 
 
            } 
 
            // 
            // Make sure the caller's input buffer is of the right size 
            // 
            if (inputBufferLength < sizeof(BAR_GRAPH_STATE)) { 
 
                // 
                // Let the user know how big the buffer was 
                //  supposed to be 
                // 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User's input buffer is too small for this IOCTL, expecting an BAR_GRAPH_STATE\n")); 
 
                status = STATUS_BUFFER_TOO_SMALL; 
                bytesReturned = sizeof(BAR_GRAPH_STATE); 
                break; 
 
            } 
 
            // 
            // Post the IRP off to the set bar graph code.  
            //  This request may pend while the device powers up, 
            //  so just return whatever SubmitSetBarGraphState 
            //  returns to us and don't touch the IRP 
            // 
            status = SubmitSetBarGraphState(devExt, Irp); 
 
            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND, 
               ("UsbFx2LkDeviceControl: SubmitSetBarGraphState returned "\ 
                                                    "0x%x (%s). Exiting...\n", 
                status,OsrNtStatusToString(status))); 
 
            return status; 
 
        } 
        case IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY: { 
 
            // 
            // This IOCTL doesn't use an input 
            //  buffer. Make sure that the caller knows that 
            //  and is playing by the rules. 
            // 
            if (inputBufferLength) { 
 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User passed an input buffer - Incorrect usage for this IOCTL\n")); 
 
                status = STATUS_INVALID_PARAMETER; 
                bytesReturned = 0; 
                break; 
 
            } 
 
            // 
            // Make sure the caller's output buffer is large enough 
            //  to hold the state of the 7 segment 
            // 
            if (outputBufferLength < sizeof(UCHAR)) { 
 
                // 
                // Let the user know how big the buffer was 
                //  supposed to be 
                // 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User's output buffer is too small for this IOCTL, expecting an UCHAR\n")); 
 
                status = STATUS_BUFFER_TOO_SMALL; 
                bytesReturned = sizeof(UCHAR); 
                break; 
 
            } 
 
            // 
            // Post the IRP off to the get seven segment code.  
            //  This request may pend while the device powers up, 
            //  so just return whatever SubmitGetSevenSegmentState 
            //  returns to us and don't touch the IRP 
            // 
            status = SubmitGetSevenSegmentState(devExt, Irp); 
 
            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND, 
               ("UsbFx2LkDeviceControl: SubmitGetSevenSegmentState returned "\ 
                                                    "0x%x (%s). Exiting...\n", 
                status,OsrNtStatusToString(status))); 
 
            return status; 
 
        } 
        case IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY: { 
 
            // 
            // This IOCTL doesn't use an output 
            //  buffer. Make sure that the caller knows that 
            //  and is playing by the rules. 
            // 
            if (outputBufferLength) { 
 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User passed an output buffer - Incorrect usage for this IOCTL\n")); 
 
                status = STATUS_INVALID_PARAMETER; 
                bytesReturned = 0; 
                break; 
 
            } 
 
            // 
            // Make sure the caller's input buffer is of the right size 
            // 
            if (inputBufferLength < sizeof(UCHAR)) { 
 
                // 
                // Let the user know how big the buffer was 
                //  supposed to be 
                // 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User's input buffer is too small for this IOCTL, expecting an UCHAR\n")); 
 
                status = STATUS_BUFFER_TOO_SMALL; 
                bytesReturned = sizeof(UCHAR); 
                break; 
 
            } 
 
            // 
            // Post the IRP off to the set seven segment code.  
            //  This request may pend while the device powers up, 
            //  so just return whatever SubmitSetSevenSegmentState 
            //  returns to us and don't touch the IRP 
            // 
            status = SubmitSetSevenSegmentState(devExt, Irp); 
 
            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND, 
               ("UsbFx2LkDeviceControl: SubmitSetSevenSegmentState returned "\ 
                                                    "0x%x (%s). Exiting...\n", 
                status,OsrNtStatusToString(status))); 
 
            return status; 
        } 
        case IOCTL_OSRUSBFX2_READ_SWITCHES: { 
 
 
            // 
            // This IOCTL doesn't use an input 
            //  buffer. Make sure that the caller knows that 
            //  and is playing by the rules. 
            // 
            if (inputBufferLength) { 
 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User passed an input buffer - Incorrect usage for this IOCTL\n")); 
 
                status = STATUS_INVALID_PARAMETER; 
                bytesReturned = 0; 
                break; 
 
            } 
 
            // 
            // Make sure the caller's output buffer is large enough 
            //  to hold the state of the switches 
            // 
            if (outputBufferLength < sizeof(SWITCH_STATE)) { 
 
                // 
                // Let the user know how big the buffer was 
                //  supposed to be 
                // 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User's output buffer is too small for this IOCTL, expecting a SWITCH_STATE\n")); 
 
                status = STATUS_BUFFER_TOO_SMALL; 
                bytesReturned = sizeof(SWITCH_STATE); 
                break; 
 
            } 
 
            // 
            // Post the IRP off to the get switch state code.  
            //  This request may pend while the device powers up, 
            //  so just return whatever SubmitGetSwitchState 
            //  returns to us and don't touch the IRP 
            // 
            status = SubmitGetSwitchState(devExt, Irp); 
 
            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND, 
               ("UsbFx2LkDeviceControl: SubmitGetSwitchState returned "\ 
                                                    "0x%x (%s). Exiting...\n", 
                status,OsrNtStatusToString(status))); 
 
            return status; 
 
        } 
        case IOCTL_OSRUSBFX2_RESET_PIPE: { 
 
            USBFX2_PIPE_ENUM whichPipe; 
 
            // 
            // This IOCTL uses no output  buffer. Make sure  
            //  that the caller knows that and is playing by the rules. 
            // 
            if (outputBufferLength) { 
 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User passed an output buffer - Incorrect usage for this IOCTL\n")); 
 
                status = STATUS_INVALID_PARAMETER; 
                bytesReturned = 0; 
                break; 
 
            } 
 
            if (inputBufferLength < sizeof(USBFX2_PIPE_ENUM)) { 
 
                // 
                // Let the user know how big the buffer was 
                //  supposed to be 
                // 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User's input buffer is too small for this IOCTL, expecting a USBFX2_PIPE_ENUM\n")); 
 
                status = STATUS_BUFFER_TOO_SMALL; 
                bytesReturned = sizeof(USBFX2_PIPE_ENUM); 
                break; 
 
            } 
 
            // 
            // This is a METHOD_BUFFERED request 
            // 
            whichPipe = *(PUSBFX2_PIPE_ENUM)Irp->AssociatedIrp.SystemBuffer; 
 
            // 
            // Post the IRP off to the reset pipe code.  
            //  This request may pend while the device powers up, 
            //  so just return whatever SubmitResetPipe 
            //  returns to us and don't touch the IRP 
            // 
            status = SubmitResetPipe(devExt, Irp, whichPipe); 
 
            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND, 
               ("UsbFx2LkDeviceControl: SubmitResetPipe returned "\ 
                                                "0x%x (%s). Exiting...\n", 
                status,OsrNtStatusToString(status))); 
 
            return status; 
 
        } 
        case IOCTL_OSRUSBFX2_GET_DEVICE_DESCRIPTOR: { 
 
            PUSB_DEVICE_DESCRIPTOR deviceDescriptor = NULL; 
 
            // 
            // This IOCTL doesn't use an input 
            //  buffer. Make sure that the caller knows that 
            //  and is playing by the rules. 
            // 
            if (inputBufferLength) { 
 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User passed an input buffer - Incorrect usage for this IOCTL\n")); 
 
                status = STATUS_INVALID_PARAMETER; 
                bytesReturned = 0; 
                break; 
 
            } 
 
            // 
            // Make sure the caller's output buffer is large enough 
            //  to hold the device descriptor 
            // 
            if (outputBufferLength < sizeof(USB_DEVICE_DESCRIPTOR)) { 
 
                // 
                // Let the user know how big the buffer was 
                //  supposed to be 
                // 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User's output buffer is too small for this IOCTL\n")); 
 
                status = STATUS_BUFFER_TOO_SMALL; 
                bytesReturned = sizeof(USB_DEVICE_DESCRIPTOR); 
                break; 
 
            } 
 
            // 
            // This is a METHOD_BUFFERED request 
            // 
            deviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer; 
 
            // 
            // Get our device's descriptor and return it to the user 
            //  
            status = GetDeviceDescriptor(devExt, deviceDescriptor, &bytesReturned); 
 
            break; 
        } 
        case IOCTL_OSRUSBFX2_GET_CONFIGURATION_DESCRIPTOR: { 
 
            PUSB_CONFIGURATION_DESCRIPTOR configDescriptor = NULL; 
 
            // 
            // This IOCTL doesn't use an input 
            //  buffer. Make sure that the caller knows that 
            //  and is playing by the rules. 
            // 
            if (inputBufferLength) { 
 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User passed an input buffer - Incorrect usage for this IOCTL\n")); 
 
                status = STATUS_INVALID_PARAMETER; 
                bytesReturned = 0; 
                break; 
 
            } 
 
            // 
            // Make sure the caller's output buffer is large enough 
            //  to hold the configuration descriptor 
            // 
            if (outputBufferLength < sizeof(USB_CONFIGURATION_DESCRIPTOR)) { 
 
                // 
                // Let the user know how big the buffer was 
                //  supposed to be 
                // 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User's output buffer is too small for this IOCTL\n")); 
 
                status = STATUS_BUFFER_TOO_SMALL; 
                bytesReturned = sizeof(USB_CONFIGURATION_DESCRIPTOR); 
                break; 
 
            } 
 
            // 
            // This is a METHOD_BUFFERED request 
            // 
            configDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer; 
 
            // 
            // Get our device's configuration descriptor and return it  
            //  to the user 
            //  
            status = GetConfigurationDescriptor(devExt, configDescriptor, &bytesReturned); 
 
            break; 
        } 
        case IOCTL_OSRUSBFX2_GET_INTERFACE_INFORMATION: { 
 
            PUSBD_INTERFACE_INFORMATION interfaceDescriptor = NULL; 
 
            // 
            // This IOCTL doesn't use an input 
            //  buffer. Make sure that the caller knows that 
            //  and is playing by the rules. 
            // 
            if (inputBufferLength) { 
 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User passed an input buffer - Incorrect usage for this IOCTL\n")); 
 
                status = STATUS_INVALID_PARAMETER; 
                bytesReturned = 0; 
                break; 
 
            } 
 
            // 
            // Make sure the caller's output buffer is large enough 
            //  to hold the configuration descriptor 
            // 
            if (outputBufferLength < devExt->UsbInterface->Length) { 
 
                // 
                // Let the user know how big the buffer was 
                //  supposed to be 
                // 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User's output buffer is too small for this IOCTL\n")); 
 
                status = STATUS_BUFFER_TOO_SMALL; 
                bytesReturned = devExt->UsbInterface->Length; 
                break; 
 
            } 
 
            // 
            // This is a METHOD_BUFFERED request 
            // 
            interfaceDescriptor = (PUSBD_INTERFACE_INFORMATION)Irp->AssociatedIrp.SystemBuffer; 
 
            // 
            // Get our device's configuration descriptor and return it  
            //  to the user 
            //  
            status = GetInterfaceInformation(devExt, interfaceDescriptor, &bytesReturned); 
 
            break; 
        } 
        case IOCTL_OSRUSBFX2_GET_PIPE_INFORMATION: { 
 
            PUSBD_PIPE_INFORMATION pipeInfo = NULL; 
            USBFX2_PIPE_ENUM whichPipe; 
 
            // 
            // Make sure the caller's output buffer is large enough 
            //  to hold the pipe info 
            // 
            if (outputBufferLength < sizeof(USBD_PIPE_INFORMATION)) { 
 
                // 
                // Let the user know how big the buffer was 
                //  supposed to be 
                // 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User's output buffer is too small for this IOCTL, expecting a USBD_PIPE_INFORMATION\n")); 
 
                status = STATUS_BUFFER_TOO_SMALL; 
                bytesReturned = sizeof(USBD_PIPE_INFORMATION); 
                break; 
 
            } 
 
            if (inputBufferLength < sizeof(USBFX2_PIPE_ENUM)) { 
 
                // 
                // Let the user know how big the buffer was 
                //  supposed to be 
                // 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User's input buffer is too small for this IOCTL, expecting a USBFX2_PIPE_ENUM\n")); 
 
                status = STATUS_BUFFER_TOO_SMALL; 
                bytesReturned = sizeof(USBFX2_PIPE_ENUM); 
                break; 
 
            } 
 
            // 
            // For METHOD_BUFFERED requests, the input buffer is the 
            //  same as the output buffer. We need to first use the buffer 
            //  as an input buffer and capture our USBFX2_PIPE_ENUM 
            // 
            whichPipe = *(PUSBFX2_PIPE_ENUM)Irp->AssociatedIrp.SystemBuffer; 
 
            // 
            // Now we can go ahead and use the buffer as an output buffer 
            //  
            pipeInfo = (PUSBD_PIPE_INFORMATION)Irp->AssociatedIrp.SystemBuffer; 
 
            // 
            // Return information about this pipe to the user 
            // 
            status = GetPipeInformation(devExt, whichPipe, pipeInfo, &bytesReturned); 
 
            break; 
        } 
        case IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE: { 
   
            // 
            // This IOCTL doesn't use an input 
            //  buffer. Make sure that the caller knows that 
            //  and is playing by the rules. 
            // 
            if (inputBufferLength) { 
 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User passed an input buffer - Incorrect usage for this IOCTL\n")); 
 
                status = STATUS_INVALID_PARAMETER; 
                bytesReturned = 0; 
                break; 
 
            } 
 
            // 
            // Make sure the caller's output buffer is large enough 
            //  to hold the configuration descriptor 
            // 
            if (!outputBufferLength ||  
                (outputBufferLength > devExt->InterruptPipe->PipeInformation.MaximumTransferSize)) { 
 
                // 
                // Let the user know how big the buffer was 
                //  supposed to be 
                // 
                OsrTracePrint(TRACE_LEVEL_ERROR,OSRDBG_IOCTL_INFO,  
                    ("UsbFx2LkDeviceControl: User's output buffer is too small for this IOCTL\n")); 
 
                status = STATUS_BUFFER_TOO_SMALL; 
                bytesReturned = sizeof(UCHAR); 
                break; 
 
            } 
 
            // 
            // Post the IRP off to the get interrupt data code.  
            //  This request may pend for an indefinite amount of  
            //  time, so just return whatever SubmitInterruptDataRequest 
            //  returns to us and don't touch the IRP 
            // 
            status = SubmitInterruptDataRequest(devExt, Irp); 
 
            OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_SELECTIVE_SUSPEND, 
               ("UsbFx2LkDeviceControl: SubmitInterruptDataRequest returned "\ 
                                                    "0x%x (%s). Exiting...\n", 
                status,OsrNtStatusToString(status))); 
 
            return status; 
 
        } 
        default: { 
 
            OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_IOCTL_INFO,("UsbFx2LkDeviceControl: Passing on unknown IOCTL\n")); 
 
            // 
            // The default action is to just pass the IRP 
            //  down to the lower driver. Maybe HE handles it... 
            // 
            IoSkipCurrentIrpStackLocation(Irp); 
            status = IoCallDriver(devExt->DeviceToSendIrpsTo, Irp); 
 
            // 
            // We're done with this request 
            // 
            OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__); 
 
            return status; 
        } 
 
    } 
 
    OsrTracePrint(TRACE_LEVEL_INFORMATION,OSRDBG_IOCTL_INFO,  
        ("UsbFx2LkDeviceControl: Completing IRP: 0x%p, Status: 0x%x, BytesReturned: 0x%x\n",  
        Irp, status, bytesReturned)); 
 
 
    // 
    // Complete the IRP appropriately 
    // 
    Irp->IoStatus.Status = status; 
    Irp->IoStatus.Information = bytesReturned; 
    IoCompleteRequest(Irp,IO_NO_INCREMENT); 
 
    // 
    // We're done with this request 
    // 
    OsrDecrementOutstandingIoCount(devExt,__FILE__,__LINE__); 
 
    OsrTracePrint(TRACE_LEVEL_VERBOSE,OSRDBG_IOCTL_INFO,("UsbFx2LkDeviceControl: Exit\n")); 
 
    return status; 
} 
 
 
/////////////////////////////////////////////////////////////////////////////// 
// 
// IoctlToString 
// 
//  Takes the IOCTL passed in and tries to match it up with 
//   one of our supported IOCTLs. If there's a match, returns 
//   a string to be used for debugging purposes. 
// 
// 
//  INPUTS: 
// 
//      Ioctl  -  An IOCTL value 
// 
//  OUTPUTS: 
// 
//      None 
// 
//  RETURNS: 
// 
//      A string containing the manifest oonstant name of the 
//      IOCTL if there is one. "Unknown" otherwiese 
// 
//  IRQL: 
// 
//      IRQL == Any 
// 
//  CONTEXT: 
// 
//      Any 
// 
//  NOTES: 
// 
/////////////////////////////////////////////////////////////////////////////// 
LPCSTR IoctlToString(ULONG Ioctl)  
{ 
    switch (Ioctl) { 
 
        case IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY: 
            return "IOCTL_OSRUSBFX2_GET_BAR_GRAPH_DISPLAY"; 
 
        case IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY: 
            return "IOCTL_OSRUSBFX2_SET_BAR_GRAPH_DISPLAY"; 
 
        case IOCTL_OSRUSBFX2_READ_SWITCHES: 
            return "IOCTL_OSRUSBFX2_READ_SWITCHES"; 
 
        case IOCTL_OSRUSBFX2_RESET_PIPE: 
            return "IOCTL_OSRUSBFX2_RESET_PIPE"; 
 
        case IOCTL_OSRUSBFX2_GET_DEVICE_DESCRIPTOR: 
            return "IOCTL_OSRUSBFX2_GET_DEVICE_DESCRIPTOR"; 
 
        case IOCTL_OSRUSBFX2_GET_CONFIGURATION_DESCRIPTOR: 
            return "IOCTL_OSRUSBFX2_GET_CONFIGURATION_DESCRIPTOR"; 
 
        case IOCTL_OSRUSBFX2_GET_PIPE_INFORMATION: 
            return "IOCTL_OSRUSBFX2_GET_PIPE_INFORMATION"; 
 
        case IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY: 
            return "IOCTL_OSRUSBFX2_GET_7_SEGMENT_DISPLAY"; 
 
        case IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY: 
            return "IOCTL_OSRUSBFX2_SET_7_SEGMENT_DISPLAY"; 
 
        case IOCTL_OSRUSBFX2_GET_INTERFACE_INFORMATION: 
            return "IOCTL_OSRUSBFX2_GET_INTERFACE_INFORMATION"; 
 
        case IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE: 
            return "IOCTL_OSRUSBFX2_GET_INTERRUPT_MESSAGE"; 
 
        default: 
            break; 
    } 
 
    return "Unknown IOCTL"; 
}