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

📄 drvpnp.c

📁 ddk编写的usb驱动源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
				USB_DEVICE_DESCRIPTOR_TYPE,
				0,				//Specifies the device-defined index of the descriptor that is to be retrieved. 
				0,				//Specifies the language ID of the descriptor to be retrieved when USB_STRING_DESCRIPTOR_TYPE is set in DescriptorType. This parameter must be 0 for any other value in DescriptorType.
				deviceDescriptor,	//Points to a resident buffer to receive the descriptor data or is NULL if an MDL is supplied in TransferBufferMDL. 
				NULL,			//Points to an MDL that describes a resident buffer to receive the descriptor data or is NULL if a buffer is supplied in TransferBuffer. 
				siz,				//Specifies the length of the buffer specified in TransferBuffer or described in TransferBufferMDL
				NULL			//Points to an caller-initialized URB. Link becomes the subsequent URB in a chain of requests with Urb being its predecessor
			);
			
			(*p_ntStatus) = hwCallUSBD(fdo, urb);
			hwDbgPrint ( "hwCallUSBD %s \n",NT_SUCCESS((*p_ntStatus))?"SUCCESS":"FAILED" );
			if (NT_SUCCESS((*p_ntStatus)))
			{
				hwDbgPrint ( "/******************* Device Descriptor ******************/\n" );
				hwDbgPrint("deviceDescriptor = 0x%x, len %d\n",deviceDescriptor,urb->UrbControlDescriptorRequest.TransferBufferLength);
				hwDbgPrint("bLength :  %d\n", deviceDescriptor->bLength);
				hwDbgPrint("bDescriptorType 0x%x\n", deviceDescriptor->bDescriptorType);
				hwDbgPrint("bcdUSB 0x%x\n", deviceDescriptor->bcdUSB);
				hwDbgPrint("bDeviceClass 0x%x\n", deviceDescriptor->bDeviceClass);
				hwDbgPrint("bDeviceSubClass 0x%x\n", deviceDescriptor->bDeviceSubClass);
				hwDbgPrint("bDeviceProtocol 0x%x\n", deviceDescriptor->bDeviceProtocol);
				hwDbgPrint("bMaxPacketSize0 0x%x\n", deviceDescriptor->bMaxPacketSize0);
				hwDbgPrint("idVendor 0x%x\n", deviceDescriptor->idVendor);
				hwDbgPrint("idProduct 0x%x\n", deviceDescriptor->idProduct);
				hwDbgPrint("bcdDevice 0x%x\n", deviceDescriptor->bcdDevice);
				hwDbgPrint("iManufacturer 0x%x\n", deviceDescriptor->iManufacturer);
				hwDbgPrint("iProduct 0x%x\n", deviceDescriptor->iProduct);
				hwDbgPrint("iSerialNumber 0x%x\n", deviceDescriptor->iSerialNumber);
				hwDbgPrint("bNumConfigurations 0x%x\n", deviceDescriptor->bNumConfigurations);
			}
		} 
		
		if (NT_SUCCESS((*p_ntStatus)))
		{
			dx->UsbDeviceDescriptor = deviceDescriptor;
		}
		
		FreeIfAllocated(urb);
	}
	else
	{
		// if we got here we failed to allocate the urb
		(*p_ntStatus) = STATUS_INSUFFICIENT_RESOURCES;
	}
	
	if (NT_SUCCESS((*p_ntStatus)))
	{
		(*p_ntStatus) = hwConfigureDevice(fdo);
		dx->DeviceStarted = TRUE;
	}

done:
	hwDbgPrint("hwStartDevice (%x)-->>>>>>\n", (*p_ntStatus));
	(*p_ntStatus) = CompleteIrp( Irp, (*p_ntStatus),0,IO_NO_INCREMENT);
	hwDecrementIoCount(fdo);
	return TRUE;
}
/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
* Return Value	:	TRUE			-	已经处理完了,调用者可以停止以后的处理
*										直接返回
*					FALSE			-	处理还没完,调用者应该接着执行以后的操作
* Description		:	查询停止设备
*************************************************************************************************/
BOOLEAN hwQueryStopDevice(IN  PDEVICE_OBJECT fdo, IN PIRP Irp, OUT PNTSTATUS p_ntStatus)
{
	PDEVICE_EXTENSION		dx;	
	hwDbgPrint(" -->>>>>> hwQueryStopDevice(fdo=0x%x,Irp=0x%x,p_ntStatus=0x%x)\n",fdo,Irp,p_ntStatus);	
	dx = fdo->DeviceExtension;
	(*p_ntStatus) = STATUS_SUCCESS;
	
	//------------------------------------------------------------------
	// IRP_MN_QUERY_STOP_DEVICE/IRP_MN_STOP_DEVICE只有在安全礼貌地
	// 关闭计算机时才会收到,如果设备突然被移走是不会
	// 收到这两个PNP IRP的

	// 如果驱动将这个IRP的状态设置为STATUS_SUCCESS
	// 那么驱动必须是没有在这个设备上启动任何操作
	// 以防止驱动刚好完成一个IRP_MN_STOP_DEVICE的处理
		
      	// 对于大数据量存储的设备如磁盘驱动器,当设备在stop-pending
      	// 状态时,驱动将保存这些访问设备的IRPs请求,但是大多数
      	// 设备是不会保持长久地存储的。因此我们在IRP_MN_QUERY_STOP_DEVICE
      	// 时将拒绝所有I/O请求直到设备被重启或者放弃停止设备

	// 如果设备栈中的驱动确定设备不能停下来进行资源的重新
	// 分配,那么它没必要停止

	// IRP下到设备栈后,如果"查询停止设备"返回失败,
	// Pnp管理器发送IRP_MN_CANCEL_STOP_DEVICE给设备栈,通知驱动查询
	// 已经放弃,设备不用停止
		
       // 当设备没启动的时候可能会收到这个IRP( as on a boot device )
       //------------------------------------------------------------------

	// 如果设备没有启动,那么将这个IRP交给下层驱动去处理
	if (!dx->DeviceStarted)
	{
		hwDbgPrint("IRP_MN_QUERY_STOP_DEVICE when device not started\n");
		IoSkipCurrentIrpStackLocation (Irp);
		(*p_ntStatus) = IoCallDriver (dx->LowerDeviceObject, Irp);
		hwDecrementIoCount(fdo);
		return TRUE;
	}
		
	//可以停止设备
	dx->StopDeviceRequested = TRUE;
	Irp->IoStatus.Status = STATUS_SUCCESS;
	(*p_ntStatus) = Irp->IoStatus.Status;
	
	hwDbgPrint("hwQueryStopDevice()-->>>>>>\n");
	return FALSE;
}
/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
* Return Value	:	TRUE			-	已经处理完了,调用者可以停止以后的处理
*										直接返回
*					FALSE			-	处理还没完,调用者应该接着执行以后的操作
* Description		:	查询移除设备
*************************************************************************************************/
BOOLEAN hwQueryRemoveDevice(IN  PDEVICE_OBJECT fdo, IN PIRP Irp, IN PNTSTATUS p_ntStatus)
{
	PDEVICE_EXTENSION		dx;	
	hwDbgPrint(" -->>>>>> hwQueryRemoveDevice(fdo=0x%x,Irp=0x%x,p_ntStatus=0x%x)\n",fdo,Irp,p_ntStatus);	
	dx = fdo->DeviceExtension;
	(*p_ntStatus) = STATUS_SUCCESS;
	
	//------------------------------------------------------------------
	// 驱动响应这个irp是指示了是否给设备可以被移除
	// 而不会破坏整个系统
	// 如果一个设备确定设备可以安全移除,驱动将完成所有
	// 显著的 I/O请求,安排保存好并发的读写请求,设置
	// Irp->IoStatus.Status 为STATUS_SUCCESS。功能驱动和过滤驱动传递
	// 这个irp给下层设备栈,下层总线驱动调用IoCompleteRequest()
	// 如果驱动给这个irp设置STATUS_SUCCESS,驱动必须不要启动
	// 任何在该设备上的操作以保证驱动成功地完成IRP_MN_REMOVE_DEVICE
	// IRP,如果驱动确定设备不能被移除,驱动就没必要传递
	// query-remove IRP给下层设备栈,如果query-remove IRP失败,PNP
	// 管理器将发送一个IRP_MN_CANCEL_REMOVE_DEVICE给设备栈,通知
	// 驱动查询移除的irp已经放弃,设备将不会被移除
	//------------------------------------------------------------------

	// 当设备没有启动的时候可能会收到这个IRP,将这个IRP交给下层驱动处理
	if (!dx->DeviceStarted)
	{
		hwDbgPrint("IRP_MN_QUERY_STOP_DEVICE when device not started\n");
		IoSkipCurrentIrpStackLocation (Irp);
		(*p_ntStatus) = IoCallDriver (dx->LowerDeviceObject, Irp);
		hwDecrementIoCount(fdo);
		hwDbgPrint(" hwQueryRemoveDevice(ntStatus = 0x%x)-->>>>>>\n",(*p_ntStatus));
		return TRUE;
	}
	
	// 将这个标志设为真,新的IOCTL和read/write irps 将被直接传给
	// 下层驱动,所有的irps很快地就failed了
	dx->RemoveDeviceRequested = TRUE;
	
	// 在返回Success之前等到所有IO请求处理完成,当
	// dx->PendingIoCount达到1时将置这个事件
	KeWaitForSingleObject(	&dx->NoPendingIoEvent,
									Suspended,
									KernelMode,
									FALSE,
									NULL);
	Irp->IoStatus.Status = STATUS_SUCCESS;
	(*p_ntStatus) = Irp->IoStatus.Status;
	hwDbgPrint(" hwQueryRemoveDevice(ntStatus = 0x%x)-->>>>>>\n",(*p_ntStatus));
	return FALSE;
}
/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
* Return Value	:	TRUE			-	已经处理完了,调用者可以停止以后的处理
*										直接返回
*					FALSE			-	处理还没完,调用者应该接着执行以后的操作
* Description		:	放弃移除设备
*************************************************************************************************/
BOOLEAN hwCancelRemoveDevice(IN  PDEVICE_OBJECT fdo, IN PIRP Irp, IN PNTSTATUS p_ntStatus)
{
	PDEVICE_EXTENSION		dx;	
	hwDbgPrint(" -->>>>>> hwCancelRemoveDevice(fdo=0x%x,Irp=0x%x,p_ntStatus=0x%x)\n",fdo,Irp,p_ntStatus);	
	dx = fdo->DeviceExtension;
	(*p_ntStatus) = STATUS_SUCCESS;
	
	//------------------------------------------------------------------
	// Pnp管理器使用这个IPR来通知驱动设备将不会被移走
	//------------------------------------------------------------------
	
	// 当设备没有启动的时候可能会收到这个IRP,将这个IRP交给下层驱动处理
	if (!dx->DeviceStarted)
	{
		hwDbgPrint("IRP_MN_CANCEL_REMOVE_DEVICE when device not started\n");
		IoSkipCurrentIrpStackLocation (Irp);
		(*p_ntStatus)  = IoCallDriver (dx->LowerDeviceObject, Irp);
		hwDecrementIoCount(fdo);
		hwDbgPrint(" hwCancelRemoveDevice(ntStatus = 0x%x)-->>>>>>\n",(*p_ntStatus));
		return TRUE;
	}
		
	// 重设这个标志,使IOCTL、IO IRP又将被允许处理
	dx->RemoveDeviceRequested = FALSE;
	Irp->IoStatus.Status = STATUS_SUCCESS;
	(*p_ntStatus) = Irp->IoStatus.Status;
	hwDbgPrint(" hwCancelRemoveDevice(ntStatus = 0x%x)-->>>>>>\n",(*p_ntStatus));
	return FALSE;
}

/************************************************************************************************
* Function Type	:	global
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
* Return Value	:	NT status code
* Description		:	设备意外被移除时调用。放弃将所有打开的管道的正在
*					处理的传输。用URB_FUNCTION_ABORT_PIPE参数调用USBD,并且
*					在我们保存的管道配置信息(PzjHMCFUsb_PIPESTATE)将这些管道
*					标记为"关闭"
*************************************************************************************************/
NTSTATUS hwAbortPipes(IN PDEVICE_OBJECT fdo)
{
	NTSTATUS						ntStatus = STATUS_SUCCESS;
	PURB							urb;
	PDEVICE_EXTENSION				dx = fdo->DeviceExtension;
	ULONG							i;	
	PUSBD_INTERFACE_INFORMATION	interface;
	
	interface = dx->UsbInterface;

	if ( !dx->PipeState )
		return STATUS_UNSUCCESSFUL;
	//使用URB_FUNCTION_ABORT_PIPE功能关闭打开的管道
	for (i=0; i<interface->NumberOfPipes; i++)
	{
		if ( dx->PipeState[i].fPipeOpened )		// we set this if open, clear if closed
		{
			hwDbgPrint("Aborting open  Pipe %d\n", i);
			urb = ExAllocatePool(NonPagedPool,sizeof(struct _URB_PIPE_REQUEST));
			if (urb)
			{
				urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
				urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
				urb->UrbPipeRequest.PipeHandle = interface->Pipes[i].PipeHandle;
				ntStatus = hwCallUSBD(fdo, urb);
				FreeIfAllocated(urb);
			}
			else
			{
				ntStatus = STATUS_INSUFFICIENT_RESOURCES;
				hwDbgPrint("Allocate urb memory failed\n" );
				break;
			}
			
			
			if (!(NT_SUCCESS(ntStatus)))
			{
				break;
			}
			else
			{
				dx->PipeState[i].fPipeOpened = FALSE; // mark the pipe 'closed'
				dx->OpenPipeCount--;
			}
		} // end, if pipe open
	} // end, for all pipes
	
	return ntStatus;
}

/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
* Return Value	:	TRUE			-	已经处理完了,调用者可以停止以后的处理
*										直接返回
*					FALSE			-	处理还没完,调用者应该接着执行以后的操作
* Description		:	意外移除设备
*************************************************************************************************/
BOOLEAN hwSurpriseRemovalDevice(IN  PDEVICE_OBJECT fdo, IN PIRP Irp, IN PNTSTATUS p_ntStatus)
{
	PDEVICE_EXTENSION		dx;	
	hwDbgPrint(" -->>>>>> hwSurpriseRemovalDevice(fdo=0x%x,Irp=0x%x,p_ntStatus=0x%x)\n",fdo,Irp,p_ntStatus);	
	dx = fdo->DeviceExtension;
	(*p_ntStatus) = STATUS_SUCCESS;
	
	//------------------------------------------------------------------
	// 当设备被突然移走时PNP管理器发送这个IRP,这个
	// 这个IRP之前并没有发送"查询移走"的IRP,设备无论在
	// 什么状态都得处理这个"设备移走"的IRP
	//------------------------------------------------------------------
		
	hwDecrementIoCount(fdo);
		
	// 一旦DeviceRemoved标志被设置,IOCTL 或 read/write irps将被直接
	// 发送到下层驱动,所有的irps将很快地处理失败		
	dx->DeviceRemoved = TRUE;
	
	hwAbortPipes( fdo );
		
	// Mark this handled
	Irp->IoStatus.Status = STATUS_SUCCESS;
		
	// We don't explicitly wait for the below driver to complete, but just make
	// the call and go on, finishing cleanup
	IoCopyCurrentIrpStackLocationToNext(Irp);
	(*p_ntStatus) = IoCallDriver(dx->LowerDeviceObject, Irp);

	hwDbgPrint(" hwSurpriseRemovalDevice(ntStatus = 0x%x)-->>>>>>\n",(*p_ntStatus));
	return TRUE;
}

/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
* Return Value	:	TRUE			-	已经处理完了,调用者可以停止以后的处理
*										直接返回

⌨️ 快捷键说明

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