📄 drvdispatch.c
字号:
hwDbgPrint("IoCallDriver() USBD returned ntStatus = 0x%x\n", ntStatus);
if (ntStatus == STATUS_PENDING)
{
hwDbgPrint("Wait for single object\n");
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
hwDbgPrint("hwGetPortStatus() Wait for single object, returned 0x%x\n", status);
}
else
{
ioStatus.Status = ntStatus;
}
// USBD maps the error code for us
ntStatus = ioStatus.Status;
hwDbgPrint("hwGetPortStatus (ntStatus = 0x%x)-->>>>>>\n", ntStatus);
return ntStatus;
}
/************************************************************************************************
* Function Type : global
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* Return Value : STATUS_SUCCESS - if successful,
* STATUS_UNSUCCESSFUL - otherwise
* Description : Reset the our parent port
*************************************************************************************************/
NTSTATUS hwResetParentPort(IN PDEVICE_OBJECT fdo)
{
NTSTATUS ntStatus, status = STATUS_SUCCESS;
PIRP irp;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIO_STACK_LOCATION nextStack;
PDEVICE_EXTENSION dx;
hwDbgPrint(" -->>>>>> hwResetParentPort(fdo=0x%x)\n",fdo);
dx = fdo->DeviceExtension;
//------------------------------------------------------------------
// issue a synchronous request
//------------------------------------------------------------------
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_RESET_PORT,
dx->LowerDeviceObject,
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);
hwASSERT(nextStack != NULL);
hwDbgPrint("hwResetParentPort() calling USBD enable port api\n");
ntStatus = IoCallDriver(dx->LowerDeviceObject,irp);
hwDbgPrint("hwResetParentPort() return from IoCallDriver USBD %x\n", ntStatus);
if (ntStatus == STATUS_PENDING)
{
hwDbgPrint("hwResetParentPort() Wait for single object\n");
status = KeWaitForSingleObject(
&event,
Suspended,
KernelMode,
FALSE,
NULL);
hwDbgPrint("hwResetParentPort() Wait for single object, returned %x\n", status);
}
else
{
ioStatus.Status = ntStatus;
}
// USBD maps the error code for us
ntStatus = ioStatus.Status;
hwDbgPrint(" zjHMCFUsb_ResetPort (%x)-->>>>>>\n ", ntStatus);
return ntStatus;
}
/************************************************************************************************
* Function Type : global
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* Return Value : NT status code
* Description : Checks port status; if OK, return success and do no more;
* If bad, attempt reset
*************************************************************************************************/
NTSTATUS hwResetDevice( IN PDEVICE_OBJECT fdo )
{
NTSTATUS ntStatus;
ULONG portStatus;
hwDbgPrint(" -->>>>>> hwResetDevice(fdo=0x%x)\n",fdo);
//------------------------------------------------------------------
// Check the port state, if it is disabled we will need
// to re-enable it
//------------------------------------------------------------------
ntStatus = hwGetPortStatus(fdo, &portStatus);
if (NT_SUCCESS(ntStatus) && !(portStatus & USBD_PORT_ENABLED) &&
portStatus & USBD_PORT_CONNECTED)
{
// port is disabled, attempt reset
hwDbgPrint("Device will reset\n");
ntStatus = hwResetParentPort(fdo);
}
hwDbgPrint(" hwResetDevice(ntStatus=0x%x)-->>>>>>\n",ntStatus);
return ntStatus;
}
/************************************************************************************************
* Function Type : global
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* Return Value : NT status code
* Description : Dispatch table handler for IRP_MJ_DEVICE_CONTROL;
* Handle DeviceIoControl() calls from User mode
*************************************************************************************************/
NTSTATUS zjHMCFUsb_IOCTL(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
PDEVICE_EXTENSION dx;
ULONG ioControlCode;
NTSTATUS ntStatus = STATUS_SUCCESS;
ULONG length;
PUCHAR pch;
PUSBD_PIPE_INFORMATION pipe;
PFILE_OBJECT fileObject;
PUSB_CONFIGURATION_DESCRIPTOR configurationDescriptor;
PUSB_DEVICE_DESCRIPTOR usbDeviceDescriptor;
ULONG_PTR IrpInfo = 0;
hwDbgPrint("-->>>>>>zjHMCFUsb_IOCTL(fdo=0x%x,Irp=0x%x)\n",fdo,Irp);
PrintCurIrql();
hwIncrementIoCount(fdo);
dx = fdo->DeviceExtension;
if ( !hwCanAcceptIoRequests( fdo ) )
{
hwDecrementIoCount(fdo);
return CompleteIrp( Irp, STATUS_DELETE_PENDING,0,IO_NO_INCREMENT);
}
//------------------------------------------------------------------
// 取得当前IRP栈指针,以从中获取功能代码和参数
//------------------------------------------------------------------
irpStack = IoGetCurrentIrpStackLocation (Irp);
//------------------------------------------------------------------
// 获取用户的I/O缓冲地址和长度以及IOCTL代码
//------------------------------------------------------------------
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode)
{
case IOCTL_zjHMCFUsb_RESET_PIPE:
// 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 = STATUS_INVALID_PARAMETER;
}
else
{
hwResetPipe(fdo, pipe );
ntStatus = STATUS_SUCCESS;
}
break;
case IOCTL_zjHMCFUsb_GET_CONFIG_DESCRIPTOR:
//------------------------------------------------------------------
// 这个API返回配置描述符和所有的端点、接点描
// 述符的拷贝。
// 输入 - 没有
// 输出 - 配置描述符加上接点、端点描述符
//------------------------------------------------------------------
pch = (PUCHAR) ioBuffer;
configurationDescriptor = dx->UsbConfigurationDescriptor;
if (configurationDescriptor)
{
length = configurationDescriptor->wTotalLength;
if (outputBufferLength >= length)
{
RtlCopyMemory(pch,(PUCHAR) configurationDescriptor,length);
IrpInfo = length;
ntStatus = STATUS_SUCCESS;
}
else
{
ntStatus = STATUS_INVALID_PARAMETER;
}
}
else
{
ntStatus = STATUS_DEVICE_DATA_ERROR;
}
break;
case IOCTL_zjHMCFUsb_GET_DEVICE_DESCRIPTOR:
// 将设备描述符数据拷贝给用户层
pch = (PUCHAR) ioBuffer;
usbDeviceDescriptor = dx->UsbDeviceDescriptor;
if ( usbDeviceDescriptor )
{
length = usbDeviceDescriptor->bLength;
if (outputBufferLength >= length)
{
RtlCopyMemory(pch,(PUCHAR) usbDeviceDescriptor,length);
IrpInfo = length;
ntStatus = STATUS_SUCCESS;
}
else
{
ntStatus = STATUS_INVALID_PARAMETER;
}
}
else
{
ntStatus = STATUS_DEVICE_DATA_ERROR;
}
break;
case IOCTL_zjHMCFUsb_RESET_DEVICE:
ntStatus = hwResetDevice( fdo );
break;
default:
ntStatus = STATUS_INVALID_PARAMETER;
}
hwDecrementIoCount(fdo);
return CompleteIrp( Irp, ntStatus,IrpInfo,IO_NO_INCREMENT);;
}
/************************************************************************************************
* Function Type : global
* Parameter : fdo - pointer to our FDO (Functional Device Object )
* Return Value : NT status code
* Description : This is the dispatch table routine for IRP_MJ_CREATE.
* It's the entry point for CreateFile() calls
* user mode apps may open "<name genned fron GUID>.\yy"
* where yy is the internal pipe id
* Note : 1、根据名字获得管道信息
* 2、从接口中找到这个管道,将标志
* 设置为"打开",打开的管道数加1
* 3、激活这个设备
*************************************************************************************************/
NTSTATUS zjHMCFUsb_Create(IN PDEVICE_OBJECT fdo, IN PIRP Irp )
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PFILE_OBJECT fileObject;
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION dx;
ULONG i,
ix;
NTSTATUS actStat;
PUSBD_INTERFACE_INFORMATION interface;
PUSBD_PIPE_INFORMATION PipeInfo;
PzjHMCFUsb_PIPESTATE PipeState = NULL;
int PipeIndex;
PAGED_CODE(); //此代码包含可分页代码
dx = fdo->DeviceExtension;
interface = dx->UsbInterface; //获取接口信息
hwDbgPrint( " -->>>>>>zjHMCFUsb_Create(fdo=0x%x,Irp=0x%x)\n",fdo,Irp);
PrintCurIrql();
hwIncrementIoCount(fdo);
if ( !hwCanAcceptIoRequests( fdo ) )
{
ntStatus = STATUS_DELETE_PENDING;
hwDbgPrint( "ABORTING!!!\n");
goto done;
}
irpStack = IoGetCurrentIrpStackLocation (Irp);
fileObject = irpStack->FileObject;
fileObject->FsContext = NULL; //初始化文件对象中的内容参数
if ( 0 == fileObject->FileName.Length ) //文件名长度为0则应用程序打开的只是设备本身
goto done; // nothing more to do
PipeIndex = hwPipeWithName( fdo, &fileObject->FileName );
if ( PipeIndex == -1 )
{
ntStatus = STATUS_INVALID_PARAMETER;
goto done;
}
// init status to bad; will set good in below loop on success
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
hwDbgPrint ( "Open pipe %d",PipeIndex );
PipeState = &dx->PipeState[ PipeIndex ];
PipeInfo = &interface->Pipes[ PipeIndex ];
fileObject->FsContext = PipeInfo;
if ( PipeState->fPipeOpened ) // 这个管道已经被打开了 //d
{
ntStatus = STATUS_UNSUCCESSFUL;
goto done;
}
PipeState->fPipeOpened = TRUE; // set flag for opened
ntStatus = STATUS_SUCCESS;
dx->OpenPipeCount++;
// try to power up device if its not in D0
actStat = hwSelfSuspendOrActivate( fdo, FALSE );
done:
hwDecrementIoCount(fdo);
hwDbgPrint("zjHMCFUsb_Create() OpenPipeCount = %d, status = 0x%x-->>>>>>\n",
dx->OpenPipeCount, ntStatus);
return CompleteIrp( Irp, ntStatus,0,IO_NO_INCREMENT);
}
#ifdef _PRINT_COMM_DATA
VOID PrintCommData ( char *data, int dwLength )
{
int i;
for ( i=0; i<dwLength; i++ )
{
DbgPrint ( "%02x ", (UCHAR)data[i] );
}
DbgPrint ( "\n" );
}
#endif
/************************************************************************************************
* Function Type : global
* Parameter : fdo - Pointer to the device object for next lower device in the driver stack
* Irp - Irp completed.
* Context - our FDO.
* Return Value : 此次IP操作的最后状态
* Description : 单次URB传输的完成例程
*************************************************************************************************/
NTSTATUS hwReadWriteComplete
(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp,
IN PVOID Context
)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PURB urb;
PDEVICE_OBJECT deviceObject;
PDEVICE_EXTENSION dx;
//------------------------------------------------------------------
// 我们不得不从Context中取得设备对象(deviceObject),因为
// 传入的设备对象(fdo)是属于下层驱动的,因为
// 我们调用了IoCallDriver()将irp传给下层,下层处理完irp
// 后就调这个完成例程了。
// 但是我们想要的设备对象应该是我们自己的,在
// hwProcessReadWrite()中设置完成例程时我们将它放
// 到上下文参数(Context)中了
//------------------------------------------------------------------
deviceObject = (PDEVICE_OBJECT) Context;
dx = deviceObject->DeviceExtension;
urb = dx->TransferDataUrb; //get the urb we alloced for this xfer
// If the lower driver returned PENDING, mark our stack location as pending also.
if ( Irp->PendingReturned )
{
IoMarkIrpPending(Irp);
}
hwDbgPrint(" -->>>>>> hwReadWriteComplete(): Length 0x%08X decimal %d\n Status 0x%08X\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -