📄 usb.c
字号:
//
// USB2COM driver only supports one interface, we must parse
// the configuration descriptor for the interface
// and remember the pipes.
//
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 descriptro
-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 ) {
USB2COM_KdPrint( DBGLVL_HIGH,("USB2COM_SelectInterface() ParseConfigurationDescriptorEx() failed\n returning STATUS_INSUFFICIENT_RESOURCES\n"));
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 = USB2COM_ExAllocatePool(
NonPagedPool,
Interface->NumberOfPipes * sizeof ( USB2COM_PIPEINFO ) );
if ( !deviceExtension->PipeInfo ) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(deviceExtension->PipeInfo,
Interface->NumberOfPipes * sizeof ( USB2COM_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
//
( (PUSB2COM_PIPEINFO) pInf)->fPipeOpened = FALSE;
pInf += sizeof ( USB2COM_PIPEINFO );
}
UsbBuildSelectConfigurationRequest(urb,
(USHORT) siz,
ConfigurationDescriptor);
ntStatus = USB2COM_CallUSBD(DeviceObject, urb);
deviceExtension->UsbConfigurationHandle =
urb->UrbSelectConfiguration.ConfigurationHandle;
} else {
USB2COM_KdPrint( DBGLVL_HIGH,("USB2COM_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 = USB2COM_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
//
USB2COM_KdPrint( DBGLVL_MEDIUM,("---------\n"));
USB2COM_KdPrint( DBGLVL_MEDIUM,("NumberOfPipes 0x%x\n", deviceExtension->UsbInterface->NumberOfPipes));
USB2COM_KdPrint( DBGLVL_MEDIUM,("Length 0x%x\n", deviceExtension->UsbInterface->Length));
USB2COM_KdPrint( DBGLVL_MEDIUM,("Alt Setting 0x%x\n", deviceExtension->UsbInterface->AlternateSetting));
USB2COM_KdPrint( DBGLVL_MEDIUM,("Interface Number 0x%x\n", deviceExtension->UsbInterface->InterfaceNumber));
USB2COM_KdPrint( DBGLVL_MEDIUM,("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];
USB2COM_KdPrint( DBGLVL_MEDIUM,("---------\n"));
USB2COM_KdPrint( DBGLVL_MEDIUM,("PipeType 0x%x\n", pipeInformation->PipeType));
USB2COM_KdPrint( DBGLVL_MEDIUM,("EndpointAddress 0x%x\n", pipeInformation->EndpointAddress));
USB2COM_KdPrint( DBGLVL_MEDIUM,("MaxPacketSize 0x%x\n", pipeInformation->MaximumPacketSize));
USB2COM_KdPrint( DBGLVL_MEDIUM,("Interval 0x%x\n", pipeInformation->Interval));
USB2COM_KdPrint( DBGLVL_MEDIUM,("Handle 0x%x\n", pipeInformation->PipeHandle));
USB2COM_KdPrint( DBGLVL_MEDIUM,("MaximumTransferSize 0x%x\n", pipeInformation->MaximumTransferSize));
}
USB2COM_KdPrint( DBGLVL_MEDIUM,("---------\n"));
}
}
if (urb) {
// don't call the USB2COM_ExFreePool since the buffer was
// alloced by USBD_CreateConfigurationRequest, not USB2COM_ExAllocatePool()
ExFreePool(urb);
}
USB2COM_KdPrint( DBGLVL_HIGH,("exit USB2COM_SelectInterface (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
USB2COM_ResetPipe(
IN PDEVICE_OBJECT DeviceObject,
IN PUSBD_PIPE_INFORMATION PipeInfo
)
/*++
Routine Description:
Reset a given USB pipe.
NOTES:
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 ntStatus;
PURB urb;
PDEVICE_EXTENSION deviceExtension;
deviceExtension = DeviceObject->DeviceExtension;
USB2COM_KdPrint( DBGLVL_DEFAULT,("USB2COM_ResetPipe() Reset Pipe %x\n", PipeInfo));
urb = USB2COM_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 = USB2COM_CallUSBD(DeviceObject, urb);
USB2COM_ExFreePool(urb);
} else {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
if (!(NT_SUCCESS(ntStatus))) {
#if DBG
if ( gpDbg )
gpDbg->PipeErrorCount++;
#endif
USB2COM_KdPrint( DBGLVL_DEFAULT,("USB2COM_ResetPipe() FAILED, ntStatus =0x%x\n", ntStatus ));
}
else {
#if DBG
if ( gpDbg )
gpDbg->ResetPipeCount++;
#endif
USB2COM_KdPrint( DBGLVL_DEFAULT,("USB2COM_ResetPipe() SUCCESS, ntStatus =0x%x\n", ntStatus ));
}
return ntStatus;
}
LONG
USB2COM_DecrementIoCount(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
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
--*/
{
PDEVICE_EXTENSION deviceExtension;
LONG ioCount;
KIRQL oldIrql;
deviceExtension = DeviceObject->DeviceExtension;
KeAcquireSpinLock (&deviceExtension->IoCountSpinLock, &oldIrql);
ioCount = InterlockedDecrement(&deviceExtension->PendingIoCount);
#if DBG
InterlockedDecrement(&gpDbg->PendingIoCount);
#endif
USB2COM_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);
USB2COM_KdPrint( DBGLVL_HIGH,("Exit USB2COM_DecrementIoCount() Pending io count = %x\n", ioCount));
return ioCount;
}
VOID
USB2COM_IncrementIoCount(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
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
--*/
{
PDEVICE_EXTENSION deviceExtension;
KIRQL oldIrql;
LONG ioCount;
deviceExtension = DeviceObject->DeviceExtension;
USB2COM_KdPrint( DBGLVL_MAXIMUM,("Enter USB2COM_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount));
KeAcquireSpinLock (&deviceExtension->IoCountSpinLock, &oldIrql);
ioCount = InterlockedIncrement(&deviceExtension->PendingIoCount);
//************************************************************
//see uscrpnp.c line 273. yanglq 2005-6-25
if(ioCount > 1)
{
KeClearEvent(&deviceExtension->NoPendingIoEvent);
//USCR_KdPrint( DBGLVL_DEFAULT,("Clear NoPendingIoEvent\n"));
}
//************************************************************
#if DBG
InterlockedIncrement(&gpDbg->PendingIoCount);
#endif
KeReleaseSpinLock (&deviceExtension->IoCountSpinLock, oldIrql);
USB2COM_KdPrint( DBGLVL_HIGH,("Exit USB2COM_IncrementIoCount() Pending io count = %x\n", deviceExtension->PendingIoCount));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -