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

📄 mavusb.c

📁 基于EP7312的MP3播放器源代码,包括MCU和PC端代码.
💻 C
📖 第 1 页 / 共 2 页
字号:
{
    PDEVICE_EXTENSION deviceExtension;
    NTSTATUS ntStatus;
    PURB urb;
    ULONG siz;

    //
    // Get a pointer to the device extension.
    //
    deviceExtension = DeviceObject->DeviceExtension;

    //
    // The device has no pending staged IO transactions.
    //
    deviceExtension->StagedIoPending = FALSE;

    //
    // Allocate memory for a URB.
    //
    urb = ExAllocatePool(NonPagedPool,
                         sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
    if(!urb)
    {
        return(STATUS_INSUFFICIENT_RESOURCES);
    }

    //
    // When USB_CONFIGURATION_DESCRIPTOR_TYPE is specified for DescriptorType
    // in a call to UsbBuildGetDescriptorRequest(), all interface, endpoint,
    // class-specific, and vendor-specific descriptors for the configuration
    // also are retrieved.  The caller must allocate a buffer large enough to
    // hold all of this information or the data is truncated without error.
    // Therefore the 'siz' set below is just a 'good guess', and we may have to
    // retry.
    //
    siz = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 512;

    //
    // We will break out of this 'retry loop' when
    // UsbBuildGetDescriptorRequest() has a big enough
    // deviceExtension->UsbConfigurationDescriptor buffer not to truncate.
    //
    while(1)
    {
        //
        // Allocate memory for the configuration descriptor.
        //
        deviceExtension->UsbConfigurationDescriptor =
            ExAllocatePool(NonPagedPool, siz);
        if(!deviceExtension->UsbConfigurationDescriptor)
        {
            ExFreePool(urb);
            return(STATUS_INSUFFICIENT_RESOURCES);
        }

        //
        // Build the get descriptor URB.
        //
        UsbBuildGetDescriptorRequest(urb,
                                     (USHORT)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
                                     USB_CONFIGURATION_DESCRIPTOR_TYPE,
                                     0,
                                     0,
                                     deviceExtension->UsbConfigurationDescriptor,
                                     NULL,
                                     siz,
                                     NULL);

        //
        // Send the URB to the PDO.
        //
        ntStatus = MavUsb_CallUSBD(DeviceObject, urb);

        //
        // If we got some data see if it was enough.  NOTE: we may get an error
        // in URB because of buffer overrun.
        //
        if((urb->UrbControlDescriptorRequest.TransferBufferLength > 0) &&
           (deviceExtension->UsbConfigurationDescriptor->wTotalLength > siz))
        {
            //
            // Update size based on the actual size of the configuration
            // descriptor.
            //
            siz = deviceExtension->UsbConfigurationDescriptor->wTotalLength;

            //
            // Free the currently allocated memory for the configuration
            // descriptor.
            //
            ExFreePool(deviceExtension->UsbConfigurationDescriptor);
            deviceExtension->UsbConfigurationDescriptor = NULL;
        }
        else
        {
            //
            // We have all the data.
            //
            break;
        }
    }

    //
    // Free up the memory for the URB.
    //
    ExFreePool(urb);

    //
    // We have the configuration descriptor for the configuration we want.
    // Now, we issue the select configuration command to get the pipes
    // associated with this configuration.
    //
    ntStatus =
        MavUsb_SelectInterface(DeviceObject,
                               deviceExtension->UsbConfigurationDescriptor);

    //
    // Return the result.
    //
    return(ntStatus);
}

//****************************************************************************
//
// Initializes the device with (possibly) multiple interfaces.  This
// minidriver only supports one interface (with multiple endpoints).
//
// Arguments:
//
//     DeviceObject - pointer to the device object for this instance of the
//                    device.
//
//     ConfigDescriptor - pointer to the USB configuration descriptor
//                        containing the interface and endpoint descriptors.
//
// Return Value:
//
//     NT status code
//
//****************************************************************************
NTSTATUS
MavUsb_SelectInterface(IN PDEVICE_OBJECT DeviceObject,
                       IN PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc)
{
    PDEVICE_EXTENSION deviceExtension;
    NTSTATUS ntStatus;
    PURB urb = NULL;
    ULONG i;
    PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor = NULL;
    PUSBD_INTERFACE_INFORMATION Interface = NULL;
    USHORT siz;

    //
    // Get a pointer to the device extension.
    //
    deviceExtension = DeviceObject->DeviceExtension;

    //
    // The Maverick driver only supports one interface, we must parse the
    // configuration descriptor for the interface and remember the pipes.
    //
    urb = USBD_CreateConfigurationRequest(ConfigDesc, &siz);

    //
    // See if USBD was able to allocate a URB.
    //
    if(urb)
    {
        //
        // USBD_ParseConfigurationDescriptorEx searches a given configuration
        // descriptor and returns a pointer to an interface that matches the
        // given search criteria.  We only support one interface on this
        // device.
        //
        interfaceDescriptor =
            USBD_ParseConfigurationDescriptorEx(ConfigDesc, ConfigDesc, -1, -1,
                                                -1, -1, -1);

        //
        // Make sure we found an interface.
        //
        if(!interfaceDescriptor)
        {
            //
            // We could not find an interface.
            //
            ExFreePool(urb);
            return(STATUS_INSUFFICIENT_RESOURCES);
        }

        //
        // Get a pointer to the interface information structure in the URB.
        //
        Interface = &urb->UrbSelectConfiguration.Interface;

        //
        // Loop through all the pipes on the device.
        //
        for(i = 0; i < Interface->NumberOfPipes; i++)
        {
            //
            // Perform any pipe initialization here.  We set the max transfer
            // size and any pipe flags we use; USBD sets the rest of the
            // interface struct members.
            //
            Interface->Pipes[i].MaximumTransferSize = 16384;
        }

        //
        // Build the select configuration URB.
        //
        UsbBuildSelectConfigurationRequest(urb, (USHORT)siz, ConfigDesc);

        //
        // Send the URB to the PDO.
        //
        ntStatus = MavUsb_CallUSBD(DeviceObject, urb);
    }
    else
    {
        //
        // We could not allocate the URB.
        //
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // See if the select configuration was successful.
    //
    if(NT_SUCCESS(ntStatus))
    {
        //
        // Save the configuration handle for this device.
        //
        deviceExtension->UsbConfigurationHandle =
            urb->UrbSelectConfiguration.ConfigurationHandle;

        //
        // Allocate memory for our saved copy of the interface structure.
        //
        deviceExtension->UsbInterface = ExAllocatePool(NonPagedPool,
                                                       Interface->Length);

        //
        // See if we were able to allocate memory for the interface structure.
        //
        if(deviceExtension->UsbInterface)
        {
            //
            // Save a copy of the interface information returned.
            //
            RtlCopyMemory(deviceExtension->UsbInterface, Interface,
                          Interface->Length);
        }
    }

    //
    // If the URB was allocated, then free it now.
    //
    if(urb)
    {
        ExFreePool(urb);
    }

    //
    // Return the result.
    //
    return(ntStatus);
}

//****************************************************************************
//
// Reset a given USB pipe.
//
// NOTE:  This will reset the host to Data0 and should also reset the device
// to Data0.
//
// Arguments:
//
//     Ptrs to our FDO and a USBD_PIPE_INFORMATION struct
//
// Return Value:
//
//     NT status code
//
//****************************************************************************
NTSTATUS
MavUsb_ResetPipe(IN PDEVICE_OBJECT DeviceObject,
                 IN PUSBD_PIPE_INFORMATION PipeInfo)
{
    NTSTATUS ntStatus;
    PURB urb;
    PDEVICE_EXTENSION deviceExtension;

    //
    // Get a pointer to the device extension.
    //
    deviceExtension = DeviceObject->DeviceExtension;

    //
    // Allocate memory for the URB.
    //
    urb = ExAllocatePool(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));

    //
    // See if we were able to allocate memory for the URB.
    //
    if(urb)
    {
        //
        // Fill in the URB.
        //
        urb->UrbHeader.Length = (USHORT)sizeof(struct _URB_PIPE_REQUEST);
        urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
        urb->UrbPipeRequest.PipeHandle = PipeInfo->PipeHandle;

        //
        // Send the URB to the PDO.
        //
        ntStatus = MavUsb_CallUSBD(DeviceObject, urb);

        //
        // Free the memory for the URB.
        //
        ExFreePool(urb);
    }
    else
    {
        //
        // We were unable to allocate memory for the URB.
        //
        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // Return the result.
    //
    return(ntStatus);
}

//****************************************************************************
//
// We keep a pending IO count (extension->PendingIoCount) in the device
// extension.
//
// The first increment of this count is done on adding the device.
// Subsequently, the count is incremented for each new IRP received and
// decremented when each IRP is completed or passed on.
//
// Transition to 'one' therefore indicates no IO is pending and signals
// deviceExtension->NoPendingIoEvent.  This is needed for processing
// IRP_MN_QUERY_REMOVE_DEVICE.
//
// Transition to 'zero' signals an event (deviceExtension->RemoveEvent) to
// enable device removal.  This is used in processing for
// IRP_MN_REMOVE_DEVICE.
//
// Arguments:
//
//     DeviceObject - ptr to our FDO
//
// Return Value:
//
//     deviceExtension->PendingIoCount
//
//****************************************************************************
LONG
MavUsb_DecrementIoCount(IN PDEVICE_OBJECT DeviceObject)
{
    PDEVICE_EXTENSION deviceExtension;
    LONG ioCount;
    KIRQL             oldIrql;

    //
    // Get a pointer to our device extension.
    //
    deviceExtension = DeviceObject->DeviceExtension;

    //
    // Acquire the spin lock which protects the pending IO count.
    //
    KeAcquireSpinLock(&deviceExtension->IoCountSpinLock, &oldIrql);

    //
    // Decrement the pending IO count.
    //
    ioCount = InterlockedDecrement(&deviceExtension->PendingIoCount);

    //
    // See if the IO count is now one.
    //
    if(ioCount == 1)
    {
        //
        // Trigger the no pending IO event.
        //
        KeSetEvent(&deviceExtension->NoPendingIoEvent, 1, FALSE);
    }

    //
    // See if the IO count is now zero.
    //
    if(ioCount == 0)
    {
        //
        // Trigger the remove device event.
        //
        KeSetEvent(&deviceExtension->RemoveEvent, 1, FALSE);
    }

    //
    // Release the spin lock.
    //
    KeReleaseSpinLock(&deviceExtension->IoCountSpinLock, oldIrql);

    //
    // Return the new pending IO count.
    //
    return(ioCount);
}

//****************************************************************************
//
// We keep a pending IO count (extension->PendingIoCount) in the device
// extension.
//
// The first increment of this count is done on adding the device.
// Subsequently, the count is incremented for each new IRP received and
// decremented when each IRP is completed or passed on.
//
// Arguments:
//
//     DeviceObject - ptr to our FDO
//
// Return Value:
//
//     None
//
//****************************************************************************
VOID
MavUsb_IncrementIoCount(IN PDEVICE_OBJECT DeviceObject)
{
    PDEVICE_EXTENSION deviceExtension;
    KIRQL             oldIrql;

    //
    // Get a pointer to the device extension.
    //
    deviceExtension = DeviceObject->DeviceExtension;

    //
    // Acquire the spin lock which protects the pending IO count.
    //
    KeAcquireSpinLock(&deviceExtension->IoCountSpinLock, &oldIrql);

    //
    // Increment the pending IO count.
    //
    InterlockedIncrement(&deviceExtension->PendingIoCount);

    //
    // Release the spin lock.
    //
    KeReleaseSpinLock(&deviceExtension->IoCountSpinLock, oldIrql);
}

⌨️ 快捷键说明

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