📄 isopnp.c
字号:
//
nextStack = IoGetNextIrpStackLocation(irp);
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->Parameters.Others.Argument1 = Urb;
// Set the completion routine, which will signal the event
//
IoSetCompletionRoutine(irp,
IsoUsb_SyncCompletionRoutine,
&localevent,
TRUE, // InvokeOnSuccess
TRUE, // InvokeOnError
TRUE); // InvokeOnCancel
// Pass the Irp & Urb down the stack
//
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
// If the request is pending, block until it completes
//
if (ntStatus == STATUS_PENDING)
{
LARGE_INTEGER timeout;
// Specify a timeout of 5 seconds to wait for this call to complete.
//
timeout.QuadPart = -10000 * 5000;
ntStatus = KeWaitForSingleObject(&localevent,
Executive,
KernelMode,
FALSE,
&timeout);
if (ntStatus == STATUS_TIMEOUT)
{
ntStatus = STATUS_IO_TIMEOUT;
// Cancel the Irp we just sent.
//
IoCancelIrp(irp);
// And wait until the cancel completes
//
KeWaitForSingleObject(&localevent,
Executive,
KernelMode,
FALSE,
NULL);
}
else
{
ntStatus = irp->IoStatus.Status;
}
}
// Done with the Irp, now free it.
//
IoFreeIrp(irp);
IsoUsb_DbgPrint(2, ("exit: IsoUsb_SyncSendUsbRequest %08X\n", ntStatus));
return ntStatus;
}
NTSTATUS
IsoUsb_GetDescriptor (
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR Recipient,
IN UCHAR DescriptorType,
IN UCHAR Index,
IN USHORT LanguageId,
IN ULONG RetryCount,
IN ULONG DescriptorLength,
OUT PUCHAR *Descriptor
)
/*++
Routine Description:
This routine attempts to retrieve a specified descriptor from the
device.
This routine must be called at IRQL PASSIVE_LEVEL
--*/
{
USHORT function;
PURB urb;
NTSTATUS ntStatus;
IsoUsb_DbgPrint(2, ("enter: IsoUsb_GetDescriptor\n"));
*Descriptor = NULL;
// Set the URB function based on Recipient {Device, Interface, Endpoint}
//
switch (Recipient)
{
case USB_RECIPIENT_DEVICE:
function = URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE;
break;
case USB_RECIPIENT_INTERFACE:
function = URB_FUNCTION_GET_DESCRIPTOR_FROM_INTERFACE;
break;
case USB_RECIPIENT_ENDPOINT:
function = URB_FUNCTION_GET_DESCRIPTOR_FROM_ENDPOINT;
break;
default:
return STATUS_INVALID_PARAMETER;
}
// Allocate a descriptor buffer
//
*Descriptor = ExAllocatePool(NonPagedPool,
DescriptorLength);
if (*Descriptor != NULL)
{
// Allocate a URB for the Get Descriptor request
//
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if (urb != NULL)
{
do
{
// Initialize the URB
//
urb->UrbHeader.Function = function;
urb->UrbHeader.Length = sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST);
urb->UrbControlDescriptorRequest.TransferBufferLength = DescriptorLength;
urb->UrbControlDescriptorRequest.TransferBuffer = *Descriptor;
urb->UrbControlDescriptorRequest.TransferBufferMDL = NULL;
urb->UrbControlDescriptorRequest.UrbLink = NULL;
urb->UrbControlDescriptorRequest.DescriptorType = DescriptorType;
urb->UrbControlDescriptorRequest.Index = Index;
urb->UrbControlDescriptorRequest.LanguageId = LanguageId;
// Send the URB down the stack
//
ntStatus = IsoUsb_SyncSendUsbRequest(DeviceObject,
urb);
if (NT_SUCCESS(ntStatus))
{
// No error, make sure the length and type are correct
//
if ((DescriptorLength ==
urb->UrbControlDescriptorRequest.TransferBufferLength) &&
(DescriptorType ==
((PUSB_COMMON_DESCRIPTOR)*Descriptor)->bDescriptorType))
{
// The length and type are correct, all done
//
break;
}
else
{
// No error, but the length or type is incorrect
//
ntStatus = STATUS_DEVICE_DATA_ERROR;
}
}
} while (RetryCount-- > 0);
ExFreePool(urb);
}
else
{
// Failed to allocate the URB
//
ExFreePool(*Descriptor);
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
}
else
{
// Failed to allocate the descriptor buffer
//
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
if (!NT_SUCCESS(ntStatus))
{
if (*Descriptor != NULL)
{
ExFreePool(*Descriptor);
*Descriptor = NULL;
}
}
IsoUsb_DbgPrint(2, ("exit: IsoUsb_GetDescriptor %08X\n", ntStatus));
return ntStatus;
}
NTSTATUS
IsoUsb_GetDescriptors (
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This routine is called at START_DEVICE time for the FDO to retrieve
the Device and Configurations descriptors from the device and store
them in the Device Extension.
This routine must be called at PASSIVE_LEVEL.
--*/
{
PDEVICE_EXTENSION deviceExtension;
PUCHAR descriptor;
ULONG descriptorLength;
NTSTATUS ntStatus;
IsoUsb_DbgPrint(2, ("enter: IsoUsb_GetDescriptors\n"));
deviceExtension = DeviceObject->DeviceExtension;
//
// Get Device Descriptor
//
ntStatus = IsoUsb_GetDescriptor(DeviceObject,
USB_RECIPIENT_DEVICE,
USB_DEVICE_DESCRIPTOR_TYPE,
0, // Index
0, // LanguageId
2, // RetryCount
sizeof(USB_DEVICE_DESCRIPTOR),
&descriptor);
if (!NT_SUCCESS(ntStatus))
{
IsoUsb_DbgPrint(1, ("Get Device Descriptor failed\n"));
goto IsoUsb_GetDescriptorsDone;
}
ASSERT(deviceExtension->DeviceDescriptor == NULL);
deviceExtension->DeviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)descriptor;
//
// Get Configuration Descriptor (just the Configuration Descriptor)
//
ntStatus = IsoUsb_GetDescriptor(DeviceObject,
USB_RECIPIENT_DEVICE,
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0, // Index
0, // LanguageId
2, // RetryCount
sizeof(USB_CONFIGURATION_DESCRIPTOR),
&descriptor);
if (!NT_SUCCESS(ntStatus))
{
IsoUsb_DbgPrint(1, ("Get Configuration Descriptor failed (1)\n"));
goto IsoUsb_GetDescriptorsDone;
}
descriptorLength = ((PUSB_CONFIGURATION_DESCRIPTOR)descriptor)->wTotalLength;
ExFreePool(descriptor);
if (descriptorLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))
{
ntStatus = STATUS_DEVICE_DATA_ERROR;
IsoUsb_DbgPrint(1, ("Get Configuration Descriptor failed (2)\n"));
goto IsoUsb_GetDescriptorsDone;
}
//
// Get Configuration Descriptor (and Interface and Endpoint Descriptors)
//
ntStatus = IsoUsb_GetDescriptor(DeviceObject,
USB_RECIPIENT_DEVICE,
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0, // Index
0, // LanguageId
2, // RetryCount
descriptorLength,
&descriptor);
if (!NT_SUCCESS(ntStatus))
{
IsoUsb_DbgPrint(1, ("Get Configuration Descriptor failed (3)\n"));
goto IsoUsb_GetDescriptorsDone;
}
ASSERT(deviceExtension->ConfigurationDescriptor == NULL);
deviceExtension->ConfigurationDescriptor = (PUSB_CONFIGURATION_DESCRIPTOR)descriptor;
if (deviceExtension->ConfigurationDescriptor->bmAttributes & REMOTE_WAKEUP_MASK)
{
//
// this configuration supports remote wakeup
//
deviceExtension->WaitWakeEnable = 1;
}
else
{
deviceExtension->WaitWakeEnable = 0;
}
#if DBG
DumpDeviceDesc(deviceExtension->DeviceDescriptor);
DumpConfigDesc(deviceExtension->ConfigurationDescriptor);
#endif
IsoUsb_GetDescriptorsDone:
IsoUsb_DbgPrint(2, ("exit: IsoUsb_GetDescriptors %08X\n", ntStatus));
return ntStatus;
}
PUSBD_INTERFACE_LIST_ENTRY
IsoUsb_BuildInterfaceList (
PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
/*++
Routine Description:
This routine builds an array of USBD_INTERFACE_LIST_ENTRY structures
from a Configuration Descriptor. This array will then be suitable
for use in a call to USBD_CreateConfigurationRequestEx().
It is the responsibility of the caller to free the returned array
of USBD_INTERFACE_LIST_ENTRY structures.
--*/
{
PUSBD_INTERFACE_LIST_ENTRY interfaceList;
PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
ULONG numInterfaces;
ULONG numInterfacesFound;
ULONG interfaceNumber;
interfaceList = NULL;
numInterfaces = ConfigurationDescriptor->bNumInterfaces;
if (numInterfaces > 0)
{
// Allocate a USBD_INTERFACE_LIST_ENTRY structure for each
// Interface in the Configuration Descriptor, plus one more to
// null terminate the array.
//
interfaceList = ExAllocatePool(NonPagedPool,
(numInterfaces + 1) *
sizeof(USBD_INTERFACE_LIST_ENTRY));
if (interfaceList)
{
// Parse out the Interface Descriptor for Alternate
// Interface setting zero for each Interface from the
// Configuration Descriptor.
//
// Note that some devices have been implemented which do
// not consecutively number their Interface Descriptors.
//
// interfaceNumber may increment and skip an interface
// number without incrementing numInterfacesFound.
//
numInterfacesFound = 0;
interfaceNumber = 0;
// Note that this also null terminates the list.
//
RtlZeroMemory(interfaceList,
(numInterfaces + 1) *
sizeof(USBD_INTERFACE_LIST_ENTRY));
while (numInterfacesFound < numInterfaces)
{
interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
ConfigurationDescriptor,
ConfigurationDescriptor,
interfaceNumber, // InterfaceNumber
0, // AlternateSetting Zero
-1, // InterfaceClass, don't care
-1, // InterfaceSubClass, don't care
-1 // InterfaceProtocol, don't care
);
if (interfaceDescriptor)
{
interfaceList[numInterfacesFound].InterfaceDescriptor =
interfaceDescriptor;
numInterfacesFound++;
}
interfaceNumber++;
// Prevent an endless loop due to an incorrectly formed
// Configuration Descriptor. The maximum interface
// number is 255.
if (interfaceNumber > 256)
{
ExFreePool(interfaceList);
return NULL;
}
}
}
}
ASSERT(interfaceList);
return interfaceList;
}
NTSTATUS
IsoUsb_SelectConfiguration (
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This routine is called at START_DEVICE time for the FDO to configure
the device, i.e. to send an URB_FUNCTION_SELECT_CONFIGURATION
request down the driver stack for the device.
It assumes that the Configuration Descriptor has already been
successfully retrieved from the device and stored in the Device
Extension.
--*/
{
PDEVICE_EXTENSION deviceExtension;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
ULONG numInterfaces;
PUSBD_INTERFACE_LIST_ENTRY interfaceList;
PURB urb;
PUSBD_INTERFACE_INFORMATION interfaceInfo;
PUSBD_INTERFACE_INFORMATION * interfaceInfoList;
ULONG i;
ULONG j;
NTSTATUS ntStatus;
IsoUsb_DbgPrint(2, ("enter: IsoUsb_SelectConfiguration\n"));
deviceExtension = DeviceObject->DeviceExtension;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -