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

📄 drvdispatch.c

📁 ddk编写的usb驱动源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "zjHMCFUsb.h"
#include "DrvIoCode.h"


/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo		-	ptr to our FDO
* Return Value	:	dx->PendingIoCount
* Description		:	减少正在处理的IO计数
*************************************************************************************************/
LONG hwDecrementIoCount(IN PDEVICE_OBJECT fdo)
{
	PDEVICE_EXTENSION		dx;
	LONG					ioCount;
	KIRQL					oldIrql;
	
	dx = fdo->DeviceExtension;
	KeAcquireSpinLock (&dx->IoCountSpinLock, &oldIrql);
	ioCount = InterlockedDecrement(&dx->PendingIoCount);
	
	if ( ioCount == 1 )
	{
		 // 触发没有正在处理的IO的事件
		KeSetEvent(&dx->NoPendingIoEvent, 1, FALSE);
	}
	
	if ( ioCount == 0)
	{
		// 触发设备移除的事件
		KeSetEvent(&dx->RemoveEvent, 1, FALSE);
	}
	KeReleaseSpinLock (&dx->IoCountSpinLock, oldIrql);
	hwDbgPrint("hwDecrementIoCount() Pending io count = %x\n", ioCount);
	return ioCount;
}

/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo		-	ptr to our FDO
* Return Value	:	None
* Description		:	我们保存着一个正在处理的IO计数在设备扩展(dx->PendingIoCount)中
*					这个计数第一次加1表示我们新增了设备,以后每收到一个
*					IRP就加1,处理完一个IRP就减1
*************************************************************************************************/
VOID hwIncrementIoCount(IN PDEVICE_OBJECT fdo)
{
	PDEVICE_EXTENSION		dx;
	KIRQL             			oldIrql;

	dx = fdo->DeviceExtension;
	hwDbgPrint(" -->>>>>> hwIncrementIoCount() Pending io count = %x\n", dx->PendingIoCount);

	KeAcquireSpinLock (&dx->IoCountSpinLock, &oldIrql);
	InterlockedIncrement(&dx->PendingIoCount);	
	KeReleaseSpinLock (&dx->IoCountSpinLock, oldIrql);
	hwDbgPrint("hwIncrementIoCount() Pending io count = %x -->>>>>\n", dx->PendingIoCount);
}
/************************************************************************************************
* Function Type	:	global
* Parameter		:	fdo		-	pointer to the device object for this instance of the device
* Return Value	:	TRUE			-	if can accept new io requests
*					FALSE			-	can't accept new io requests
* Description		:	检测是否可以接受IO请求
*					Can't accept a new io request if device:
*					1) is removed, 
*					2) has never been started, 
*					3) is stopped,
*					4) has a remove request pending, or
*					5) has a stop device pending
*************************************************************************************************/
BOOLEAN hwCanAcceptIoRequests(IN PDEVICE_OBJECT fdo )
{
	PDEVICE_EXTENSION				dx;
	BOOLEAN							fCan = FALSE;

	dx = fdo->DeviceExtension;

	if ( !dx->DeviceRemoved &&			// 处理IRP_MN_REMOVE_DEVICE时这个标记会被置位
		dx->DeviceStarted &&				// 设备已经启动
		!dx->RemoveDeviceRequested &&	// 当成功应答IRP_MN_QUERY_REMOVE_DEVICE时这个标记被置位,表示设备可以被移除
		!dx->StopDeviceRequested 			// 当成功应答IRP_MN_QUERY_STOP_DEVICE时这个标志被置位,表示设备可以被停止
		)
	{
		fCan = TRUE;
	}

	hwDbgPrint("hwCanAcceptIoRequests() return %s\n",fCan?"TRUE":"FALSE");
	return fCan;
}

/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo		-	pointer to the device object for this instance of the device
*					FileName			-	file name
* Return Value	:	>=0				-	pipe index
*					-1				-	error occured
* Description		:	从文件名中获取管道ID
*************************************************************************************************/
int hwPipeWithName
(
	IN	PDEVICE_OBJECT		fdo,
	IN	PUNICODE_STRING	FileName
)
{
	PDEVICE_EXTENSION		dx = fdo->DeviceExtension; 
	ULONG					i, nameLen, ix, uval , umultiplier;
	int						PipeIndex = -1;
	
	nameLen = FileName->Length;
	hwDbgPrint ( "-->>>>>>hwPipeWithName(fdo=0x%x,FileName=%T)\n",fdo,FileName );
	if ( nameLen <= 0 )
	{
		PipeIndex =  -1;
		goto done;
	}
		
	// 获取管道ID
	ix = nameLen -1;  // index last char of pipe name		
	// 从后往前找,先跳过非数字
	while( ( (FileName->Buffer[ ix ] < (WCHAR) '0') ||
			(FileName->Buffer[ ix ] > (WCHAR) '9') ) && ix )
	{
		ix--;
	}
		
	if (  ix > 0 )									//  filename better have had at least one ascii digit!    
	{
		//------------------------------------------------------------------
		// 将管道名字转为管道ID
		// 将Asscii码的字符转为10进制的数字
		//------------------------------------------------------------------
		uval = 0;
		umultiplier = 1;
		// 将字符串转为数字,相当于atoi()函数
		while( ( (FileName->Buffer[ ix ] >= (WCHAR) '0') &&
				(FileName->Buffer[ ix ] <= (WCHAR) '9') ) && ix )
		{
			uval +=  (umultiplier * (ULONG) (FileName->Buffer[ ix ] - (WCHAR) '0'));
			ix--;
			umultiplier *= 10; 
		}
	}
	if ( uval >= dx->UsbInterface->NumberOfPipes )
	{
		PipeIndex =  -1;
		goto done;
	}
	PipeIndex = uval;
	
done:
	hwDbgPrint ( "hwPipeWithName(PipeIndex=%d)-->>>>>>\n",PipeIndex);	
	return PipeIndex;
}
/************************************************************************************************
* 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_CLOSE.
*					It handles user mode CloseHandle() calls for a pipe
*					It closes the File Object for the pipe handle it represents.
*************************************************************************************************/
NTSTATUS zjHMCFUsb_Close(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
	NTSTATUS				ntStatus = STATUS_SUCCESS;
	NTSTATUS				actStat;
	PFILE_OBJECT				fileObject;
	PIO_STACK_LOCATION		irpStack;
	PDEVICE_EXTENSION		dx;
	PUSBD_PIPE_INFORMATION	pipeHandle = NULL;
	PzjHMCFUsb_PIPESTATE	PipeState = NULL;
	int						PipeIndex;
	
	hwDbgPrint( " -->>>>>> zjHMCFUsb_Close(fdo=0x%x,Irp=0x%x)\n",fdo,Irp);
	PrintCurIrql();
	hwIncrementIoCount(fdo);
	
	dx = fdo->DeviceExtension;
	irpStack = IoGetCurrentIrpStackLocation (Irp);
	fileObject = irpStack->FileObject;

	if (!fileObject->FsContext)
		goto done;
	
	// closing pipe handle
	pipeHandle =  fileObject->FsContext;		
	PipeIndex = hwPipeWithName( fdo, &fileObject->FileName );
	if ( -1 == PipeIndex )
		goto done;
	PipeState = &dx->PipeState[ PipeIndex ];
	
	if ( PipeState->fPipeOpened )// set if opened
	{
		// may have been aborted
		hwDbgPrint("Closing pipe%d ( pipeHandle = 0x%x)\n",PipeIndex, pipeHandle);
		dx->OpenPipeCount--;
		PipeState->fPipeOpened = FALSE;
	}
	else 
	{
		// pipe was already closed; this can only be if we got a sudden REMOVE_DEVICE
		hwASSERT(  dx->DeviceRemoved );
		hwDbgPrint( "Pipe %x was already closed\n ", pipeHandle);
	}
	
done:
	// try to power down device if this is the last pipe
	actStat = hwSelfSuspendOrActivate( fdo, TRUE );	
	hwDbgPrint("zjHMCFUsb_Close() OpenPipeCount = %d, status = 0x%x-->>>>>>\n",
		dx->OpenPipeCount, ntStatus);
	hwDecrementIoCount(fdo);
	
	return CompleteIrp( Irp, ntStatus,0,IO_NO_INCREMENT);
}
/************************************************************************************************
* Function Type	:	global
* Parameter		:	fdo						-	pointer to our FDO (Functional Device Object )
*					Urb						-	pointer to an already-formatted Urb request block
* Return Value	:	STATUS_SUCCESS			-	if successful,
*					STATUS_UNSUCCESSFUL	-	otherwise
* Description		:	传递一个URB给USBD类驱动
*					客户设备驱动传递一个URB给类驱动,将Irp->MajorFunction参数
*					设置为IRP_MJ_INTERNAL_DEVICE_CONTROL,下层IRP栈位置参数
*					Parameters.DeviceIoControl.IoControlCode域设置为IOCTL_INTERNAL_USB_SUBMIT_URB
*************************************************************************************************/
NTSTATUS hwCallUSBD(IN PDEVICE_OBJECT fdo, IN PURB Urb )
{
	NTSTATUS				ntStatus, status = STATUS_SUCCESS;
	PDEVICE_EXTENSION		dx;
	PIRP						irp;
	KEVENT					event;
	IO_STATUS_BLOCK		ioStatus;
	PIO_STACK_LOCATION		nextStack;
	
	hwDbgPrint(" -->>>>>> hwCallUSBD(fdo=0x%x,Urb=0x%x\n",fdo,Urb);
	dx = fdo->DeviceExtension;
	
	//------------------------------------------------------------------
	// 构造一个IRP
	//------------------------------------------------------------------
	KeInitializeEvent(&event, NotificationEvent, FALSE);
	irp = IoBuildDeviceIoControlRequest
		(
			IOCTL_INTERNAL_USB_SUBMIT_URB,
			dx->LowerDeviceObject,		// Points to the next-lower driver's device object
			NULL,							// optional input bufer; none needed here
			0,								// input buffer len if used
			NULL,							// optional output bufer; none needed here
			0,								// output buffer len if used
			TRUE,							// If InternalDeviceControl is TRUE the target driver's Dispatch
											// outine for IRP_MJ_INTERNAL_DEVICE_CONTROL or IRP_MJ_SCSI 
											// is called; otherwise, the Dispatch routine for 
											// IRP_MJ_DEVICE_CONTROL is called.
			&event,							// event to be signalled on completion
			&ioStatus							// Specifies an I/O status block to be set when the request is completed the lower driver. 
		);
	
	//------------------------------------------------------------------
	// As an alternative, we could call KeDelayExecutionThread, wait for some
	// period of time, and try again....but we keep it simple for right now
	//------------------------------------------------------------------
	if (!irp)
	{
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	//------------------------------------------------------------------
	// 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);
	 
	// pass the URB to the USB driver stack 
	nextStack->Parameters.Others.Argument1 = Urb; 
	ntStatus = IoCallDriver(dx->LowerDeviceObject, irp); 
	hwDbgPrint("IoCallDriver()  return ntStatus =  0x%x\n", ntStatus);
	
	if (ntStatus == STATUS_PENDING)
	{		
		status = KeWaitForSingleObject(
				&event,
				Suspended,
				KernelMode,
				FALSE,
				NULL);
		
	}
	else
	{
       	 ioStatus.Status = ntStatus;
	}
	
	hwDbgPrint("hwCallUSBD() URB status = %x status = %x irp status %x\n",
		Urb->UrbHeader.Status, status, ioStatus.Status);
	
	// USBD maps the error code for us
	ntStatus = ioStatus.Status;
	hwDbgPrint("hwCallUSBD ntStatus = 0x%x -->>>>>>\n ", ntStatus);	
	return ntStatus;
}

/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
*					PipeInfo			-	Ptrs to our a USBD_PIPE_INFORMATION struct
* Return Value	:	NT status code
* Description		:	Reset a given USB pipe.
* NOTES			:	This will reset the host to Data0 and should also reset the device to Data0 								
*************************************************************************************************/
NTSTATUS hwResetPipe(IN PDEVICE_OBJECT fdo,IN PUSBD_PIPE_INFORMATION PipeInfo)
{
	NTSTATUS			ntStatus;
	PURB				urb;
	PDEVICE_EXTENSION	dx = fdo->DeviceExtension;
	
	hwDbgPrint("-->>>>> hwResetPipe(fdo=0x%x,PipeInfo = 0x%x\n", fdo,PipeInfo);
	
	urb = 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 = hwCallUSBD(fdo, urb);
		FreeIfAllocated(urb);
	}
	else
	{
		ntStatus = STATUS_INSUFFICIENT_RESOURCES;
	}
	
	hwDbgPrint("hwResetPipe(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		:	returns the port status for our device
*************************************************************************************************/
NTSTATUS hwGetPortStatus(IN PDEVICE_OBJECT fdo,IN PULONG PortStatus)
{
	NTSTATUS			ntStatus, status = STATUS_SUCCESS;
	PIRP					irp;
	KEVENT				event;
	IO_STATUS_BLOCK	ioStatus;
	PIO_STACK_LOCATION	nextStack;
	PDEVICE_EXTENSION	dx;
	
	hwDbgPrint(" -->>>>>> hwGetPortStatus(fdo=0x%x,PortStatus=0x%x)\n",fdo,PortStatus);
	dx = fdo->DeviceExtension;
	*PortStatus = 0;
	//------------------------------------------------------------------
	// issue a synchronous request
	//------------------------------------------------------------------
	KeInitializeEvent(&event, NotificationEvent, FALSE);
	
	// IoBuildDeviceIoControlRequest allocates and sets up an IRP for a device control request
	irp = IoBuildDeviceIoControlRequest(
				IOCTL_INTERNAL_USB_GET_PORT_STATUS,
				dx->LowerDeviceObject,	//next-lower driver's device object, representing the target device.
				NULL,						// no input or output buffers
				0,
				NULL,
				0,
				TRUE,						// internal ( use IRP_MJ_INTERNAL_DEVICE_CONTROL )
				&event,						// event to be signalled on completion ( we wait for it below )
				&ioStatus);
	
	//------------------------------------------------------------------
	// 调用类驱动来执行这个操作,如果返回状态为
	// PENDING,等待请求完成
	//
	// IoGetNextIrpStackLocation()获取一个高层驱动在一个IRP里访问下层驱动
	// 的I/O栈位置	//------------------------------------------------------------------
	nextStack = IoGetNextIrpStackLocation(irp);
	hwASSERT(nextStack != NULL);

	nextStack->Parameters.Others.Argument1 = PortStatus;

	hwDbgPrint("calling IoCallDriver() USBD port status api\n");
	ntStatus = IoCallDriver(dx->LowerDeviceObject, irp);

⌨️ 快捷键说明

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