📄 isopnp.c
字号:
urb = NULL;
configurationDescriptor = NULL;
deviceExtension = DeviceObject->DeviceExtension;
//
// Read the first configuration descriptor
// This requires two steps:
// 1. Read the fixed sized configuration desciptor (CD)
// 2. Read the CD with all embedded interface and endpoint descriptors
//
urb = ExAllocatePool(NonPagedPool,
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if(urb) {
siz = sizeof(USB_CONFIGURATION_DESCRIPTOR);
configurationDescriptor = ExAllocatePool(NonPagedPool, siz);
if(configurationDescriptor) {
UsbBuildGetDescriptorRequest(
urb,
(USHORT) sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
configurationDescriptor,
NULL,
sizeof(USB_CONFIGURATION_DESCRIPTOR),
NULL);
ntStatus = CallUSBD(DeviceObject, urb);
if(!NT_SUCCESS(ntStatus)) {
IsoUsb_DbgPrint(1, ("UsbBuildGetDescriptorRequest failed\n"));
goto ConfigureDevice_Exit;
}
}
else {
IsoUsb_DbgPrint(1, ("Failed to allocate mem for config Descriptor\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto ConfigureDevice_Exit;
}
siz = configurationDescriptor->wTotalLength;
ExFreePool(configurationDescriptor);
configurationDescriptor = ExAllocatePool(NonPagedPool, siz);
if(configurationDescriptor) {
UsbBuildGetDescriptorRequest(
urb,
(USHORT)sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
configurationDescriptor,
NULL,
siz,
NULL);
ntStatus = CallUSBD(DeviceObject, urb);
if(!NT_SUCCESS(ntStatus)) {
IsoUsb_DbgPrint(1,("Failed to read configuration descriptor"));
goto ConfigureDevice_Exit;
}
}
else {
IsoUsb_DbgPrint(1, ("Failed to alloc mem for config Descriptor\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto ConfigureDevice_Exit;
}
}
else {
IsoUsb_DbgPrint(1, ("Failed to allocate memory for urb\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto ConfigureDevice_Exit;
}
if(configurationDescriptor) {
//
// save a copy of configurationDescriptor in deviceExtension
// remember to free it later.
//
deviceExtension->UsbConfigurationDescriptor = configurationDescriptor;
if(configurationDescriptor->bmAttributes & REMOTE_WAKEUP_MASK)
{
//
// this configuration supports remote wakeup
//
deviceExtension->WaitWakeEnable = 1;
}
else
{
deviceExtension->WaitWakeEnable = 0;
}
ntStatus = SelectInterfaces(DeviceObject, configurationDescriptor);
}
else {
deviceExtension->UsbConfigurationDescriptor = NULL;
}
ConfigureDevice_Exit:
if(urb) {
ExFreePool(urb);
}
return ntStatus;
}
NTSTATUS
SelectInterfaces(
IN PDEVICE_OBJECT DeviceObject,
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
/*++
Routine Description:
This helper routine selects the configuration
Arguments:
DeviceObject - pointer to device object
ConfigurationDescriptor - pointer to the configuration
descriptor for the device
Return Value:
NT status value
--*/
{
LONG numberOfInterfaces,
interfaceNumber,
interfaceindex;
ULONG i;
PURB urb;
PUCHAR pInf;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor;
PUSBD_INTERFACE_LIST_ENTRY interfaceList,
tmp;
PUSBD_INTERFACE_INFORMATION Interface;
//
// initialize the variables
//
urb = NULL;
Interface = NULL;
interfaceDescriptor = NULL;
deviceExtension = DeviceObject->DeviceExtension;
numberOfInterfaces = ConfigurationDescriptor->bNumInterfaces;
interfaceindex = interfaceNumber = 0;
//
// Parse the configuration descriptor for the interface;
//
tmp = interfaceList =
ExAllocatePool(
NonPagedPool,
sizeof(USBD_INTERFACE_LIST_ENTRY) * (numberOfInterfaces + 1));
if(!tmp) {
IsoUsb_DbgPrint(1, ("Failed to allocate mem for interfaceList\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
while(interfaceNumber < numberOfInterfaces) {
interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
ConfigurationDescriptor,
ConfigurationDescriptor,
interfaceindex,
0, -1, -1, -1);
if(interfaceDescriptor) {
interfaceList->InterfaceDescriptor = interfaceDescriptor;
interfaceList->Interface = NULL;
interfaceList++;
interfaceNumber++;
}
interfaceindex++;
}
interfaceList->InterfaceDescriptor = NULL;
interfaceList->Interface = NULL;
urb = USBD_CreateConfigurationRequestEx(ConfigurationDescriptor, tmp);
if(urb) {
Interface = &urb->UrbSelectConfiguration.Interface;
for(i=0; i<Interface->NumberOfPipes; i++) {
//
// perform pipe initialization here
// set the transfer size and any pipe flags we use
// USBD sets the rest of the Interface struct members
//
Interface->Pipes[i].MaximumTransferSize =
USBD_DEFAULT_MAXIMUM_TRANSFER_SIZE;
}
ntStatus = CallUSBD(DeviceObject, urb);
if(NT_SUCCESS(ntStatus)) {
//
// save a copy of interface information in the device extension.
//
deviceExtension->UsbInterface = ExAllocatePool(NonPagedPool,
Interface->Length);
if(deviceExtension->UsbInterface) {
RtlCopyMemory(deviceExtension->UsbInterface,
Interface,
Interface->Length);
}
else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
IsoUsb_DbgPrint(1, ("memory alloc for UsbInterface failed\n"));
}
//
// Dump the interface to the debugger
//
Interface = &urb->UrbSelectConfiguration.Interface;
IsoUsb_DbgPrint(3, ("---------\n"));
IsoUsb_DbgPrint(3, ("NumberOfPipes 0x%x\n",
Interface->NumberOfPipes));
IsoUsb_DbgPrint(3, ("Length 0x%x\n",
Interface->Length));
IsoUsb_DbgPrint(3, ("Alt Setting 0x%x\n",
Interface->AlternateSetting));
IsoUsb_DbgPrint(3, ("Interface Number 0x%x\n",
Interface->InterfaceNumber));
IsoUsb_DbgPrint(3, ("Class, subclass, protocol 0x%x 0x%x 0x%x\n",
Interface->Class,
Interface->SubClass,
Interface->Protocol));
for(i=0; i<Interface->NumberOfPipes; i++) {
IsoUsb_DbgPrint(3, ("---------\n"));
IsoUsb_DbgPrint(3, ("PipeType 0x%x\n",
Interface->Pipes[i].PipeType));
IsoUsb_DbgPrint(3, ("EndpointAddress 0x%x\n",
Interface->Pipes[i].EndpointAddress));
IsoUsb_DbgPrint(3, ("MaxPacketSize 0x%x\n",
Interface->Pipes[i].MaximumPacketSize));
IsoUsb_DbgPrint(3, ("Interval 0x%x\n",
Interface->Pipes[i].Interval));
IsoUsb_DbgPrint(3, ("Handle 0x%x\n",
Interface->Pipes[i].PipeHandle));
IsoUsb_DbgPrint(3, ("MaximumTransferSize 0x%x\n",
Interface->Pipes[i].MaximumTransferSize));
}
IsoUsb_DbgPrint(3, ("---------\n"));
}
else {
IsoUsb_DbgPrint(1, ("Failed to select an interface\n"));
}
}
else {
IsoUsb_DbgPrint(1, ("USBD_CreateConfigurationRequestEx failed\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
if(tmp) {
ExFreePool(tmp);
}
if(urb) {
ExFreePool(urb);
}
return ntStatus;
}
NTSTATUS
DeconfigureDevice(
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
--*/
{
PURB urb;
ULONG siz;
NTSTATUS ntStatus;
//
// initialize variables
//
siz = sizeof(struct _URB_SELECT_CONFIGURATION);
urb = ExAllocatePool(NonPagedPool, siz);
if(urb) {
UsbBuildSelectConfigurationRequest(urb, (USHORT)siz, NULL);
ntStatus = CallUSBD(DeviceObject, urb);
if(!NT_SUCCESS(ntStatus)) {
IsoUsb_DbgPrint(3, ("Failed to deconfigure device\n"));
}
ExFreePool(urb);
}
else {
IsoUsb_DbgPrint(1, ("Failed to allocate urb\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
return ntStatus;
}
NTSTATUS
CallUSBD(
IN PDEVICE_OBJECT DeviceObject,
IN PURB Urb
)
/*++
Routine Description:
This routine synchronously submits an urb down the stack.
Arguments:
DeviceObject - pointer to device object
Urb - USB request block
Return Value:
NT status value
--*/
{
PIRP irp;
KEVENT event;
NTSTATUS ntStatus;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
PDEVICE_EXTENSION deviceExtension;
//
// initialize the variables
//
irp = NULL;
deviceExtension = DeviceObject->DeviceExtension;
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_USB_SUBMIT_URB,
deviceExtension->TopOfStackDeviceObject,
NULL,
0,
NULL,
0,
TRUE,
&event,
&ioStatus);
if(!irp) {
IsoUsb_DbgPrint(1, ("IoBuildDeviceIoControlRequest failed\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
nextStack = IoGetNextIrpStackLocation(irp);
ASSERT(nextStack != NULL);
nextStack->Parameters.Others.Argument1 = Urb;
IsoUsb_DbgPrint(3, ("CallUSBD::"));
IsoUsb_IoIncrement(deviceExtension);
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject, irp);
if(ntStatus == STATUS_PENDING) {
KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);
ntStatus = ioStatus.Status;
}
IsoUsb_DbgPrint(3, ("CallUSBD::"));
IsoUsb_IoDecrement(deviceExtension);
return ntStatus;
}
NTSTATUS
HandleQueryStopDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine services the Irps of minor type IRP_MN_QUERY_STOP_DEVICE
Arguments:
DeviceObject - pointer to device object
Irp - I/O request packet sent by the pnp manager.
Return Value:
NT status value
--*/
{
KIRQL oldIrql;
NTSTATUS ntStatus;
PDEVICE_EXTENSION deviceExtension;
IsoUsb_DbgPrint(3, ("HandleQueryStopDevice - begins\n"));
//
// initialize variables
//
deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
//
// If we can stop the device, we need to set the QueueState to
// HoldRequests so further requests will be queued.
//
KeAcquireSpinLock(&deviceExtension->DevStateLock, &oldIrql);
SET_NEW_PNP_STATE(deviceExtension, PendingStop);
deviceExtension->QueueState = HoldRequests;
KeReleaseSpinLock(&deviceExtension->DevStateLock, oldIrql);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -