📄 mavusb.c
字号:
{
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 + -