📄 usb.c
字号:
sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
if ( !urb )
{
USB_KdPrint( DBGLVL_DEFAULT,("ERROR USB_ExAllocatePool return !urb\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
siz = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 100;
USB_KdPrint( DBGLVL_DEFAULT,("sizeof(USB_CONFIGURATION_DESCRIPTOR) + 512 = (%x)\n",
siz));
// We will break out of this 'retry loop' when UsbBuildGetDescriptorRequest()
// has a big enough deviceExtension->UsbConfigurationDescriptor buffer not to truncate
while( 1 ) {
deviceExtension->UsbConfigurationDescriptor = USB_ExAllocatePool(NonPagedPool, siz);
if ( !deviceExtension->UsbConfigurationDescriptor ) {
USB_KdPrint( DBGLVL_DEFAULT,("ERROR USB_ExAllocatePool return !UsbConfigurationDescriptor\n"));
USB_ExFreePool(urb);
return STATUS_INSUFFICIENT_RESOURCES;
}
UsbBuildGetDescriptorRequest(urb,
(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
USB_CONFIGURATION_DESCRIPTOR_TYPE,
0,
0,
deviceExtension->UsbConfigurationDescriptor,
NULL,
siz,
NULL);
ntStatus = USB_CallUSBD(DeviceObject, urb);
USB_KdPrint( DBGLVL_DEFAULT,("USB_CallUSBD() Configuration Descriptor = %x, len %x , ntStatus %x\n",
deviceExtension->UsbConfigurationDescriptor,
urb->UrbControlDescriptorRequest.TransferBufferLength,ntStatus));
//
// 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) {
siz = deviceExtension->UsbConfigurationDescriptor->wTotalLength;
USB_ExFreePool(deviceExtension->UsbConfigurationDescriptor);
deviceExtension->UsbConfigurationDescriptor = NULL;
} else {
break; // we got it on the first try
}
} // end, while (retry loop )
USB_KdPrint( DBGLVL_DEFAULT,("UsbConfigurationDescriptor->wTotalLength = (%x)\n",
deviceExtension->UsbConfigurationDescriptor->wTotalLength));
USB_ExFreePool(urb);
USB_ASSERT( deviceExtension->UsbConfigurationDescriptor );
//
// 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 = USB_SelectInterface(DeviceObject,
deviceExtension->UsbConfigurationDescriptor);
USB_KdPrint( DBGLVL_HIGH,("exit USB_ConfigureDevice (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
USB_SelectInterface(
IN PDEVICE_OBJECT DeviceObject,
IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor
)
{
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus;
PURB urb = NULL;
ULONG i;
PUSB_INTERFACE_DESCRIPTOR interfaceDescriptor = NULL;
PUSBD_INTERFACE_INFORMATION Interface = NULL;
USHORT siz;
PUCHAR pInf;
USB_KdPrint( DBGLVL_MEDIUM,("enter USB_SelectInterface\n"));
deviceExtension = DeviceObject->DeviceExtension;
USB_KdPrint( DBGLVL_DEFAULT,("USB_SelectInterface() called with NULL Interface\n"));
urb = USBD_CreateConfigurationRequest(ConfigurationDescriptor, &siz);
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(ConfigurationDescriptor,
ConfigurationDescriptor, //search from start of config descriptror
-1, // interface number not a criteria; we only support one interface
-1, // not interested in alternate setting here either
-1, // interface class not a criteria
-1, // interface subclass not a criteria
-1 // interface protocol not a criteria
);
if ( !interfaceDescriptor ) {
USB_KdPrint( DBGLVL_DEFAULT,("USB_SelectInterface() ParseConfigurationDescriptorEx() failed\n returning STATUS_INSUFFICIENT_RESOURCES\n"));
USB_ExFreePool(urb);
return STATUS_INSUFFICIENT_RESOURCES;
}
Interface = &urb->UrbSelectConfiguration.Interface;
// allocate space for an array of pipe information structs;
// in this basic sample, just used to track if opened/closed
deviceExtension->PipeInfo = USB_ExAllocatePool(
NonPagedPool,
Interface->NumberOfPipes * sizeof ( USB_PIPEINFO ) );
if ( !deviceExtension->PipeInfo ) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(deviceExtension->PipeInfo,
Interface->NumberOfPipes * sizeof ( USB_PIPEINFO ) );
pInf = (PUCHAR ) deviceExtension->PipeInfo;
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 = deviceExtension->MaximumTransferSize;
( (PUSB_PIPEINFO) pInf)->fPipeOpened = FALSE;
pInf += sizeof ( USB_PIPEINFO );
}
UsbBuildSelectConfigurationRequest(urb,
(USHORT) siz,
ConfigurationDescriptor);
ntStatus = USB_CallUSBD(DeviceObject, urb);
deviceExtension->UsbConfigurationHandle =
urb->UrbSelectConfiguration.ConfigurationHandle;
} else {
USB_KdPrint( DBGLVL_DEFAULT,("USB_SelectInterface() USBD_CreateConfigurationRequest() failed\n returning STATUS_INSUFFICIENT_RESOURCES\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
if (NT_SUCCESS(ntStatus)) {
//
// Save the configuration handle for this device
//
deviceExtension->UsbConfigurationHandle =
urb->UrbSelectConfiguration.ConfigurationHandle;
deviceExtension->UsbInterface = USB_ExAllocatePool(NonPagedPool,
Interface->Length);
if (deviceExtension->UsbInterface) {
ULONG j;
//
// save a copy of the interface information returned
//
RtlCopyMemory(deviceExtension->UsbInterface, Interface, Interface->Length);
//
// Dump the interface to the debugger
//
USB_KdPrint( DBGLVL_DEFAULT,("---------\n"));
USB_KdPrint( DBGLVL_DEFAULT,("NumberOfPipes 0x%x\n", deviceExtension->UsbInterface->NumberOfPipes));
USB_KdPrint( DBGLVL_DEFAULT,("Length 0x%x\n", deviceExtension->UsbInterface->Length));
USB_KdPrint( DBGLVL_DEFAULT,("Alt Setting 0x%x\n", deviceExtension->UsbInterface->AlternateSetting));
USB_KdPrint( DBGLVL_DEFAULT,("Interface Number 0x%x\n", deviceExtension->UsbInterface->InterfaceNumber));
USB_KdPrint( DBGLVL_DEFAULT,("Class, subclass, protocol 0x%x 0x%x 0x%x\n",
deviceExtension->UsbInterface->Class,
deviceExtension->UsbInterface->SubClass,
deviceExtension->UsbInterface->Protocol));
// Dump the pipe info
for (j=0; j<Interface->NumberOfPipes; j++) {
PUSBD_PIPE_INFORMATION pipeInformation;
pipeInformation = &deviceExtension->UsbInterface->Pipes[j];
USB_KdPrint( DBGLVL_DEFAULT,("---------\n"));
USB_KdPrint( DBGLVL_DEFAULT,("PipeType 0x%x\n", pipeInformation->PipeType));
USB_KdPrint( DBGLVL_DEFAULT,("EndpointAddress 0x%x\n", pipeInformation->EndpointAddress));
USB_KdPrint( DBGLVL_DEFAULT,("MaxPacketSize 0x%x\n", pipeInformation->MaximumPacketSize));
USB_KdPrint( DBGLVL_DEFAULT,("Interval 0x%x\n", pipeInformation->Interval));
USB_KdPrint( DBGLVL_DEFAULT,("Handle 0x%x\n", pipeInformation->PipeHandle));
USB_KdPrint( DBGLVL_DEFAULT,("MaximumTransferSize 0x%x\n", pipeInformation->MaximumTransferSize));
}
USB_KdPrint( DBGLVL_DEFAULT,("---------\n"));
}
}
if (urb) {
// don't call the USB_ExFreePool since the buffer was
// alloced by USBD_CreateConfigurationRequest, not USB_ExAllocatePool()
ExFreePool(urb);
}
USB_KdPrint( DBGLVL_DEFAULT,("exit USB_SelectInterface (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
USB_ResetPipe(
IN PDEVICE_OBJECT DeviceObject,
IN PUSBD_PIPE_INFORMATION PipeInfo
)
{
NTSTATUS ntStatus;
PURB urb;
PDEVICE_EXTENSION deviceExtension;
deviceExtension = DeviceObject->DeviceExtension;
USB_KdPrint( DBGLVL_DEFAULT,("USB_ResetPipe() Reset Pipe %x\n", PipeInfo));
urb = USB_ExAllocatePool(NonPagedPool,
sizeof(struct _URB_PIPE_REQUEST));
if (urb) {
urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
urb->UrbPipeRequest.PipeHandle =
PipeInfo->PipeHandle;
ntStatus = USB_CallUSBD(DeviceObject, urb);
USB_ExFreePool(urb);
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
if (!(NT_SUCCESS(ntStatus))) {
#if DBG
if ( gpDbg )
gpDbg->PipeErrorCount++;
#endif
USB_KdPrint( DBGLVL_DEFAULT,("USB_ResetPipe() FAILED, ntStatus =0x%x\n", ntStatus ));
}
else {
#if DBG
if ( gpDbg )
gpDbg->ResetPipeCount++;
#endif
USB_KdPrint( DBGLVL_DEFAULT,("USB_ResetPipe() SUCCESS, ntStatus =0x%x\n", ntStatus ));
}
return ntStatus;
}
LONG
USB_DecrementIoCount(
IN PDEVICE_OBJECT DeviceObject
)
{
PDEVICE_EXTENSION deviceExtension;
LONG ioCount;
KIRQL oldIrql;
deviceExtension = DeviceObject->DeviceExtension;
KeAcquireSpinLock (&deviceExtension->IoCountSpinLock, &oldIrql);
ioCount = InterlockedDecrement(&deviceExtension->PendingIoCount);
#if DBG
InterlockedDecrement(&gpDbg->PendingIoCount);
#endif
USB_TrapCond( DBGLVL_HIGH,( 0 > ioCount ) );
if (ioCount==1) {
// trigger no pending io
KeSetEvent(&deviceExtension->NoPendingIoEvent,
1,
FALSE);
}
if (ioCount==0) {
// trigger remove-device event
KeSetEvent(&deviceExtension->RemoveEvent,
1,
FALSE);
}
KeReleaseSpinLock (&deviceExtension->IoCountSpinLock, oldIrql);
USB_KdPrint( DBGLVL_HIGH,("Exit USB_DecrementIoCount() Pending io count = %x\n", ioCount));
return ioCount;
}
VOID
USB_IncrementIoCount(
IN PDEVICE_OBJECT DeviceObject
)
{
PDEVICE_EXTENSION deviceExtension;
KIRQL oldIrql;
deviceExtension = DeviceObject->DeviceExtension;
USB_KdPrint( DBGLVL_MAXIMUM,("Enter USB_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount));
KeAcquireSpinLock (&deviceExtension->IoCountSpinLock, &oldIrql);
InterlockedIncrement(&deviceExtension->PendingIoCount);
#if DBG
InterlockedIncrement(&gpDbg->PendingIoCount);
#endif
KeReleaseSpinLock (&deviceExtension->IoCountSpinLock, oldIrql);
USB_KdPrint( DBGLVL_HIGH,("Exit USB_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount));
}
////////////////////////////////////////
NTSTATUS
USB_ProcessPnPIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus = STATUS_SUCCESS;
NTSTATUS waitStatus;
PDEVICE_OBJECT stackDeviceObject;
KEVENT startDeviceEvent;
irpStack = IoGetCurrentIrpStackLocation (Irp);
deviceExtension = DeviceObject->DeviceExtension;
stackDeviceObject = deviceExtension->TopOfStackDeviceObject;
USB_KdPrint( DBGLVL_DEFAULT,("USB_ProcessPnPIrp()\n"));
USB_KdPrint( DBGLVL_MEDIUM, ( "enter USB_ProcessPnPIrp() IRP_MJ_PNP, minor %s\n",
USB_StringForPnpMnFunc( irpStack->MinorFunction ) ));
// inc the FDO device extension's pending IO count for this Irp
USB_IncrementIoCount(DeviceObject);
USB_ASSERT( IRP_MJ_PNP == irpStack->MajorFunction );
switch (irpStack->MinorFunction) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -