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

📄 drvpnp.c

📁 ddk编写的usb驱动源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
* Return Value	:	NTSTATUS value from the IoCallDriver() call.
* Description		:	产生一个内部的IRP来获得设备性能信息,主要是获取
*					设备电源状态信息
*************************************************************************************************/
NTSTATUS hwQueryCapabilities
(
	IN PDEVICE_OBJECT		LowerDeviceObject,
	IN PDEVICE_CAPABILITIES	DeviceCapabilities
)											
{
	PIO_STACK_LOCATION		nextStack;
	PIRP						irp;
	NTSTATUS				ntStatus;
	KEVENT					event;	

	hwDbgPrint ( " -->>>>>>  hwQueryCapabilities()\n" );
	hwDbgPrint ( "LowerDeviceObject = 0x%x \n",LowerDeviceObject );
	hwDbgPrint ( "DeviceCapabilities = 0x%x \n",DeviceCapabilities );
	// 这是DDK定义的调试版本的宏,IRQL高于APC_LEVEL时我们的可分页代码
	// 将不会被运行
	PAGED_CODE();	

	// 构造一个IRP用来产生内部对PDO的查询请求
	irp = IoAllocateIrp(LowerDeviceObject->StackSize, FALSE);
	if (!irp)
	{
		// 资源不够
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	 
	// Preinit the device capability structures appropriately. 
	RtlZeroMemory( DeviceCapabilities, sizeof(DEVICE_CAPABILITIES) );
	DeviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
	DeviceCapabilities->Version = 1;
	DeviceCapabilities->Address = -1;
	DeviceCapabilities->UINumber = -1;
	
	// IoGetNextIrpStackLocation()获取一个高层驱动在一个IRP里访问下层驱动
	// 的I/O栈位置
	nextStack = IoGetNextIrpStackLocation(irp);
	nextStack->MajorFunction= IRP_MJ_PNP;					// 主功能代码
	nextStack->MinorFunction= IRP_MN_QUERY_CAPABILITIES;	// 次功能代码
 
	// 初始化一个完成例程将要使用的事件,这个事件将告诉我们
	// 下层驱动处理我们的irp已经完成了。
	KeInitializeEvent(&event, NotificationEvent, FALSE);
	
	// 设置一个完成例程
	IoSetCompletionRoutine(irp,
						hwIRPCompletionRoutine,
						&event,  // pass the event as Context to completion routine
						TRUE,    // invoke on success
						TRUE,    // invoke on error
						TRUE);   // invoke on cancellation of the Irp
	
	
	// 在下层驱动I/O栈位置的参数中填好我们的DEVICE_CAPABILITIES结构体
	// 指针
	nextStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
	
	// 事先调整irp为不支持的状态
	irp->IoStatus.Status = STATUS_NOT_SUPPORTED;

	// 将irp提交给下层驱动
	ntStatus = IoCallDriver(LowerDeviceObject,irp);

	hwDbgPrint(" ntStatus returned by IoCallDriver 0x%x\n", ntStatus);

	if (ntStatus == STATUS_PENDING)
	{
		// 等待irp处理完成
		KeWaitForSingleObject(
							&event,
							Suspended,
							KernelMode,
							FALSE,
							NULL);		
		ntStatus = irp->IoStatus.Status;
	}
	
	// failed? this is probably a bug
	hwDbgPrint("hwQueryCapabilities() %s -->>>>>>\n",NT_SUCCESS(ntStatus)?"success":"falied");

	// 释放前面申请的irp
	IoFreeIrp(irp);
	
	return ntStatus;
}

/************************************************************************************************
* Function Type	:	global
* Parameter		:	DriverObject				-	pointer to the driver object for device
*					pdo						-	pointer to a device object created by the bus
*												指向设备堆栈底部的物理设备对象。
* Return Value	:	STATUS_SUCCESS			-	if successful,
*					STATUS_UNSUCCESSFUL	-	otherwise
* Description		:	This routine is called to create and initialize our Functional Device Object (FDO).
*					For monolithic drivers, this is done in DriverEntry(), but Plug and Play devices
*					wait for a PnP event
*Note			:	1、创建功能设备对象(FDO)、符号连接
*					2、设置IO读写方式为直接IO
*					3、将FDO与PDO挂钩
*					4、查询设备性能,设置好最低的电源状态
*					5、将设备挂起
*************************************************************************************************/
NTSTATUS zjHMCFUsb_AddDevice
(
	IN PDRIVER_OBJECT	DriverObject,
	IN PDEVICE_OBJECT	pdo
)
{
	NTSTATUS               			ntStatus = STATUS_SUCCESS;
	PDEVICE_OBJECT				fdo = NULL;
	PDEVICE_EXTENSION			dx;
	USBD_VERSION_INFORMATION	versionInformation;
	ULONG						i;
	NTSTATUS					actStat;
	UNICODE_STRING				deviceLinkUnicodeString;
	
	hwDbgPrint(" -->>>>>> zjHMCFUsb_AddDevice(DriverObject=0x%x,pdo=0x%s)\n",
		DriverObject,pdo);
	PrintCurIrql();
	
	// 创建功能设备对象(FDO)
	ntStatus = hwCreateDeviceObject ( DriverObject, pdo, &fdo );
	
	if (!NT_SUCCESS(ntStatus))
	{
		hwDbgPrint ( "Create device object failed!\n");
		goto done;
	}
	dx = fdo->DeviceExtension;

	// 注册一个符号连接供应用程序使用打开该设备时使用
	ntStatus = hwRegisterSymbolicLink( pdo, fdo, &deviceLinkUnicodeString );
	if ( NT_SUCCESS(ntStatus) )
	{
		hwDbgPrint("Create GUID_CLASS_zjHMCFUsb_BULK-based Device name success\n" );
	}
	else
	{
		hwDbgPrint("Create GUID_CLASS_zjHMCFUsb_BULK-based Device name failed\n" );
		goto done;
	}
	
	// 设置IO读写方式为直接IO或缓冲IO
	#ifdef _BUFFERED_IO
	fdo->Flags |= DO_BUFFERED_IO;
	#else
	fdo->Flags |= DO_DIRECT_IO;
	#endif
		
	// 设置这个标志以使驱动在设备挂起的时候不会收到
	// IRP_MN_STOP_DEVICE,在设备恢复使用的时候不会收到
	// IRP_MN_START_DEVICE,这个标志必须设置,因为在启动设备时
	// 调用GetDescriptors()从USB栈中获取描述信息将会失败。
	fdo->Flags |= DO_POWER_PAGABLE;
	
	// 保存物理设备对象到设备扩展结构体中
	dx->pdo = pdo;
	// 保存功能设备对象到设备扩展结构体中
	dx->fdo = fdo;
	
		
	//将FDO与PDO挂钩,并获取设备对象堆栈顶端DO保存起来,
	//它将是我们的FDO的直接下属
	dx->LowerDeviceObject = IoAttachDeviceToDeviceStack(fdo, pdo);
	hwDbgPrint ( "LowerDeviceObject = 0x%x,fdo=0x%x,pdo=0x%x\n",
			dx->LowerDeviceObject,fdo,pdo );


	// 将物理设备的性能拷贝一份到我们的设备扩展的DEVICE_CAPABILITIES
	// 结构体中,我们感兴趣的是哪一种系统电源状态被映射到哪一种
	// 设备电源状态来处理IRP_MJ_SET_POWER IRPs
	hwQueryCapabilities(dx->LowerDeviceObject,&dx->DeviceCapabilities);
		
	// 我们要确定一下自动关闭电源的标准。最低的睡眠标准小于D3
	// 如果所有的被设置到D3,驱动关闭/开启电源的功能将被禁用
	dx->PowerDownLevel = PowerDeviceUnspecified; // 初始化为禁用
	for (i=PowerSystemSleeping1; i<= PowerSystemSleeping3; i++)
	{			
		if ( dx->DeviceCapabilities.DeviceState[i] < PowerDeviceD3 )
			dx->PowerDownLevel = dx->DeviceCapabilities.DeviceState[i];
	}
		
	// 我们首先让正在处理的IO计数(dx->PendingIoCount)加1,这个1表示
	// 我们增加了一个设备。以后每新收到1个irp就加1,irp处理完
	// 后就减1

	// 如果IO计数是1则表示没有正在处理的IO并且dx->NoPendingIoEvent
	// 被置信号,在处理IRP_MN_QUERY_REMOVE_DEVICE的时候这是必须的。
		
	// 当处理IRP_MN_REMOVE_DEVICE时这个IO计数将减到0,并且dx->RemoveEvent
	// 被置为有信号,表明设备可以被移除
      	hwIncrementIoCount(fdo);

	// 获取控制客户USB设备的HCD(host controller driver)的版本信息
	USBD_GetUSBDIVersion(&versionInformation);
	hwDbgPrint( "USB Version : 0x%x - 0x%x\n",
		versionInformation.USBDI_Version, versionInformation.Supported_USB_Version);

	// 先将电源关闭直到有实际的IO请求
	actStat = hwSelfSuspendOrActivate( fdo, TRUE );
	// 当这个标志设置时,I/O管理器将拒绝任何打开该设备句柄
	// 的请求或向该设备对象上附着其它设备对象的请求
	fdo->Flags &= ~DO_DEVICE_INITIALIZING;
	
done:
	//free buffer from unicode string we used to init interface
	RtlFreeUnicodeString( &deviceLinkUnicodeString );
	hwDbgPrint("zjHMCFUsb_AddDevice() (%x) -->>>>>\n", ntStatus);
	if ( !NT_SUCCESS( ntStatus ) )
		ntStatus = STATUS_DEVICE_REMOVED;
	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		:	Dispatch table routine for IRP_MJ_PNP.
*					Process the Plug and Play IRPs sent to this device.
*************************************************************************************************/
NTSTATUS zjHMCFUsb_PNP(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
	PIO_STACK_LOCATION		irpStack;
	PDEVICE_EXTENSION		dx;
	NTSTATUS				ntStatus = STATUS_SUCCESS;
	
	// 获取当前IRP位置,以从中取得功能代码和参数
	irpStack = IoGetCurrentIrpStackLocation (Irp);
	
	// Get a pointer to the device extension
	dx = fdo->DeviceExtension;

	hwDbgPrint(" -->>>>>> zjHMCFUsb_PNP() IRP_MJ_PNP\n" );
	PrintCurIrql();
	// 增加正在处理的IO数量
	hwIncrementIoCount(fdo);
	hwASSERT( IRP_MJ_PNP == irpStack->MajorFunction );

	switch (irpStack->MinorFunction)
	{
	case IRP_MN_START_DEVICE:
		hwDbgPrint ( "IRP_MN_START_DEVICE\n");
		hwStartDevice( fdo , Irp ,&ntStatus);
		return ntStatus;
		
	case IRP_MN_QUERY_STOP_DEVICE:
		hwDbgPrint ( "IRP_MN_QUERY_STOP_DEVICE\n");
		if ( hwQueryStopDevice ( fdo , Irp ,&ntStatus) )
			return ntStatus;
		break;
		
	case IRP_MN_CANCEL_STOP_DEVICE:
		hwDbgPrint ( "IRP_MN_CANCEL_STOP_DEVICE\n");
		if ( hwCancelStopDevice ( fdo , Irp ,&ntStatus) )
			return ntStatus;
		break;
		
    case IRP_MN_STOP_DEVICE:
    		hwDbgPrint ( "IRP_MN_STOP_DEVICE\n");
		ntStatus = hwStopDevice(fdo);
		Irp->IoStatus.Status = ntStatus;
		break; 
		
	case IRP_MN_QUERY_REMOVE_DEVICE:
		hwDbgPrint ( "IRP_MN_QUERY_REMOVE_DEVICE\n");
		if ( hwQueryRemoveDevice ( fdo , Irp ,&ntStatus) )
			return ntStatus;
		break; 

	case IRP_MN_CANCEL_REMOVE_DEVICE:
		hwDbgPrint ( "IRP_MN_QUERY_REMOVE_DEVICE\n");
		if ( hwCancelRemoveDevice ( fdo , Irp ,&ntStatus) )
			return ntStatus;
		break;
		
	case IRP_MN_SURPRISE_REMOVAL:
		hwDbgPrint("IRP_MN_SURPRISE_REMOVAL\n");
		hwSurpriseRemovalDevice ( fdo , Irp ,&ntStatus);
		return ntStatus;
		
	case IRP_MN_REMOVE_DEVICE:
		hwDbgPrint("IRP_MN_REMOVE_DEVICE\n");
		hwRemoveDevice( fdo , Irp ,&ntStatus);
		return ntStatus;
		
	default:
		hwDbgPrint("IRP_MJ_PNP Minor PnP IOCTL not handled!!!\n");
	} /* case MinorFunction  */
	
	if (!NT_SUCCESS(ntStatus))
	{
		// 如果产生错误就不用将IRP下传了,直接返回失败
		ntStatus = CompleteIrp( Irp, ntStatus,0,IO_NO_INCREMENT);
		hwDecrementIoCount(fdo);
		hwDbgPrint("zjHMCFUsb_PNP() Exit zjHMCFUsb_PNP FAILURE %x\n", ntStatus);
		return ntStatus;
	}

	IoCopyCurrentIrpStackLocationToNext(Irp);
	hwDbgPrint("zjHMCFUsb_PNP() Passing PnP Irp down, status = %x\n", ntStatus);

	ntStatus = IoCallDriver(dx->LowerDeviceObject,	Irp);
	hwDecrementIoCount(fdo);

	hwDbgPrint("zjHMCFUsb_PNP(ntStatus = 0x%x) -->>>>>>\n", ntStatus);

	return ntStatus;
}

⌨️ 快捷键说明

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