📄 uscrusb.c
字号:
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
PDEVICE_EXTENSION deviceExtension;
USCR_KdPrint( DBGLVL_DEFAULT,("enter USCR_ResetParentPort\n"));
deviceExtension = DeviceObject->DeviceExtension;
//
// issue a synchronous request
//
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_RESET_PORT,
deviceExtension->TopOfStackDeviceObject,
NULL,
0,
NULL,
0,
TRUE, // internal ( use IRP_MJ_INTERNAL_DEVICE_CONTROL )
&event,
&ioStatus);
//
// Call the class driver to perform the operation. If the returned status
// is PENDING, wait for the request to complete.
//
nextStack = IoGetNextIrpStackLocation(irp);
USCR_ASSERT(nextStack != NULL);
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetParentPort() calling USBD enable port api\n"));
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetParentPort() return from IoCallDriver USBD %x\n", ntStatus));
if (ntStatus == STATUS_PENDING) {
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetParentPort() Wait for single object\n"));
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_ResetParentPort() Wait for single object, returned %x\n", status));
} else {
ioStatus.Status = ntStatus;
}
//
// USBD maps the error code for us
//
ntStatus = ioStatus.Status;
USCR_KdPrint( DBGLVL_DEFAULT,("Exit USCR_ResetPort (%x)\n", ntStatus));
return ntStatus;
}
NTSTATUS
USCR_USBIoctl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Dispatch table handler for IRP_MJ_DEVICE_CONTROL;
Handle DeviceIoControl() calls from User mode
Arguments:
DeviceObject - pointer to the FDO for this instance of the 82930 device.
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
PDEVICE_EXTENSION deviceExtension;
ULONG ioControlCode;
NTSTATUS ntStatus;
ULONG length;
PUCHAR pch;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
USCR_KdPrint( DBGLVL_DEFAULT,("USCR_USBIoctl\n"));
// USCR_IncrementIoCount(DeviceObject);
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
deviceExtension = DeviceObject->DeviceExtension;
// Can't accept a new io request if:
// 1) device is removed,
// 2) has never been started,
// 3) is stopped,
// 4) has a remove request pending,
// 5) has a stop device pending
//if ( !USCR_CanAcceptIoRequests( DeviceObject ) ) {
// ntStatus = STATUS_DELETE_PENDING;
// Irp->IoStatus.Status = ntStatus;
// Irp->IoStatus.Information = 0;
// IoCompleteRequest( Irp, IO_NO_INCREMENT );
// USCR_DecrementIoCount(DeviceObject);
// return ntStatus;
//}
irpStack = IoGetCurrentIrpStackLocation (Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
// get pointers and lengths of the caller's (user's) IO buffer
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
//
// Handle Ioctls from User mode
//
switch (ioControlCode) {
case IOCTL_USCR_RESET_PIPE:
{
PUSBD_PIPE_INFORMATION pipe;
PFILE_OBJECT fileObject;
// get our context and see if it is a pipe
fileObject = irpStack->FileObject;
pipe = (PUSBD_PIPE_INFORMATION) fileObject->FsContext;
if(pipe == NULL) {
// error, this is not a pipe
ntStatus =
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
} else {
USCR_ResetPipe(DeviceObject, pipe );
ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
}
}
break;
case IOCTL_USCR_GET_CONFIG_DESCRIPTOR:
//
// This api returns a copy of the configuration descriptor
// and all endpoint/interface descriptors.
//
//
// inputs - none
// outputs - configuration descriptor plus interface
// and endpoint descriptors
//
pch = (PUCHAR) ioBuffer;
configurationDescriptor =
deviceExtension->UsbConfigurationDescriptor;
if (configurationDescriptor) {
length = configurationDescriptor->wTotalLength;
if (outputBufferLength >= length) {
RtlCopyMemory(pch,
(PUCHAR) configurationDescriptor,
length);
Irp->IoStatus.Information = length;
ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
}
else {
Irp->IoStatus.Information = 0;
ntStatus = Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
}
else {
Irp->IoStatus.Information = 0;
ntStatus = Irp->IoStatus.Status = STATUS_DEVICE_DATA_ERROR;
}
break;
case IOCTL_USCR_RESET_DEVICE:
ntStatus = USCR_ResetDevice( DeviceObject );
break;
default:
ntStatus =
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}
//IoCompleteRequest (Irp,
// IO_NO_INCREMENT
// );
//USCR_DecrementIoCount(DeviceObject);
return ntStatus;
}
NTSTATUS
UsbDoInterruptOrBulkTransfer(
IN PDEVICE_OBJECT DeviceObject,
IN USBD_PIPE_HANDLE PipeHandle,
IN ULONG TransferFlags,
IN PVOID UserBuffer,
ULONG *UserBufferSize)
{
ULONG InputBufferSize;
NTSTATUS status = STATUS_SUCCESS;
USHORT UrbSize;
PURB urb;
LARGE_INTEGER StartTickCount;
LARGE_INTEGER TickCountNow;
ULONG UnitsOf100ns;
ULONG ticks;
ULONG nRetries = 10000;
USCR_KdPrint( DBGLVL_MEDIUM,("enter UsbDoInterruptOrBulkTransfer\n"));
// Check we're selected
if( PipeHandle == NULL)
return STATUS_INVALID_HANDLE;
// Check input parameters
InputBufferSize = *UserBufferSize;
RetryCallUSBD:
*UserBufferSize = 0;
if( UserBuffer==NULL || InputBufferSize <= 0)
return STATUS_INVALID_PARAMETER;
// Allocate memory for URB
UrbSize = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
urb = (PURB)USCR_ExAllocatePool(NonPagedPool, UrbSize);
if( urb == NULL)
{
USCR_KdPrint( DBGLVL_HIGH,("No URB memory\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
// Remember when we started
// Get start tick count and length of tick in 100ns units
KeQueryTickCount( &StartTickCount);
UnitsOf100ns = KeQueryTimeIncrement();
USCR_KdPrint( DBGLVL_MEDIUM,("Time increment %d\n", UnitsOf100ns));
USCR_KdPrint(DBGLVL_MEDIUM,("Request len=%d\n",InputBufferSize));
// Build Do Bulk or Interrupt transfer request
UsbBuildInterruptOrBulkTransferRequest(
urb, UrbSize,
PipeHandle,
UserBuffer, NULL, InputBufferSize,
TransferFlags,
NULL);
// Call the USB driver
status = USCR_CallUSBD(DeviceObject, urb);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
USCR_KdPrint(
DBGLVL_HIGH,
("status %x URB status %x\n", status, urb->UrbHeader.Status)
);
status = STATUS_UNSUCCESSFUL;
}
USCR_KdPrint(
DBGLVL_MEDIUM,
("TransferBufferLength = %d\n",
urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
);
// Check for timeout
KeQueryTickCount( &TickCountNow);
ticks = (ULONG)(TickCountNow.QuadPart - StartTickCount.QuadPart);
USCR_KdPrint(
DBGLVL_MEDIUM,
("Time elapsed: %d us\n",
ticks*UnitsOf100ns/10)
);
*UserBufferSize = urb->UrbBulkOrInterruptTransfer.TransferBufferLength;
if( NT_SUCCESS(status))
{
HEXDUMP((PUCHAR)UserBuffer,*UserBufferSize);
}
if(USBD_STATUS_DEV_NOT_RESPONDING == urb->UrbHeader.Status ||
urb->UrbHeader.Status == 0x80000005)//for win2k
{
USCR_ExFreePool(urb);
if( KeGetCurrentIrql() < DISPATCH_LEVEL ){
LARGE_INTEGER delay;
delay.QuadPart = - 10 * 1000 * 5; // 5 ms
KeDelayExecutionThread( KernelMode, TRUE, &delay );
USCR_KdPrint(DBGLVL_DEFAULT,("Device not responding sleep 10 ms\n"));
}else{
USCR_KdPrint(DBGLVL_DEFAULT,("Device not responding want sleep but KeGetCurrentIrql() >= DISPATCH_LEVEL\n"));
}
if(--nRetries)
goto RetryCallUSBD;
}else
USCR_ExFreePool(urb);
USCR_KdPrint( DBGLVL_MEDIUM,("leave UsbDoInterruptOrBulkTransfer status=%x\n",status));
return status;
}
NTSTATUS
UsbDoControlTransfer(
IN PDEVICE_OBJECT DeviceObject,
IN PSETUP_PACKET SetupPacket,
IN ULONG TransferFlags,
IN PVOID UserBuffer,
ULONG *UserBufferSize)
{
ULONG InputBufferSize;
NTSTATUS status = STATUS_SUCCESS;
USHORT UrbSize;
PURB urb;
LARGE_INTEGER StartTickCount;
LARGE_INTEGER TickCountNow;
ULONG UnitsOf100ns;
ULONG ticks;
ULONG nRetries = 1000000;
USCR_KdPrint( DBGLVL_MEDIUM,("enter UsbDoControlTransfer\n"));
// Check input parameters
InputBufferSize = *UserBufferSize;
RetryCallUSBD:
*UserBufferSize = 0;
if( UserBuffer==NULL)
return STATUS_INVALID_PARAMETER;
// Allocate memory for URB
UrbSize = sizeof(struct _URB_CONTROL_VENDOR_OR_CLASS_REQUEST );
urb = (PURB)USCR_ExAllocatePool(NonPagedPool, UrbSize);
if( urb == NULL)
{
USCR_KdPrint( DBGLVL_HIGH,("No URB memory\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
// Remember when we started
// Get start tick count and length of tick in 100ns units
KeQueryTickCount( &StartTickCount);
UnitsOf100ns = KeQueryTimeIncrement();
//USCR_KdPrint( DBGLVL_MEDIUM,("Time increment %d\n", UnitsOf100ns));
// Build Do Control transfer request
UsbBuildVendorRequest(
urb,
URB_FUNCTION_CLASS_DEVICE,
UrbSize,
TransferFlags,
0,//Specifies a value, from 4 to 31 inclusive,
//that becomes part of the request type code in the USB-defined setup packet.
SetupPacket->bRequest,
SetupPacket->wValue,
SetupPacket->wIndex,
UserBuffer,
NULL,
SetupPacket->wLength,
NULL
);
// Call the USB driver
status = USCR_CallUSBD(DeviceObject, urb);
// Check statuses
if( !NT_SUCCESS(status) || !USBD_SUCCESS( urb->UrbHeader.Status))
{
USCR_KdPrint(
DBGLVL_HIGH,
("status %x URB status %x\n", status, urb->UrbHeader.Status)
);
status = STATUS_UNSUCCESSFUL;
}
USCR_KdPrint(
DBGLVL_MEDIUM,
("TransferBufferLength = %d\n",
urb->UrbBulkOrInterruptTransfer.TransferBufferLength)
);
// Check for timeout
KeQueryTickCount( &TickCountNow);
ticks = (ULONG)(TickCountNow.QuadPart - StartTickCount.QuadPart);
//USCR_KdPrint(
// DBGLVL_MEDIUM,
// ("Time elapsed: %d us\n",
// ticks*UnitsOf100ns/10)
// );
*UserBufferSize = urb->UrbControlVendorClassRequest.TransferBufferLength;
if( NT_SUCCESS(status))
{
HEXDUMP((PUCHAR)UserBuffer,*UserBufferSize);
}
if(USBD_STATUS_DEV_NOT_RESPONDING == urb->UrbHeader.Status ||
urb->UrbHeader.Status == 0x80000005)//for win2k
{
USCR_ExFreePool(urb);
if( KeGetCurrentIrql() < DISPATCH_LEVEL ){
LARGE_INTEGER delay;
delay.QuadPart = - 10 * 1000 * 5; // 5 ms
KeDelayExecutionThread( KernelMode, TRUE, &delay );
USCR_KdPrint(DBGLVL_DEFAULT,("Device not responding sleep 10 ms\n"));
}else{
USCR_KdPrint(DBGLVL_DEFAULT,("Device not responding want sleep but KeGetCurrentIrql() >= DISPATCH_LEVEL\n"));
}
if(--nRetries)
goto RetryCallUSBD;
}else
USCR_ExFreePool(urb);
USCR_KdPrint( DBGLVL_MEDIUM,("leave UsbDoControlTransfer status=%x\n",status));
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -