Linux下获取usb视频设备vendor id和product id的8种方法
在使用usb摄像头获取视频时,有时需要获取此摄像头供应商ID(vendor id, vid)和产品ID(product id, pid),这里在Linux下提供获取vid和pid的8种方法:
1. 通过v4l2中结构体v4l2_capability的成员变量card:此变量中会包含设备名、vid、pid信息,其内容例如为“UVC Camera (046d:081b)”,其中”:”前四个字符为vid,”:”后四个字符为pid,代码段如下:其中str存放card的值
std::string str = (*it).second;
auto pos = str.find(":");
if (pos != std::string::npos) {std::string vid_str = str.substr(pos-4, 4);std::string pid_str = str.substr(pos+1, 4);std::istringstream(vid_str) >> std::hex >> vid_value;std::istringstream(pid_str) >> std::hex >> pid_value;fprintf(stdout, " vid: str: %s, value: %d; pid: str: %s, value: %d\n", vid_str.c_str(), vid_value, pid_str.c_str(), pid_value);
}
2. 通过解析/sys/class/video4linux/xxxx/device/modalias文件,其中xxxx为video0或video1等,当有usb camera插入到Linux上时,则会有此文件,其内容例如为” usb:v046Dp081Bd0012dcEFdsc02dp01ic0Eisc01ip00in00”,其中”usb:v”后四个字符为vid,”usb:v046Dp”后四个字符为pid,代码段如下:其中str为设备地址,如"/dev/video0"
str = (*it).first;
pos = str.find_last_of("/");
if (pos == std::string::npos) {fprintf(stderr, " fail to get vid and pid\n");
}
std::string name = str.substr(pos+1);
std::string modalias;
vid_value = 0; pid_value = 0;
if (!(std::ifstream("/sys/class/video4linux/" + name + "/device/modalias") >> modalias))fprintf(stderr, " fail to read modalias\n");
if (modalias.size() < 14 || modalias.substr(0,5) != "usb:v" || modalias[9] != 'p')fprintf(stderr, " not a usb format modalias\n");
if (!(std::istringstream(modalias.substr(5,4)) >> std::hex >> vid_value))fprintf(stderr, " fail to read vid\n");
if (!(std::istringstream(modalias.substr(10,4)) >> std::hex >> pid_value))fprintf(stderr, " fail to read pid\n");
fprintf(stdout, " vid value: %d, pid value: %d\n", vid_value, pid_value);
3. 通过解析/proc/bus/input/devices文件,输入设备名可以获取对应的vid和pid,代码段如下:其中bus_line为"I: Bus=0003 Vendor=046d Product=081b Version=0012"
auto pos = bus_line.find("Vendor");
if (pos != std::string::npos) {std::string str = bus_line.substr(pos+7, 4);std::istringstream(str) >> std::hex >> vid;
} else {fprintf(stderr, "not found vid\n");return -1;
}pos = bus_line.find("Product");
if (pos != std::string::npos) {std::string str = bus_line.substr(pos+8, 4);std::istringstream(str) >> std::hex >> pid;
} else {fprintf(stderr, "not found pid\n");return -1;
}
4. 通过设备的event可以直接读取vid和pid,如event为event6,则为/sys/class/input/event6/device/id/vendor和/sys/class/input/event6/device/id/product,可通过解析/proc/bus/input/devices得到指定设备的event,代码段为:其中event_line为"H: Handlers=kbd event6"
auto pos = event_line.find(search_event_line);
if (pos != std::string::npos) {std::string str = event_line.substr(pos, std::string::npos);str.erase(std::remove_if(str.begin(), str.end(), isspace), str.end());std::string vid_str, pid_str;std::string prefix = "/sys/class/input/" + str + "/device/id/";if (!(std::ifstream(prefix +"vendor") >> vid_str)) {fprintf(stderr, "not found /device/id/vendor\n");return -1;}if (!(std::ifstream(prefix + "product") >> pid_str)) {fprintf(stderr, "not found /device/id/product\n");return -1;}std::istringstream(vid_str) >> std::hex >> vid;std::istringstream(pid_str) >> std::hex >> pid;
}
5. 通过解析/sys/kernel/debug/usb/devices可获取vid和pid,但是好像需要root权限。
6. 通过在Linux上安装libusb,然后调用其库提供的相应接口来获取vid和pid。
7. 可以通过执行lsusb命令获取vid和pid,执行结果如下:其中红框标注的为真实usb摄像头信息
8. 可以通过执行v4l2-ctl --list-devices命令获取vid和pid,执行结果如下:
以下是上面1--4种方法实现的完整C++代码:
#include "funset.hpp"
#include <map>
#include <string>
#include <sstream>
#include <fstream>
#include <algorithm>
#ifndef _MSC_VER
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#else
#endif#ifndef _MSC_VER
namespace {int v4l2_is_v4l_dev(const char *name)
{return !strncmp(name, "video", 5) ||!strncmp(name, "radio", 5) ||!strncmp(name, "vbi", 3) ||!strncmp(name, "v4l-subdev", 10);
}int test_v4l2_get_device_list(std::map<std::string, std::string>& device_list)
{device_list.clear();const char* dir_name = "/dev";DIR* dir = opendir(dir_name);if (!dir) {fprintf(stderr, "Error: couldn't open the directory: %s\n", dir_name);return -1;}struct dirent* entry = nullptr;int fd;while ((entry = readdir(dir))) {char device_name[256];if (!v4l2_is_v4l_dev(entry->d_name))continue;snprintf(device_name, sizeof(device_name), "/dev/%s", entry->d_name);if ((fd = device_open(device_name)) < 0)continue;struct v4l2_capability cap;if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0) {fprintf(stderr, "Error: cam_info: can't open device: %s\n", device_name);goto fail;}device_list[device_name] = reinterpret_cast<char*>(cap.card);close(fd);continue;fail:if (fd >= 0) close(fd);break;}closedir(dir);return 0;
}int parse_input_devices(const std::string& name, unsigned int& vid, unsigned int& pid)
{const std::string device_list_file = "/proc/bus/input/devices";std::ifstream file_input(device_list_file.c_str());if (!file_input.is_open()) {fprintf(stderr, "fail to open file: %s\n", device_list_file.c_str());return -1;}std::string current_line, bus_line, search_name_line = name, search_bus_line = "Bus=";while (getline(file_input, current_line)) {auto pos = current_line.find(search_bus_line);if (pos != std::string::npos)bus_line = current_line;pos = current_line.find(search_name_line);if (pos != std::string::npos)break;}file_input.close();auto pos = bus_line.find("Vendor");if (pos != std::string::npos) {std::string str = bus_line.substr(pos+7, 4);std::istringstream(str) >> std::hex >> vid;} else {fprintf(stderr, "not found vid\n");return -1;}pos = bus_line.find("Product");if (pos != std::string::npos) {std::string str = bus_line.substr(pos+8, 4);std::istringstream(str) >> std::hex >> pid;} else {fprintf(stderr, "not found pid\n");return -1;}return 0;
}int parse_input_devices2(const std::string& name, unsigned int& vid, unsigned int& pid)
{const std::string device_list_file = "/proc/bus/input/devices";std::ifstream file_input(device_list_file.c_str());if (!file_input.is_open()) {fprintf(stderr, "fail to open file: %s\n", device_list_file.c_str());return -1;}std::string current_line, event_line, search_name_line = name, search_event_line = "event";bool flag = false;while (getline(file_input, current_line)) {auto pos = current_line.find(search_name_line);if (pos != std::string::npos)flag = true;else if (!flag)continue;if (flag) {pos = current_line.find(search_event_line);if (pos != std::string::npos) {event_line = current_line;break;}}}file_input.close();if (!flag) {fprintf(stderr, "not found event\n");return -1;}auto pos = event_line.find(search_event_line);if (pos != std::string::npos) {std::string str = event_line.substr(pos, std::string::npos);str.erase(std::remove_if(str.begin(), str.end(), isspace), str.end());std::string vid_str, pid_str;std::string prefix = "/sys/class/input/" + str + "/device/id/";if (!(std::ifstream(prefix +"vendor") >> vid_str)) {fprintf(stderr, "not found /device/id/vendor\n");return -1;}if (!(std::ifstream(prefix + "product") >> pid_str)) {fprintf(stderr, "not found /device/id/product\n");return -1;}std::istringstream(vid_str) >> std::hex >> vid;std::istringstream(pid_str) >> std::hex >> pid;}return 0;
}} // namespaceint test_get_usb_camera_vid_pid()
{// get usb video device liststd::map<std::string, std::string> device_list;if (test_v4l2_get_device_list(device_list) !=0) {fprintf(stderr, "fail to get usb video device list\n");return -1;}int count = 1;fprintf(stdout, "device count: %d\n", device_list.size());for (auto it = device_list.cbegin(); it != device_list.cend(); ++it) {fprintf(stdout, "%d. device address: %s, description(name): %s\n", count++, (*it).first.c_str(), (*it).second.c_str());unsigned int vid_value, pid_value;fprintf(stdout, " method1. get vid and pid through v4l2:\n");std::string str = (*it).second;auto pos = str.find(":");if (pos != std::string::npos) {std::string vid_str = str.substr(pos-4, 4);std::string pid_str = str.substr(pos+1, 4);std::istringstream(vid_str) >> std::hex >> vid_value;std::istringstream(pid_str) >> std::hex >> pid_value;fprintf(stdout, " vid: str: %s, value: %d; pid: str: %s, value: %d\n", vid_str.c_str(), vid_value, pid_str.c_str(), pid_value);} else {fprintf(stderr, " fail to get vid and pid\n"); }fprintf(stdout, " method2. get vid and pid through device/modalias:\n");str = (*it).first;pos = str.find_last_of("/");if (pos == std::string::npos) {fprintf(stderr, " fail to get vid and pid\n");}std::string name = str.substr(pos+1);std::string modalias;vid_value = 0; pid_value = 0;if (!(std::ifstream("/sys/class/video4linux/" + name + "/device/modalias") >> modalias))fprintf(stderr, " fail to read modalias\n");if (modalias.size() < 14 || modalias.substr(0,5) != "usb:v" || modalias[9] != 'p')fprintf(stderr, " not a usb format modalias\n");if (!(std::istringstream(modalias.substr(5,4)) >> std::hex >> vid_value))fprintf(stderr, " fail to read vid\n");if (!(std::istringstream(modalias.substr(10,4)) >> std::hex >> pid_value))fprintf(stderr, " fail to read pid\n");fprintf(stdout, " vid value: %d, pid value: %d\n", vid_value, pid_value);fprintf(stdout, " method3. get vid and pid through /proc/bus/input/devices:\n");vid_value = 0; pid_value = 0;parse_input_devices((*it).second, vid_value, pid_value);fprintf(stdout, " vid value: %d, pid value: %d\n", vid_value, pid_value);fprintf(stderr, " method4. get vid and pid through /sys/class/input/eventXXX:\n");vid_value = 0; pid_value = 0;parse_input_devices2((*it).second, vid_value, pid_value);fprintf(stdout, " vid value: %d, pid value: %d\n", vid_value, pid_value);} return 0;
}
#else
int test_get_usb_camera_vid_pid()
{fprintf(stderr, "only support linux platform\n");return -1;
}
#endif
执行结果如下:从结果可知,这四种方法与通过命令行获取到的pid和vid是一致的。
GitHub:https://github.com//fengbingchun/OpenCV_Test
相关文章:

JAVA 设计模式 模板方法模式
定义 模板方法模式 (Template Method) 定义了一个操作中的算法的骨架,而将部分步骤的实现在子类中完成。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。模板方法模式是所有模式中最为常见的几个模式之一,是基于继承的代…
这类程序员成华为宠儿,分分钟秒杀众应届毕业生
近日,华为20亿奖励员工的新闻频频刷屏。其中20亿奖金不是面向所有的华为员工,20亿奖金包涉及到的是研发体系、造AI芯片和建设生态的员工。从5G开始部署以来,华为获得了来自全球各地运营商的订单,签订了40多个5G商用合同。另外华为…

Swift 使用CoreLocation获取定位与位置信息
大多数情况下APP会在开启应用的时候获取当前的位置,所以我写在APPDelegate里第一步 import CoreLocationvar locationManager CLLocationManager() 第二步func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: …

FFmpeg在Windows上设置dshow mjpeg编码+libyuv解码显示测试代码
之前在https://blog.csdn.net/fengbingchun/article/details/103444891中介绍过在Windows上通过ffmpeg dshow设置为mjpeg编解码方式进行实时显示的测试代码。这里测试仅调用ffmpeg的mjpeg编码接口,获取到packet后,通过libyuvlibjpeg-turbo对mjpeg进行解码…

转:浅谈Linux的内存管理机制
一 物理内存和虚拟内存 我们知道,直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样就引出了物理内存与虚拟内存的概念。 物理内存就是系统硬件提…

swift3.0阿里百川反馈
闲言少叙 直接上不熟 1.导入自己工程阿里百川demo中的Util文件,并引用其中的头文件 2.剩余就是swift3.0代码.在自己需要的地方书写 (前提是你已经申请了APPKey) 3.代码 //调用意见反馈 func actionOpenFeedback(){ //key self.appKey "此处填写自己申请的key" s…
通俗易懂:8大步骤图解注意力机制
作者 | Raimi Karim译者 | 夕颜出品 | AI科技大本营(ID:rgznai100)【导读】这是一份用图片和代码详解自注意力机制的指南,请收好。BERT、RoBERTa、ALBERT、SpanBERT、DistilBERT、SesameBERT、SemBERT、MobileBERT、TinyBERT和CamemBERT的共同…

Windows上VS2017单步调试FFmpeg源码的方法
之前在https://blog.csdn.net/fengbingchun/article/details/90114411 介绍过如何在Windows7/10上通过MinGW方式编译FFmpeg 4.1.3源码生成库的步骤,那时只能生成最终的库,却不能产生vs工程,无法进行单步调试。GitHub上有个项目ShiftMediaProj…

ormlite 多表联合查询
ormlite 多表联合查询 QueryBuilder shopBrandQueryBuilder shopBrandDao.queryBuilder(); QueryBuilder shopQueryBuilder shopDao.queryBuilder();Where shopBrandWhere shopBrandQueryBuilder.where(); shopBrandWhere .eq(ShopBrand.SHOP_NO, shopNo);Where shopWhere …

C++中关键字volatile和mutable用法
C/C中的volatile关键字和const对应,用来修饰变量,用于告诉编译器该变量值是不稳定的,可能被更改。使用volatile注意事项: (1). 编译器会对带有volatile关键字的变量禁用优化(A volatile specifier is a hint to a compiler that …
基于生成对抗网络(GAN)的人脸变形(附链接) | CSDN博文精选
扫码参与CSDN“原力计划”翻译 | 张一豪校对 | 吴金笛来源 | 数据派THU*点击阅读原文,查看「CSDN原力计划」详细说明。本文详细介绍了生成对抗网络(GAN)的知识,并用其变换人脸,并探寻如何利用StyleGAN生成不同属性&…

Jmeter连接Oracle数据库
一、Jmeter要连接oracle数据库,就必须复制JDBC驱动jar包文件ojdbc14.jar到Jmeter的lib目录下二、进入Jmeter的bin目录运行Jmeter.bat,启动Jmeter三、Jmeter软件配置如下:1、添加线程组右击线程组,选择“添加--配置元件--JDBC Conn…

swift3.0友盟分享
经过(一)的讲解,大家应该可以按照友盟提供的测试账号可以集成友盟分享了,友盟目前集合了18个APP共27种分享,可以授权的有10个App:微信、QQ、新浪微博、腾讯微博、人人网、豆瓣、Facebook、Twitter、Linkedi…

C++11中std::future的使用
C11中的std::future是一个模板类。std::future提供了一种用于访问异步操作结果的机制。std::future所引用的共享状态不能与任何其它异步返回的对象共享(与std::shared_future相反)( std::future references shared state that is not shared with any other asynchronous retur…
给算法工程师和研究员的「霸王餐」| 附招聘信息
现在的算法工程师真的是太难了!要让AI会看人眼都分辨不清的医疗影像!数据又不够,还得用前沿技术!好不容易学会看片,还要让AI会分析病理!然后模型搞出来了,还要把几十种模型,做N次计算…

swift3.0三种反向传值
一 :通知 1.通知传值所用方法 // MARK: - private methods(内部接口) let NotifMycation NSNotification.Name(rawValue:"MyNSNotification") func tempbuttonAction() { //这个方法可以传一个值 NotificationCenter.default.post(name: NotifMycation, object: &q…

C++11中std::shared_future的使用
C11中的std::shared_future是个模板类。与std::future类似,std::shared_future提供了一种访问异步操作结果的机制;不同于std::future,std::shared_future允许多个线程等待同一个共享状态;不同于std::future仅支持移动操作…
聊聊抖音、奈飞、Twitch、大疆、快手、B站的多媒体关键技术
随着5G牌照发放,5G终端正在迎来集中上市潮,对于5G带来的变革一触即发。目前互联网上超过七成的流量来自多媒体,未来这个比例将超过八成。音视频就像空气和水一样普及,深度到每个人的生活和工作中。同时,深度学习技术则…

Linux安全事件应急响应排查方法总结
Linux安全事件应急响应排查方法总结 Linux是服务器操作系统中最常用的操作系统,因为其拥有高性能、高扩展性、高安全性,受到了越来越多的运维人员追捧。但是针对Linux服务器操作系统的安全事件也非常多的。攻击方式主要是弱口令攻击、远程溢出攻击及其他…

C++11中std::packaged_task的使用
C11中的std::packaged_task是个模板类。std::packaged_task包装任何可调用目标(函数、lambda表达式、bind表达式、函数对象)以便它可以被异步调用。它的返回值或抛出的异常被存储于能通过std::future对象访问的共享状态中。 std::packaged_task类似于std::function,…

Swift3.0和OC桥接方法
1.直接在工程中commandn,出现如图,点击Header File创建桥接文件Bridging-Header.h,如图: 2.点击next,出现如图画面,一定要记得勾选第一项,再点击create创建完成。 3.配置桥接文件,点击target - …

量子算命,在线掷筊:一个IBM量子云计算机的应用实践,代码都有了
整理 | Jane 出品| AI科技大本营(ID:rgznai100) “算命”,古今中外,亘古不衰的一门学问,哪怕到了今天,大家对算命占卜都抱着一些”敬畏“的信任心理,西方流行塔罗牌,国…

rails应用ajax之二:使用rails自身支持
考虑另一种情况: 1. 页面上半部分显示当前的所有用户,页面下半部分是输入新用户的界面; 2. 每当输入新用户时,页面上半部分会动态更新新加用户的内容; 我们还是用ajax实现,不过这次用rails内部对ajax的支持…

C++11中std::async的使用
C11中的std::async是个模板函数。std::async异步调用函数,在某个时候以Args作为参数(可变长参数)调用Fn,无需等待Fn执行完成就可返回,返回结果是个std::future对象。Fn返回的值可通过std::future对象的get成员函数获取。一旦完成Fn的执行&…
BAT数据披露:缺人!110万AI人才缺口,两者矛盾,凉凉了!
人工智能到底有多火?近日国内首份《BAT人工智能领域人才发展报告》新鲜出炉,此次报告是针对国内人工智能领域的人才争夺情况进行了梳理。并把研究对象锁定在BAT三大巨头的身上。来源:《BAT人工智能领域人才发展报告》其中得出最为核心的结论&…

swift3.0最新拨打电话方法
let alertVC : UIAlertController UIAlertController.init(title: "是否拨打报警电话:10086", message: "", preferredStyle: .alert) let falseAA : UIAlertAction UIAlertAction.init(title: "取消", style: .cancel, handler: nil) let tr…

关于手机已处理里重复单据的处理办法
更新视图 VWFE_TASK去掉 union TWFE_TASK_BAK 的部分,原因是因为后面做了流程预演导致的问题转载于:https://blog.51cto.com/iderun/1602828

swiftswift3.0自己封装的快速构建页面的方法
//#param mark 控件 func creatLabel(frame:CGRect,text:String,textColor:UIColor,textFont:CGFloat,textAlignment:NSTextAlignment) -> UILabel { let label UILabel.init(frame: frame) label.text text label.textColor textColor label.font UIFont.systemFont(of…
Google是如何做Code Review的?| CSDN原力计划
作者 | 帅昕 xindoo 编辑 | 屠敏出品 | CSDN 博客我和几个小伙伴一起翻译了Google前一段时间放出来的Google’s Engineering Practices documentation(https://github.com/google/eng-practices),翻译后的GitHub仓库:https://gith…

从FFmpeg 4. 2源码中提取dshow mjpeg code步骤
之前在https://blog.csdn.net/fengbingchun/article/details/103735560 中介绍过在Windows上通过vs2017编译FFmpeg源码进行单步调试的步骤,为了进一步熟悉FFmpeg这里以提取FFmpeg dshow mjpeg源码为例介绍其实现过程及注意事项: FFmpeg是用C实现的&…