📄 isopnp.c
字号:
configurationDescriptor = deviceExtension->ConfigurationDescriptor;
numInterfaces = configurationDescriptor->bNumInterfaces;
// Build an USBD_INTERFACE_LIST_ENTRY array to use as an
// input/output parameter to USBD_CreateConfigurationRequestEx().
//
interfaceList = IsoUsb_BuildInterfaceList(configurationDescriptor);
if (interfaceList == NULL)
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto IsoUsb_SelectConfigurationExit;
}
// Create a SELECT_CONFIGURATION URB, turning the Interface
// Descriptors in the interfaceList into
// USBD_INTERFACE_INFORMATION structures in the URB.
//
urb = USBD_CreateConfigurationRequestEx(configurationDescriptor,
interfaceList);
// Now done with the interfaceList as soon as the URB is built (or
// not built).
//
ExFreePool(interfaceList);
interfaceList = NULL;
if (urb == NULL)
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto IsoUsb_SelectConfigurationExit;
}
// Now issue the USB request to set the Configuration
//
ntStatus = IsoUsb_SyncSendUsbRequest(DeviceObject,
urb);
if (!NT_SUCCESS(ntStatus))
{
// Now done with the URB
//
ExFreePool(urb);
urb = NULL;
goto IsoUsb_SelectConfigurationExit;
}
// Save the configuration handle for this device in the Device
// Extension.
//
deviceExtension->ConfigurationHandle = urb->UrbSelectConfiguration.ConfigurationHandle;
ASSERT(deviceExtension->InterfaceInfoList == NULL);
// Allocate an array to hold pointers to one
// USBD_INTERFACE_INFORMATION structure per configured Interface.
// Save this array in the Device Extension.
//
interfaceInfoList = (PUSBD_INTERFACE_INFORMATION *)
ExAllocatePool(NonPagedPool,
numInterfaces *
sizeof(PUSBD_INTERFACE_INFORMATION));
if (interfaceInfoList == NULL)
{
// Now done with the URB
//
ExFreePool(urb);
urb = NULL;
goto IsoUsb_SelectConfigurationExit;
}
deviceExtension->InterfaceInfoList = interfaceInfoList;
// The end of the SELECT_CONFIGURATION URB contains a contiguous
// array of variably sized USBD_INTERFACE_INFORMATION structures,
// one per configured Interface.
//
// Get a pointer to the USBD_INTERFACE_INFORMATION structure for
// the first configured Interface.
//
interfaceInfo = &urb->UrbSelectConfiguration.Interface;
// Iterate over each configured Interface. Allocate memory for a
// copy of the USBD_INTERFACE_INFORMATION structure for the
// Interface and save a copy of the structure from the URB.
//
for (i = 0; i < numInterfaces; i++)
{
interfaceInfoList[i] = ExAllocatePool(NonPagedPool,
interfaceInfo->Length);
if (interfaceInfoList[i] == NULL)
{
// Allocation failure, free the previously allocated
// USBD_INTERFACE_INFORMATION structure copies.
//
for (i = 0; i < numInterfaces; i++)
{
if (interfaceInfoList[i] != NULL)
{
ExFreePool(interfaceInfoList[i]);
}
}
// Free the list of pointers to allocated
// USBD_INTERFACE_INFORMATION structure copies.
//
ExFreePool(deviceExtension->InterfaceInfoList);
deviceExtension->InterfaceInfoList = NULL;
// Now done with the URB
//
ExFreePool(urb);
urb = NULL;
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto IsoUsb_SelectConfigurationExit;
}
// Save a copy of the USBD_INTERFACE_INFORMATION structure from
// the URB in the Device Extension InterfaceInfoList.
//
RtlCopyMemory(interfaceInfoList[i],
interfaceInfo,
interfaceInfo->Length);
// Save pointers back into the USBD_PIPE_INFORMATION structures
// contained within the above saved USBD_INTERFACE_INFORMATION
// structure.
//
// This is makes it easier to iterate over all currently
// configured pipes without having to interate over all
// currently configured interfaces as we are in the middle of
// doing right now.
//
for (j = 0; j < interfaceInfo->NumberOfPipes; j++)
{
if (deviceExtension->NumberOfPipes < ISOUSB_MAX_PIPES)
{
deviceExtension->PipeInformation[deviceExtension->NumberOfPipes] =
&interfaceInfoList[i]->Pipes[j];
deviceExtension->NumberOfPipes++;
}
}
#if DBG
DumpInterfaceInformation(interfaceInfo);
#endif
// Advance to the next variably sized USBD_INTERFACE_INFORMATION
// structure in the SELECT_CONFIGURATION URB.
//
interfaceInfo = (PUSBD_INTERFACE_INFORMATION)
((PUCHAR)interfaceInfo + interfaceInfo->Length);
}
// Now done with the URB
//
ExFreePool(urb);
IsoUsb_SelectConfigurationExit:
IsoUsb_DbgPrint(2, ("exit: IsoUsb_SelectConfiguration %08X\n", ntStatus));
return ntStatus;
}
NTSTATUS
IsoUsb_SelectAlternateInterface (
IN PDEVICE_OBJECT DeviceObject,
IN UCHAR InterfaceNumber,
IN UCHAR AlternateSetting
)
/*++
Routine Description:
This routine attempts to select the specified alternate interface
setting for the specified interface.
The InterfaceNumber and AlternateSetting parameters will be
validated by this routine and are not assumed to be valid.
This routines assumes that the device is currently configured, i.e.
IsoUsb_SelectConfiguration() has been successfully called and
IsoUsb_UnConfigure() has not been called.
This routine assumes that no pipes will be accessed while this
routine is executing as the deviceExtension->InterfaceInfoList and
deviceExtension->PipeInformation data is updated by this routine.
This exclusion synchronization must be handled external to this
routine.
--*/
{
PDEVICE_EXTENSION deviceExtension;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
ULONG numInterfaces;
PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
UCHAR numEndpoints;
USHORT urbSize;
PURB urb;
PUSBD_INTERFACE_INFORMATION interfaceInfoUrb;
PUSBD_INTERFACE_INFORMATION interfaceInfoCopy;
ULONG i;
ULONG j;
NTSTATUS ntStatus;
IsoUsb_DbgPrint(2, ("enter: IsoUsb_SelectAlternateInterface\n"));
deviceExtension = DeviceObject->DeviceExtension;
configurationDescriptor = deviceExtension->ConfigurationDescriptor;
numInterfaces = configurationDescriptor->bNumInterfaces;
// Find the Interface Descriptor which matches the InterfaceNumber
// and AlternateSetting parameters.
//
interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
configurationDescriptor,
configurationDescriptor,
InterfaceNumber,
AlternateSetting,
-1, // InterfaceClass, don't care
-1, // InterfaceSubClass, don't care
-1 // InterfaceProtocol, don't care
);
if (interfaceDescriptor == NULL)
{
// Interface Descriptor not found, bad InterfaceNumber or
// AlternateSetting.
//
ntStatus = STATUS_INVALID_PARAMETER;
goto IsoUsb_SelectAlternateInterfaceExit;
}
// Allocate a URB_FUNCTION_SELECT_INTERFACE request structure
//
numEndpoints = interfaceDescriptor->bNumEndpoints;
urbSize = GET_SELECT_INTERFACE_REQUEST_SIZE(numEndpoints);
urb = ExAllocatePool(NonPagedPool,
urbSize);
if (urb == NULL)
{
// Could not allocate the URB.
//
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto IsoUsb_SelectAlternateInterfaceExit;
}
// Initialize the URB
//
RtlZeroMemory(urb, urbSize);
urb->UrbHeader.Length = urbSize;
urb->UrbHeader.Function = URB_FUNCTION_SELECT_INTERFACE;
urb->UrbSelectInterface.ConfigurationHandle =
deviceExtension->ConfigurationHandle;
interfaceInfoUrb = &urb->UrbSelectInterface.Interface;
interfaceInfoUrb->Length = GET_USBD_INTERFACE_SIZE(numEndpoints);
interfaceInfoUrb->InterfaceNumber = InterfaceNumber;
interfaceInfoUrb->AlternateSetting = AlternateSetting;
for (i = 0; i < numEndpoints; i++)
{
interfaceInfoUrb->Pipes[i].MaximumTransferSize =
USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
}
// Allocate a USBD_INTERFACE_INFORMATION structure to hold the
// result of the URB_FUNCTION_SELECT_INTERFACE request.
//
interfaceInfoCopy = ExAllocatePool(NonPagedPool,
GET_USBD_INTERFACE_SIZE(numEndpoints));
// Could not allocate the USBD_INTERFACE_INFORMATION copy.
//
if (interfaceInfoCopy == NULL)
{
ExFreePool(urb);
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto IsoUsb_SelectAlternateInterfaceExit;
}
// Now issue the USB request to select the alternate interface
//
ntStatus = IsoUsb_SyncSendUsbRequest(DeviceObject,
urb);
if (NT_SUCCESS(ntStatus))
{
// Save a copy of the interface information returned by the
// SELECT_INTERFACE request. This gives us a list of
// PIPE_INFORMATION structures for each pipe opened in this
// selected alternate interface setting.
//
ASSERT(interfaceInfoUrb->Length == GET_USBD_INTERFACE_SIZE(numEndpoints));
RtlCopyMemory(interfaceInfoCopy,
interfaceInfoUrb,
GET_USBD_INTERFACE_SIZE(numEndpoints));
#if DBG
DumpInterfaceInformation(interfaceInfoCopy);
#endif
}
else
{
// How to recover from a select alternate interface failure?
//
// The other currently configured interfaces (if any) should
// not be disturbed by this select alternate interface failure.
//
// Just note that this interface now has no currently
// configured pipes (i.e. interfaceInfoCopy->NumberOfPipes == 0)
//
RtlZeroMemory(interfaceInfoCopy,
GET_USBD_INTERFACE_SIZE(numEndpoints));
interfaceInfoCopy->Length = GET_USBD_INTERFACE_SIZE(numEndpoints);
interfaceInfoCopy->InterfaceNumber = InterfaceNumber;
interfaceInfoCopy->AlternateSetting = AlternateSetting;
}
// Zero out and then reset the currently configured
// USBD_PIPE_INFORMATION
//
deviceExtension->NumberOfPipes = 0;
RtlZeroMemory(deviceExtension->PipeInformation,
sizeof(deviceExtension->PipeInformation));
for (i = 0; i < numInterfaces; i++)
{
// Save pointers back into the USBD_PIPE_INFORMATION structures
// contained within the above saved USBD_INTERFACE_INFORMATION
// structure.
//
// This is makes it easier to iterate over all currently
// configured pipes without having to interate over all
// currently configured interfaces as we are in the middle of
// doing right now.
//
if ((deviceExtension->InterfaceInfoList[i]->InterfaceNumber ==
InterfaceNumber) &&
(interfaceInfoCopy != NULL))
{
// Free the USBD_INTERFACE_INFORMATION for the previously
// selected alternate interface setting and swap in the new
// USBD_INTERFACE_INFORMATION copy.
//
ExFreePool(deviceExtension->InterfaceInfoList[i]);
deviceExtension->InterfaceInfoList[i] = interfaceInfoCopy;
interfaceInfoCopy = NULL;
}
for (j = 0; j < deviceExtension->InterfaceInfoList[i]->NumberOfPipes; j++)
{
if (deviceExtension->NumberOfPipes < ISOUSB_MAX_PIPES)
{
deviceExtension->PipeInformation[deviceExtension->NumberOfPipes] =
&deviceExtension->InterfaceInfoList[i]->Pipes[j];
deviceExtension->NumberOfPipes++;
}
}
}
// Done with the URB
//
ExFreePool(urb);
IsoUsb_SelectAlternateInterfaceExit:
IsoUsb_DbgPrint(2, ("exit: IsoUsb_SelectAlternateInterface %08X\n", ntStatus));
return ntStatus;
}
NTSTATUS
IsoUsb_UnConfigure (
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
This routine is invoked when the device is removed or stopped.
This routine de-configures the usb device.
Arguments:
DeviceObject - pointer to device object
Return Value:
NT status value
--*/
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus;
PURB urb;
ULONG ulSize;
ULONG numInterfaces;
ULONG i;
IsoUsb_DbgPrint(2, ("enter: IsoUsb_UnConfigure\n"));
deviceExtension = DeviceObject->DeviceExtension;
// Allocate a URB for the SELECT_CONFIGURATION request. As we are
// unconfiguring the device, the request needs no pipe and interface
// information structures.
//
ulSize = sizeof(struct _URB_SELECT_CONFIGURATION) -
sizeof(USBD_INTERFACE_INFORMATION);
urb = ExAllocatePool(
NonPagedPool,
ulSize
);
if (urb)
{
// Initialize the URB. A NULL Configuration Descriptor indicates
// that the device should be unconfigured.
//
UsbBuildSelectConfigurationRequest(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -