⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 drvdispatch.c

📁 ddk编写的usb驱动源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
		urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
		urb->UrbHeader.Status);

	// decrement the driver's overall pending irp count
	hwDecrementIoCount(deviceObject);
    
	//------------------------------------------------------------------ 
	// IoCallDriver has been called on this Irp;
	// Set the length based on the TransferBufferLength
	// value in the URB
	//------------------------------------------------------------------

	ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
	CompleteIrp (	Irp,
					STATUS_SUCCESS,
					urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
					IO_NO_INCREMENT);

#if DBG
#ifdef _BUFFERED_IO
	hwDbgPrint ( "TransferFlags = %d, TransferBuffer = 0x%x, TransferBufferLength = %d\n", 
		urb->UrbBulkOrInterruptTransfer.TransferFlags ,
		urb->UrbBulkOrInterruptTransfer.TransferBuffer, 
		urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
	if ( urb->UrbBulkOrInterruptTransfer.TransferBuffer )
	{
		hwPrintCommData ( (char*)urb->UrbBulkOrInterruptTransfer.TransferBuffer ,
			urb->UrbBulkOrInterruptTransfer.TransferBufferLength );
	}
#else
	hwDbgPrint ( "TransferFlags = %d, TransferBufferMDL = 0x%x, TransferBufferLength = %d\n", 
		urb->UrbBulkOrInterruptTransfer.TransferFlags ,
		urb->UrbBulkOrInterruptTransfer.TransferBufferMDL, 
		urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
	if ( urb->UrbBulkOrInterruptTransfer.TransferBufferMDL )
	{
		hwPrintCommData ( (char*) urb->UrbBulkOrInterruptTransfer.TransferBufferMDL ,
			urb->UrbBulkOrInterruptTransfer.TransferBufferLength );
	}
#endif
#endif
	hwDbgPrint("hwReadWriteComplete( ntStatus = 0x%x )-->>>>>>\n",ntStatus ); 

	return ntStatus;
}

/************************************************************************************************
* Function Type	:	global
* Parameter		:	fdo			-	pointer to the FDO ( Functional Device Object )
*					Irp			-	A staged IRP allocated and mapped by this driver in zjHMCFUsb_StageReadWrite()
*									to perform a single dx->MaximumTransferSize IO request
*					PipeHandle	-	我们要读或写的端点句柄
*					pUserBuffer	-	用户缓冲,如果使用缓冲IO时这个参数有用
*					Read		-	TRUE for reads, FALSE for writes
* Return Value	:	ptr to initialized async urb. ( USB Request Block )
* Description		:	Called from zjHMCFUsb_StageReadWrite() for IRP_MJ_READ or IRP_MJ_WRITE
* Note			:
*	1. 调用ExAllocatePool()分配一个非分页的内存用来存储URB结构体,这个内存
* 将在完成例程zjHMCFUsb_SimpleReadWrite_Complete()中释放
*	2. 填好里面的参数,主要是端点句柄、传输标志、缓冲地址、要传输
* 的数据长度
*************************************************************************************************/
PURB hwBuildAsyncReadWriteURB
(
		IN	PDEVICE_OBJECT			fdo,
		IN	PIRP						Irp,
		IN	PURB					urb,
		IN	PVOID					pUserBuffer,
		IN	PUSBD_PIPE_INFORMATION PipeHandle,
		IN	ULONG					length,
		IN	BOOLEAN					Read
)
{
	ULONG SizeofUrbBulkOrInterruptTransfer;
	hwASSERT( urb );

	SizeofUrbBulkOrInterruptTransfer = sizeof ( struct _URB_BULK_OR_INTERRUPT_TRANSFER );
	
	hwDbgPrint(" -->>>>>> hwBuildAsyncReadWriteURB() len = 0x%x decimal %d \n SizeofUrbBulkOrInterruptTransfer = 0x%x  urb 0x%x\n Pipehandle 0x%x",
		length, length, SizeofUrbBulkOrInterruptTransfer, urb, PipeHandle);
	RtlZeroMemory(urb, SizeofUrbBulkOrInterruptTransfer);
	urb->UrbBulkOrInterruptTransfer.Hdr.Length = (USHORT) SizeofUrbBulkOrInterruptTransfer;
	urb->UrbBulkOrInterruptTransfer.Hdr.Function = URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER;
	urb->UrbBulkOrInterruptTransfer.PipeHandle =	PipeHandle->PipeHandle;
	// 传输方向
	urb->UrbBulkOrInterruptTransfer.TransferFlags = Read ? USBD_TRANSFER_DIRECTION_IN : 0;	
	// short packet is not treated as an error.
	urb->UrbBulkOrInterruptTransfer.TransferFlags |= USBD_SHORT_TRANSFER_OK;
	// not using linked urb's
	urb->UrbBulkOrInterruptTransfer.UrbLink = NULL;
#ifdef _BUFFERED_IO
	urb->UrbBulkOrInterruptTransfer.TransferBuffer = pUserBuffer;
	urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = NULL;
#else
	urb->UrbBulkOrInterruptTransfer.TransferBuffer = NULL;
	urb->UrbBulkOrInterruptTransfer.TransferBufferMDL = Irp->MdlAddress;
#endif
	urb->UrbBulkOrInterruptTransfer.TransferBufferLength = length;
	hwDbgPrint("hwBuildAsyncReadWriteURB() Init async urb Length = 0x%x decimal %d, buf = 0x%x, MDLBuf = 0x%x\n",
		urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
		urb->UrbBulkOrInterruptTransfer.TransferBufferLength,
		urb->UrbBulkOrInterruptTransfer.TransferBuffer,
		urb->UrbBulkOrInterruptTransfer.TransferBufferMDL);
	
	hwDbgPrint(" <<<<< hwBuildAsyncReadWriteURB()\n");
	
	return urb;
}

/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
*					Irp				-	pointer to the IRP_MJ_READ or IRP_MJ_WRITE
*					Read			-	Read - TRUE for read, FALSE for write
* Return Value	:	NT status code
* Description		:	要传输的长度小于dx->MaximumTransferSize字节,因此不需要进行
*					多次提交URB,提交一次就可以搞定
* Note			:
*	1. 从文件对象fileObject中取到管道信息pipeHandle。这个pipeHandle是在Create()时
* 也就是应用程序CreateFile()时驱动保存起来的,实际就是我们要进行读或写
* 的端点。应用程序在同时多次打开同一设备时,文件对象fileObject是各不
* 相同的,可以使用fileObject->FsContext 来保存一些可以相互区分的信息,比如
* 这里保存了同一设备的不同 管道信息
*	2. 调用zjHMCFUsb_BuildAsyncRequest() 构建一个URB
*	3. 调用IoGetNextIrpStackLocation()函数取得下层驱动栈的地址nextStack
*	4. 将创建好的URB赋到nextStack里面去,并设置好其他IRP请求参数
*	5. 设置好完成例程zjHMCFUsb_SimpleReadWrite_Complete(),调用zjHMCFUsb_IncrementIoCount()
* 将IO计数加1
*	6. 调用IoCallDriver()将这个带有URB的IRP提交给下层驱动USBD, IoCallDriver()会返回
* 一个STATUS_PENDING上来,我们将它直接返回给应用层,告诉它你的IRP正
* 在处理
*
*************************************************************************************************/
NTSTATUS hwProcessReadWrite
(
	IN PDEVICE_OBJECT		fdo,
	IN PIRP					Irp,
	IN BOOLEAN				Read
)
{
	NTSTATUS				ntStatus;
	ULONG					siz;
	PURB					urb;
	PFILE_OBJECT				fileObject;
	PIO_STACK_LOCATION		irpStack, nextStack;
	PUSBD_PIPE_INFORMATION	pipeHandle = NULL;
	PDEVICE_EXTENSION		dx = fdo->DeviceExtension;
	ULONG					totalLength;
	PUCHAR					pUserBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;

	hwDbgPrint(" -->>>>>> hwProcessReadWrite ( fdo = %x, Irp = 0x%x, Read = %d\n",
			fdo,Irp,Read );
	PrintCurIrql();
	Irp->IoStatus.Information = 0;
	if ( !hwCanAcceptIoRequests( fdo ) )
	{
		hwDbgPrint("Can't accept requests, returning STATUS_INSUFFICIENT_RESOURCES\n");
		return CompleteIrp( Irp, STATUS_DELETE_PENDING,0,IO_NO_INCREMENT);
	}	

	siz = sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER);
	irpStack = IoGetCurrentIrpStackLocation (Irp);
	fileObject = irpStack->FileObject;
	pipeHandle =  fileObject->FsContext;
	
#ifdef _BUFFERED_IO
	if ( Read )
	{
		totalLength = irpStack->Parameters.Read.Length;
	}
	else
	{
		totalLength = irpStack->Parameters.Write.Length;
	}
	hwDbgPrint("totalLength = decimal %d, pUserBuffer = 0x%x\n",totalLength, pUserBuffer );
#else
	if ( !Irp->MdlAddress )
	{
		hwDbgPrint("Irp->MdlAddress = NULL!!!\n");
		return CompleteIrp( Irp, STATUS_INVALID_PARAMETER,0,IO_NO_INCREMENT);
	}
	totalLength = MmGetMdlByteCount(Irp->MdlAddress);
	hwDbgPrint("totalLength = decimal %d, Irp->MdlAddress = 0x%x\n",totalLength, Irp->MdlAddress );
#endif

	
	if ( totalLength > dx->MaximumTransferSize )
	{	
		hwDbgPrint ( "totalLength(%d) > dx->MaximumTransferSize(%d)\n",totalLength,dx->MaximumTransferSize );
		totalLength = dx->MaximumTransferSize;
	}
	
	if (!pipeHandle)
	{
		ntStatus = STATUS_INVALID_HANDLE;
		hwDbgPrint("Rejecting on invalid pipeHandle 0x%x decimal %d\n",pipeHandle, pipeHandle );
		Irp->IoStatus.Status = ntStatus;
		IoCompleteRequest (Irp, IO_NO_INCREMENT );
		return ntStatus;
	}
	
	hwASSERT( UsbdPipeTypeBulk == pipeHandle->PipeType );

	// Build our URB for USBD	
	urb = hwBuildAsyncReadWriteURB(fdo,
									Irp,
									dx->TransferDataUrb,
									pUserBuffer,
									pipeHandle,
									totalLength,
									Read);
	
	//------------------------------------------------------------------
	// 现在我们已经创建好了URB,我们将发送一个请求
	// 给USB设备对象
	//
	// 调用类驱动来履行这个操作
	//
	// IoGetNextIrpStackLocation()给于一个通过IRP从高层驱动访问
	// 下层驱动I/O栈位置,因此调用者可以设置下层驱动
	//------------------------------------------------------------------
	nextStack = IoGetNextIrpStackLocation(Irp);
	hwASSERT(nextStack != NULL);
	
	// pass the URB to the USB driver stack
	nextStack->Parameters.Others.Argument1 = urb;
	nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
	nextStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
	IoSetCompletionRoutine(Irp,                       					// irp to use
						hwReadWriteComplete,				// routine to call when irp is done
						fdo,									// we pass our FDO as context to pass routine
						TRUE,								// call on success
						TRUE,								// call on error
						TRUE);								// call on cancel
	
	
    // Call IoCallDriver to send the irp to the usb port.
	hwIncrementIoCount(fdo);
	ntStatus = IoCallDriver(dx->LowerDeviceObject, Irp );
	
	hwDbgPrint("IoCallDriver status (pending) 0x%x\n", ntStatus);
	//------------------------------------------------------------------
	// The USB driver should always return STATUS_PENDING when
	// it receives an irp with major function code IRP_MJ_WRITE or IRP_MJ_READ.
	//------------------------------------------------------------------
	ASSERT( ntStatus == STATUS_PENDING);
	hwDbgPrint("hwProcessReadWrite(ntStatus = 0x%x) -->>>>>>\n",ntStatus); 

	return ntStatus; 	
}

/************************************************************************************************
* Function Type	:	global
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
*					IRP				-	pointer to the IRP_MJ_WRITE
* Return Value	:	NT status code
* Description		:	This is the IRP_MJ_WRITE routine set in our dispatch table;
*					WriteFile() calls from user mode ultimately land here
*************************************************************************************************/
NTSTATUS zjHMCFUsb_Write(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
    NTSTATUS ntStatus = hwProcessReadWrite(fdo,Irp,FALSE);	// false to write, true to read
    return ntStatus;
}
/************************************************************************************************
* Function Type	:	global
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
*					IRP				-	pointer to the IRP_MJ_READ
* Return Value	:	NT status code
* Description		:	This is the IRP_MJ_READ routine set in our dispatch table;
*					ReadFile() calls from user mode ultimately land here
*************************************************************************************************/
NTSTATUS zjHMCFUsb_Read(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
	NTSTATUS ntStatus = hwProcessReadWrite(fdo,Irp,	TRUE);	// false to write, true to read
	return ntStatus;	
}
/************************************************************************************************
* Function Type	:	global
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
*					IRP				-	pointer to an I/O Request Packet
* Return Value	:	Status returned from lower driver
* Description		:	Main dispatch table routine for IRP_MJ_SYSTEM_CONTROL
*					We basically just pass these down to the PDO
*************************************************************************************************/
NTSTATUS zjHMCFUsb_SysControl(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
	
	PIO_STACK_LOCATION irpStack;
	PDEVICE_EXTENSION dx;
	NTSTATUS ntStatus = STATUS_SUCCESS;
	NTSTATUS waitStatus;
	PDEVICE_OBJECT stackDeviceObject;

	hwDbgPrint(" -->>>>>> zjHMCFUsb_SysControl()\n");
	PrintCurIrql();
	
	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 0;
	
	//------------------------------------------------------------------
	//  Get a pointer to the current location in the Irp. This is where
	//  the function codes and parameters are located.
	//------------------------------------------------------------------
	irpStack = IoGetCurrentIrpStackLocation (Irp);
	// Get a pointer to the device extension
	dx = fdo->DeviceExtension;
	stackDeviceObject = dx->LowerDeviceObject;
	hwIncrementIoCount(fdo);
	hwASSERT( IRP_MJ_SYSTEM_CONTROL == irpStack->MajorFunction);
	IoCopyCurrentIrpStackLocationToNext(Irp);
	ntStatus = IoCallDriver(stackDeviceObject,Irp);
	hwDecrementIoCount(fdo);
	hwDbgPrint("zjHMCFUsb_SysControl() Exit zjHMCFUsb_SysControl %x\n", ntStatus);
	
	return ntStatus;
}


NTSTATUS zjHMCFUsb_Cleanup( IN PDEVICE_OBJECT fdo, IN PIRP Irp)
{
	PDEVICE_EXTENSION		dx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
	KIRQL					OldIrql;
	PIO_STACK_LOCATION		irpStack = IoGetCurrentIrpStackLocation (Irp);
	PFILE_OBJECT				fileObject = irpStack->FileObject;
	
	// Cancel all IRPs in the I/O Manager maintained queue in device object
	PKDEVICE_QUEUE_ENTRY QueueEntry;

	hwDbgPrint("-->>>>>> ZjMdmDispatchCleanup(fdo=0x%x, Irp=0x%x\n",fdo,Irp);
	PrintCurIrql();
	IoAcquireCancelSpinLock(&OldIrql);
	while( (QueueEntry=KeRemoveDeviceQueue(&fdo->DeviceQueue)) != NULL)
	{
		PIRP CancelIrp = CONTAINING_RECORD( QueueEntry, IRP, Tail.Overlay.DeviceQueueEntry);
		PIO_STACK_LOCATION CancelIrpStack = 
			IoGetCurrentIrpStackLocation(CancelIrp);
		 if (CancelIrpStack->FileObject != fileObject )
		 {
		 	hwDbgPrint ( "因为文件对象不同,所以说明这个IRP不应该放弃\n");
			continue;
		 }
		CancelIrp->Cancel = TRUE;
		CancelIrp->CancelIrql = OldIrql;
		CancelIrp->CancelRoutine = NULL;

		IoReleaseCancelSpinLock(OldIrql);
		hwDbgPrint("ZjMdmDispatchCleanup: Cancelling %x 0x%x\n",CancelIrp,CancelIrp);
		CompleteIrp( CancelIrp, STATUS_CANCELLED,0,IO_NO_INCREMENT);
		IoAcquireCancelSpinLock(&OldIrql);
	}
	IoReleaseCancelSpinLock(OldIrql);
	hwDbgPrint("ZjMdmDispatchCleanup()-->>>>>>\n");
	return CompleteIrp( Irp, STATUS_SUCCESS,0,IO_NO_INCREMENT);
}

/////////////////////////////////////////////////////////////////////////////
//	CompleteIrp:	Sets IoStatus and completes the IRP
/************************************************************************************************
* Function Type	:	global
* Parameter		:	Irp			-	要完成的IRP
*					status		-	IRP的状态
*					info			-	IRP的附加信息,一般是返回传输的字节数
*					PriorityBoost	-	Specifies a system-defined constant by which to increment the runtime 
*									priority of the original thread that requested the operation
* Return Value	:	IRP完成的状态
* Description		:	完成一个指定的IRP
*************************************************************************************************/
NTSTATUS CompleteIrp
(
	IN PIRP			Irp,
	IN NTSTATUS		status,
	IN ULONG		info/*=0*/,
	IN CCHAR		PriorityBoost/*=IO_NO_INCREMENT*/)
{
	Irp->IoStatus.Status = status;
	Irp->IoStatus.Information = info;
	IoCompleteRequest(Irp,PriorityBoost);
	return status;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -