V4L2较V4L有较大的改动,并已成为2.6的标准接口,函盖video\dvb\FM...,多数驱动都在向V4l2迁移。更好地了解V4L2先从应用入手,然后再深入到内核中结合物理设备/接口的规范实现相应的驱动。V4L2采用流水线的方式,操作更简单直观,基本遵循打开视频设备、设置格式、处理数据、关闭设备,更多的具体操作通过ioctl函数来实现。
// 用非阻塞模式打开摄像头设备int cameraFd;cameraFd = open("/dev/video0", O_RDWR | O_NONBLOCK, 0);// 如果用阻塞模式打开摄像头设备,上述代码变为://cameraFd = open("/dev/video0", O_RDWR, 0);应用程序能够使用阻塞模式或非阻塞模式打开视频设备,如果使用非阻塞模式调用视频设备,即使尚未捕获到信息,驱动依旧会把缓存(DQBUFF)里的东西返回给应用程序。
2. 设定属性及采集方式
打开视频设备后,可以设置该视频设备的属性,例如裁剪、缩放等。这一步是可选的。在Linux编程中,一般使用ioctl函数来对设备的I/O通道进行管理:
int ioctl (int __fd, unsigned long int __request, .../*args*/) ;在进行V4L2开发中,常用的命令标志符如下(some are optional):
v4l2_std_id std;do { ret = ioctl(fd, VIDIOC_QUERYSTD, &std);} while (ret == -1 && errno == EAGAIN);switch (std) { case V4L2_STD_NTSC: //…… case V4L2_STD_PAL: //……}2.2 设置视频捕获格式
当检测完视频设备支持的标准后,还需要设定视频捕获格式,结构如下:
memset ( &fmt, 0, sizeof(fmt) );fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;fmt.fmt.pix.width = 720;fmt.fmt.pix.height = 576;fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;if (ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) { return -1;}v4l2_format结构如下:struct v4l2_format{ enum v4l2_buf_type type; // 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE union { struct v4l2_pix_format pix; struct v4l2_window win; struct v4l2_vbi_format vbi; __u8 raw_data[200]; } fmt;};struct v4l2_pix_format{ __u32 width; // 宽,必须是16的倍数 __u32 height; // 高,必须是16的倍数 __u32 pixelformat; // 视频数据存储类型,例如是YUV4:2:2还是RGB enum v4l2_field field; __u32 bytesperline; __u32 sizeimage; enum v4l2_colorspace colorspace; __u32 priv; };2.3 分配内存接下来可以为视频捕获分配内存:
struct v4l2_requestbuffers req;if (ioctl(fd, VIDIOC_REQBUFS, &req) == -1) { return -1;}v4l2_requestbuffers 结构如下:struct v4l2_requestbuffers{ __u32 count; // 缓存数量,也就是说在缓存队列里保持多少张照片 enum v4l2_buf_type type; // 数据流类型,必须永远是V4L2_BUF_TYPE_VIDEO_CAPTURE enum v4l2_memory memory; // V4L2_MEMORY_MMAP 或 V4L2_MEMORY_USERPTR __u32 reserved[2];};2.4 获取并记录缓存的物理空间
使用VIDIOC_REQBUFS,我们获取了req.count个缓存,下一步通过调用VIDIOC_QUERYBUF命令来获取这些缓存的地址,然后使用mmap函数转换成应用程序中的绝对地址,最后把这段缓存放入缓存队列:
typedef struct VideoBuffer { void *start; size_t length;} VideoBuffer;VideoBuffer* buffers = calloc( req.count, sizeof(*buffers) );struct v4l2_buffer buf;for (numBufs = 0; numBufs < req.count; numBufs++) { memset( &buf, 0, sizeof(buf) ); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; buf.index = numBufs; // 读取缓存 if (ioctl(fd, VIDIOC_QUERYBUF, &buf) == -1) { return -1; } buffers[numBufs].length = buf.length; // 转换成相对地址 buffers[numBufs].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED,fd, buf.m.offset); if (buffers[numBufs].start == MAP_FAILED) { return -1; } // 放入缓存队列 if (ioctl(fd, VIDIOC_QBUF, &buf) == -1) { return -1; }}2.5 视频采集方式
操作系统一般把系统使用的内存划分成用户空间和内核空间,分别由应用程序管理和操作系统管理。应用程序可以直接访问内存的地址,而内核空间存放的是供内核访问的代码和数据,用户不能直接访问。v4l2捕获的数据,最初是存放在内核空间的,这意味着用户不能直接访问该段内存,必须通过某些手段来转换地址。
struct v4l2_buffer buf;memset(&buf,0,sizeof(buf));buf.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;buf.memory=V4L2_MEMORY_MMAP;buf.index=0;//读取缓存if (ioctl(cameraFd, VIDIOC_DQBUF, &buf) == -1){ return -1;}//…………视频处理算法//重新放入缓存队列if (ioctl(cameraFd, VIDIOC_QBUF, &buf) == -1) { return -1;}3. 关闭视频设备
使用close函数关闭一个视频设备
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ipromiseu/archive/2010/03/29/5428578.aspx
生活类博客。生活中有如此多的麻烦事,主要提供Windows、Mac os x、Linux等操作系统的技巧,当然也有诸如如何通过游泳减肥,旅行时不要带太多东西,钱包要放在前面的牛仔裤口袋里等生活小技巧。 lifehacker的口号是不要生活得像个奇客,而要像奇客一样生活?
评论性博客,博主的简介很暴力,图片上面的注释是“FBI通缉犯”,而捐款文字更是暴力:我穷困潦倒,请给我钱。(I have no life,please give me money.)而其最近的评论居然全部都是”上海翻译公司“的spam,强。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ipromiseu/archive/2010/04/22/5518004.aspx
很早以前就想写一篇和面试相关的文章了,今天在网络上看到一篇关于如何去面试程序员的英文文章,发现其中有很多和我共鸣的东西,所以仿照其标题通过自己的经历写下了这篇文章。
工作这么多年来,即被面试过,也面试过他人,对于程序员的面试,经历过很不错的面试,很专业的面试,也经历过一些BT和令人不爽的面试,我个人觉得一个好的面试,面试官是很重要的,所以,本文想从“面试官”的角度来阐述一下。于是,有了下面这样一篇的文章,希望本文对你的职场经历有用,特别是那些正在招聘和面试程序员的朋友,我觉得这篇文章会对大家有很多启示。此外,做为被面试的人,你可以看看本站的《别的程序员是怎么读你的简历的》《程序员需要具备的基本技能》《优秀程序员的十个习惯》其它一些和程序员相关的文章。
你很难从一个人的简历或是自我介绍上了解一个人。因为这些都是当事人自己写的,或是自己阐述的。所以,这并不是很准确的,通过简历,你只能知道很简单的事情,这对于是否能招入团是远远不够的。而在面试的开始,让应聘者做自我介绍,只会让面试者以很正式的态度来面对整个面试。一但面试过程很正式,很严肃,就会让人很拘禁,其实,这并不是我们想要的,我要的是应聘者真实和自然的表现,从而才能了解到最真实的东西。
问几个技术难题。比如:我个人经历过的——“ps的-a参数是什么意思?”,“vi中删除换行符的命令是什么?”,“C++的关键字explict,mutable是用来干什么?”等等,等等。以前做为一个应聘者来说,我非常讨厌这样的问题,因为这样的问题查一下手册就知道。难道他要招的是一个字典手册?不是一个人?对于这方面,重要的不是知识,重要的是其查找知识的能力。
给应聘者一个或几个很难的算法题,给上十几分钟,然后让面试者把伪代码或是代码写下来。这样的做法是相当可笑的,不能讨论不能查资料,让人在一种压力状态下作答,这根本就不是实际工作中的状态,而我们的面试也就成了一种刁难(我最变态的经历是,当我把写在两页纸上的代码上交上去后,面试官把其交给旁边程序员输出电脑做校验,结果程序员说,编译出错。于是,面试官说,“很遗憾,可能你写的程序还不多”,相当可笑)。对于这点来说,重要的不是那个解题的答案,而是解题的思路和方法。
我以前经历过很多的面试,当技术人员来和我做面试的时候,我发现,“技术人员的思维”对于某些人来说根本分不清面试和考试,在潜意识里,他们在很多时候不是在面试这个人,而是在刁难这个人并以此展示自己的技能。我个人认为我是一个好的程序员,但我可以告诉你我无法通过那样的面试,因为那样的面试是为他们自己准备的,而不是为应聘者准备的。
一、确认简历。首先,阅读一下别人的简历是需要的,从简历上,工作经历,项目经历,技术技能这三个事情是你需要了解的。一般来说,你可以先通过电话确定一下他的工作经历,项目经历和技术技能,然后,如果他和你需要的人条件相符的话,可以叫到公司做面对面的面试。千万不要把别人叫来,你又说你的经历和我们的工作有差距之类的话。(我有过一次面试经历,公司我不说了,反正是那个号称需要有良好沟通的公司,面试了我9次左右,从一般的程序员,PM,经理,到总经理,而最后一次直接告诉我,我以前的经历和他们的要求差距很大。我不禁要问了,前面若干次的面试他们都在干什么呢?)
二、面试开场。其次,把人邀请来公司面试,应聘者到了公司来面试,有一点很重要,那就是你一定要让整个面试过程变得很随意,很放松,就像普通的聊天和一般朋友间的交流一样。这样应聘者才会放松并拿出真实的样子来和你谈话和聊天,你才能在很短的时间内了解得更多。让应聘者放下心理负担,让其表现得自然一些,这是招聘方的责任。千万不要说,别人太紧张发挥的不好,有时候,招聘方得想想自己的问题。
面试开场的时候,千万不要让应聘者介绍自己,因为,应聘者早就给你发过简历了,而你也给其打过电话了。另外,应聘者对这个面试惯例通常都会准备得非常不错的,另一方面,这会让整个面试过程太正式太严肃了。所以,不妨问问应聘者是怎么过来的?最近怎么样?还可以和应聘者谈一个大众话题,比如喜欢什么体育,音乐,电影,社会热点什么的,自己也别板着个脸,说说笑笑,试图让大家都放松下来。另外,通过这些闲聊,你可以知道他/她的与人交往能力和一些性格。另外,不要让桌子放在你和应聘者之间,把环境搞得随意一些。
三、多让应聘者说说他的经历。接下来,如果你要觉得这个应聘者是否是一个可以解决问题,是一个可以把事情搞定的人,不用问他/她会做什么,直接问问其做过什么?干过什么事?对于一个好的程序员来说,很难想像其没有相关的实践,就算你是在大学里,你也应该做过什么。如果你有解决问题的能力,那么,很显然,今天你应该解决了很多问题,也搞定了很多事情,听听应聘者说一说他的那些事。(不要使用一问一答这种方式,应该让应聘者多说,而多听,多想)
沟通表达能力。应聘者能不能把一个事情讲清楚。如果这个人聪明的话,他就可以用最简单的语言把一个复杂的事情讲清楚。而且,这是一个好的程序员最基本的能力。而且,你可以在应聘者一边描述其经历的时候,你可以和应聘者有一些的良好的来来回回的交谈,这样就可以知道,他的沟通能力和沟通方式,从而了解他的性格,。
角色和位置。也许他参与了一个很大的项目,但只是做了一个很简单的模块。所以,了解其在项目中的担任的角色和位置是非常必要的。当应聘者说到“我们”或者“大家”之类的词汇时,一定要向下细化和明确。
做出的贡献和解决了什么的问题。这个很重要,通过了解这个,你可以知道面试者是否聪明,是否有能力解决问题,是否有好的技术底子。
演示。如果可能,你可以让应聘者展示一些其写过的代码,做过的设计,或是直接给你看看他写的程序的演示。(从设计上,代码的风格,重用性,维护性上你可以了解很多很多)
基础知识。了解该项目中应聘者使用的技术的一些基础知识,比如,通过整个过程,你可以问一些网络,语言,面象对象,系统的一些基础知识。基础知识是非常重要的,这直接关系到了他的能力。
流程和工具。了解应聘者所熟悉的项目的流程(银弹,瀑布,敏捷,……),还有流程中的一些工件(如:需求文档,设计文档,测试方档等),以及在开发过程中使用的工具(内存测试,代码检查,BUG报告,版本维护,开发调试……)(关于程序员的基本技能,你可以参考——《程序员需要具备的基本技能》)
有人会说,应聘者的经历可以被他自己编出来的,他可以把一些不是他做的事说成是他做的。是的,的确是有这种可能。不过,不要忘了,一个谎言背后需要用更多的谎言来圆谎的,所以,你不必担心这个问题,只要你在应聘者的描述过程中逐步求精,细化问题,你会知道应聘者是否是在编故事的。
在面试过程中,一些招聘者会让应聘者们一起做个游戏,或是搞个辩论比赛,或是现场组个团队干个简单的事情,有的甚至让应聘者请一天假到自己的公司里来和自己的团队一同工作一天,并要完成某个事情(甚至给其设置上deadline),并通过这些来考量应聘者的实际参与能力。
是的,如果没有一起工作过,没有一些实际的事情发生,单靠几个小时的面试很难了解一个人的。设置上这些面试的环节,在最短的时间内来了解应聘者的一切,对于招聘方来说无可厚非。而且有的时候也能得到不错的效果。在这里,我只提一点,有时候这样的周期拉得很长,让应聘者付出了很多,反尔会让应聘者产生反感和厌烦情绪,从某种意义上来说,这实在是对应聘者的不尊重。
对于这一点,我一直持疑问的态度,所以,我在其后打了两个问号。老实说,对于实际参与这一环节,我个人的意见是适可而止,因为时间太短了,无论你怎么做你都无法了解完整。即然无法了解完整,那就获取你最需要的吧,就是本文开头的那三个问题,以及上面所述的“第三点”(了解应聘者的以往经历)。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ipromiseu/archive/2010/04/21/5512410.aspx
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ipromiseu/archive/2009/11/03/4764444.aspx
http://www.quickcamteam.net/software/linux/v4l2-software/luvcview/
内核函数init_timer()用来初始化一个定时器。实际上,这个初始化函数仅仅将结构中的list成员初始化为空。如下所示(include/linux/timer.h):
#define time_after(a,b) ((long)(b) - (long)(a) < 0)
#define time_before(a,b) time_after(b,a)
#define time_after_eq(a,b) ((long)(a) - (long)(b) >= 0)
#define time_before_eq(a,b) time_after_eq(b,a) |
7.6.2 动态内核定时器机制的原理
Linux是怎样为其内核定时器机制提供动态扩展能力的呢?其关键就在于“定时器向量”的概念。所谓“定时器向量”
就是指这样一条双向循环定时器队列(对列中的每一个元素都是一个timer_list结构):对列中的所有定时器都在同
一个时刻到期,也即对列中的每一个timer_list结构都具有相同的expires值。显然,可以用一个timer_list结构类型
的指针来表示一个定时器向量。
显然,定时器expires成员的值与jiffies变量的差值决定了一个定时器将在多长时间后到期。在32位系统中,这个时间
差值的最大值应该是0xffffffff。因此如果是基于“定时器向量”基本定义,内核将至少要维护0xffffffff个timer_list
结构类型的指针,这显然是不现实的。
另一方面,从内核本身这个角度看,它所关心的定时器显然不是那些已经过期而被执行过的定时器(这些定时器完全可
以被丢弃),也不是那些要经过很长时间才会到期的定时器,而是那些当前已经到期或者马上就要到期的定时器
(注意!时间间隔是以滴答次数为计数单位的)。
基于上述考虑,并假定一个定时器要经过interval个时钟滴答后才到期(interval=expires-jiffies),则Linux采用
了下列思想来实现其动态内核定时器机制:对于那些0≤interval≤255的定时器,Linux严格按照定时器向量的基本
语义来组织这些定时器,也即Linux内核最关心那些在接下来的255个时钟节拍内就要到期的定时器,因此将它们按
照各自不同的expires值组织成256个定时器向量。而对于那些256≤interval≤0xffffffff的定时器,由于他们离到
期还有一段时间,因此内核并不关心他们,而是将它们以一种扩展的定时器向量语义(或称为“松散的定时器向量语义”)
进行组织。所谓“松散的定时器向量语义”就是指:各定时器的expires值可以互不相同的一个定时器队列。
具体的组织方案可以分为两大部分:
(1)对于内核最关心的、interval值在[0,255]之间的前256个定时器向量,内核是这样组织它们的:这256个定
时器向量被组织在一起组成一个定时器向量数组,并作为数据结构timer_vec_root的一部分,该数据结构定义
在kernel/timer.c文件中,如下述代码段所示:
/*
* Event timer code
*/
#define TVN_BITS 6
#define TVR_BITS 8
#define TVN_SIZE (1 << TVN_BITS)
#define TVR_SIZE (1 << TVR_BITS)
#define TVN_MASK (TVN_SIZE - 1)
#define TVR_MASK (TVR_SIZE - 1)
struct timer_vec {
int index;
struct list_head vec[TVN_SIZE];
};
struct timer_vec_root {
int index;
struct list_head vec[TVR_SIZE];
};
static struct timer_vec tv5;
static struct timer_vec tv4;
static struct timer_vec tv3;
static struct timer_vec tv2;
static struct timer_vec_root tv1;
static struct timer_vec * const tvecs[] = {
(struct timer_vec *)&tv1, &tv2, &tv3, &tv4, &tv5
};
#define NOOF_TVECS (sizeof(tvecs) / sizeof(tvecs[0])) |
基于数据结构timer_vec_root,Linux定义了一个全局变量tv1,以表示内核所关心的前256个定时器向量。这样
内核在处理是否有到期定时器时,它就只从定时器向量数组tv1.vec[256]中的某个定时器向量内进行扫描。
而tv1的index字段则指定当前正在扫描定时器向量数组tv1.vec[256]中的哪一个定时器向量,也即该数组的索引,
其初值为0,最大值为255(以256为模)。每个时钟节拍时index字段都会加1。显然,index字段所指定的定时器
向量tv1.vec[index]中包含了当前时钟节拍内已经到期的所有动态定时器。而定时器向量tv1.vec[index+k]则
包含了接下来第k个时钟节拍时刻将到期的所有动态定时器。当index值又重新变为0时,就意味着内核已经扫描
了tv1变量中的所有256个定时器向量。在这种情况下就必须将那些以松散定时器向量语义来组织的定时器向量补充到tv1中来。
(2)而对于内核不关心的、interval值在[0xff,0xffffffff]之间的定时器,它们的到期紧迫程度也随其interval值
的不同而不同。显然interval值越小,定时器紧迫程度也越高。因此在将它们以松散定时器向量进行组织时也应该区别
对待。通常,定时器的interval值越小,它所处的定时器向量的松散度也就越低(也即向量中的各定时器的expires值
相差越小);而interval值越大,它所处的定时器向量的松散度也就越大(也即向量中的各定时器的expires值相差越大)。
内核规定,对于那些满足条件:0x100≤interval≤0x3fff的定时器,只要表达式(interval>>8)具有相同值的定时
器都将被组织在同一个松散定时器向量中。因此,为组织所有满足条件0x100≤interval≤0x3fff的定时器,就需
要26=64个松散定时器向量。同样地,为方便起见,这64个松散定时器向量也放在一起形成数组,并作为数据结
构timer_vec的一部分。基于数据结构timer_vec,Linux定义了全局变量tv2,来表示这64条松散定时器向量。如
上述代码段所示。
对于那些满足条件0x4000≤interval≤0xfffff的定时器,只要表达式(interval>>8+6)的值相同的定时器都将被
放在同一个松散定时器向量中。同样,要组织所有满足条件0x4000≤interval≤0xfffff的定时器,也需要26=64个
松散定时器向量。类似地,这64个松散定时器向量也可以用一个timer_vec结构来描述,相应地Linux定义了tv3全
局变量来表示这64个松散定时器向量。
对于那些满足条件0x100000≤interval≤0x3ffffff的定时器,只要表达式(interval>>8+6+6)的值相同的定时
器都将被放在同一个松散定时器向量中。同样,要组织所有满足条件0x100000≤interval≤0x3ffffff的定时器,也
需要26=64个松散定时器向量。类似地,这64个松散定时器向量也可以用一个timer_vec结构来描述,相应地Linux
定义了tv4全局变量来表示这64个松散定时器向量。
对于那些满足条件0x4000000≤interval≤0xffffffff的定时器,只要表达式(interval>>8+6+6+6)的值相同的
定时器都将被放在同一个松散定时器向量中。同样,要组织所有满足条件0x4000000≤interval≤0xffffffff的定时器,
也需要26=64个松散定时器向量。类似地,这64个松散定时器向量也可以用一个timer_vec结构来描述,相应地Linux定
义了tv5全局变量来表示这64个松散定时器向量。
最后,为了引用方便,Linux定义了一个指针数组tvecs[],来分别指向tv1、tv2、…、tv5结构变量。如上述代码所示。
7.6.3 内核动态定时器机制的实现
在内核动态定时器机制的实现中,有三个操作时非常重要的:
(1)将一个定时器插入到它应该所处的定时器向量中。
(2)定时器的迁移,也即将一个定时器从它原来所处的定时器向量迁移到另一个定时器向量中。
(3)扫描并执行当前已经到期的定时器。
7.6.3.1 动态定时器机制的初始化
函数init_timervecs()实现对动态定时器机制的初始化。该函数仅被sched_init()初始化例程所调用。动态定时
器机制初始化过程的主要任务就是将tv1、tv2、…、tv5这5个结构变量中的定时器向量指针数组vec[]初始化
为NULL。如下所示(kernel/timer.c):
void init_timervecs (void)
{
int i;
for (i = 0; i < TVN_SIZE; i++) {
INIT_LIST_HEAD(tv5.vec + i);
INIT_LIST_HEAD(tv4.vec + i);
INIT_LIST_HEAD(tv3.vec + i);
INIT_LIST_HEAD(tv2.vec + i);
}
for (i = 0; i < TVR_SIZE; i++)
INIT_LIST_HEAD(tv1.vec + i);
} |
上述函数中的宏TVN_SIZE是指timer_vec结构类型中的定时器向量指针数组vec[]的大小,值为64。
宏TVR_SIZE是指timer_vec_root结构类型中的定时器向量数组vec[]的大小,值为256。
7.6.3.2 动态定时器的时钟滴答基准timer_jiffies
由于动态定时器是在时钟中断的Bottom Half中被执行的,而从TIMER_BH向量被激活到其timer_bh()函数真正
执行这段时间内可能会有几次时钟中断发生。因此内核必须记住上一次运行定时器机制是什么时候,也即内核必须
保存上一次运行定时器机制时的jiffies值。为此,Linux在kernel/timer.c文件中定义了全局变量timer_jiffies来表
示上一次运行定时器机制时的jiffies值。该变量的定义如下所示:
static unsigned long timer_jiffies; |
7.6.3.3 对内核动态定时器链表的保护
由于内核动态定时器链表是一种系统全局共享资源,为了实现对它的互斥访问,Linux定义了专门的自旋锁timerlist_lock
来保护。任何想要访问动态定时器链表的代码段都首先必须先持有该自旋锁,并且在访问结束后释放该自旋锁。其定义
如下(kernel/timer.c):
/* Initialize both explicitly - let's try to have them in the same cache line */
spinlock_t timerlist_lock = SPIN_LOCK_UNLOCKED; |
7.6.3.4 将一个定时器插入到链表中
函 数add_timer()用来将参数timer指针所指向的定时器插入到一个合适的定时器链表中。它首先调用timer_pending()函
数判断所指 定的定时器是否已经位于在某个定时器向量中等待执行。如果是,则不进行任何操作,只是打印一条内核告警
信息就返回了;如果不是,则调用 internal_add_timer()函数完成实际的插入操作。其源码如下(kernel/timer.c):
void add_timer(struct timer_list *timer) { unsigned long flags; spin_lock_irqsave(&timerlist_lock, flags); if (timer_pending(timer)) goto bug; internal_add_timer(timer); spin_unlock_irqrestore(&timerlist_lock, flags); return; bug: spin_unlock_irqrestore(&timerlist_lock, flags); printk("bug: kernel timer added twice at %p.\n", __builtin_return_address(0)); } |
函数internal_add_timer()用于将一个不处于任何定时器向量中的定时器插入到它应该所处的定时器向量中去(根据定
时器的expires值来决定)。如下所示(kernel/timer.c):
static inline void internal_add_timer(struct timer_list *timer) { /* * must be cli-ed when calling this */ unsigned long expires = timer->expires; unsigned long idx = expires - timer_jiffies; struct list_head * vec; if (idx < TVR_SIZE) { int i = expires & TVR_MASK; vec = tv1.vec + i; } else if (idx < 1 << (TVR_BITS + TVN_BITS)) { int i = (expires >> TVR_BITS) & TVN_MASK; vec = tv2.vec + i; } else if (idx < 1 << (TVR_BITS + 2 * TVN_BITS)) { int i = (expires >> (TVR_BITS + TVN_BITS)) & TVN_MASK; vec = tv3.vec + i; } else if (idx < 1 << (TVR_BITS + 3 * TVN_BITS)) { int i = (expires >> (TVR_BITS + 2 * TVN_BITS)) & TVN_MASK; vec = tv4.vec + i; } else if ((signed long) idx < 0) { /* can happen if you add a timer with expires == jiffies, * or you set a timer to go off in the past */ vec = tv1.vec + tv1.index; } else if (idx <= 0xffffffffUL) { int i = (expires >> (TVR_BITS + 3 * TVN_BITS)) & TVN_MASK; vec = tv5.vec + i; } else { /* Can only get here on architectures with 64-bit jiffies */ INIT_LIST_HEAD(&timer->list); return; } /* * Timers are FIFO! */ list_add(&timer->list, vec->prev); } |
对该函数的注释如下:
(1)首先,计算定时器的expires值与timer_jiffies的插值(注意!这里应该使用动态定时器自己的时间基准),这个差值
就表示这个定时器相对于上一次运行定时器机制的那个时刻还需要多长时间间隔才到期。局部变量idx保存这个差值。
(2)根据idx的值确定这个定时器应被插入到哪一个定时器向量中。其具体的确定方法我们在7.6.2节已经说过了,这里不再
详述。最后,定时器向量的头部指针vec表示这个定时器应该所处的定时器向量链表头部。
(3)最后,调用list_add()函数将定时器插入到vec指针所指向的定时器队列的尾部。
7.6.3.5 修改一个定时器的expires值
当一个定时器已经被插入到内核动态定时器链表中后,我们还可以修改该定时器的expires值。函数mod_timer()实现这一点。
如下所示(kernel/timer.c):
int mod_timer(struct timer_list *timer, unsigned long expires) { int ret; unsigned long flags; spin_lock_irqsave(&timerlist_lock, flags); timer->expires = expires; ret = detach_timer(timer); internal_add_timer(timer); spin_unlock_irqrestore(&timerlist_lock, flags); return ret; } |
该函数首先根据参数expires值更新定时器的expires成员。然后调用detach_timer()函数将该定时器从它原来所属的链表
中删除。最后调用internal_add_timer()函数将该定时器根据它新的expires值重新插入到相应的链表中。
函 数detach_timer()首先调用timer_pending()来判断指定的定时器是否已经处于某个链表中,如果定时器原来就不处于任
何链表中, 则detach_timer()函数什么也不做,直接返回0值,表示失败。否则,就调用list_del()函数将定时器从它原来所
处的链表中摘除。如下 所示(kernel/timer.c):
static inline int detach_timer (struct timer_list *timer) { if (!timer_pending(timer)) return 0; list_del(&timer->list); return 1; } |
7.6.3.6 删除一个定时器
函数del_timer()用来将一个定时器从相应的内核定时器队列中删除。该函数实际上是对detach_timer()函数的高层封装。
如下所示(kernel/timer.c):
int del_timer(struct timer_list * timer)
{
int ret;
unsigned long flags;
spin_lock_irqsave(&timerlist_lock, flags);
ret = detach_timer(timer);
timer->list.next = timer->list.prev = NULL;
spin_unlock_irqrestore(&timerlist_lock, flags);
return ret;
} |
7.6.3.7 定时器迁移操作
由于一个定时器的interval值会随着时间的不断流逝(即jiffies值的不断增大)而不断变小,因此那些原本到期紧迫程度较
低的定时器会随着jiffies值的不断增大而成为既把马上到期的定时器。比如定时器向量tv2.vec[0]中的定时器在经过256个
时钟滴答后会成为未来256个时钟滴答内会到期的定时器。因此,定时器在内核动态定时器链表中的位置也应相应地随着改
变。改变的规则是:当tv1.index重新变为0时(意味着tv1中的256个定时器向量都已被内核扫描一遍了,从而使tv1中的
256个定时器向量变为空),则用tv2.vec[index]定时器向量中的定时器去填充tv1,同时使tv2.index加1(它以64为模)。
当tv2.index重新变为0(意味着tv2中的64个定时器向量都已经被全部填充到tv1中去了,从而使得tv2变为空),则
用tv3.vec[index]定时器向量中的定时器去填充tv2。如此一直类推下去,直到tv5。
函数cascade_timers()完成这种定时器迁移操作,该函数只有一个timer_vec结构类型指针的参数tv。这个函数把把定时
器向量tv->vec[tv->index]中的所有定时器重新填充到上一层定时器向量中去。如下所示(kernel/timer.c):
static inline void cascade_timers(struct timer_vec *tv)
{
/* cascade all the timers from tv up one level */
struct list_head *head, *curr, *next;
head = tv->vec + tv->index;
curr = head->next;
/*
* We are removing _all_ timers from the list, so we don't have to
* detach them individually, just clear the list afterwards.
*/
while (curr != head) {
struct timer_list *tmp;
tmp = list_entry(curr, struct timer_list, list);
next = curr->next;
list_del(curr); // not needed
internal_add_timer(tmp);
curr = next;
}
INIT_LIST_HEAD(head);
tv->index = (tv->index + 1) & TVN_MASK;
} |
对该函数的注释如下:
(1)首先,用指针head指向定时器头部向量头部的list_head结构。指针curr指向定时器向量中的第一个定时器。
(2)然后,用一个while{}循环来遍历定时器向量tv->vec[tv->index]。由于定时器向量是一个双向循环队列,因此循环
的终止条件是curr=head。对于每一个被扫描的定时器,循环体都先调用list_del()函数把当前定时器从链表中摘除,然后调
用internal_add_timer()函数重新确定该定时器应该被放到哪个定时器向量中去。
(3)当从while{}循环退出后,定时器向量tv->vec[tv->index]中所有的定时器都已被迁移到其它地方(到它们该呆的地
方:-),因此它本身就成为一个空队列。这里我们显示地调用INIT_LIST_HEAD()宏来把定时器向量的表头结构初始化为空。
(4)最后,把tv->index值加1,当然它是以64为模。 以上文章内容均为网络转载或者本站会员原创,"Linux-cn.com不对
文章内容做任何保证。
7.6.4.8 扫描并执行当前已经到期的定时器
函数run_timer_list()完成这个功能。如前所述,该函数是被timer_bh()函数所调用的,因此内核定时器是在时钟中
断的Bottom Half中被执行的。记住这一点非常重要。全局变量timer_jiffies表示了内核上一次执行run_timer_list()函
数的时间,因此jiffies与timer_jiffies的差值就表示了自从上一次处理定时器以来,期间一共发生了多少次时钟中断,显
然run_timer_list()函数必须为期间所发生的每一次时钟中断补上定时器服务。该函数的源码如下(kernel/timer.c):
static inline void run_timer_list(void)
{
spin_lock_irq(&timerlist_lock);
while ((long)(jiffies - timer_jiffies) >= 0) {
struct list_head *head, *curr;
if (!tv1.index) {
int n = 1;
do {
cascade_timers(tvecs[n]);
} while (tvecs[n]->index == 1 && ++n < NOOF_TVECS);
}
repeat:
head = tv1.vec + tv1.index;
curr = head->next;
if (curr != head) {
struct timer_list *timer;
void (*fn)(unsigned long);
unsigned long data;
timer = list_entry(curr, struct timer_list, list);
fn = timer->function;
data= timer->data;
detach_timer(timer);
timer->list.next = timer->list.prev = NULL;
timer_enter(timer);
spin_unlock_irq(&timerlist_lock);
fn(data);
spin_lock_irq(&timerlist_lock);
timer_exit();
goto repeat;
}
++timer_jiffies;
tv1.index = (tv1.index + 1) & TVR_MASK;
}
spin_unlock_irq(&timerlist_lock);
} |
函数run_timer_list()的执行过程主要就是用一个大while{}循环来为时钟中断执行定时器服务,每一次循环服务一次时钟
中断。因此一共要执行(jiffies-timer_jiffies+1)次循环。循环体所执行的服务步骤如下:
(1)首先,判断tv1.index是否为0,如果为0则需要从tv2中补充定时器到tv1中来。但tv2也可能为空而需要从tv3中补充
定时器,因此用一个do{}while循环来调用cascade_timer()函数来依次视需要从tv2中补充tv1,从tv3中补充tv2、…、
从tv5中补充tv4。显然如果tvi.index=0(2≤i≤5),则对于tvi执行cascade_timers()函数后,tvi.index肯定为1。
反过来讲,如果对tvi执行过cascade_timers()函数后tvi.index不等于1,那么可以肯定在未对tvi执行cascade_timers()函
数之前,tvi.index值肯定不为0,因此这时tvi不需要从tv(i+1)中补充定时器,这时就可以终止do{}while循环。
(2)接下来,就要执行定时器向量tv1.vec[tv1.index]中的所有到期定时器。因此这里用一个goto repeat循环从头到尾
依次扫描整个定时器对列。由于在执行定时器的关联函数时并不需要关CPU中断,所以在用detach_timer()函数把当前定时
器从对列中摘除后,就可以调用spin_unlock_irq()函数进行解锁和开中断,然后在执行完当前定时器的关联函数后重新用
spin_lock_irq()函数加锁和关中断。
(3)当执行完定时器向量tv1.vec[tv1.index]中的所有到期定时器后,tv1.vec[tv1.index]应该是个空队列。至此这一次
定时器服务也就宣告结束。
(4)最后,把timer_jiffies值加1,把tv1.index值加1,当然它的模是256。然后,回到while循环开始下一次定时器服务。
posted @ 2010-08-19 12:23 海王 阅读(2081) 评论(0)
编辑
http://blog.chinaunix.net/u/26710/showart_387765.html
0 前言
在Linux下驱动USB摄像头一直不是容易的事情,尽管其内核中就集成了对0V511系列摄像头的支持,开源驱动spca5xx/gspca也提供了对大部分主流摄像头的支持,但还是无法涵盖所有品牌的各种型号的摄像头,尤其是对于国内的中低端用户,很难找到直接可用的Linux下的驱动。
本文简单介绍了gspca驱动程序、spcagui和spcaview等测试程序的安装过程,并以在gspca中添加对Logitech QuickCam Easy/Cool(快看灵讯版)摄像头的支持为例,给出了在gspca驱动程序中添加新的摄像头支持的一般方法。
1 安装gspca驱动程序
gspca用于2.6.17以上的内核版本,以前的版本使用spca5xx驱动程序。gspca可直接支持的摄像头列表可见http://mxhaard.free.fr/spca5xx.html。
(1)安装内核头文件
#uname -r
2.6.20-1.2962.fc6
#arch
i686
#wget http://fedora.fastbull.org/updates/testing/6/i386/kernel-
devel-2.6.20-1.2962.fc6.i686.rpm
#rpm -ivh kernel-devel-2.6.20-1.2962.fc6.i686.rpm
这样,内核头文件被安装到/usr/src/kernels/2.6.20-1.2962.fc6-i686目录下。
(2)安装gspca驱动:
#wget http://mxhaard.free.fr/spca50x/Download/gspcav1-
20070508.tar.gz
#tar xfv gspcav1-20070508.tar.gz
#cd gspcav1-20070508
#./gspca_build
gspca_build是一个自动编译、安装、加载驱动模块的腳本。可以使用命令“depmod -ae”来检查内核模块的依赖关系是否冲突。
注意,安装好驱动并加载gspca.ko模块后,一般会有/dev/video和/dev/video0等设备文件的存在,否则可能是驱动程序对本机的摄像头的支持有问题。另外,要正常使用摄像头,内核中应有video for linux的支持(Fedora内核一般是默认支持)。
(3)安装spcagui、spcaview等摄像头测试程序
实际上,只要正确安装好驱动之后,就可以使用"应用程序->Internet->Kopete"或gnome-netmeeting等程序来测试摄像头是否能正常工作了。当然也可以使用spcagui、spcaview等专门的摄像头工具软件。
要安装spcagui或spcaview,必须先安装SDL、SDL-devel、SDL_image和SDL_image-devel软件包。然后直接make并make install即可。
2 gspca不能直接支持Logitech QuickCam Easy/Cool(快看灵讯版,046d:08af)
Logitech的摄像头有个“特点”,一个英文名有好几个中文名,例如快看灵讯版和快看酷讯版,包装盒上都写的是Logitech QuickCam Cool,由于在gspca的摄像头支持列表中看到了Logitech QuickCam Cool,于是买了个灵讯版。
首先在Windows上试验摄像头效果,插入USB口,显示设备为Logitech QuickCam Easy/Cool,就感觉情况不妙,一看Vendor ID:Product ID是046d:08af,果然不在gspca的摄像头支持列表内。不管怎么样,先到Fedora下试试再说。
#lsusb
Bus 002 Device 001: ID 0000:0000
Bus 002 Device 003: ID 046d:08af Logitech, Inc.
Bus 001 Device 001: ID 0000:0000
Bus 004 Device 001: ID 0000:0000
Bus 003 Device 001: ID 0000:0000
可见设备ID的确是046d:08af。加载gspca驱动模块后,运行spcagui或者spcaview,提示“No such file or directory.”
“ls /dev/video*”发现没有任何相应的设备文件,于是手动建立:
#mknod /dev/video0 c 81 0
#ln -s /dev/video0 /dev/video
之后再运行spcagui或者spcaview,提示“Device not found.”
在Google上搜了两个晚上,还是没能找到解决问题的办法。看来唯一能找到问题所在并加以解决的办法就是从gspca驱动程序的源代码入手了。
3 使gspca驱动程序支持Logitech QuickCam Easy/Cool
(1)gspca驱动程序结构简析
gspca驱动程序的核心代码是gspca_core.c,包括了设备注册、注销、各种操作方法集(定义了所支持的摄像头设备列表,设备检测和初始化,设备打开、参数设置、关闭等各种操作函数)。
gspca.h是一个核心头文件,它的主要内容有:
a)定义所支持的Vendor ID号,例如:
#define VENDOR_LOGITECH 0x046d
b)为所支持的DSP桥接控制芯片型号进行编号,例如:
#define BRIDGE_ZC3XX 12
c)为所支持的CMOS/CCD图像传感器型号进行编号,例如:
#define SENSOR_HV7131B 2
#define SENSOR_HDCS2020 9
#define SENSOR_HV7131C 12
#define SENSOR_HV7131R 15
#define SENSOR_PAS202 19
#define SENSOR_TAS5130C_VF0250 22
另外,它还定义了图像格式相关的常量和数据结构(如图像分辨率,色彩空间,调色板等),帧数据结构,摄像头操作方法集等。
Vimicro,Sonix,PixArt,Sunplus等文件夹中定义了各传感器相关的头文件。
decoder文件夹中包含了对各种图像格式进行编解码的源代码。
结论:要驱动一个摄像头,首先要知道它的DSP芯片和CMOS芯片型号。如果摄像头的Vendor ID,DSP芯片,image sensor不在其中,则要定义DSP和sensor芯片的相应头文件,并在gspca.h中添加相应的设备信息,还要把摄像头加入到gspca_core.c的摄像头设备列表中。
(2)与Logitech QuickCam Easy/Cool相近的摄像头信息列表
Camera Type
Product ID
Bridge DSP
Sensor
Comments(sensor in driver code)
QC IM
08a0
zc030x
HDCS2020
TAS5130C(08a0/a1/a3,08d9/da)
QC IM
08a6
zc030x
HV7131R
HV7131C (08a6/ad, 08d7)
NoteBook Deluxe
08a9
zc0302
HV7131B
HDCS2020 (08a2/a9/ae, 08d8)
QC Image
08a7
zc030x
PAS202
QC for Notebook
08ae
zc030x
PAS202
HDCS2020
QC Cool
08ac
zc030x
PAS202
HV7131B
Communicate STX
08ad
zc0302
TAS5130C
HV7131C
Communicate STX
08d7
vc0302/zc0302
TAS5130C
HV7131C
QC IM/Connect
08d9
zc030x
TAS5130C
QC Messenger
08da
zc030x
TAS5130C
NoteBook Deluxe
08d8
vc0302/zc0302
TAS5130C
QC Easy/Cool
08af
?(zc030x)
?
(HV7131C/HV7131B/TAS5130C/HDCS2020)
上面是Logitech摄像头产品中与Logitech QuickCam Easy/Cool相近的产品(从Product ID,摄像头英文名,产品价格等判断),摘自http://mxhaard.free.fr/spca5xx.html,其中最后一列的注释是gspca_core.c源文件中给相应型号摄像头定义的CMOS芯片型号,与网页上的列表并不完全一致,我们以驱动程序中定义的为准。
列出上面的表,主要是为了要推断出Logitech QuickCam Easy/Cool的DSP芯片型号和CMOS传感器型号。从上表可以发现,所有的摄像头都使用了zc030x(包括zc0302)作为DSP控制芯片,因此可以断定,Easy/Cool也使用了这一系列的DSP芯片,在驱动程序中用BRIDGE_ZC3XX表示。而CMOS芯片也无非是HV7131C/HV7131B/TAS5130C/HDCS2020中的一种,我们可以逐一试验。
(3)在gspca_core.c中添加Logitech QuickCam Easy/Cool相关信息
由于Logitech QuickCam Easy/Cool的Vendor、DSP型号、CMOS传感器型号在gspca.h中均有定义,也有相关的芯片头文件,因此,只需改动gspca_core.c,把Easy/Cool摄像头的信息加入到其中即可。
以下蓝色部分是添加的相关内容。
在gspca_core.c中有一个Camera型号列表,如下: enum {
UnknownCamera = 0, // 0
IntelPCCameraPro,
IntelCreateAndShare,
......
PhilipsDMVC1300K,
LogitechQC_EasyCool, // added by aaron
LastCamera
};
static struct cam_list clist[] = {
{UnknownCamera, "Unknown"},
{IntelPCCameraPro, "Intel PC Camera Pro"},
{IntelCreateAndShare, "Intel Create and Share"},
......
{PhilipsDMVC1300K,"Philips DMVC 1300K"},
{LogitechQC_EasyCool,"Logitech QuickCam Easy_Cool"}, //added by aaron
{-1, NULL}
};
static __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0733, 0x0430)}, /*Intel PC Camera Pro*/
{USB_DEVICE(0x0733, 0x0401)}, /* Intel Create and Share */
......
{USB_DEVICE(0x0471, 0x0322)}, /* Philips DMVC1300K */
{USB_DEVICE(0x046d, 0x08af)},
/* Logitech QuickCam Easy_Cool, added by aaron */
{USB_DEVICE(0x0000, 0x0000)}, /* MystFromOri Unknow Camera */
{} /* Terminating entry */
};
static int
gspca_attach_bridge(struct usb_spca50x *spca50x)
{
/* set the default epadr */
spca50x->epadr =1;
switch (spca50x->bridge) {
......
case BRIDGE_ZC3XX:
spca50x->cameratype = JPGH;
info("USB GSPCA camera found.(ZC3XX) ");
memcpy(&spca50x->funct, &fzc3xx, sizeof (struct cam_operation));
break;
...... //other DSP bridges
default:
return -ENODEV;
}
return 0;
}
检测摄像头型号: static int
spcaDetectCamera(struct usb_spca50x *spca50x)
{
struct usb_device *dev = spca50x->dev;
__u8 fw = 0;
__u16 vendor;
__u16 product;
/* Is it a recognised camera ? */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
vendor = le16_to_cpu(dev->descriptor.idVendor);
product = le16_to_cpu(dev->descriptor.idProduct);
#else
vendor = dev->descriptor.idVendor;
product = dev->descriptor.idProduct;
#endif
switch (vendor) {
case 0x046d: /* Logitech Labtec */
switch (product) {
case 0x08af: //added by aaron
spca50x->desc = LogitechQC_EasyCool;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HV7131B;
break;
......
case 0x08a0:
spca50x->desc = QCim;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_TAS5130CXX;
break;
case 0x08a1:
spca50x->desc = QCimA1;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_TAS5130CXX;
break;
case 0x08a2: // zc302 chips
spca50x->desc = LabtecPro;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HDCS2020;
break;
case 0x08a3:
spca50x->desc = QCchat;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_TAS5130CXX;
break;
case 0x08a6:
spca50x->desc = LogitechQCim;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HV7131C;
break;
case 0x08a7:
spca50x->desc = LogitechQCImage;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_PAS202;
break;
case 0x08d8:
case 0x08a9:
spca50x->desc = LogitechNotebookDeluxe;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HDCS2020;
break;
case 0x08ae:
spca50x->desc = QuickCamNB;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HDCS2020;
break;
case 0x08ac:
spca50x->desc = LogitechQCCool;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HV7131B;
break;
......
default:
goto error;
};
break;
...... //other vendors
return gspca_attach_bridge(spca50x);
error:
return -ENODEV; //no camera match
}
static int
spca5xx_probe(struct usb_interface *intf, const struct usb_device_id *id){
......
if ((err_probe = spcaDetectCamera(spca50x)) < 0) {
err(" Devices not found !! ");
goto error;
}
......
}
到此,我们对gspca驱动程序的扩展就算完成了。在函数spcaDetectCamera()中的switch结构中,将我们的摄像头放到第一个case,是为了在探测摄像头时第一个就找到我们的摄像头,提高检测速度。
需要指出两点,一是在函数spcaDetectCamera()中,我们假定Logitech QC Easy/Cool的CMOS传感器型号为SENSOR_HV7131B,这需要在后续的实验中进行验证;二是spca5xx_probe()函数中,红色代码部分,实际上调用了spcaDetectCamera()函数来探测摄像头,如果出错则报错" Devices not found !! "并退出,由于之前gspca中没有Easy/Cool摄像头的信息,因此,之前即使自己创建了/dev/video0等设备文件,还是会报错“找不到设备”。
(4)卸载旧的gspca驱动模块,安装新的gspca驱动模块 #rm -f /dev/video* //删除旧的自己创建的设备节点
#modprobe -rv gspca
#make uninstall
#make clean
#./gspca_build
#ls /dev/video*
lrwxrwxrwx 1 root root 6 09-22 21:44 /dev/video->video0
crw------- 1 aaronwong root 81, 0 09-22 21:42 /dev/video0
可见,这次在加载gspca驱动模块后,自动生成了设备文件/dev/video0和/dev/video。
(5)摄像头试用效果 $spcagui
SpcaGui version: 0.3.5 date: 18 September 2005
video device /dev/video0
Camera found: Logitech QuickCam Easy_Cool
VIDIOCGPICT brightnes=32768 hue=0 color=0 contrast=32768 whiteness=0depth=24 palette=4
Bridge found: ZC301-2
Unable to find a StreamId !!
StreamId: 6 Unknow Camera
try palette 15 depth 12
Available palette 15
try palette 3 depth 16
Available palette 3
try palette 4 depth 24
Available palette 4
try palette 5 depth 32
Available palette 5
probe size in
Available Resolutions width 640 heigth 480
Available Resolutions width 384 heigth 288
Available Resolutions width 352 heigth 288
Available Resolutions width 320 heigth 240
Available Resolutions width 192 heigth 144
Available Resolutions width 176 heigth 144
grabbing method default MMAP asked
VIDIOCGMBUF size 2457616 frames 2 offets[0]=0 offsets[1]=1228808
......
截图如下:
(6)修正CMOS芯片型号信息 #modprobe -v gspca
insmod /lib/modules/2.6.20-1.2962.fc6/kernel/drivers/media/video/v4l1-compat.ko
insmod /lib/modules/2.6.20-1.2962.fc6/kernel/drivers/media/video/v4l2-common.ko
insmod /lib/modules/2.6.20-1.2962.fc6/kernel/drivers/media/video/videodev.ko
insmod /lib/modules/2.6.20-1.2962.fc6/kernel/drivers/usb/media/gspca.ko
#dmesg | grep gspca
/home/aaronwong/webcam/driver/gspcav1-20070508/gspca_core.c: USB GSPCA camera found.(ZC3XX)
/home/aaronwong/webcam/driver/gspcav1-20070508/gspca_core.c: [spca5xx_probe:4109] Camera type JPEG
/home/aaronwong/webcam/driver/gspcav1-20070508/Vimicro/zc3xx.h: [zc3xx_config:515] Sensor ID:2
/home/aaronwong/webcam/driver/gspcav1-20070508/Vimicro/zc3xx.h: [zc3xx_config:597] Find Sensor HV7131R(c)
/home/aaronwong/webcam/driver/gspcav1-20070508/gspca_core.c: [spca5xx_getcapability:1218] maxw 640 maxh 480 minw 176 minh 144
usbcore: registered new interface driver gspca
/home/aaronwong/webcam/driver/gspcav1-20070508/gspca_core.c: gspca driver 01.00.18 registered
注意红色标出的部分,即使在驱动程序中指定QuickCam Easy/Cool摄像头的CMOS SENSOR类型为SENSOR_HV7131B(或者是SENSOR_HDCS2020等其他类型),在加载gspca.ko模块时,找到的还是HV7131R(c),因此,QuickCam Easy/Cool摄像头的CMOS SENSOR类型应该就是SENSOR_HV7131R或SENSOR_HV7131C。
在源程序gspca_core.c的spcaDetectCamera()函数的相应部分修改如下: case 0x08af: //added by aaron
spca50x->desc = LogitechQC_EasyCool;
spca50x->bridge = BRIDGE_ZC3XX;
spca50x->sensor = SENSOR_HV7131R;
//SENSOR_HV7131C;
break;
卸载gspca驱动模块,再重新编译安装gspca驱动即可。
由此也可知,在gspca摄像头驱动中最重要的是要正确识别DSP控制芯片的型号,而CMOS传感器的型号并不是必须的。所以,只要摄像头使用了gspca所支持的DSP控制芯片,就可以很容易地按照上面的方法,添加gspca对新的摄像头的支持。即使使用了别的DSP控制芯片,也可以利用gspca的程序架构,为新的DSP芯片添加头文件等信息,来扩展gspca对更多系列的USB摄像头的支持。
不管你的摄像头是ANC奥尼,还是环宇飞扬,或是恋影双双,如果你发现它的DSP芯片是gspca所支持的,不妨都来一试,相信你的摄像头也不会让你失望。
本文来自: (www.91linux.com) 详细出处参考:http://www.91linux.com/html/article/media/20090517/16857.html
posted @ 2010-08-19 01:08 海王 阅读(549) 评论(0)
编辑
http://weijb0606.blog.163.com/blog/static/131286274201062610734604/
USB Camera driver
其实 问题主要出在:山寨所产摄像头 其驱动不易获得 等所致
解决步骤:
1. 取得摄像头型号 主要是硬件ID 的获取
通过硬件ID精确找到你要的驱动或寻求帮助。
什么是硬件ID呢?
硬件ID是电脑所有硬件的一个编号,所有设备都有如下编号:VEN_1106&DEV_3038,VEN代表硬件厂商,DEV代表产品编号。 USB设备会有如下编号:VID_045E&PID_0039,道理跟上面的是一样的。所有的测试软件都有可能会出错,只有硬件ID是最可靠的,各位只要确认下INF文件包含需要的硬件ID,就保证是可以用的。具体到摄像头,我们需要知道VID和PID。VID/PID是全球USB组织统一分配的代码,VID是代表厂家,PID 是代表产品型号,任何一个USB设备生产商必须注册此两个号码,且注册后不能修改,因此该代码可以作为判断的依据。
如何获得摄像头硬件ID?
方法1:
最简单的方法是直接在设备管理器中查看。右键“我的电脑”---管理----“设备管理器”---“图像处理设备”选择任意一个摄像头设备双击,在“详细信息”一栏即可看到下面这个信息:
上面的那段代码表示的意思是:
其中VID_0C45代表松瀚,PID_62C0代表芯片288
方法2:
使用USBVIEW软件查询
下载地址:http://tools.mydrivers.com/soft/287.htm
下面是目前主流摄像头芯片厂家的代码,仅供参考:
VID(厂家代号)
PID(芯片代号)
厂家与芯片型号
VID_0C45
PID_62C0
台湾松瀚288,其中288与288P是同一个代号
USB2.0免驱
VID_0AC8
PID_303B
中星微301H,即303, USB1.1,需要安装驱动
VID_0AC8
PID_3340
中星微334,USB2.0免驱
VID_1781
PID_0306
台湾嘉映308H USB2.0免驱
附VID、PID查询网站
http://www.linux-usb.org/usb.ids
获取VID、PID后,据此下载驱动,然后打开驱动的INF文件,可以找到里面对应设备管理器的硬件ID即可判断驱动是否正确。
以最常见的摄像头为例,由于摄像头厂家众多,驱动非常混乱,各个网站也出现所谓的万能,这个世界有万能的东西吗?让我们相信硬件ID吧,集中市面的硬件ID,因为摄像头的芯片厂家就那么几家,这样就可以让大家可以很方便找到自己所有需要的驱动。
下面列举常见摄像头的VID、PID及对应的解决方案,驱动下载地址
最常见的摄像头硬件ID:VID_0AC8&PID_0302
VID_0AC8是中芯微的代码,
常见方案如下:
USB\VID_0AC8&PID_303B 301PLH方案 下载地址:
http://drivers.mydrivers.com/search/902-1418-h17139/
USB\VID_0AC8&PID_301B 301B方案 下载地址:
http://drivers.mydrivers.com/drivers/204-81603-VIMICRO-ZC0301PL-301.4.328.07-Win2000-XP-XP-64-Vista-Vista-64/
USB\VID_0AC8&PID_305B 305B方案 http://drivers.mydrivers.com/search/902-1418-h19124/
USB\VID_0AC8&PID_307B ZS211方案 http://drivers.mydrivers.com/search/902-1418-h28374/
USB\VID_0ac8&PID_0321 VC0321 http://drivers.mydrivers.com/search/902-1418-h24807/
USB\VID_0ac8&PID_0323 VC0323 http://drivers.mydrivers.com/search/902-1418-h24805/
USB\VID_0ac8&PID_0323 ZC0323P http://drivers.mydrivers.com/search/902-1418-h29222/
USB\VID_0ac8&PID_0328 ZC0326
USB\VID_0ac8&PID_0326 ZC0326 下载地址:
http://drivers.mydrivers.com/drivers/260-104356-VIMICRO-VC0326-For-Win98SE-ME-2000-XP/
看到很多朋友找无驱的摄像头驱动,更新一个中星微出的方案
下载地址:
http://drivers.mydrivers.com/search/902-1418-h29045/
支持下列硬件ID:
USB\VID_0ac8&PID_3313
USB\VID_0ac8&PID_0331
USB\VID_0ac8&PID_331B
USB\VID_0ac8&PID_0332
USB\VID_0ac8&PID_332D
USB\VID_0ac8&PID_3330
USB\VID_0ac8&PID_3332
USB\VID_0ac8&PID_3333
USB\VID_0ac8&PID_3340
USB\VID_0ac8&PID_3342
USB\VID_0ac8&PID_3343
USB\VID_0ac8&PID_0336
USB\VID_0ac8&PID_336D
USB\VID_0ac8&PID_3410
USB\VID_0ac8&PID_3420
USB\VID_0ac8&PID_3430
USB\VID_0ac8&PID_3440
USB\VID_0ac8&PID_3000
VID_0C45是台湾松翰电子Sonix出的。
【更新几个比较少见的OEM松瀚方案】下载地址:
USB\VID_0c46&PID_605a
http://drivers.mydrivers.com/drivers/259-103869-SONiX-SN9C102P-105-110-120-4.31.3.10-For-Win2000-XP/
USB\VID_0c45&PID_8008 下载地址:
http://drivers.mydrivers.com/drivers/259-103870-SONiX-SN9C202-2.18.1.0-For-Win2000-XP/
USB\VID_0C45&PID_600D 下载地址:
http://drivers.mydrivers.com/drivers/205-82011-Chicony-DC-2110(TwinkleCam)-1.0-For-Win98SE-ME-2000-XP/
【SN9C101方案 】 下载地址:http://drivers.mydrivers.com/drivers/204-81784-SONiX-SN9C101-SN9C102-4.20.1.001-For-Win98SE-ME-2000-XP/
USB\VID_0c45&PID_603f ; SN9C101 + CISVF10
USB\VID_0c45&PID_602a ; SN9C101 + HV7131 D/E
USB\VID_0c45&PID_602d ; SN9C101 + HV7131 R
USB\VID_0c45&PID_6009 ; SN9C101 + PAS106
USB\VID_0c45&PID_6005 ; SN9C101 + TAS5110
USB\VID_0c45&PID_6019 ; SN9C101 + OV7630
USB\VID_0c45&PID_6011 ; SN9C101 + OV6650
USB\VID_0c45&PID_6007 ; SN9C101 + TAS5110D
【SN9C102方案 】 下载地址:http://drivers.mydrivers.com/drivers/204-81784-SONiX-SN9C101-SN9C102-4.20.1.001-For-Win98SE-ME-2000-XP/
USB\VID_0c45&PID_602c ; SN9C102 + OV7630
USB\VID_0c45&PID_6030 ; SN9C102 + MI0343 MI0360 MI0330
USB\VID_0c45&PID_6024 ; SN9C102 + TAS5130
USB\VID_0c45&PID_6025 ; SN9C102 + TAS5130
USB\VID_0c45&PID_6028 ; SN9C102 + PAS202
USB\VID_0c45&PID_6029 ; SN9C102 + PAS106
【SN9C102P方案】 下载地址:http://drivers.mydrivers.com/search/902-1303-h24842/
USB\VID_0c45&PID_6040 ; SN9C102P + MI0360
USB\VID_0c45&PID_607a ; SN9C102P + OV7648
USB\VID_0c45&PID_607c ; SN9C102P + HV7131R
USB\VID_0c45&PID_607e ; SN9C102P + OV7630
USB\VID_0c45&PID_607b ; SN9C102P + OV7660
【SN9C103方案】 下载地址:http://drivers.mydrivers.com/search/902-1303-h24843/
USB\VID_0c45&PID_608e ;CISVF10
USB\VID_0c45&PID_6083 ;HY7131D/E
USB\VID_0c45&PID_608c ;HY7131/R
USB\VID_0c45&PID_608f ;OV7630
USB\VID_0c45&PID_60af ;PAS202
USB\VID_0c45&PID_60a8 ;PAS106
USB\VID_0c45&PID_6082 ;MI0343,MI0360
USB\VID_0c45&PID_60aa ;TAS5130
USB\VID_0c45&PID_6025 ;TAS5130
【SN9C105方案】 下载地址:http://drivers.mydrivers.com/search/902-1303-h24842/
USB\VID_0c45&PID_60c0&MI_00 ; SN9C105 + MI0360
USB\VID_0c45&PID_60fa&MI_00 ; SN9C105 + OV7648
USB\VID_0c45&PID_60fc&MI_00 ; SN9C105 + HV7131R
USB\VID_0c45&PID_60fe&MI_00 ; SN9C105 + OV7630
USB\VID_0c45&PID_60fb&MI_00 ; SN9C105 + OV7660
USB\VID_0c45&PID_60f2&MI_00 ; SN9C105 + OV7670
USB\VID_0c45&PID_60ef&MI_00 ; SN9C105 + ICM105C
USB\VID_0c45&PID_60cc&MI_00 ; SN9C105 + HV7131GP
USB\VID_0c45&PID_60ec&MI_00 ; SN9C105 + MO4000
USB\VID_0c45&PID_60c8&MI_00 ; SN9C105 + OM6802
USB\VID_0c45&PID_60c2&MI_00 ; SN9C105 + P1030xC
USB\VID_0c45&PID_60ce&MI_00 ; SN9C105 + SP80708
【SN9C110方案】 下载地址:http://drivers.mydrivers.com/search/902-1303-h24842/
USB\VID_0c45&PID_612e ; SN9C110 + OV7630
USB\VID_0c45&PID_612f ; SN9C110 + ICM105C
USB\VID_0c45&PID_6122 ; SN9C110 + ICM105C
USB\VID_0c45&PID_612a ; SN9C110 + OV7648
USB\VID_0c45&PID_6123 ; SN9C110 + SanyoCCD
USB\VID_0c45&PID_612c ; SN9C110 + MO4000
【SN9C120方案】 下载地址:http://drivers.mydrivers.com/search/902-1303-h24842/
USB\VID_0c45&PID_6130 ; 120+MI0360/MT9V111/MI0360B
USB\VID_0c45&PID_613a ; SN9C120 + OV7648
USB\VID_0c45&PID_613c ; SN9C120 + HV7131R
USB\VID_0c45&PID_613e ; SN9C120 + OV7630
USB\VID_0c45&PID_6132 ; SN9C120 /SN9C120B+ OV7670
USB\VID_0c45&PID_613b ; SN9C120 + OV7660
USB\VID_0c45&PID_6138 ; SN9C120 + MO4000
USB\VID_0c45&PID_6108 ; SN9C120 + OM6802
USB\VID_0c45&PID_6148 ; SN9C120B + OM6802
USB\VID_0c45&PID_6102 ; SN9C120 + PO2030N/GC0305
USB\VID_0c45&PID_6142 ; SN9C120B + PO2030N/GC0305
USB\VID_0c45&PID_6143 ; SN9C120B + SP80708
USB\VID_0c45&PID_614c ; SN9C120B + GC0306
【SN9C128方案】 下载地址:http://drivers.mydrivers.com/search/902-1303-h21430/
USB\VID_0c45&PID_6100 ; MI0360 / MT9V111 / MI0360B
USB\VID_0c45&PID_610a ; OV7648
USB\VID_0c45&PID_610c ; HV7131R
USB\VID_0c45&PID_610e ; OV7630
USB\VID_0c45&PID_610b ; OV7660
【SN9C201方案 】 下载地址:http://drivers.mydrivers.com/search/902-1303-h21429/
USB\VID_0c45&PID_6240 ; SN9C201 + MI1300
USB\VID_0c45&PID_6242 ; SN9C201 + MI1310
USB\VID_0c45&PID_624e ; SN9C201 + SOI968
USB\VID_0c45&PID_624f ; SN9C201 + OV9650
USB\VID_0c45&PID_6243 ; SN9C201 + S5K4AAFX
USB\VID_0c45&PID_624b ; SN9C201 + CX1332
USB\VID_0c45&PID_627f ; EEPROM
USB\VID_0c45&PID_6248 ; SN9C201 + OV9655
USB\VID_0c45&PID_624c ; SN9C201 + MI1320
USB\VID_0c45&PID_6270 ; SN9C201 + MI0360\MT9V111
USB\VID_0c45&PID_627c ; SN9C201 + HV7131R
USB\VID_0c45&PID_627b ; SN9C201 + OV7660
USB\VID_0c45&PID_627a ; SN9C201 + S5K53BEB
USB\VID_0c45&PID_6260 ; SN9C201 + OV7670ISP
USB\VID_0c45&PID_6262 ; SN9C201 + OM6802
【SN9C202方案 】 下载地址:http://drivers.mydrivers.com/search/902-1303-h21429/
USB\VID_0c45&PID_6280&MI_00 ; SN9C202 + MI1300
USB\VID_0c45&PID_6282&MI_00 ; SN9C202 + MI1310
USB\VID_0c45&PID_628e&MI_00 ; SN9C202 + SOI968
USB\VID_0c45&PID_628f&MI_00 ; SN9C202 + OV9650
USB\VID_0c45&PID_6288&MI_00 ; SN9C202 + OV9655
USB\VID_0c45&PID_628a&MI_00 ; SN9C202 + ICM107
USB\VID_0c45&PID_628c&MI_00 ; SN9C202 + MI1320
USB\VID_0c45&PID_62b0&MI_00 ; SN9C202 + MI0360\MT9V111
USB\VID_0c45&PID_62bc&MI_00 ; SN9C202 + HV7131R
USB\VID_0c45&PID_62bb&MI_00 ; SN9C202 + Ov7660
USB\VID_0c45&PID_62ba&MI_00 ; SN9C202 + S5K53BEB
USB\VID_0c45&PID_628b&MI_00 ; SN9C202 + CX1332
USB\VID_0c45&PID_6283&MI_00 ; SN9C202 + S5K4AAFX
USB\VID_0c45&PID_62a0&MI_00 ; SN9C202 + Ov7670ISP
USB\VID_0c45&PID_62a2&MI_00 ; SN9C202 + OM6802
【SN9C255方案】 下载地址:http://drivers.mydrivers.com/search/902-1303-h24844/
USB\VID_0C45&PID_62C0
USB\VID_0C45&PID_62C1
USB\VID_0C45&PID_62E0
【SN9C325方案】 下载地址:http://drivers.mydrivers.com/search/902-1303-h24846/
USB\VID_0c45&PID_612a ; SN9C325 + OV7648 + POx1030xC + SOI768 + PO2030N + OV7660 + OV7670 + HV7131R
USB\VID_0c45&PID_6128 ; SN9C325 + OM6802
应论坛上的朋友提醒,增加一个松瀚电子出的免驱摄像头方案。
【松瀚SNP2UVC】 下载地址:http://drivers.mydrivers.com/search/902-1303-h29223/
USB\VID_0C45&PID_62C0 ;SN9C211/213/230
USB\VID_0C45&PID_6300 ;SN9C216/236
USB\VID_0C45&PID_6310 ;SN9C230C
USB\VID_0C45&PID_62E1 ;SN9C255 non-audio
USB\VID_0C45&PID_62F0 ;SN9C210/233
USB\VID_0C45&PID_62C1 ;SN9C212
USB\VID_0C45&PID_62E0 ;SN9C255
USB\VID_0C45&PID_6301 ;SN9C226
USB\VID_0C45&PID_62F1 ;SN9C253
VID_05A9 OmniVision
USB\VID_05A9&PID_A518 http://drivers.mydrivers.com/drivers/259-103879-OmniVision-OV518-2.1.0.0-For-Win2000-XP/
USB\VID_05A9&PID_A511 http://drivers.mydrivers.com/drivers/259-103878-OmniVision-OV511-2.1.11.28-For-Win2000-XP/
USB\VID_05A9&PID_4519 http://drivers.mydrivers.com/drivers/259-103877-OmniVision-OV530-2.1.0.1-For-Win2000-XP/
USB\VID_05a9&PID_0519 http://drivers.mydrivers.com/drivers/259-103877-OmniVision-OV530-2.1.0.1-For-Win2000-XP/
USB\VID_05a9&PID_0531 http://drivers.mydrivers.com/drivers/259-103876-OmniVision-OV534-2.1.0.1-For-Win2000-XP/
USB\VID_05a9&PID_0550 http://drivers.mydrivers.com/drivers/259-103875-OmniVision-OV550-2.1.0.1-For-Win2000-XP/
USB\VID_05a9&PID_2800 http://drivers.mydrivers.com/drivers/259-103874-OmniVision-2800lus-2.1.0.1-For-Win2000-XP/
VID_1B17 CNLTF
CNLTF A380摄像头方案 下载地址:http://drivers.mydrivers.com/drivers/259-103880-CNLTF-A380-1.2.51.0928-For-Win2000-XP-XP-64-Vista-Vista-64/
硬件ID:
USB\VID_1B17&PID_6100
USB\VID_1B17&PID_6101
USB\VID_1B17&PID_6110
USB\VID_1B17&PID_6111
VID_1871 Aveo 嘉映微电子有限公司
388摄像头方案 下载地址:http://drivers.mydrivers.com/drivers/259-103881-Aveo-388-For-Win2000-XP-XP-64-Vista-Vista-64/
硬件ID:
USB\VID_1871&PID_0306
USB\VID_1871&PID_01f0
USB\VID_1871&PID_56CC
VID_093A 台湾原相科技。
USB\VID_093A&PID_2468
USB\VID_093A&PID_2460
下载地址:http://drivers.mydrivers.com/search/902-1580-h24847/
【原相PAP7501方案】
USB\VID_093A&PID_2700
USB\VID_093A&PID_2800
USB\VID_093A&PID_2801
下载地址:http://drivers.mydrivers.com/search/902-1580-h29232/
VID_093A 原相 PAC7302
USB\VID_093A&PID_2620
USB\VID_093A&PID_2628
下载地址:http://drivers.mydrivers.com/search/902-1580-h25427/
USB\VID_093a&PID_010e
下载地址:
http://drivers.mydrivers.com/drivers/260-104357-PixArt-MR97310-For-Win98SE-ME-2000-XP/
SiGma Micro
SG310方案 http://drivers.mydrivers.com/drivers/259-103884-SIGMA-MICRO-SG310-1.0.0.0-For-Win2000-XP/
USB\VID_1C4F&PID_3000
USB\VID_0F35&PID_FAF5
VID_EB1A 台湾和瑞亚(empia)
USB\VID_EB1A&PID_2710
USB\VID_EB1A&PID_2711
USB\VID_EB1A&PID_2750
USB\VID_EB1A&PID_2751
USB\VID_EB1A&PID_2870
下载地址:
http://drivers.mydrivers.com/search/902-1579-h24833/
eMPIA EM27xx和EM28xx/EM29xx方案摄像头
USB\VID_EB1A&PID_2800
USB\VID_EB1A&PID_2801
USB\VID_EB1A&PID_2820
USB\VID_EB1A&PID_2821
USB\VID_EB1A&PID_2840
USB\VID_EB1A&PID_2841
USB\VID_EB1A&PID_2860
USB\VID_EB1A&PID_2861
USB\VID_EB1A&PID_2870
USB\VID_EB1A&PID_2880
USB\VID_EB1A&PID_2881
USB\VID_EB1A&PID_2710
USB\VID_EB1A&PID_2711
USB\VID_EB1A&PID_2750
USB\VID_EB1A&PID_2751
USB\VID_EB1A&PID_2761
USB\VID_EB1A&PID_2766
USB\VID_EB1A&PID_2901
下载地址:
http://drivers.mydrivers.com/drivers/259-103885-GENESYS-GL860-1.0.11.20-For-Win2000-XP/
VID_05E3 台湾创惟GenesysLogic
USB\VID_05E3&PID_0503
USB\VID_05E3&PID_F191
下载地址:
http://drivers.mydrivers.com/search/902-1632-h29234/
VID_0402 台湾扬智Ali
USB\VID_0402&PID_5602
下载地址:
http://drivers.mydrivers.com/search/902-75-h29235/
VID_06A2 台湾凌越 Topro
USB\VID_06A2&PID_0003
下载地址:
http://drivers.mydrivers.com/search/902-1583-h24884/
PS:凌越 TP6800方案的摄像头有四种芯片组合,4种芯片组合分别是:TP6800+HY7131R;TP6800+MT9V011;TP6800+PAS302;TP6800+EVS350。大家可以测试下驱动那个效果会比较好。
有朋友反映凌越的TP6800方案有些摄像头不能正常工作。再次更新一个凌越TP6801的方案,硬件ID一样也有可能是TP6801的方案。
TP6801方案
USB\VID_06A2&PID_0001
USB\VID_06A2&PID_0003
USB\VID_06A2&PID_6810
下载地址:
http://drivers.mydrivers.com/search/902-1583-h29236/
【爱普泰克网易拍方案】
VID_0553 意法半导体 STMicroelectronics
USB\VID_0553&PID_0200
USB\VID_0553&PID_0201
USB\VID_0553&PID_0202
下载地址:
http://drivers.mydrivers.com/drivers/259-103888-STMicroelectronics-STV680-2.00.0.3-For-Win2000-XP/
早期在国内的爱普泰克网易拍采用过的意法半导体STV0680的芯片方案。
爱普泰克DV5900
USB\VID_08CA&PID_2024
http://drivers.mydrivers.com/search/902-1549-h29240/
芯片实际是凌阳CA536A
台湾凌阳科技Sunplus【代码:VID_04FC】给爱普泰克提供的摄像头方案,采用CA533A方案。
USB\VID_08CA&PID_2010
USB\VID_08CA&PID_2012
USB\VID_08CA&PID_2020
USB\VID_08CA&PID_2022
下载地址:
http://drivers.mydrivers.com/search/902-1549-h29238/
VID_04FC 台湾凌阳科技Sunplus
【凌阳CA533A方案】
USB\VID_03F0&PID_6902
USB\VID_052B&PID_1708
下载地址:
http://drivers.mydrivers.com/search/902-1549-h29238/
【凌阳CA504A方案】
USB\VID_04FC&PID_504A
下载地址:
http://drivers.mydrivers.com/search/902-1549-h29239/
【凌阳CA536A方案】
USB\VID_04FC&PID_5360
下载地址:
http://drivers.mydrivers.com/search/902-1549-h29240/
【凌阳SPCA561方案】
USB\VID_04fc&PID_0561
下载地址:
http://drivers.mydrivers.com/search/902-1549-h21431/
【凌阳Ca522B方案】
USB\VID_04FC&PID_2000
下载地址:
http://drivers.mydrivers.com/search/902-1549-h29241/
【凌阳CA2001方案】
USB\VID_04FC&PID_2001
下载地址:
http://drivers.mydrivers.com/search/902-1549-h29242/
VID_05e1 台湾太欣半导体 Syntek
【Syntek STK013方案】
USB\VID_05e1&PID_0892
下载地址:
http://drivers.mydrivers.com/drivers/259-103942-Syntek-STK013-1.68.88.03-For-Win2000-XP/
【Syntek STK014方案】
USB\VID_05e1&PID_0893
下载地址:
http://drivers.mydrivers.com/drivers/259-103943-Syntek-STK014-For-Win2000-XP/
【Syntek STK016方案】
USB\VID_05e1&PID_0895
下载地址:
http://drivers.mydrivers.com/drivers/259-103944-Syntek-STK016-For-Win2000-XP/
VID_2770 台湾倚强科技
【SQ9120芯片】
USB\VID_2770&PID_9130
USB\VID_2770&PID_9120
下载地址:
http://drivers.mydrivers.com/drivers/259-103945-SQ-SQ9120-For-Win2000-XP/
【SQ930b芯片】
USB\VID_2770&PID_930B
USB\VID_2770&PID_930C
USB\VID_041E&PID_4038
USB\VID_0471&PID_0329
USB\VID_04F2&PID_A120
USB\VID_04F2&PID_A121
USB\VID_04F2&PID_A122
USB\VID_04F2&PID_A123
USB\VID_04F2&PID_A124
下载地址:
http://drivers.mydrivers.com/drivers/259-103946-SQ-SQ930b-For-Win2000-XP/
USB\VID_2770&PID_9060 倚强SQ9060方案..
下载地址:
http://drivers.mydrivers.com/drivers/260-104358-SQ-SQ9060-For-Win2000-XP/
VID_0595 卓然Zoran公司
USB\VID_0595&PID_4343
下载地址:
http://drivers.mydrivers.com/drivers/259-103947-Zoran-Coach-Digital-Camera-For-Win2000-XP/
【视乐奇摄手星MX-500】
USB\VID_052B&PID_6A02
下载地址:
http://drivers.mydrivers.com/drivers/259-103948--MX-500-4.55.0.0-For-Win2000-XP/
VID_0DDA 台湾矽成积体电路
USB\VID_0DDA&PID_3011
下载地址:
http://drivers.mydrivers.com/drivers/259-103949-ISSI-5.0.1868.1-For-Win2000-XP/
【ICM532A方案】 来自台湾ICM
USB\VID_8751&PID_010F
USB\VID_0923&PID_010F
下载地址:http://drivers.mydrivers.com/drivers/259-103950-ICM-ICM532A-1.2.0.0-For-Win2000-XP/
UPDATA 08/10/21
VID_090C 来自台湾慧荣科技Silicon Motion
USB\VID_090C&PID_B370
USB\VID_090C&PID_B371
下载地址:http://drivers.mydrivers.com/drivers/259-103951-Silicon-Motion-SM370-5.3.5.0-For-Win2000-XP/
VID_058F 来自台湾安国科技
USB\VID_058F&PID_3820
下载地址:http://drivers.mydrivers.com/drivers/259-103952-ONKOK-cam3820-For-Win2000-XP/
VID_102C 来自台湾Etoms
USB\VID_102C&PID_6151
下载地址:http://drivers.mydrivers.com/drivers/259-103953-Etoms-ET151-For-Win2000-XP/
USB\VID_102C&PID_6251 非常常见的IBM Q-CAM摄像头
下载地址:http://drivers.mydrivers.com/drivers/259-103954-Etoms-ET251-For-Win2000-XP/
VID_0733 来自ViewQuest
有出过不少的方案
【VC5100Z】
USB\VID_0733&PID_5100
下载地址:http://drivers.mydrivers.com/drivers/259-103955-ViewQuest-VC5100Z-For-Win2000-XP/
【VC6100Z】
USB\VID_0733&PID_6100
下载地址:http://drivers.mydrivers.com/drivers/259-103956-ViewQuest-VC6100Z-For-Win2000-XP/
【VQ5300Z】
USB\VID_0733&PID_5300
下载地址:http://drivers.mydrivers.com/drivers/259-103957-ViewQuest-VQ5300Z-For-Win2000-XP/
【VQ2210】
USB\VID_0733&PID_2211
下载地址:http://drivers.mydrivers.com/drivers/259-103958-ViewQuest-VQ2210-For-Win2000-XP/
posted @ 2010-08-19 01:00 海王 阅读(356) 评论(0)
编辑
http://weijb0606.blog.163.com/blog/static/131286274201063145521107/
Kernel version :2.6.22.6
Crosstool :arm-linux-gcc-3.4.5
Board :FS2410
System :Fedora 8
Source :gspcav1-20071224、servfox-R1_1_3、spcaview-20061208
Author :http://viviwei.cublog.cn
一、移植gspcav1-20071224
gspcav1-20071224下载地址:http://www.slackware.com/~alien/slackbuilds/gspcav1/build/gspcav1-20071224.tar.gz
FS2410开发板上移植的是Linux-2.6.22.6内核,USB及CS8900A均能工作,由于linux-2.6.22.6/drivers/usb 目录下没有 media 目录,故移植步骤如下:
a) 在 linux-2.6.22.6/drivers/usb 目录下新建 media 目录,将gspcav1-20071224.tar.gz copy 到 media 下并解压。为了使media 编译进内核,需修改linux-2.6.22.6/drivers/usb 目录下的Kconfig、Makefile 文件。
[linux@weijing usb]$ pwd
/work/kernel/linux-2.6.22.6/drivers/usb
[linux@weijing usb]$ vi Kconfig
添加
source "drivers/usb/media/Kconfig"
[linux@weijing usb]$ vi Makefile
添加
obj-$(CONFIG_USB_SPCA5XX) += media/
b) 为添加 gspcav1-20071224 编译选项,在 media 下新建 Kconfig、Makefile 文件。
[linux@weijing media]$ pwd
/work/kernel/linux-2.6.22.6/drivers/usb/media
[linux@weijing media]$ vi Kconfig
#
# USB Multimedia device configuration
#
comment "USB Multimedia devices"
depends on USB
config USB_SPCA5XX
tristate "USB SPCA5XX Sunplus/Vimicro/Sonix jpeg Cameras"
depends on USB && VIDEO_DEV
---help---
Say Y or M here if you want to use one of these webcams:
The built-in microphone is enabled by selecting USB Audio support.
This driver uses the Video For Linux API. You must say Y or M to
"Video For Linux" (under Character Devices) to use this driver.
Information on this API and pointers to "v4l" programs may be found
at <Documentation/video4linux/API.html>.
To compile this driver as a module, choose M here: the
module will be called spca5xx.
[linux@weijing media]$ vi Makefile
#
# Makefile for USB Media drivers
#
obj-$(CONFIG_USB_SPCA5XX) += gspcav1-20071224/
c) 修改 gspcav1-20071224 的 Makefile
[linux@weijing gspcav1-20071224]$ pwd
/work/kernel/linux-2.6.22.6/drivers/usb/media/gspcav1-20071224
[linux@weijing gspcav1-20071224]$ vi Makefile
gspca-objs := gspca_core.o decoder/gspcadecoder.o
obj-$(CONFIG_USB_SPCA5XX) += gspca.o
clean:
rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c
rm -rf .tmp_versions
d) 编译内核
(1)Multimedia devices --->
Video For Linux
(2) USB support --->
Support for Host-side USB
--- USB Host Controller Drivers
OHCI HCD support
(3)--- USB Multimedia devices
USB SPCA5XX Sunplus/Vimicro/Sonix jpeg Cameras
此时,可能会提示 gspca_core.c 的一些轻微错误,稍作修改即可:
//static const char gspca_version[] = GSPCA_VERSION;
static const char gspca_version[] = "00.60.00";
把新生成的 uImage 烧进开发板,重启,插上中星微芯片的摄像头,命令行出现
# usb 1-1: new full speed USB device using s3c2410-ohci and address 2
usb 1-1: configuration #1 chosen from 1 choice
drivers/usb/media/gspcav1-20071224/gspca_core.c: USB GSPCA camera found.(ZC3XX)
说明移植的驱动已经能识别设备,设备名所在路径 /dev/video0。
二、servfox
服务器端程序用是servfox,通过它可以在PC上看到开发板采集来的图像,从这里下载
http://mxhaard.free.fr/spca50x/embedded/Servfox/servfox-R1_1_3.tar.gz
下载,解压,进入其目录,发现没有一个makefile.arm,还有一个makefile.386,将makefile.arm改名为makefile,然后输入命令 make,生成 servfox 可实行文件,copy 到开发板运行之:
# ./servfox -d /dev/video0 -g -s 640x480 -w 7070
servfox version: 1.1.3 date: 11:12:2005 (C) mxhaard@magic.fr
wrong spca5xx device
Waiting .... for connection. CTrl_c to stop !!!!
Got connection from 192.168.1.2
三、spcaview
客户端程序使用的是spcaview,下载地址为:
http://mxhaard.free.fr/spca50x/Download/spcaview-20061208.tar.gz
这个程序在PC 上运行,直接解压编译,生成 spcaview 可实行文件,运行如下:
[root@weijing spcaview-20061208]# ./spcaview -g -w 192.168.1.17
Spcaview version: 1.1.7 date: 06:11:2006 (C) mxhaard@magic.fr
ERROR Set default port to 7070
using Server 192.168.1.17 Port 7070
bright 32768 contrast 32768
附件2是在 Fedora 8 下看到的图像。
参考:http://blog.chinaunix.net/u/26710/showart_387765.html
http://blog.chinaunix.net/u/31/showart_692727.html
posted @ 2010-08-19 00:56 海王 阅读(228) 评论(0)
编辑
http://weijb0606.blog.163.com/blog/static/131286274201063145356429/
我的摄像头终于出现图像了!
李迟按:本文章不是教程,不是心得总结,而是记录我在做毕业设计过程中遇到的一些问题,以及怎么去解决
(有些还是没有解决)。可能带有牢骚,可能带有某些让人不悦的话。希望大家见谅。
今晚很高兴,捣鼓了几天,郁闷了几天的事,今天解决了一些了。起码我能在linux下看到摄像头的图像了。
提起USB摄像在linux下的使用,无论是百度还是Google,出现的多数是法国人写的一个通用驱动程序,即spca5xx,
我也是找了很久才找到,——因为在网上看到的那个网站已经不能登陆了,就是说不再维护了(这个后来再作说明),所以
找了很久。可惜不能用。因为我make都不通过,出现的错误如下:
make -C /lib/modules/`uname -r`/build SUBDIRS=/usr/local/gspcav1-20071224 CC=cc modules
make[1]: Entering directory `/usr/src/linux-2.6.30.2'
CC [M] /usr/local/gspcav1-20071224/gspca_core.o
/usr/local/gspcav1-20071224/gspca_core.c:54:27: error: asm/semaphore.h: No such file or directory
In file included from /usr/local/gspcav1-20071224/gspca_core.c:845:
/usr/local/gspcav1-20071224/utils/spcausb.h: In function ‘spca5xxRegRead’:
/usr/local/gspcav1-20071224/utils/spcausb.h:95: error: implicit declaration of function ‘info’
/usr/local/gspcav1-20071224/utils/spcausb.h: In function ‘spca_set_interface’:
/usr/local/gspcav1-20071224/utils/spcausb.h:278: error: implicit declaration of function ‘warn’
In file included from /usr/local/gspcav1-20071224/gspca_core.c:853:
/usr/local/gspcav1-20071224/Sunplus-jpeg/sp5xxfw2.h: In function ‘sp5xxfw2_init’:
/usr/local/gspcav1-20071224/Sunplus-jpeg/sp5xxfw2.h:122: error: called object ‘info’ is not a function
/usr/local/gspcav1-20071224/Sunplus-jpeg/sp5xxfw2.h:136: error: called object ‘info’ is not a function
/usr/local/gspcav1-20071224/Sunplus-jpeg/sp5xxfw2.h:141: error: called object ‘info’ is not a function
/usr/local/gspcav1-20071224/Sunplus-jpeg/sp5xxfw2.h:148: error: called object ‘info’ is not a function
/usr/local/gspcav1-20071224/Sunplus-jpeg/sp5xxfw2.h:176: error: called object ‘info’ is not a function
/usr/local/gspcav1-20071224/Sunplus-jpeg/sp5xxfw2.h: In function ‘sp5xxfw2_start’:
/usr/local/gspcav1-20071224/Sunplus-jpeg/sp5xxfw2.h:214: error: called object ‘info’ is not a function
/usr/local/gspcav1-20071224/Sunplus-jpeg/sp5xxfw2.h:230: error: called object ‘info’ is not a function
/usr/local/gspcav1-20071224/gspca_core.c: In function ‘spca5xx_ioctl’:
/usr/local/gspcav1-20071224/gspca_core.c:2463: error: implicit declaration of function ‘video_usercopy’
/usr/local/gspcav1-20071224/gspca_core.c: At top level:
/usr/local/gspcav1-20071224/gspca_core.c:2609: error: unknown field ‘owner’ specified in initializer
/usr/local/gspcav1-20071224/gspca_core.c:2609: warning: initialization from incompatible pointer type
/usr/local/gspcav1-20071224/gspca_core.c:2611: error: unknown field ‘type’ specified in initializer
/usr/local/gspcav1-20071224/gspca_core.c:2615: warning: initialization from incompatible pointer type
/usr/local/gspcav1-20071224/gspca_core.c: In function ‘spca50x_create_sysfs’:
/usr/local/gspcav1-20071224/gspca_core.c:2769: error: implicit declaration of function ‘video_device_create_file’
/usr/local/gspcav1-20071224/gspca_core.c:2780: error: implicit declaration of function ‘video_device_remove_file’
/usr/local/gspcav1-20071224/gspca_core.c: In function ‘spca5xx_probe’:
/usr/local/gspcav1-20071224/gspca_core.c:4301: error: incompatible types in assignment
make[2]: *** [/usr/local/gspcav1-20071224/gspca_core.o] Error 1
make[1]: *** [_module_/usr/local/gspcav1-20071224] Error 2
make[1]: Leaving directory `/usr/src/linux-2.6.30.2'
make: *** [default] Error 2
以我现在的能力,我不能解决,我google过,但得不到好的解决方法。
更重要的是,现在想找一个几年前驱动支持的摄像头很难啊!现在都流行免驱了——根据OS相关理论,这是不成功的,
设备没有驱动哪能访问?他们说的是用户免去安装驱动程序这一步骤,——是这个“免驱”。我买的摄像头不
在spca5xx支持范围之中。我好容易找到一个,是小郭用的,摄像头ID刚好是上述驱动所支持的。当时很兴
奋,心想,万事俱备,只差编译、测试了。可惜,以失败告终。错误如上所述。
我试的几个版本为spca5xx-20060501和gspcav1-20071224,都不行。
在网上找了那么多文章看,但一个也行不通。我不知大家的感受是什么,反正我很郁闷,很无奈。
后来,在插入我买的摄像头时,使用了lsusb,将ID那一行复制到google中,一不小心,发现了一个
好网站:http://linux-uvc.berlios.de/。上面竟然有我摄像头的ID号!!继续研究,发现有UVC这个东东,
我在配置内核时也碰到过,但没有注意,没想到如此有用!后来在一个网站中找到有关使用UVC驱动摄像头的
文章,地址忘了,我也不知是怎么搜索到的。此外还下载一个观看图像的小软件(补充一下:luvcview 或者cheese[debian自带])。
结果成了!可以显示图像了!下面写一下过程:
如果你能在http://linux-uvc.berlios.de/找到你的摄像头的ID,即UVC支持的,那么就可以在linux下使用了。
至于从哪个版本开始内核支持UVC,官方的话是“Linux 2.6.26 and newer includes the Linux UVC driver natively.”
1、查看摄像头ID:
[root@151 dev]# lsusb
Bus 002 Device 013: ID 0ac8:3313 Z-Star Microelectronics Corp.
0xc8:3313在UVC中支持了。
2、插入摄像头后,就可以在/dev/下查看是否有video设备文件:
[root@151 dev]# ls | grep video
video
video0
其中,video是video0的连接。如果没有再现,可能UVC没有配置到内核中,重新配置就可以了
(大致在Device DriversàMultimedia devicesàVideo capture adaptersàV4L USB devices下面)。如果内核配置了,
还是不出现,可以使用modprobe uvcvideo来加载该模块。
3、先看看摄像头的相关信息:
lshal | grep Cam
出现:
info.product = 'Vega USB 2.0 Camera.' (string)
usb_device.product = 'Vega USB 2.0 Camera.' (string)
usb.interface.description = 'Vega USB 2.0 Camera.' (string)
info.product = 'Vega USB 2.0 Camera.' (string)
input.product = 'Vega USB 2.0 Camera.' (string)
info.product = 'Vega USB 2.0 Camera.' (string)
对USB有研究的,就很熟悉这些字段。
再看一下系统能不能识别出摄像头:
[root@151 log]# dmesg | grep Cam
uvcvideo: Found UVC 1.00 device Vega USB 2.0 Camera. (0ac8:3313)
input: Vega USB 2.0 Camera. as /class/input/input6
usb 2-7: Product: Vega USB 2.0 Camera.
uvcvideo: Found UVC 1.00 device Vega USB 2.0 Camera. (0ac8:3313)
input: Vega USB 2.0 Camera. as /class/input/input7
usb 2-7: Product: Vega USB 2.0 Camera.
uvcvideo: Found UVC 1.00 device Vega USB 2.0 Camera. (0ac8:3313)
input: Vega USB 2.0 Camera. as /class/input/input8
usb 2-7: Product: Vega USB 2.0 Camera.
[root@151 ~]# dmesg | grep video
pci 0000:05:00.0: Boot video device
Linux video capture interface: v2.00
usbcore: registered new interface driver uvcvideo
uvcvideo 2-7:1.0: usb_probe_interface
uvcvideo 2-7:1.0: usb_probe_interface - got id
uvcvideo: Found UVC 1.00 device Vega USB 2.0 Camera. (0ac8:3313)
uvcvideo 2-7:1.0: usb_probe_interface
uvcvideo 2-7:1.0: usb_probe_interface - got id
uvcvideo: Found UVC 1.00 device Vega USB 2.0 Camera. (0ac8:3313)
uvcvideo 2-7:1.0: usb_probe_interface
uvcvideo 2-7:1.0: usb_probe_interface - got id
uvcvideo: Found UVC 1.00 device Vega USB 2.0 Camera. (0ac8:3313)
哈哈,识别出来了!可以测试了。
4、我使用的软件是luvcview,这个软件google就可以找到的。安装过程很简单,——make,make install就可以了。(哈哈,这里才说)
下面这个过程是测试过程,从看到图像到结束的过程:
[root@151 dev]# luvcview -d /dev/video0 -f yuv -s 640x480 (直接运行luvcview也可)
uvcview verion 0.1.4
size width: 640 height: 480
Video driver: x11
A window manager is available
video /dev/video0
Stop asked
Clean Up done Quit
[root@151 dev]#
解释命令:
-d 设备名,这里/dev/video或/dev/video0都可以,因为它们都是一个文件
-f 格式,有yuv和jpg两种,后者测试不行
-s 大小,能支持的最大尺度可能由luvcview决定,也可能由摄像头决定,(应该是后者,暂没有研究)
更具体的参见luvcview目录下的README文件。
另外,如果没有插入摄像头,即使modprobe uvcvideo也不会出现/dev/video设备文件;插入摄像头,即使没有modprobe uvcvideo,
也会出现/dev/video设备文件,当然这是我的测试,没有代表性,也没有理论根据的。
注:
1、UVC:USB Video Class
2、gspcav不是不再维护,而是在某一版本开始已经纳入内核了,至于哪个版本(2.6.26),就不太清楚了。特此说明。
3、这次毕业设计所不再编译gspca到内核中了。不支持它,直接使用UVC。
第一张图:红旗6.2,内核2.6.28.8
500)this.width=500;" width="500" border="0">
虚拟机FC9,内核2.6.30
500)this.width=500;" width="500" border="0">
发表于: 2010-03-19,修改于:
我跟作者经历简直太相似了,起先搞了好几天真是有点摸不着头脑,哈哈!!
posted @ 2010-08-19 00:54 海王 阅读(4090) 评论(0)
编辑
http://eatdrinkmanwoman.spaces.live.com/blog/cns!97719476F5BAEDA4!1336.entry
http://weijb0606.blog.163.com/blog/static/131286274201063152423963/
本文所说的摄像头(Webcam),特指USB摄像头。
在Windows下,摄像头驱动由厂商开发并提供。但在Linux下,因商业利益有限,只有极少厂商愿意提供摄像头驱动支持。这并不妨碍Linux下摄像头的使用——广大第三方志愿者维护着大大小小的驱动。之前做过一个嵌入式皮毛项目,虽然摄像头驱动不关我的事,在好奇心驱使下简要探索了一番。结果是有些胸闷,它们像蜘蛛丝一样杂乱。写本文的动机是想理清一下主线,给后来者提供一点有限的参考,但无法保证下面的文字完全正确。
常见的摄像头驱动有以下几个系列: OVCam drivers(ov5xx)
该系列驱动是针对OmniVision OV5xx系列芯片,此类芯片被广泛运用于各种USB摄像头中,在嵌入式开发板上尤其常见。凡是使用了OV511/OV511+/OV518 /OV6620/OV6630/OV7610/OV7620/OV7 620AE等图像传感器的摄像头都可以在该驱动下工作。
项目主页:http://alpha.dyndns.org/ov511/
Philips USB Webcam Driver(pwc) 该驱动主要用于Philips及pwc芯片兼容摄像头。由于原开发者与Philips公司签有保密协定,该驱动以二进制形式提供,后来被踢出内核,引起一场口水战:是用户需求重要还是保持内核纯洁重要?所幸后续开发者从原项目上创建了一个新的分支,使得该项目继续存活。
项目主页:http://www.saillard.org/linux/pwc/
QuickCam USB camera driver (qc-usb) 该驱动主要用于Logitech公司的QuickCam Express系列和其它兼容型号摄像头。最初由Georg Acher开发,当时命名为qce-ga。Jean-Frederic Clere参考该驱动创建出了第一个Video4Linux兼容驱动。从那开始,不断有开发者加入,使得该驱动逐渐能够支持新的摄像头和芯片。在此期间,该驱动更名为qc-usb,更为广泛地支持其它QuickCam USB摄像头,而不再是局限于Express系列。
项目主页:http://qce-ga.sourceforge.net/
QuickCam Messenger & Communicate driver(quickcam) 这是另一个针对QuickCam摄像头的驱动,它仅支持某一些型号,并且与qc-usb驱动不兼容。项目主页:http://home.mag.cx/messenger/
SPCA webcam driver(gspca/spca5xx) 该系列驱动适用于Sunplus芯片摄像头,也适用于其它芯片,如目前国内山寨摄像头一哥“中星微”(Z-Star)芯片。Michel Xhaard是该项目的维护者,他在60岁左右的时候(大约是2003年)从一种普通常见的驱动入手,进而不断修改开发成一个支持250种以上摄像头的通用驱动。他还写了流媒体服务器spcaserv与客户端spcaview。不少高校所谓的嵌入式无线网络视频传输项目,就是从这两个东西来的。
项目主页:http://mxhaard.free.fr/spca5xx.html
Linux UVC driver(uvc) 该驱动适用于符合USB视频类(USB Video Class)规范的摄像头设备,它包括V4L2内核设备驱动和用户空间工具补丁。大多数大容量存储器设备(如优盘)都遵循USB规范,因而仅用一个单一驱动就可以操作它们。与此类似,UVC兼容外设只需要一个通用驱动即可。
USB摄像头大体上可以二分为UVC cameras和non-UVC cameras。推荐购买UVC cameras。UVC是一个开放的标准,拥有维护良好的驱动,它属于内核代码的一部分。插入摄像头后就可以工作,而无须编译或安装额外的驱动。non- UVC cameras通常情况下不比UVC cameras工作出色,前者的驱动并不遵循通用的协议,需要针对每种摄像头做出单独的处理,这往往需要一个逆向工程的探索过程。
判断一个摄像头是否属于UVC规范可以使用下面方法:
1.使用lsusb命令或其它硬件信息查看工具找出摄像头的设备号(Vendor ID)和产品号(Product ID)。如Logitech Quickcam for Notebooks Pro摄像头是046d:08cb;
2.查找是否有视频类接口信息
lsusb -d 046d:08cb -v | grep "14 Video"
如果该摄像头兼容UVC,则会输出类似信息
bFunctionClass 14 Video
bInterfaceClass 14 Video
bInterfaceClass 14 Video
bInterfaceClass 14 Video
若无以上信息,则是non-UVC设备。
项目主页:http://linux-uvc.berlios.de/
在Linux下摄像头驱动有三种存在形式,内置于内核(within the kernel),做为一个外挂的模块(module),或者是预编译的二进制程序(pre-compiled binary)。
Linux内核树会不断合并优秀的驱动。从2.4内核起,ov5xx驱动就已经是内核代码的一部分。从2.6.26开始,Linux内核原生包含uvc 驱动。2.6.27内核又吸收进了gspca/spca5xx系列驱动。常见的Linux发行版所配置的内核,一般都已将这些驱动选项打开,而无需用户另外编译。内核的.config文件中有许多配置变量等式,用来说明内核配置的结果。y表示本编译选项对应的内核代码被静态编译进 Linux内核;m表示本编译选项对应的内核代码被编译成模块;n表示不选择此编译选项。
以Fedora12/boot下的config文件为例
cat /boot/config-2.6.31.12-174.2.3.fc12.i686 | grep CONFIG_USB_GSPCA
CONFIG_USB_GSPCA=m
CONFIG_USB_GSPCA_CONEX=m
CONFIG_USB_GSPCA_ETOMS=m
CONFIG_USB_GSPCA_FINEPIX=m
CONFIG_USB_GSPCA_MARS=m
CONFIG_USB_GSPCA_MR97310A=m
CONFIG_USB_GSPCA_OV519=m
CONFIG_USB_GSPCA_OV534=m
CONFIG_USB_GSPCA_PAC207=m
CONFIG_USB_GSPCA_PAC7311=m
CONFIG_USB_GSPCA_SN9C20X=m
CONFIG_USB_GSPCA_SN9C20X_EVDEV=y
CONFIG_USB_GSPCA_SONIXB=m
CONFIG_USB_GSPCA_SONIXJ=m
CONFIG_USB_GSPCA_SPCA500=m
CONFIG_USB_GSPCA_SPCA501=m
CONFIG_USB_GSPCA_SPCA505=m
CONFIG_USB_GSPCA_SPCA506=m
CONFIG_USB_GSPCA_SPCA508=m
CONFIG_USB_GSPCA_SPCA561=m
CONFIG_USB_GSPCA_SQ905=m
CONFIG_USB_GSPCA_SQ905C=m
CONFIG_USB_GSPCA_STK014=m
CONFIG_USB_GSPCA_SUNPLUS=m
CONFIG_USB_GSPCA_T613=m
CONFIG_USB_GSPCA_TV8532=m
CONFIG_USB_GSPCA_VC032X=m
CONFIG_USB_GSPCA_ZC3XX=m
可以看到gspca系列驱动被编译为模块。当插入摄像头后,使用dmesg命令可以打印出以下信息:
usb 1-1.2: new full speed USB device using ehci_hcd and address 6
usb 1-1.2: New USB device found, idVendor=046d, idProduct=08af
usb 1-1.2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
usb 1-1.2: configuration #1 chosen from 1 choice
gspca: probing 046d:08af
zc3xx: probe 2wr ov vga 0x0000
zc3xx: probe sensor -> 0011
zc3xx: Find Sensor HV7131R(c)
gspca: probe ok
这说明该摄像头被识别,且自动挂载了gspca系列下的zc3xx驱动。
如果由于某种原因,已配置的内核中没有包括摄像头驱动,可以重新配置内核选项,用新编译的内核替换原有的旧内核。或者是依据设备号及产品号,直接到对应驱动的项目主页,下载源码进行编译。
最后总结一下
如果你想买一个摄像头,推荐买Logitech的,买符合UVC驱动的,可以到这里挑一款。
如果你已经有了一个摄像头,先插进去看看,Linux对它有没有反应。记录dmesg输出信息,记录lsusb输出设备号,以设备号为关键字上Google搜索。
参考资源 http://www.tldp.org/HOWTO/Webcam-HOWTO/
http://www.chineselinuxuniversity.net/courses/kern el/articles/19988.shtml
http://www.quickcamteam.net/
posted @ 2010-08-19 00:36 海王 阅读(1036) 评论(0)
编辑