登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

面包会有的

... ...

 
 
 

日志

 
 

WinXP下虚拟摄像头驱动程序开发  

2011-05-09 20:21:43|  分类: VC++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

摄像头驱动程序的主要目的是通过硬件捕捉视频信号。微软公司提供了一套视频驱动的接口,可以满足这个接口的视频驱动程序。第三方厂商开发的软件,如QQ和MSN等软件,都可以通过这个接口读取视频摄像头采集的数据。本文将介绍一个虚拟摄像头的实现,读者可以根据自己的需要,结合硬件设计出符合这个接口的USB或者PCI摄像头驱动程序。


1               驱动框架

WinXP下采用WDM模式进行摄像头驱动程序开发主要包含两个部分,一部分时类驱动程序,一部分是小驱动程序。类驱动程序由微软提供,而小驱动程序是由程序自己编写,并实现相关扩展功能。

摄像头采集的数据都是纯粹的数据文件,然后源源不断地传递给PC机。因此得名Stream(流设备)。编写摄像头驱动程序就是编写流设备的小驱动,但首先需要了解类设备驱动与小驱动之间是如何配合的。在WDM驱动程序当中,小驱动需要首先将自己注册给类驱动,类驱动拥有真正的设备对象,然而小驱动程序不创建对象,它仅利用类驱动程序实现系统调用。

流设备的类驱动主要是控制请求。这需要通过调用小驱动的适配器来访问具体的硬件。在流设备的类驱动和小驱动都初始化以后,小驱动需要被动地等待类驱动来调用。类驱动用(stream request block)SRB向小驱动程序发送标准的请求,小驱动通过解析SRB后向Class Driver的请求。例如在SRB中,类驱动与小驱动采用数据结构HW_STREAM_REQUEST_BLOCK来传送命令和数据。


2               初始化

与其他驱动程序不同,类驱动与小驱动采用HW_INITIALIZATION_DATA数据结构进行初始化操作,其初始化步骤如下。

当设备接入插口时,即插即用管理器能够监测到新的设备,进而调用Mini Driver的DriverEntry例程。

申请HW_INITIALIZATION_DATA数据内存,并填充相关域,调用StreamClassRegisterMinidriver函数注册该小驱动。如下代码;

RtlZeroMemory(&HwInitData, sizeof(HwInitData));

    HwInitData.HwInitializationDataSize = sizeof(HwInitData);

    //

    // Set the Adapter entry points for the driver

    //

    HwInitData.HwInterrupt               = NULL; // HwInterrupt;         

    HwInitData.HwReceivePacket          = AdapterReceivePacket;

    HwInitData.HwCancelPacket           = AdapterCancelPacket;

    HwInitData.HwRequestTimeoutHandler   = AdapterTimeoutPacket;

    HwInitData.DeviceExtensionSize        = sizeof(HW_DEVICE_EXTENSION);

    HwInitData.PerRequestExtensionSize     = sizeof(SRB_EXTENSION);

    HwInitData.FilterInstanceExtensionSize   = 0;

    HwInitData.PerStreamExtensionSize      = sizeof(STREAMEX);

    HwInitData.BusMasterDMA            = FALSE;

    HwInitData.Dma24BitAddresses         = FALSE;

    HwInitData.BufferAlignment          = 3;

    HwInitData.DmaBufferSize           = 0;

    // Don't rely on the stream class using raised IRQL to synchronize

    // execution.  This single paramter most affects the overall structure

    // of the driver.

    HwInitData.TurnOffSynchronization   = TRUE;

    ReturnValue = StreamClassRegisterAdapter(DriverObject, RegistryPath, &HwInitData);

AdapterReceivePacket函数用于接收类驱动向小驱动发送的SRB,其中SRB_INITIALIZE_DEVICE用于初始化小驱动,SRB_INITIALIZE_DEVICE结构体中ConfigInfo记录着摄像头的意见相关信息。初始化之后类驱动再向小驱动发送SRB_GET_STREAM_INFO类型的SRB,用于向小驱动程序咨询HW_STREAM_HEADER数据信息和HW_STREAM_INFORMATION等信息。这些信息包含了摄像头驱动提供的视频图像大小、图像格式等信息。最后类驱动程序小驱动再发送HW_STREAM_INFORMATION的SRB,这次请求之后,小驱动的初始化操作基本完成,并返回给类驱动程序。上述这些过程的代码如下;

switch (pSrb->Command)

{

case SRB_INITIALIZE_DEVICE:

// open the device

HwInitialize(pSrb);

break;

case SRB_UNINITIALIZE_DEVICE:

// close the device.

HwUnInitialize(pSrb);

break;

case SRB_OPEN_STREAM:

        // open a stream

AdapterOpenStream(pSrb);

break;

case SRB_CLOSE_STREAM:

// close a stream

AdapterCloseStream(pSrb);

break;

case SRB_GET_STREAM_INFO:

        AdapterStreamInfo(pSrb);

        break;

    case SRB_GET_DATA_INTERSECTION:

        AdapterFormatFromRange(pSrb);

break;

case SRB_OPEN_DEVICE_INSTANCE:

case SRB_CLOSE_DEVICE_INSTANCE:

 

        TRAP;

        pSrb->Status = STATUS_NOT_IMPLEMENTED;

        break;

    case SRB_GET_DEVICE_PROPERTY:

        AdapterGetProperty (pSrb);

        break;

    case SRB_SET_DEVICE_PROPERTY:

        AdapterSetProperty (pSrb);

        break;

case SRB_PAGING_OUT_DRIVER:

    DbgLogInfo(("'Testcap: Receiving SRB_PAGING_OUT_DRIVER -- SRB=%x\n", pSrb));

        break;

case SRB_CHANGE_POWER_STATE:

    DbgLogInfo(("'Testcap: Receiving SRB_CHANGE_POWER_STATE ------ SRB=%x\n", pSrb));

        AdapterPowerState(pSrb);

        break;

case SRB_INITIALIZATION_COMPLETE:

    DbgLogInfo(("'Testcap: Receiving SRB_INITIALIZATION_COMPLETE-- SRB=%x\n", pSrb));

        break;

case SRB_UNKNOWN_DEVICE_COMMAND:

default:

pSrb->Status = STATUS_NOT_IMPLEMENTED;

}

CompleteDeviceSRB (pSrb);


3               编写小驱动程序

类驱动程序的目标是与操作系统进行交互,其中包括处理同步、提供标准接口。而小驱动由类驱动调用,主要负责具体的硬件相关操作。因此编写小驱动的程序应该会向类驱动注册一些回调函数,方便类驱动调用。其中有几个函数是必须注册的,如下;

?         StrMiniCancelPacket:对HW_STREAM_REQUEST_BLOCK数据包进行取消的回调函数。

?         StrMiniReceieveDevicePacket:获取HW_STREAM_REQUEST_BLOCK数据包回调函数。

?         StrMiniRequestTimeout:当HW_STREAM_REQUEST_BLOCK数据包超时的回调函数。

?         StrMiniEvent:使小驱动程序支持某种事件。

?         StrMiniInterrupt:当驱动获取中断时还用该支持中断处理函数。

编写小驱动程序时,还需要注意实现流控制操作,流控制命令和数据主要保存在SRB当中,其中以下几种流控制命令必须实现。

?         SRB_INITIALIZE_DEVICE:调用HW_INITIALIZATION_DATA数据结构中初始化小驱动程序。

?         SRB_GET_STREAM_INFO:调用HW_INITIALIZATION_DATA数据结构中获取流相关信息。

?         SRB_OPEN_STREAM:打开一个流实例,并填充HW_STREAM_OBJECT结构体流描述信息。

?         SRB_READ_DATA和SRB_WRITE_DATA:这两个命令用于接收和发送数据。

?         HW_STREAM_REQUEST_BLOCK:类驱动为了获得或者设置小驱动的某项属性或者流的某项属性,会向小驱动提供HwReceivePacket函数发送HW_STREAM_OBJECT请求。

?         SRB_CLOSE_STREAM:用于关闭小驱动程序。


4               总结

  在微软提供的类驱动程序之上编写虚拟驱动程序,其实最主要的工作就是编写子驱动程序,实现初始化、流控制、数据接收等相关回调函数。

  评论这张
 
阅读(2106)| 评论(0)

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018