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

📄 drvpnp.c

📁 ddk编写的usb驱动源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
#include "zjHMCFUsb.h"
#include "DrvIoCode.h"
/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo					-	pointer to the device object for this instance 
*											of the device.
*					ConfigurationDescriptor	-	pointer to the USB configuration
*											descriptor containing the interface and endpoint 
*											descriptors.
* Return Value	:	NT status code
* Description		:	从配置描述符里取得接点和端点信息
*************************************************************************************************/
NTSTATUS hwSelectInterface
(
	IN	PDEVICE_OBJECT					fdo,
	IN	PUSB_CONFIGURATION_DESCRIPTOR	ConfigurationDescriptor
)
{
	PDEVICE_EXTENSION				dx;
	NTSTATUS						ntStatus;
	PURB							urb = NULL;
	ULONG							i;
	PUSB_INTERFACE_DESCRIPTOR		interfaceDescriptor = NULL;
	PUSBD_INTERFACE_INFORMATION	Interface = NULL;
	USHORT							siz;
	
	hwDbgPrint(" -->>>>>> hwSelectInterface()\n");
	hwDbgPrint ( "fdo = 0x%x\n",fdo );
	hwDbgPrint ( "ConfigurationDescriptor = 0x%x\n",ConfigurationDescriptor );
	
	dx = fdo->DeviceExtension;

	//------------------------------------------------------------------
	// BulkUsb驱动只支持一个接点,我们必须解析这个
	// 接点的配置描述符并记下管道信息
	//------------------------------------------------------------------

	urb = USBD_CreateConfigurationRequest(ConfigurationDescriptor, &siz);
	if (urb)
	{
		//------------------------------------------------------------------
		// USBD_ParseConfigurationDescriptorEx()搜索一个给定的配置描述符
		// 并且返回一个匹配指定搜索标准的接点描述符
		// 这个设备我们只支持一个接点
		//------------------------------------------------------------------
		interfaceDescriptor = USBD_ParseConfigurationDescriptorEx(
									ConfigurationDescriptor,
									ConfigurationDescriptor,	//search from start of config  descriptro
									-1,						// interface number not a criteria; we only support one interface
									-1,						// not interested in alternate setting here either
									-1,						// interface class not a criteria
									-1,						// interface subclass not a criteria
									-1);						// interface protocol not a criteria
		
		if ( !interfaceDescriptor )
		{
			hwDbgPrint("ParseConfigurationDescriptorEx() failed, Returning STATUS_INSUFFICIENT_RESOURCES\n");
			FreeIfAllocated(urb);
			return STATUS_INSUFFICIENT_RESOURCES;
		}
		
		Interface = &urb->UrbSelectConfiguration.Interface;
		
		// 为管道信息结构体申请空间
		dx->PipeState = (PzjHMCFUsb_PIPESTATE)ExAllocatePool (	NonPagedPool, 
									Interface->NumberOfPipes * sizeof ( zjHMCFUsb_PIPESTATE ));

		if ( !dx->PipeState )
		{
			FreeIfAllocated(urb);
			return STATUS_INSUFFICIENT_RESOURCES;
		}		
		RtlZeroMemory (	dx->PipeState,
						Interface->NumberOfPipes * sizeof ( zjHMCFUsb_PIPESTATE ) );
		
		//------------------------------------------------------------------
		// 在此执行所有管道的初始化工作
		// 我们将设置最大传输大小和任何被使用的管道
		//------------------------------------------------------------------
		for (i=0; i< Interface->NumberOfPipes; i++)
		{
			Interface->Pipes[i].MaximumTransferSize = dx->MaximumTransferSize;
			dx->PipeState[i].fPipeOpened = FALSE;
		}
		UsbBuildSelectConfigurationRequest (	urb,
										(USHORT) siz,
										ConfigurationDescriptor);	
		ntStatus = hwCallUSBD(fdo, urb);		
		
	}
	else
	{
		hwDbgPrint("USBD_CreateConfigurationRequest() failed, returning STATUS_INSUFFICIENT_RESOURCES\n");
		ntStatus = STATUS_INSUFFICIENT_RESOURCES;
	}
	
	if (NT_SUCCESS(ntStatus))
	{
		// Save the configuration handle for this device		
		dx->UsbConfigurationHandle = urb->UrbSelectConfiguration.ConfigurationHandle;
		
		dx->UsbInterface = ExAllocatePool (	NonPagedPool,
										Interface->Length);
		
		if (dx->UsbInterface)
		{
			ULONG j;
			// save a copy of the interface information returned
			RtlCopyMemory(dx->UsbInterface, Interface, Interface->Length);
			// Dump the interface to the debugger
			hwDbgPrint("/**************** Interface information ****************/\n");
			hwDbgPrint("NumberOfPipes %d\n", dx->UsbInterface->NumberOfPipes);
			hwDbgPrint("Length %d\n", dx->UsbInterface->Length);
			hwDbgPrint("Alt Setting 0x%x\n", dx->UsbInterface->AlternateSetting);
			hwDbgPrint("Interface Number %d\n", dx->UsbInterface->InterfaceNumber);
			hwDbgPrint("Class, subclass, protocol 0x%x 0x%x 0x%x\n",
					dx->UsbInterface->Class,
					dx->UsbInterface->SubClass,
					dx->UsbInterface->Protocol);
			
            		// Dump the pipe info			
	            	for (j=0; j<Interface->NumberOfPipes; j++)
			{
				PUSBD_PIPE_INFORMATION pipeInformation;				
				pipeInformation = &dx->UsbInterface->Pipes[j];				
				hwDbgPrint("---------\n");
				hwDbgPrint("PipeType 0x%x\n", pipeInformation->PipeType);
				hwDbgPrint("EndpointAddress 0x%x\n", pipeInformation->EndpointAddress);
				hwDbgPrint("MaxPacketSize 0x%x\n", pipeInformation->MaximumPacketSize);
				hwDbgPrint("Interval 0x%x\n", pipeInformation->Interval);
				hwDbgPrint("Handle 0x%x\n", pipeInformation->PipeHandle);
				hwDbgPrint("MaximumTransferSize 0x%x\n", pipeInformation->MaximumTransferSize);
			}
			hwDbgPrint("/****************************************************/\n");
		}
	}
	
	if (urb)
	{
        	FreeIfAllocated(urb);
    	}
	hwDbgPrint("hwSelectInterface(), ntStatus 0x%x-->>>>>>\n",ntStatus);
	
	return ntStatus; 
}
/************************************************************************************************
* Function Type	:	private
* Parameter		:	fdo				-	pointer to our FDO (Functional Device Object )
* Return Value	:	NT status code
* Description		:	初始化一个指定的USB设备实例,并且选择和保存这个配置
*************************************************************************************************/
NTSTATUS hwConfigureDevice(IN PDEVICE_OBJECT fdo)
{
	PDEVICE_EXTENSION dx;
	NTSTATUS ntStatus;
	PURB urb;
	ULONG siz;
	
	hwDbgPrint(" -->>>>>> hwConfigureDevice(fdo=0x%x)\n",fdo);
	dx = fdo->DeviceExtension;	
	hwASSERT( dx->UsbConfigurationDescriptor == NULL );
	urb = ExAllocatePool(NonPagedPool,
				sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
	if ( !urb )
		return STATUS_INSUFFICIENT_RESOURCES;
	//------------------------------------------------------------------
	// 指定DescriptorType为USB_CONFIGURATION_DESCRIPTOR_TYPE来调用
	// UsbBuildGetDescriptorRequest()获取所有的接点、端点、厂商
	// 等信息,配置信息也将被获得。
	// 调用者必须申请足够大的缓冲来保存这些信息,否则
	// 数据将被切割而不报任何错误。
	// 因此先猜想一个合适的"siz"大小,调用UsbBuildGetDescriptorRequest()
	// 后获取实际需要的"siz"大小,然后以实际的"siz"大小
	//  重新调用UsbBuildGetDescriptorRequest()
	//------------------------------------------------------------------

	siz = sizeof(USB_CONFIGURATION_DESCRIPTOR) + 512;  
	
	// 当dx->UsbConfigurationDescriptor有足够大的缓冲以至于
	// 数据不被切割时我们将退出这个循环
	while( 1 )
	{
		dx->UsbConfigurationDescriptor = ExAllocatePool(NonPagedPool, siz);
		if ( !dx->UsbConfigurationDescriptor )
		{
			FreeIfAllocated(urb);
			return STATUS_INSUFFICIENT_RESOURCES;
		}

		UsbBuildGetDescriptorRequest
		(
			urb,
			(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),
			USB_CONFIGURATION_DESCRIPTOR_TYPE,
			0,
			0,
			dx->UsbConfigurationDescriptor,
			NULL,
			siz,
			NULL
		);
		
		ntStatus = hwCallUSBD(fdo, urb);
		
		hwDbgPrint("hwCallUSBD() Configuration Descriptor = 0x%x, len %d\n",
					dx->UsbConfigurationDescriptor,
					urb->UrbControlDescriptorRequest.TransferBufferLength);
		// if we got some data see if it was enough.
		// NOTE: we may get an error in URB because of buffer overrun
		if (urb->UrbControlDescriptorRequest.TransferBufferLength>0 &&
			dx->UsbConfigurationDescriptor->wTotalLength > siz)
		{
			siz = dx->UsbConfigurationDescriptor->wTotalLength;
			FreeIfAllocated(dx->UsbConfigurationDescriptor);
		}
		else
		{
			break;  // 我们已经获取了配置描述符
		}
	} // end, while (retry loop )

	FreeIfAllocated(urb);
	hwASSERT( dx->UsbConfigurationDescriptor );
	
	//------------------------------------------------------------------
	// 我们已经获得了配置描述符
	// 现在我们要选择配置命令来获取配置相关联的
	// 管道信息
	//------------------------------------------------------------------
	ntStatus = hwSelectInterface(fdo, dx->UsbConfigurationDescriptor);
	
	hwDbgPrint("hwConfigureDevice (%x)-->>>>>>\n", ntStatus);

	return ntStatus;
} 
/************************************************************************************************
* Function Type	:	global
* Parameter		:	fdo			-	pointer to our FDO (Functional Device Object )
* Return Value	:	NT status code
* Description		:	这个例程是处理IRP_MJ_PNP,初始化一个给定USB设备的实例
*					USB客户驱动像我们一样设置好URBs(USB请求包)发送请求
*					到主控制驱动(HCD)。URB结构定义了一个包含所有可能
*					的命令发送给USB设备。这里,我们请求驱动的描述符并
*					保存它,并且配制我们的设备
* Note			:	1、先让下层驱动处理这个irp
*					2、分配URB非分页内存
*					3、构建一个获取描述符的URB请求
*					4、调用hwCallUSBD()函数递交这个URB
*					5、释放URB所占的非分页内存空间
*					6、调用hwConfigureDevice()获取设备配置信息
*************************************************************************************************/
NTSTATUS hwStartDevice( IN  PDEVICE_OBJECT fdo, IN PIRP Irp, IN PNTSTATUS p_ntStatus)
{
	PDEVICE_EXTENSION			dx;
	PUSB_DEVICE_DESCRIPTOR		deviceDescriptor = NULL;
	PURB						urb;
	ULONG						siz;
	NTSTATUS					waitStatus;
	KEVENT						startDeviceEvent;

	hwDbgPrint(" -->>>>>> hwStartDevice(fdo = 0x%x)\n",fdo);
	dx = fdo->DeviceExtension;
	(*p_ntStatus) = STATUS_SUCCESS;
	
	//------------------------------------------------------------------
	//这个IPR是在分配资源之后发送的,这个设备最近被
	//枚举并第一次启动,或者是在停止后重新启动将会
	// 收到这个IRP
	// 先让FDO处理这个IRP
	//------------------------------------------------------------------
	KeInitializeEvent(&startDeviceEvent, NotificationEvent, FALSE);
	IoCopyCurrentIrpStackLocationToNext(Irp);
	IoSetCompletionRoutine (	Irp,
							hwIRPCompletionRoutine,
							&startDeviceEvent,		// pass the event to the completion routine as the Context
							TRUE,				// invoke on success
							TRUE,				// invoke on error
							TRUE);				// invoke on cancellation
	
	(*p_ntStatus) = IoCallDriver(dx->LowerDeviceObject,Irp);
	if ((*p_ntStatus) == STATUS_PENDING)
	{
		waitStatus = KeWaitForSingleObject(
									&startDeviceEvent,
									Suspended,
									KernelMode,
									FALSE,
									NULL);
		(*p_ntStatus) = Irp->IoStatus.Status;
	}
	if (!NT_SUCCESS((*p_ntStatus)))
	{
		goto done;
	}

	//现在我们准备启动我们的设备
	urb = ExAllocatePool(NonPagedPool,sizeof(struct _URB_CONTROL_DESCRIPTOR_REQUEST));
	if (urb)
    	{
		siz = sizeof(USB_DEVICE_DESCRIPTOR);
		deviceDescriptor = ExAllocatePool(NonPagedPool,siz);
		hwDbgPrint("ExAllocatePool() for deviceDescriptor %s\n",
			deviceDescriptor?"SUCCESS":"FAILED");
		if ( !deviceDescriptor )
		{
			// 分配deviceDescriptor内存失败
			(*p_ntStatus) = STATUS_INSUFFICIENT_RESOURCES;
		}
		else
		{
			UsbBuildGetDescriptorRequest
			(
				urb,				//Points to an URB to be formatted for a get descriptor request to the HCD. The caller must allocate nonpaged pool for this URB.
				(USHORT) sizeof (struct _URB_CONTROL_DESCRIPTOR_REQUEST),

⌨️ 快捷键说明

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