怎么在linux下驱动usb摄像头
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎么在linux下驱动usb摄像头相关的知识,希望对你有一定的参考价值。
在linux下所有设备都是文件。所以对摄像头的操作其实就是对文件的操作。USB摄像头的设备文件就是在/dev目录下的video0(假如只有一个摄像头)。在linux下操作摄像头就是使用v4l2对摄像头进行视频的操作,操作步骤如下1. 打开设备文件。
int fd=open(”/dev/video0″,O_RDWR);
2. 取得设备的capability,看看设备具有什么功能,比如是否具有视频输入,或者音频输入输出等。VIDIOC_QUERYCAP,struct v4l2_capability
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:
//……
3. 选择视频输入,一个视频设备可以有多个视频输入。VIDIOC_S_INPUT,struct v4l2_input(可不要)
4. 设置视频的制式和帧格式,制式包括PAL,NTSC,帧的格式个包括宽度和高度等。
VIDIOC_S_STD,VIDIOC_S_FMT,struct v4l2_std_id,struct v4l2_format
struct v4l2_format fmt;
memset ( &fmt, 0, sizeof(fmt) );
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width = 320;
fmt.fmt.pix.height = 240;
fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_JPEG;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0)
printf("set format failed\n");
//return 0;
5. 向驱动申请帧缓冲,一般不超过5个。struct v4l2_requestbuffers
struct v4l2_requestbuffers req;
memset(&req, 0, sizeof (req));
req.count = 4;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if (ioctl(fd,VIDIOC_REQBUFS,&req) == -1)
perror("VIDIOC_REQBUFS error \n");
//return -1;
6.申请物理内存
将申请到的帧缓冲映射到用户空间,这样就可以直接操作采集到的帧了,而不必去复制。将申请到的帧缓冲全部入队列,以便存放采集到的数据.VIDIOC_QBUF,struct v4l2_buffer
VideoBuffer* buffers = calloc( req.count, sizeof(VideoBuffer) );
printf("sizeof(VideoBuffer) is %d\n",sizeof(VideoBuffer));
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) < 0)
printf("VIDIOC_QUERYBUF error\n");
//return -1;
printf("buf len is %d\n",sizeof(buf));
//内存映射
buffers[numBufs].length = buf.length;
buffers[numBufs].offset = (size_t) buf.m.offset;
buffers[numBufs].start = mmap (NULL, buf.length,PROT_READ | PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
printf("buffers.length = %d,buffers.offset = %d ,buffers.start[0] = %d\n",buffers[numBufs].length,buffers[numBufs].offset,buffers[numBufs].start[0]);
printf("buf2 len is %d\n",sizeof(buffers[numBufs].start));
if (buffers[numBufs].start == MAP_FAILED)
perror("buffers error\n");
//return -1;
if (ioctl (fd, VIDIOC_QBUF, &buf) < 0)
printf("VIDIOC_QBUF error\n");
//return -1;
7. 开始视频的采集。
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl (fd, VIDIOC_STREAMON, &type) < 0)
printf("VIDIOC_STREAMON error\n");
// return -1;
8. 出队列以取得已采集数据的帧缓冲,取得原始采集数据。VIDIOC_DQBUF, 将缓冲重新入队列尾,这样可以循环采集。VIDIOC_QBUF
if (ioctl(fd, VIDIOC_DQBUF, &buf) < 0)
perror("VIDIOC_DQBUF failed.\n");
//return -1;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
unsigned char *ptcur = buffers[numBufs].start;
DEBUG("buf.bytesused = %d \n",buf.bytesused);
int i1;
for(i1=0; i1<buf.bytesused; i1++)
if((buffers[numBufs].start[i1] == 0x000000FF) && (buffers[numBufs].start[i1+1] == 0x000000C4))
DEBUG("huffman table finded! \nbuf.bytesused = %d\nFFC4 = %d \n",buf.bytesused,i1);
break;
if(i1 == buf.bytesused)printf("huffman table don't exist! \n");
int i;
for(i=0; i<buf.bytesused; i++)
if((buffers[numBufs].start[i] == 0x000000FF) && (buffers[numBufs].start[i+1] == 0x000000D8)) break;
ptcur++;
DEBUG("i=%d,FF=%02x,D8=%02x\n",i,buffers[numBufs].start[i],buffers[numBufs].start[i+1]);
int imagesize =buf.bytesused - i;
DEBUG("buf.bytesused = %d \n",buf.bytesused);
DEBUG ("imagesize = %d \n",imagesize);
9. 停止视频的采集。VIDIOC_STREAMOFF
10. 关闭视频设备。close(fd); 参考技术A 建议你还是在windows下玩 摄像头
我之前试过一次 ubuntu 安装一个摄像头程序 就直接好了
不用我装驱动
如果运气不好 恰巧不支持你的摄像头的话 你可以去摄像头的厂商官网下载 如果他们支持linux的话
国内厂商 一般都没~~
最后说句 linux里 摄像头的效果 比 win差好多本回答被提问者和网友采纳
Linux下USB驱动开发之USB光谱仪驱动
30.1 USB简介
30.1.1 什么是USB?
USB是连接计算机系统与外部设备的一种串口总线标准,也是一种输入输出接口的技术规范,被广泛地应用于个人电脑和移动设备等信息通讯产品,USB就是简写,中文叫通用串行总线。最早出现在1995年,伴随着奔腾机发展而来。自微软在Windows 98中加入对USB接口的支持后,USB接口才推广开来,USB设备也日渐增多,如数码相机、摄像头、扫描仪、游戏杆、打印机、键盘、鼠标等等,其中应用最广的就是摄像头和U盘了。
USB包括老旧的USB 1.1标准和时下正流行的USB 2.0标准。传统的USB 1.1最高传输速率为12Mbps,一般厂商将其符合USB 1.1标准的产品称为“全速USB”。而高速USB 2.0最初推出时最高传输速率仅为240Mbps,后来USB2.0推广组(USB Promoter Group)在1999年10月将该速率提高到480Mbps,比传统的USB 1.1快40倍。
USB2.0向下兼容USB 1.1,当然USB1.1设备也“向上兼容”USB 2.0,但是无法实现USB2.0的传输能力,并自动以低速传输。USB 2.0连接线的最大长度为5米,但如果用五个USB适配器,则最大长度可达30米。
最新一代是USB 3.1,传输速度为10Gbit/s,三段式电压5V/12V/20V,最大供电100W ,新型Type C插型不再分正反。
USB采用四线电缆,其中两根是用来传送数据的串行通道,另两根为下游(Downstream)设备提供电源,对于高速且需要高带宽的外设,USB以全速12Mbps的传输数据;对于低速外设,USB则以1.5Mbps的传输速率来传输数据。USB总线会根据外设情况在两种传输模式中自动地动态转换。USB是基于令牌的总线。类似于令牌环网络或FDDI基于令牌的总线。USB主控制器广播令牌,总线上设备检测令牌中的地址是否与自身相符,通过接收或发送数据给主机来响应。USB通过支持悬挂/恢复操作来管理USB总线电源。USB系统采用级联星型拓扑,该拓扑由三个基本部分组成:主机(Host),集线器(Hub)和功能设备。
主机,也称为根,根结或根Hub,它做在主板上或作为适配卡安装在计算机上,主机包含有主控制器和根集线器(Root Hub),控制着USB总线上的数据和控制信息的流动,每个USB系统只能有一个根集线器,它连接在主控制器上。
集线器是USB结构中的特定成分,它提供叫做端口(Port)的点将设备连接到USB总线上,同时检测连接在总线上的设备,并为这些设备提供电源管理,负责总线的故障检测和恢复。集线可为总线提供能源,亦可为自身提供能源(从外部得到电源),自身提供能源的设备可插入总线提供能源的集线器中,但总线提供能源的设备不能插入自身提供能源的集线器或支持超过四个的下游端口中,如总线提供能源设备的需要超过100mA电源时,不能同总线提供电源的集线器连接。
USB介绍: http://www.usb.org/home
30.1.2 USB设备主要优点总结
1. 可以热插拔
用户在使用外接设备时,不需要关机再开机等动作,而是在电脑工作时,直接将USB插上使用。
2. 携带方便
USB设备大多以“小、轻、薄”见长,对用户来说,随身携带大量数据时,很方便。当然USB硬盘是首要之选了。
3. 标准统一。
大家常见的是IDE接口的硬盘,串口的鼠标键盘,并口的打印机扫描仪,可是有了USB之后,这些应用外设统统可以用同样的标准与个人电脑连接,这时就有了USB硬盘、USB鼠标、USB打印机等等。
4. 可以连接多个设备。
USB在个人电脑上往往具有多个接口,可以同时连接几个设备,如果接上一个有四个端口的USB HUB时,就可以再连上四个USB设备,以此类推 (注:最高可连接至127个设备,扩展到一定数量时需要外加电源)
30.1.3 USB电器接口定义
一般的排列方式是:红白绿黑从左到右
定义:
- 红色-USB电源: 标有-VCC、Power、5V、5VSB字样
- 白色-USB数据线:(负)-DATA-、USBD-、PD-、USBDT-
- 绿色-USB数据线:(正)-DATA+、USBD+、PD+、USBDT+
- 黑色-地线: GND、Ground
30.1.4 USB的插入检测机制
USB端口的D+和D-均用一个15k的电阻接地,当无设备接入时,均处于低电平;在设备端在D+(表示高速设备或者全速设备)或者D-(表示低速设备)接了一个1.5k的上拉电阻到+3.3v,一旦将设备接入,USB端口的D+或者D-其中一个被拉高为3v,系统识别到外部设备接入。
注意:高速设备首先会被识别为全速设备,然后再通过集线器和设备二者的确认最后切换到高速模式下。
在高速模式下,采用的是电流传输模式,这个时候上拉电阻需要从D+上断开。
usb主机检测到USB设备插入后,就要对设备进行枚举了。枚举的作用就是从设备是那个读取一些信息,知道设备是什么样的设备,如果通信,这样主机就可以根据这些信息选择合适的驱动程序。调试USB设备,很重要的一点就是USB枚举过程,只要枚举成功了,那就成功一大半了。
当设备没有枚举成功时(可以通过一个10K的电阻将USB的电源端和D+或者D-连接起来,电脑会发现一个无法识别的设备,这个设备的PID和VID都是0,根据每个特性可以简单的判定设备的枚举是否成功。
30.2 USB标准描述符
USB协议为USB设备定义了一套描述设备功能和属性的有固定结构的描述符,包括标准的描述符即设备描述符、配置描述符、接口描述符、端点描述符和字符串描述符。USB设备通过这些描述符向USB主机汇报设备的各种各样属性,主机通过对这些描述符的访问对设备进行类型识别、配置并为其提供相应的客户端驱动程序。
USB设备通过描述符反映自己的设备特性。USB描述符是由特定格式排列的一组数据结构组成。
在USB设备枚举过程中,主机端的协义软件需要解析从USB设备读取的所有描述符信息。在USB主向设备发送读取描述符的请求后,USB设备将所有的描述符以连续的数据流方式传输给USB主机。主机从第一个读到的字符开始,根据双方规定好的数据格式,顺序地解析读到的数据流。
USB描述符包含标准描述符、类描述符和厂商特定描述3种形式。任何一种设备必须遵循USB标准描述符(除了字符串描述符可选外)。
在USB1.X中,规定了5种标准描述符:设备描述符(Device Descriptor)、配置描述符(Configuration Descriptor)、接口描述符(Interface Descriptor)、端点描述符(Endpoint Descriptor)和字符串描述符(String Descriptor)。
每个USB设备只有一个设备描述符,而一个设备中可包含一个或多个配置描述符,即USB设备可以有多种配置。设备的每一个配置中又可以包含一个或多个接口描述符,即USB设备可以支持多种功能(接口),接口的特性通过描述符提供。
在USB主机访问USB设备的描述符时,USB设备依照设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符顺序将所有描述符传给主机。一设备至少要包含设备描述符、配置描述符和接口描述符,如果USB设备没有端点描述符,则它仅仅用默认管道与主机进行数据传输。
30.2.1 设备描述符
/* USB_DT_DEVICE: Device descriptor */
struct usb_device_descriptor
__u8 bLength;
__u8 bDescriptorType;
__le16 bcdUSB;
__u8 bDeviceClass;
__u8 bDeviceSubClass;
__u8 bDeviceProtocol;
__u8 bMaxPacketSize0;
__le16 idVendor;
__le16 idProduct;
__le16 bcdDevice;
__u8 iManufacturer;
__u8 iProduct;
__u8 iSerialNumber;
__u8 bNumConfigurations;
__attribute__ ((packed));
//USB设备信息与驱动端匹配成功的时候调用。
static int test_probe(struct usb_interface *intf,const struct usb_device_id *id) //资源探索函数
printk("识别到USB光谱仪设备,正在进行设备初始化.\\n");
printk("该设备的厂商ID=%#x,设备ID:%#x\\n",id->idVendor,id->idProduct);
/*通过接口获取设备信息*/
struct usb_device *dev = interface_to_usbdev(intf);
printk("bcdUSB = %#x\\n",dev->descriptor.bcdUSB); //从USB设备描述符中获取USB版本
printk("vidUSB = %#x\\n",dev->descriptor.idVendor); //从USB设备描述符中获取厂商ID
printk("pidUSB = %#x\\n",dev->descriptor.idProduct);//从USB设备描述符中获取产品ID
/*-------------------------------*/
设备描述符给出了USB设备的一般信息,包括对设备及在设备配置中起全程作用的信息,包括制造商标识号ID、产品序列号、所属设备类号、默认端点的最大包长度和配置描述符的个数等。一个USB设备必须有且仅有一个设备描述符。设备描述符是设备连接到总线上时USB主机所读取的第一个描述符,它包含了14个字段,结构如下:
USB设备描述符的结构 | ||||
偏移量 | 域 | 大小 | 值 | 描述 |
0 | bLength | 1 | 数字 | 此描述表的字节数 |
1 | bDecriptorType | 1 | 常量 | 描述符的类型(此处应为0x01,即设备描述符) |
2 | bcdUSB | 2 | BCD码 | 此设备与描述表兼容的USB设备说明版本号(BCD 码) |
4 | bDeviceClass | 1 | 类 | 设备类码: 如果此域的值为0则一个设置下每个接口指出它自己的类,各个接口各自独立工作。 |
5 | bDeviceSubClass | 1 | 子类 | 子类码 这些码值的具体含义根据bDeviceClass 域来看。 |
6 | bDevicePortocol | 1 | 协议 | 协议码 这些码的值视bDeviceClass 和 bDeviceSubClass 的值而定。 如果设备支持设备类相关的协议,此码标志了设备类的值。如果此域的值为零,则此设备不支持设备类相关的协议,然而,可能它的接口支持设备类相关的协议。如果此域的值为FFH,此设备使用厂商定义的协议。 |
7 | bMaxPacketSize0 | 1 | 数字 | 端点0的最大包大小(仅8,16,32,64为合法值) |
8 | idVendor | 2 | ID | 厂商标志(由USB-IF组织赋值) |
10 | idProduct | 2 | ID | 产品标志(由厂商赋值) |
12 | bcdDevice | 2 | BCD码 | 设备发行号(BCD 码) |
14 | iManufacturer | 1 | 索引 | 描述厂商信息的字符串描述符的索引值。 |
15 | iProduct | 1 | 索引 | 描述产品信息的字串描 以上是关于怎么在linux下驱动usb摄像头的主要内容,如果未能解决你的问题,请参考以下文章 ubuntu12.04下usb摄像头问题 想在ubuntu下 |