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

📄 whusb20dispatch.c

📁 linux 下的驱动程序 欢迎下载
💻 C
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////////////////////////////
//文件名称:Whceb01Dispatch.cpp
//文件功能:驱动分发例程,对设备的IOCTL操作在Whceb01DeviceControl例程中实现
//文件作者:张伟标
//工作部门:研究一室
//创建时间:2004年1月9日
//修改记录:
//版权所有:维豪信息技术有限公司
//
//Copyright 2004 WellHope Information Technology Corporation, Ltd.
//All rights reserved.
#include "Whusb20.h"
#include "Whusb20Ioctl.h"


/*******************************************************************************
	函数名:	WhAllocateMemory()
	功能描述:	分配一定长度的内存
	参数:
		Length:	要分配内存的长度
	返回值:
		分配到的内存地址
*******************************************************************************/
LPVOID WhAllocateMemory( ULONG Length )
{
	// 分配内存
	return ExAllocatePool(NonPagedPool, Length);
}


void WhFreeMemory( LPVOID BaseAddr )
{
	ExFreePool( BaseAddr );
}
/////////////////////////////////////////////////////////////////////////////
//	Whceb01Create:
//
//	Description:
//		Handle IRP_MJ_CREATE requests
//
//	Arguments:
//		Pointer to our FDO
//		Pointer to the IRP
//			IrpStack->Parameters.Create.xxx has create parameters
//			IrpStack->FileObject->FileName has file name of device
//
//	Return Value:
//		This function returns STATUS_XXX

NTSTATUS Whceb01Create(	IN PDEVICE_OBJECT fdo,
					IN PIRP Irp)
{
	NTSTATUS status;
	PWHCEB01_DEVICE_EXTENSION dx = (PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
	ULONG size = 0;
	PIO_STACK_LOCATION IrpStack ;
	LARGE_INTEGER timeout,timeout1;
	PWHCEB01_CHANNEL	pChannelInfo = NULL;
	ULONG			i = 0;
	int				Count = 0;

	timeout.QuadPart = WHCEB01_TIMEOUT;
	timeout1.QuadPart = -10000;
	IrpStack = IoGetCurrentIrpStackLocation(Irp);


	TRACE0( "--------start--Whceb01Create----------------");

	if( dx->IODisabled)
		return CompleteIrp( Irp, STATUS_DEVICE_NOT_CONNECTED, 0);

	status = KeWaitForSingleObject( &dx->ChannelMutex , 
								Executive, 
								KernelMode, 
								FALSE, 
								&timeout
								//NULL
								);
	if(STATUS_TIMEOUT == status)
	{//资源已经被其它线程占用

		TRACE1("-----------等待CEB信号量超时---- status =0x%x--",status);
		TRACE0("-----------设备忙,无法打开句柄--调用Whjk05Create---完毕--");

		status = CompleteIrp( Irp,STATUS_UNSUCCESSFUL,0);
		return status;	
	}
	
	//为该设备分配内存
	pChannelInfo = ( PWHCEB01_CHANNEL )WhAllocateMemory( sizeof( PWHCEB01_CHANNEL ) );
	if( pChannelInfo == NULL )
	{
		TRACE0("No more memory when allcate a channel infomation");
		KeReleaseMutex( &dx->ChannelMutex , FALSE );
        Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_INSUFFICIENT_RESOURCES;
	}
	

	pChannelInfo->ChannelNum = CHNL_ERROR;

	InterlockedIncrement(&dx->OpenHandleCount);
	while( Count < 5000 )
	{
		for( i = 0 ; i < VALID_CHANNEL ; i ++ )
		{
			if( !dx->ChannelisUsed[i] )
			{
				pChannelInfo->ChannelNum = i;
				pChannelInfo->InputHandle = dx->hWhceb01InterruptInHandle[i];
				pChannelInfo->OutputHandle = dx->hWhceb01InterruptOutHandle[i]; 
				dx->ChannelisUsed[i] = TRUE; 
				break;
			}
		}
		if( pChannelInfo->ChannelNum != CHNL_ERROR )
			break;
		else
		{
			status = KeWaitForSingleObject( &dx->WaitEvent , 
								Executive, 
								KernelMode, 
								FALSE, 
								&timeout1
								//NULL
								);
			Count ++;
		}
	}
	KeReleaseMutex( &dx->ChannelMutex , FALSE );

	if( pChannelInfo->ChannelNum == CHNL_ERROR )
	{
		WhFreeMemory( pChannelInfo );
		CompleteIrp( Irp , STATUS_INSUFFICIENT_RESOURCES , 0 );

		return STATUS_INSUFFICIENT_RESOURCES;
	}
	TRACE1( "Current Channel is 0x%x" , pChannelInfo->ChannelNum );

	IrpStack->FileObject->FsContext = pChannelInfo;

	TRACE1( "Create File , Handle is 0x%X", pChannelInfo );

	TRACE0( "------end----Whceb01Create----------------");

	// Complete successfully
	return CompleteIrp(Irp,STATUS_SUCCESS,0);
}

/////////////////////////////////////////////////////////////////////////////
//	Whceb01Close:
//
//	Description:
//		Handle IRP_MJ_CLOSE requests
//		Allow closes to complete if device not started
//
//	Arguments:
//		Pointer to our FDO
//		Pointer to the IRP
//
//	Return Value:
//		This function returns STATUS_XXX
NTSTATUS Whceb01Close(	IN PDEVICE_OBJECT fdo,
					IN PIRP Irp)
{
	PWHCEB01_DEVICE_EXTENSION dx = (PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
	PWHCEB01_CHANNEL	pChannelInfo = NULL;
	PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);

	TRACE0("-------Whceb01Closed!--------");
	InterlockedDecrement(&dx->OpenHandleCount);

	pChannelInfo = ( PWHCEB01_CHANNEL )IrpStack->FileObject->FsContext;
	
	if( pChannelInfo != NULL )
	{
		dx->ChannelisUsed[pChannelInfo->ChannelNum] = FALSE;  

		if( dx->GotResources )
			WhFreeMemory( pChannelInfo );

	}

	// Complete successfully
	return CompleteIrp(Irp,STATUS_SUCCESS,0);
}
 
/////////////////////////////////////////////////////////////////////////////
//	Whceb01Read:
//
//	Description:
//		Handle IRP_MJ_READ requests
//
//	Arguments:
//		Pointer to our FDO
//		Pointer to the IRP
//			IrpStack->Parameters.Read.xxx has read parameters
//			User buffer at:	AssociatedIrp.SystemBuffer	(buffered I/O)
//							MdlAddress					(direct I/O)
//
//	Return Value:
//		This function returns STATUS_XXX
NTSTATUS Whceb01Read(	IN PDEVICE_OBJECT fdo,
						IN PIRP Irp)
{
	PWHCEB01_DEVICE_EXTENSION dx = (PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
	NTSTATUS status = STATUS_SUCCESS;
	ULONG BytesTxd = 0;
	PIO_STACK_LOCATION IrpStack ;
	LONGLONG FilePointer;
	ULONG ReadLen;


	IrpStack = IoGetCurrentIrpStackLocation(Irp);
	TRACE0( "Read" );

	if( dx->IODisabled)
		return CompleteIrp( Irp, STATUS_DEVICE_NOT_CONNECTED, 0);
	if (!LockDevice(dx))
		return CompleteIrp( Irp, STATUS_DELETE_PENDING, 0);

	// Get call parameters
	FilePointer = IrpStack->Parameters.Read.ByteOffset.QuadPart;
	ReadLen = IrpStack->Parameters.Read.Length;
#ifdef DEBUG_INTERFACE
	TRACE2("Read %d bytes from file pointer %d",(int)ReadLen,(int)FilePointer);
#endif//DEBUG_INTERFACE

	// Check file pointer
	if( FilePointer<0)
		status = STATUS_INVALID_PARAMETER;
	else
	{
		status = UsbDoInterruptTransfer( dx, Irp->AssociatedIrp.SystemBuffer, &ReadLen);
		BytesTxd = ReadLen;
	}
#ifdef DEBUG_INTERFACE
	TRACE2("Read: %x %d bytes returned",status,(int)BytesTxd);
#endif//DEBUG_INTERFACE

	// Complete IRP
	CompleteIrp(Irp,status,BytesTxd);
	UnlockDevice(dx);
	return status;
}

/////////////////////////////////////////////////////////////////////////////
//	Whceb01Write:
//
//	Description:
//		Handle IRP_MJ_WRITE requests
//
//	Arguments:
//		Pointer to our FDO
//		Pointer to the IRP
//			IrpStack->Parameters.Write.xxx has write parameters
//			User buffer at:	AssociatedIrp.SystemBuffer	(buffered I/O)
//							MdlAddress					(direct I/O)
//
//	Return Value:
//		This function returns STATUS_XXX

NTSTATUS Whceb01Write(	IN PDEVICE_OBJECT fdo,
					IN PIRP Irp)
{
	PWHCEB01_DEVICE_EXTENSION dx = (PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
	NTSTATUS status = STATUS_SUCCESS;
	ULONG BytesTxd = 0;
	LONGLONG FilePointer;
	ULONG WriteLen;
	PUCHAR pData ;

	PIO_STACK_LOCATION IrpStack;


	IrpStack = IoGetCurrentIrpStackLocation(Irp);

	TRACE0( "Write" );
	if( dx->IODisabled)
		return CompleteIrp( Irp, STATUS_DEVICE_NOT_CONNECTED, 0);
	if (!LockDevice(dx))
		return CompleteIrp( Irp, STATUS_DELETE_PENDING, 0);

	// Get call parameters
	FilePointer = IrpStack->Parameters.Write.ByteOffset.QuadPart;
	WriteLen = IrpStack->Parameters.Write.Length;
#ifdef DEBUG_INTERFACE
	TRACE2("Write %d bytes from file pointer %d",(int)WriteLen,(int)FilePointer);
#endif//DEBUG_INTERFACE

	if( FilePointer<0 || WriteLen<1)
		status = STATUS_INVALID_PARAMETER;
	else
	{
		// Only ever write one byte
		BytesTxd = 1;
		pData = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
		UsbSendOutputReport( dx, *pData);
	}

#ifdef DEBUG_INTERFACE
	TRACE1("Write: %d bytes written",(int)BytesTxd);
#endif//DEBUG_INTERFACE

	// Complete IRP
	CompleteIrp(Irp,status,BytesTxd);
	UnlockDevice(dx);
	return status;
}

/////////////////////////////////////////////////////////////////////////////
//	Whceb01DeviceControl:
//
//	Description:
//		Handle IRP_MJ_DEVICE_CONTROL requests
//
//	Arguments:
//		Pointer to our FDO
//		Pointer to the IRP
//			Buffered:	AssociatedIrp.SystemBuffer (and IrpStack->Parameters.DeviceIoControl.Type3InputBuffer)
//			Direct:		MdlAddress
//
//			IrpStack->Parameters.DeviceIoControl.InputBufferLength
//			IrpStack->Parameters.DeviceIoControl.OutputBufferLength 
//
//	Return Value:
//		This function returns STATUS_XXX

NTSTATUS Whceb01DeviceControl(	IN PDEVICE_OBJECT fdo,
							IN PIRP Irp)
{
	PWHCEB01_DEVICE_EXTENSION dx = (PWHCEB01_DEVICE_EXTENSION)fdo->DeviceExtension;
	NTSTATUS status = STATUS_SUCCESS;
	ULONG BytesTxd = 0;
	ULONG OutputLength;
	ULONG InputLength;
	ULONG ControlCode;
	PIO_STACK_LOCATION IrpStack;
	PUCHAR	tempBuf;
	PWHCEB01_CHANNEL	pChannel = NULL;
	PVOID  pOutputBuffer = NULL;

	TRACE0( "DeviceControl" );
	
	if( dx->IODisabled)
		return CompleteIrp( Irp, STATUS_DEVICE_NOT_CONNECTED, 0);
	if (!LockDevice(dx))
		return CompleteIrp( Irp, STATUS_DELETE_PENDING, 0);

	IrpStack = IoGetCurrentIrpStackLocation(Irp);


	ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
	InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
	OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

	tempBuf = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;

	pChannel = ( PWHCEB01_CHANNEL )IrpStack->FileObject->FsContext;
	if( NULL == pChannel )
	{
		TRACE0( "输入句柄无效!" );
		CompleteIrp( Irp , STATUS_INVALID_PARAMETER , 0 );
		UnlockDevice( dx );
		return STATUS_INVALID_PARAMETER;
	}

	TRACE3( "Current Channel is 0x%x,In Addr:0x%X,Out Addr:0x%X." , pChannel->ChannelNum ,pChannel->InputHandle , pChannel->OutputHandle );

	TRACE3("DeviceIoControl: Control code %x InputLength %d OutputLength %d",
				ControlCode, InputLength, OutputLength);

	
	switch( ControlCode)
	{
	///////	Set read timeout
	case IOCTL_WHCEB01_SET_READ_TIMEOUT:
		if( InputLength!=4)
			status = STATUS_INVALID_PARAMETER;
		else
		{
			dx->UsbTimeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
#ifdef DEBUG_INTERFACE
			TRACE1( "USB timeout set to %d",dx->UsbTimeout);
#endif//DEBUG_INTERFACE
		}
		break;

	///////	Get device descriptor
	case IOCTL_WHCEB01_GET_DEVICE_DESCRIPTOR:
	{
		PUSB_DEVICE_DESCRIPTOR deviceDescriptor = NULL;
		ULONG size;
		NTSTATUS status = UsbGetDeviceDescriptor( dx, deviceDescriptor, &size);
		if( NT_SUCCESS(status))
		{
			BytesTxd = size;
			if( BytesTxd>OutputLength)
				BytesTxd = OutputLength;
			RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,deviceDescriptor,BytesTxd);
		}
		FreeIfAllocated(deviceDescriptor);
		break;
	}

	///////	Get configuration and other descriptors
	case IOCTL_WHCEB01_GET_CONFIGURATION_DESCRIPTORS:
	{
		PUSB_CONFIGURATION_DESCRIPTOR Descriptors = NULL;
		ULONG size;
		NTSTATUS status = UsbGetConfigurationDescriptors( dx, &Descriptors, 0, &size);
		if( NT_SUCCESS(status))
		{
			BytesTxd = size;
			if( BytesTxd>OutputLength)
				BytesTxd = OutputLength;
			RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer,Descriptors,BytesTxd);
		}
		FreeIfAllocated(Descriptors);
		break;
	}

	///////	Get HID Report descriptor
	case IOCTL_WHCEB01_GET_SPECIFIED_DESCRIPTOR:
	{
		if( InputLength!=8)
			status = STATUS_INVALID_PARAMETER;
		else
		{
			PULONG pData = (PULONG)Irp->AssociatedIrp.SystemBuffer;
			UCHAR type = (UCHAR)*pData++;
			ULONG size = *pData;
			PVOID Descriptor = NULL;
			NTSTATUS status = UsbGetSpecifiedDescriptor( dx, Descriptor, type, &size);
			if( NT_SUCCESS(status))
			{

⌨️ 快捷键说明

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