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

📄 ezusbdevice.cpp

📁 DriverStdio的一个USB驱动程序
💻 CPP
📖 第 1 页 / 共 4 页
字号:
{
	t << "Entering BulkReadWrite\n";

	NTSTATUS status = STATUS_SUCCESS;
	PBULK_TRANSFER_CONTROL p = reinterpret_cast<PBULK_TRANSFER_CONTROL>(I.IoctlBuffer());
	ULONG nBufferLength = I.IoctlOutputBufferSize();

	KUsbPipe* pipe = FindPipe(p->pipeNum);

	if(NULL == pipe)
	{
		t << "Error: Invalid pipe parameter\n";
		return STATUS_INVALID_PARAMETER;
	}

	if( nBufferLength > pipe->MaximumTransferSize() )
	{
		t << "Error: Invalid transfer size parameter\n";
		return STATUS_INVALID_PARAMETER;
	}

	KMemory M( I.Mdl() );

	PURB pUrb = pipe->BuildBulkTransfer(
						M,
						nBufferLength,
						static_cast<BOOLEAN>( USB_ENDPOINT_DIRECTION_IN(pipe->EndpointAddress()) ),
						NULL,
						TRUE
						);

	if (pUrb) {
		status = pipe->SubmitUrb(pUrb);
	}
	else {
		status = STATUS_INSUFFICIENT_RESOURCES;
	}

	if( STATUS_SUCCESS == status )
	{
		I.Information() = pUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;
	}

	delete pUrb;

	return status;
}

//=============================================================================
//	EzUsbDevice::OnDevicePowerUp 
//
//		Handler for IRP_MJ_POWER with minor function IRP_MN_SET_POWER
//		for a request to go to power on state from low power state
//		This routine runs at dispatch level.
//	
NTSTATUS EzUsbDevice::OnDevicePowerUp(KIrp I)
{
	NTSTATUS status = STATUS_SUCCESS;

	t << "Entering OnDevicePowerUp\n";

	return status;

	UNREFERENCED_PARAMETER(I);
}

//=============================================================================
// DevicePowerStateName
//
//		This routine takes as input the DEVICE_POWER_STATE value for 
//		a device power IRP and returns a string describing the state
//
PCHAR DevicePowerStateName(DEVICE_POWER_STATE ps)
{
#ifdef _DEBUG
	static PCHAR PowerStates[] = {
		"PowerDeviceUnspecified",
		"PowerDeviceD0",
		"PowerDeviceD1",
		"PowerDeviceD2",
		"PowerDeviceD3"                  
	};

	if (ps > PowerDeviceD3) 
		return "<undefined power state>";
	else
		return PowerStates[ps];
#else
	return NULL;

	UNREFERENCED_PARAMETER(ps);
#endif
}

//=============================================================================
//	EzUsbDevice::OnDeviceSleep 
//
//		Handler for IRP_MJ_POWER with minor function IRP_MN_SET_POWER
//		for a request to go to a low power state from a high power state
//		This routine runs at passive level.
//	
NTSTATUS EzUsbDevice::OnDeviceSleep(KIrp I)
{
	t << "Entering OnDeviceSleep\n";

	NTSTATUS status = STATUS_SUCCESS;

	t << DevicePowerStateName(I.PowerStateSetting().DeviceState) << "\n" ;

	return status;
}

//=============================================================================
//	EzUsbDevice::IsoStreamCompleteCallback 
//
//		This callback routine is called when an Isochronous stream is stopped.
//		All Isochronous URBs have completed.  It is called from a completion
//		routine so assume at DISPATCH_LEVEL.
//
VOID __stdcall EzUsbDevice::IsoStreamCompleteCallback(PVOID pContext)
{
	t << "Entering IsoStreamCompleteCallback\n";

	EzUsbDevice* p = (EzUsbDevice*)pContext;

	ASSERT( p );
	if( p )
	{
		//Since the Iso Transfer is completed, delete the Iso Transfer Object
		delete p->m_pIsoDM;
		p->m_pIsoDM = NULL;
		//Matching call of IncrementOutstandingRequestCount in StartIsoStream
		p->DecrementOutstandingRequestCount();
	}
}

//=============================================================================
// EzUsbDevice::StartIsoStream - Handler for IOCTL_EZUSB_START_ISO_STREAM
//
//		This starts continuous Isochronous Reads from the USB device.  The
//		data is stored in a buffer managed by the driver.  The data is 
//		accessible to user mode by IOCTL_EZUSB_READ_ISO_BUFFER.  The 
//		continuous Isochronous Reads are stopped either on error from the 
//		device or on request by IOCTL_EZUSB_STOP_ISO_STREAM.
//
NTSTATUS EzUsbDevice::StartIsoStream(KIrp I)
{
	t << "Entering StartIsoStream\n";

	NTSTATUS status = STATUS_SUCCESS;
	PISO_TRANSFER_CONTROL p = reinterpret_cast<PISO_TRANSFER_CONTROL>(I.IoctlBuffer());

	if( ! NT_SUCCESS(status = CheckIsoParameters(p)) )
	{
		return status;
	}

	if( m_pIsoDM && m_pIsoDM->IsStarted() )
	{
		return STATUS_DEVICE_BUSY;
	}

	USHORT nPacketSize = static_cast<USHORT>( p->PacketSize );
	KUsbPipe* pPipe = FindPipe(p->PipeNum);

	if( NULL == pPipe )
	{
		ASSERT( NULL != pPipe );
		return STATUS_INVALID_PARAMETER;
	}

	m_pIsoDM = new (NonPagedPool) EzUsbDriverManagedIsoTransfer(
		*pPipe,
		nPacketSize * p->PacketCount,			//Size of data Buffer
		nPacketSize,			
		static_cast<UCHAR>(p->FramesPerBuffer),
		static_cast<UCHAR>(p->BufferCount),
		p->PacketCount							//Size of Packet Buffer
		);

	if( NULL == m_pIsoDM )
	{
		ASSERT( NULL != m_pIsoDM );
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	status = m_pIsoDM->Start(
		IsoStreamCompleteCallback,
		this
		);
	
	if( NT_SUCCESS(status) )
	{
		//This will prevent removal
		IncrementOutstandingRequestCount();
	}

	return status;
}

//=============================================================================
// EzUsbDevice::ReadIsoBuffer - Handler for IOCTL_EZUSB_READ_ISO_BUFFER
//
//		This routine will read data stored in the driver from continuous 
//		Isochronous reads.
//
NTSTATUS EzUsbDevice::ReadIsoBuffer(KIrp I)
{
	t << "Entering ReadIsoBuffer\n";

	//Check input parameters
	PISO_TRANSFER_CONTROL p = (PISO_TRANSFER_CONTROL)I.IoctlBuffer();

	if( NULL == p )
	{
		t << "Error: Invalid parameter \n";
		ASSERT( NULL != p );
		return STATUS_INVALID_PARAMETER;
	}

	if(I.IoctlInputBufferSize() != sizeof(ISO_TRANSFER_CONTROL))
	{
		t << "Error: Invalid parameter \n";
		I.Information() = 0; 
		return STATUS_INVALID_PARAMETER;
	}

	if( I.IoctlOutputBufferSize() !=
			p->PacketCount * 
			(p->PacketSize + sizeof(USBD_ISO_PACKET_DESCRIPTOR))
	  )
	{
		t << "Error: OutputBuffer too small \n";
		I.Information() = 0; 
		return STATUS_INVALID_PARAMETER;
	}

	if(NULL == m_pIsoDM)
	{
		I.Information() = 0; 
		return STATUS_UNSUCCESSFUL;
	}

	//done error checking.  Perform the operation

	KMemory M(I.Mdl());
	PVOID ptr = M.MapToSystemSpace();
	ASSERT( ptr );

	ULONG dwDataBytesToRead = p->PacketCount * p->PacketSize;

	ULONG dwDataBytesRead = m_pIsoDM->ReadBuffer(
										ptr,
										dwDataBytesToRead
										);

	if( ! p->PacketSize )
	{
		ASSERT( p->PacketSize );
		return STATUS_INVALID_PARAMETER;
	}

	ULONG dwDescriptorsToRead = dwDataBytesRead / p->PacketSize;

	ULONG dwDescriptorsRead = m_pIsoDM->ReadDescriptorBuffer(
											reinterpret_cast<PUCHAR>(ptr) + dwDataBytesRead, 
											dwDescriptorsToRead
											);

	ULONG dwDescrBytesRead = dwDescriptorsRead * sizeof(USBD_ISO_PACKET_DESCRIPTOR);

	I.Information() = dwDataBytesRead + dwDescrBytesRead;
	return STATUS_SUCCESS;
}

//=============================================================================
// EzUsbDevice::CheckIsoParameters 
//
//		This routine performs some error checking on the PISO_TRANSFER_CONTROL
//		passed down from user mode to control Isochronous transfers
//
NTSTATUS EzUsbDevice::CheckIsoParameters(PISO_TRANSFER_CONTROL p)
{
	if( NULL == p )
	{
		ASSERT( NULL != p );
		return STATUS_INVALID_PARAMETER;
	}
	
	if( p->PipeNum > m_UsbInterface.NumberOfPipes() )
	{
		t << "Error: Invalid pipe parameter\n";
		return STATUS_INVALID_PARAMETER;
	}

	PUSBD_PIPE_INFORMATION pPipeInfo = m_UsbInterface.Pipes(p->PipeNum);

	if (!(pPipeInfo->PipeType == UsbdPipeTypeIsochronous))
	{
		t << "Error: Invalid pipe parameter\n";
		return STATUS_INVALID_PARAMETER;
	}

	USBD_PIPE_HANDLE PipeHandle = pPipeInfo->PipeHandle;

	if(!PipeHandle)
	{
		t << "Error: Invalid pipe parameter\n";
		return STATUS_UNSUCCESSFUL;
	}

	//Check that the FramesPerBuffer + BufferCount parameters are valid.
	//This function enforces that PacketCount must be zero
	//modulus (FramesPerBuffer * BufferCount).
	if( p->PacketCount % (p->FramesPerBuffer * p->BufferCount) )
	{
		t << "Error: Invalid parameter\n";
		return STATUS_INVALID_PARAMETER;
	}

	return STATUS_SUCCESS;
}

//=============================================================================
// EzUsbDevice::IsoReadWrite - Handler for IOCTL_EZUSB_ISO_READ and
//								   IOCTL_EZUSB_ISO_WRITE
//
//		This starts Isochronous Transfers to/from the USB device.  
//		The data buffer is split into multiple URB's.  A feature of the kit is
//		that the USBD_ISO_PACKET_DESCRIPTOR's are made available to the 
//		application for analysis.
//
NTSTATUS EzUsbDevice::IsoReadWrite(KIrp I)
{
	t << "Entering IsoReadWrite\n";

	PISO_TRANSFER_CONTROL p = (PISO_TRANSFER_CONTROL) I.IoctlBuffer();

	NTSTATUS status = STATUS_SUCCESS;

	if( ! NT_SUCCESS(status = CheckIsoParameters(p)) )
	{
		return status;
	}

	USHORT nPacketSize = static_cast<USHORT>( p->PacketSize );

	// Check that the caller has provided a buffer large enough for
	// all of the Isochronous data and all of the Iso Packet Descriptors
	// (1 descriptor for each packet transferred)
	if( I.IoctlOutputBufferSize() < (p->PacketCount * 
							(nPacketSize + sizeof(USBD_ISO_PACKET_DESCRIPTOR)))
	  )
	{
		t << "Error: OutputBuffer too small \n";
		return STATUS_UNSUCCESSFUL;
	}

	// Initiate the transfers

	//Obtain a KUsbPipe object for the transfer
	KUsbPipe* pPipe = FindPipe(p->PipeNum);
	//Instance a KMemory object for the Mdl
	KMemory M(I.Mdl());

	//Obtain a system virtual address for the Isochronous packet descriptor buffer
	PVOID ptr = reinterpret_cast<PUCHAR>(M.MapToSystemSpace()) + p->PacketCount * nPacketSize;

	//Instance an object to manage the transfer
	EzUsbIsoTransfer* pIsoTransfer = new (NonPagedPool) EzUsbIsoTransfer(
		M,								//KMemory object
		nPacketSize * p->PacketCount,	//Size of data Buffer in bytes
		*pPipe,							//KUsbPipe object
		nPacketSize,					//USHORT PacketSize = 0,
		UCHAR(p->FramesPerBuffer),		//UCHAR PacketsPerUrb = USB_MAX_NUM_ISO_PACKETS_IN_AN_URB,
		(PUCHAR) ptr,					//pointer to descriptor buffer
		UCHAR(p->BufferCount)			//UCHAR NumUrbs = 2
		);

	if( NULL == pIsoTransfer )
	{
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	if( STATUS_SUCCESS == pIsoTransfer->Status() )
	{
		//start the transfer(s) using the synchronous form 
		status = pIsoTransfer->Start();
	}

	delete pIsoTransfer ;

	I.Information() = 0;
	return status;
}


//=============================================================================
// EzUsbDevice::OnInterrupt 
//
//		This routine is called when the USB device interrupts.
//
ON_INTERRUPT_STATUS EzUsbDevice::OnInterrupt(
	PURB pUrb,
	PVOID pContext
	)
{
	t << "Entering OnInterrupt\n";

	ASSERT( pUrb );
	if( pUrb )
	{
		t << *pUrb;
	}

	return ON_INTERRUPT_SUCCESS;

	UNREFERENCED_PARAMETER(pContext);
}


//=============================================================================
// EzUsbDevice::IsFx2 
//
//		This routine checks if the hardware is the FX2 model.  The device 
//	must implement the vendor specific IN SETUP command 0xAC, which returns 1 
//	if the chip is FX2 and 0 otherwise.
//
bool EzUsbDevice::IsFx2()
{
	t << "Entering IsFx2\n";

	bool bRet = false;

	NTSTATUS status = STATUS_SUCCESS;
	UCHAR Buffer;

	PURB pUrb = m_Lower.BuildVendorRequest(
							&Buffer,		//PUCHAR Buffer
							1,				//Buffer Length
							0,				//RequestTypeReservedBits
							EZUSB_ISFX2,	//Request
							0				//Value							
							);

	if( pUrb )
	{
		// submit the URB with a timeout since not all 
		// devices will implement this command.  
		ULONG Timeout = 100;  // Timeout in milliseconds
		status = m_Lower.SubmitUrb(pUrb,NULL,NULL,Timeout);
		delete pUrb;

		if (STATUS_SUCCESS == status && 1 == Buffer)
			bRet = true;
	}

	return bRet;
}

⌨️ 快捷键说明

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