Hi3559AV100外接UVC/MJPEG相机实时采图设计(一):Linux USB摄像头驱动分析
下面将给出Hi3559AV100外接UVC/MJPEG相机实时采图设计的整体流程,主要实现是通过V4L2接口将UVC/MJPEG相机采集的数据送入至MPP平台,经过VDEC、VPSS、VO最后通过HDMI的输出,首先给出(一)Linux USB摄像头驱动加载与分析。
板载平台:BOXER-8410AI
芯片型号:Hi3559AV100
相机型号:Logitch c270
开发环境:VM15.5+ubuntu16.04+Hilinux
之后可以参考后面两篇文章:
Hi3559AV100外接UVC/MJPEG相机实时采图设计(二):V4L2接口的实现(以YUV422为例):
https://www.cnblogs.com/iFrank/p/14403397.html
Hi3559AV100外接UVC/MJPEG相机实时采图设计(三):V4L2接口通过MPP平台输出:
https://www.cnblogs.com/iFrank/p/14403620.html
1、确定USB摄像头支持UVC
首先,可以把USB摄像头插在PC端,然后通过设备管理器找到相机,右键选择属性,选择详细信息,更改属性一栏,选择硬件ID,从中可以看到USB摄像头的VID和PID,比如Logitech c270的ID号为:046d:0825,之后通过这个网页 http://www.ideasonboard.org/uvc/ 来查看是否支持 UVC,这个网站是 USB Video Class Linux device driver 的主页,里面有 UVC 的详细的介绍。根据前面的打印信息,根据自己的 ID 号, 这里是搜索 USB 摄像头的 VID 号:046d 和 PID 号:0825,主页如下所示:

通过摄像头的 ID,可以看到该摄像头是否支持 UVC 和其他信息。绿勾代表支持。
2、配置与相机型号匹配的USB host驱动
目前Hilinux系统自带了部分型号的usb摄像头驱动,但并不是支持所有市面上usb摄像头,像Logitch c270这一款usb摄像头就不支持,如果说linux kernel驱动中不支持,需要我们重新配置该驱动,或者需要进行裁剪等操作,而这个过程需要我们进行手动配置,配置过程如下:在内核目录下,输入如下命令(以emmc启动为例):
1 待进入内核源代码目录后,执行以下操作
2
3 cp arch/arm64/configs/hi3559av100_arm64_big_little_emmc_defconfig .config
4
5
6 make ARCH=arm64 CROSS_COMPILE=aarch64-himix100-linux- menuconfig
7
8
9 cp .config arch/arm64/configs/hi3559av100_arm64_big_little_emmc_defconfig
10
11
12 osdrv顶层目录下执行:make BOOT_MEDIA=emmc AMP_TYPE=linux atf
执行 make ARCH=arm64 CROSS_COMPILE=aarch64-himix100-linux- menuconfig 后,弹出如下窗口:

之后进行驱动配置,打开UVC驱动等等。
在配置好之后,弹出menuconfig窗口后,记得保存,保存完之后在手动修改usb驱动代码:修改位置如下:
linux-xxx\drivers\media\usb\uvc\uvc_driver.c
设备插入时调用probe将会按默认的id_table来加载驱动,也就是这个uvc_ids末尾说的Generic USB Video Class,具体如下所示:
1 /* Generic USB Video Class */
2 { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) },
3 { USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) },
4 {}
在struct usb_device_id uvc_ids[]中模仿之前的加上自己的USB设备信息:
1 { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
2 | USB_DEVICE_ID_MATCH_INT_INFO,
3 .idVendor = 0x046d,
4 .idProduct = 0x0825,
5 .bInterfaceClass = USB_CLASS_VIDEO,
6 .bInterfaceSubClass = 1,
7 .bInterfaceProtocol = 0,
8 .driver_info = UVC_QUIRK_RESTORE_CTRLS_ON_INIT },
注意一下这个driver_info的赋值,可以用来限制帧率,UVC_QUIRK_RESTORE_CTRLS_ON_INIT的值是0x400,这个设置好像是跟带宽有关系,没有深入了解,如果设的过小,将导致无法出图。而且USB2.0的带宽上限也只有480Mbit/s,连一个摄像头都够呛了。修改完之后,还需要重新编译内核。
之后将摄像头插在板载上,终端出现如下:

也可以通过命令ls /dev/video*查看video设备,如下所示, 到此驱动部分添加完成。
1 /dev/video0
3、UVC driver的研究
上述终端显示的信息是由uvc_probe()函数输出,对应函数位置为linux-xxx\drivers\media\usb\uvc\uvc_driver.c,函数具体内容如下:
1 static int uvc_probe(struct usb_interface *intf,
2 const struct usb_device_id *id)
3 {
4 struct usb_device *udev = interface_to_usbdev(intf);
5 struct uvc_device *dev;
6 int ret;
7
8 if (id->idVendor && id->idProduct)
9 uvc_trace(UVC_TRACE_PROBE, "Probing known UVC device %s "
10 "(%04x:%04x)\n", udev->devpath, id->idVendor,
11 id->idProduct);
12 else
13 uvc_trace(UVC_TRACE_PROBE, "Probing generic UVC device %s\n",
14 udev->devpath);
15
16 /* Allocate memory for the device and initialize it. */
17 if ((dev = kzalloc(sizeof *dev, GFP_KERNEL)) == NULL)
18 return -ENOMEM;
19
20 INIT_LIST_HEAD(&dev->entities);
21 INIT_LIST_HEAD(&dev->chains);
22 INIT_LIST_HEAD(&dev->streams);
23 atomic_set(&dev->nstreams, 0);
24 atomic_set(&dev->nmappings, 0);
25 mutex_init(&dev->lock);
26
27 dev->udev = usb_get_dev(udev);
28 dev->intf = usb_get_intf(intf);
29 dev->intfnum = intf->cur_altsetting->desc.bInterfaceNumber;
30 dev->quirks = (uvc_quirks_param == -1)
31 ? id->driver_info : uvc_quirks_param;
32
33 if (udev->product != NULL)
34 strlcpy(dev->name, udev->product, sizeof dev->name);
35 else
36 snprintf(dev->name, sizeof dev->name,
37 "UVC Camera (%04x:%04x)",
38 le16_to_cpu(udev->descriptor.idVendor),
39 le16_to_cpu(udev->descriptor.idProduct));
40
41 /* Parse the Video Class control descriptor. */
42 if (uvc_parse_control(dev) < 0) {
43 uvc_trace(UVC_TRACE_PROBE, "Unable to parse UVC "
44 "descriptors.\n");
45 goto error;
46 }
47
48 uvc_printk(KERN_INFO, "Found UVC %u.%02x device %s (%04x:%04x)\n",
49 dev->uvc_version >> 8, dev->uvc_version & 0xff,
50 udev->product ? udev->product : "<unnamed>",
51 le16_to_cpu(udev->descriptor.idVendor),
52 le16_to_cpu(udev->descriptor.idProduct));
53
54 if (dev->quirks != id->driver_info) {
55 uvc_printk(KERN_INFO, "Forcing device quirks to 0x%x by module "
56 "parameter for testing purpose.\n", dev->quirks);
57 uvc_printk(KERN_INFO, "Please report required quirks to the "
58 "linux-uvc-devel mailing list.\n");
59 }
60
61 /* Initialize the media device and register the V4L2 device. */
62 #ifdef CONFIG_MEDIA_CONTROLLER
63 dev->mdev.dev = &intf->dev;
64 strlcpy(dev->mdev.model, dev->name, sizeof(dev->mdev.model));
65 if (udev->serial)
66 strlcpy(dev->mdev.serial, udev->serial,
67 sizeof(dev->mdev.serial));
68 strcpy(dev->mdev.bus_info, udev->devpath);
69 dev->mdev.hw_revision = le16_to_cpu(udev->descriptor.bcdDevice);
70 dev->mdev.driver_version = LINUX_VERSION_CODE;
71 media_device_init(&dev->mdev);
72
73 dev->vdev.mdev = &dev->mdev;
74 #endif
75 if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)
76 goto error;
77
78 /* Initialize controls. */
79 if (uvc_ctrl_init_device(dev) < 0)
80 goto error;
81
82 /* Scan the device for video chains. */
83 if (uvc_scan_device(dev) < 0)
84 goto error;
85
86 /* Register video device nodes. */
87 if (uvc_register_chains(dev) < 0)
88 goto error;
89
90 #ifdef CONFIG_MEDIA_CONTROLLER
91 /* Register the media device node */
92 if (media_device_register(&dev->mdev) < 0)
93 goto error;
94 #endif
95 /* Save our data pointer in the interface data. */
96 usb_set_intfdata(intf, dev);
97
98 /* Initialize the interrupt URB. */
99 if ((ret = uvc_status_init(dev)) < 0) {
100 uvc_printk(KERN_INFO, "Unable to initialize the status "
101 "endpoint (%d), status interrupt will not be "
102 "supported.\n", ret);
103 }
104
105 uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
106 usb_enable_autosuspend(udev);
107 return 0;
108
109 error:
110 uvc_unregister_video(dev);
111 return -ENODEV;
112 }
1 static const struct file_operations v4l2_fops = {
2 .owner = THIS_MODULE,
3 .read = v4l2_read,
4 .write = v4l2_write,
5 .open = v4l2_open,
6 .get_unmapped_area = v4l2_get_unmapped_area,
7 .mmap = v4l2_mmap,
8 .unlocked_ioctl = v4l2_ioctl,
9 #ifdef CONFIG_COMPAT
10 .compat_ioctl = v4l2_compat_ioctl32,
11 #endif
12 .release = v4l2_release,
13 .poll = v4l2_poll,
14 .llseek = no_llseek,
15 };
Hi3559AV100外接UVC/MJPEG相机实时采图设计(一):Linux USB摄像头驱动分析的更多相关文章
- Hi3559AV100外接UVC/MJPEG相机实时采图设计(四):VDEC_Send_Stream线程分析
下面随笔将对Hi3559AV100外接UVC/MJPEG相机实现实时采图设计的关键点-VDEC_Send_Stream线程进行分析,一两个星期前我写了有三篇系列随笔,已经实现了项目功能,大家可以参考下 ...
- Hi3559AV100外接UVC/MJPEG相机实时采图设计(三):V4L2接口通过MPP平台输出
可以首先参考前面两篇文章: Hi3559AV100外接UVC/MJPEG相机实时采图设计(一):Linux USB摄像头驱动分析: https://www.cnblogs.com/iFrank/p/1 ...
- Hi3559AV100外接UVC/MJPEG相机实时采图设计(二):V4L2接口的实现(以YUV422为例)
下面将给出Hi3559AV100外接UVC/MJPEG相机实时采图设计的整体流程,主要实现是通过V4L2接口将UVC/MJPEG相机采集的数据送入至MPP平台,经过VDEC.VPSS.VO最后通过HD ...
- Dalsa 8K彩色相机Camera link C#采图
一个采图工具,所以界面做的很简单. private SapAcquisition m_Acquisition; private SapBuffer m_Buffers; private SapAcqT ...
- 相机拍的图,电脑上画的图,word里的文字,电脑屏幕,手机屏幕,相机屏幕显示大小一切的一切都搞明白了!
相机拍的图,电脑上画的图,word里的文字,电脑屏幕,手机屏幕,相机屏幕显示大小一切的一切都搞明白了! 先说图片X×dpi=点数dotX是图片实际尺寸,简单点,我们只算图片的高吧,比如说拍了张图片14 ...
- FusionCharts制作实时刷新图
转自:http://yklovejava-163-com.iteye.com/blog/1889949 下面介绍的是用FusionCharts制作实时刷新图的过程(FusionCharts确实太好用了 ...
- Android相机实时自动对焦的完美实现
https://zhidao.baidu.com/question/873328177698804372.html Android相机实时自动对焦的完美实现 http://blog.csdn.net/ ...
- 关于nagios系统下使用shell脚本自定义监控插件的编写以及没有实时监控图的问题
关于nagios系统下shell自定义监控插件的编写.脚本规范以及没有实时监控图的问题的解决办法 在自已编写监控插件之前我们首先需要对nagios监控原理有一定的了解 Nagios的功能是监控服务和主 ...
- RTSP流和USB摄像头转MJPEG使用VLC
测试环境: 系统: Ubuntu14.04 LTS Desktop 设备:海康IP摄像头和USB摄像头 1.需要先安装vlc包,命令行运行 sudo apt-get update sudo apt-g ...
随机推荐
- GPLT L2-007 家庭房产 (并查集)
题意: 给定每个人的家庭成员和其自己名下的房产,请你统计出每个家庭的人口数.人均房产面积及房产套数. 思路: 输入和输出各构造一个结构体,利用并查集归并输入,枚举编号进行输出. #include &l ...
- ACM-ICPC 2018 南京赛区网络预赛(12/12)
ACM-ICPC 2018 南京赛区网络预赛 A. An Olympian Math Problem 计算\(\sum_{i=1}^{n-1}i\cdot i!(MOD\ n)\) \(\sum_{i ...
- 【poj 1961】Period(字符串--KMP 模版题)
题意:给你一个字符串,求这个字符串到第 i 个字符为止的重复子串的个数. 解法:判断重复子串的语句很重要!!if (p && i%(i-p)==0) printf("%d % ...
- 【noi 2.6_9277】Logs Stacking堆木头(DP)
题意:给出在最底层的木头的个数,问有多少种堆放木头的方式.要求木头必须互相挨着在一起. 解法:f[i]表示最底层i个木头的堆放木头的方式.注意递推的思想!只需知道上一层堆放0~i-1个(即最底层堆放i ...
- 洛谷-P1469 找筷子 (位运算)
题意:给你一组数,求数组中唯一的出现次数为奇数的那个数. 题解:这题其实直接桶排一下就行了,但是最后一个点会TLE. 后来了解到这题可以用位运算来解决: ^(异或)运算符:用于比较两个二进制数 ...
- VXLAN学习之路-结合VRF在Linux中实践VXLAN网络
一.概述 近期在在搞网络安全HCIE.CISP的认证的事,顺便将VXLAN技术再次系统的学习一下,学习过程中看到云原生实验室里的一篇文章,就是关于VXLAN在Linux系统中的实践,感觉文章写得很好, ...
- 从 MFC 移植程序到 wxWidgets 界面库 ——《定时执行专家 5.0》的界面实现
时隔十年的更新,最大的变化就是从 MFC 移植到 wxWidgets,界面也全部重现设计,图标也都进行了更换.wxWidgets(最新版 3.1.4,经典的开源.跨平台 C++ GUI类库)特有的 ...
- 卸载vue2.9.6版本,安装新版本
1.检查vue安装目录(cmd中输入) where vue 2.删除目录中的关于vue的文件(可以将文件按时间排序,找到vue相关的文件删除) 3.检查vue是否还能找到 4.安装新版本的vue np ...
- 开源软件ffmpeg使用中的问题
error while decoding MB 20 10, bytestream -13 经过调试,发现这部是 int ret = avcodec_decode_video2(pCodecConte ...
- Deep Learning Specialization 笔记
1. numpy中的几种矩阵相乘: # x1: axn, x2:nxb np.dot(x1, x2): axn * nxb np.outer(x1, x2): nx1*1xn # 实质为: np.ra ...