You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ubuntu中通过C++从/dev/xxx路径获取USB摄像头的VID、PID及序列号

Got it, let's walk through how to read the Vendor ID (VID), Product ID (PID), and serial number of a USB camera (like your udev-mapped /dev/camera_one) in C++, then implement validation logic. This relies on Linux's sysfs filesystem, which exposes all hardware device details in a human-readable, file-based structure.

Core Approach

When you have a device node (like /dev/camera_one), Linux links it to corresponding metadata in /sys/class/video4linux/. We'll follow these symbolic links to reach the USB device's dedicated sysfs directory, then read the idVendor, idProduct, and serial files to extract the info we need for validation.

Step-by-Step Implementation

Here's a complete C++ example with robust error handling and comments to explain each step:

#include <iostream>
#include <fstream>
#include <string>
#include <unistd.h>
#include <limits.h>
#include <algorithm>

using namespace std;

// Helper: Read the raw value from a sysfs text file
string readSysfsValue(const string& filePath) {
    ifstream file(filePath);
    if (!file.is_open()) {
        cerr << "Error: Couldn't open file " << filePath << endl;
        return "";
    }
    string value;
    getline(file, value);
    file.close();
    // Trim trailing newlines/whitespace
    value.erase(find_if(value.rbegin(), value.rend(), [](int ch) {
        return !isspace(ch);
    }).base(), value.end());
    return value;
}

// Helper: Resolve a symbolic link to its target path
string resolveSymlink(const string& linkPath) {
    char resolvedBuffer[PATH_MAX];
    ssize_t linkLength = readlink(linkPath.c_str(), resolvedBuffer, sizeof(resolvedBuffer) - 1);
    if (linkLength == -1) {
        cerr << "Error: Couldn't resolve symlink " << linkPath << endl;
        return "";
    }
    resolvedBuffer[linkLength] = '\0';
    return string(resolvedBuffer);
}

// Extract VID, PID, and serial from a udev-mapped camera device
bool getCameraUsbDetails(const string& deviceNode, string& outVid, string& outPid, string& outSerial) {
    // Step 1: Get the sysfs path for the video device
    string deviceName = deviceNode.substr(deviceNode.find_last_of('/') + 1);
    string videoSysLink = "/sys/class/video4linux/" + deviceName + "/device";
    
    // Resolve the link to the actual USB device directory
    string usbDevicePath = resolveSymlink(videoSysLink);
    if (usbDevicePath.empty()) {
        cerr << "Error: Couldn't find USB device path for " << deviceNode << endl;
        return false;
    }

    // Step 2: Read VID and PID
    outVid = readSysfsValue(usbDevicePath + "/idVendor");
    outPid = readSysfsValue(usbDevicePath + "/idProduct");
    if (outVid.empty() || outPid.empty()) {
        cerr << "Error: Failed to read VID/PID for device " << deviceNode << endl;
        return false;
    }

    // Step 3: Read serial number (note: not all cameras provide this)
    outSerial = readSysfsValue(usbDevicePath + "/serial");
    if (outSerial.empty()) {
        cout << "Warning: No serial number found for this camera (some devices don't provide one)" << endl;
    }

    return true;
}

// Example validation logic: Check if the camera matches allowed specs
bool validateCamera(const string& vid, const string& pid, const string& serial) {
    // Replace these with your allowed device values
    const string allowedVid = "046d";    // Logitech's VID
    const string allowedPid = "0825";    // Logitech C920's PID
    const string allowedSerial = "ABC123XYZ"; // Example serial number

    // First validate VID/PID (required check)
    if (vid != allowedVid || pid != allowedPid) {
        return false;
    }

    // Validate serial only if the device provides one (adjust based on your needs)
    if (!serial.empty() && serial != allowedSerial) {
        return false;
    }

    return true;
}

int main() {
    string targetDevice = "/dev/camera_one";
    string vid, pid, serial;

    if (getCameraUsbDetails(targetDevice, vid, pid, serial)) {
        cout << "Camera USB Information:" << endl;
        cout << "VID: 0x" << vid << endl;
        cout << "PID: 0x" << pid << endl;
        if (!serial.empty()) {
            cout << "Serial Number: " << serial << endl;
        }

        if (validateCamera(vid, pid, serial)) {
            cout << "\n✅ Camera validation passed!" << endl;
        } else {
            cout << "\n❌ Camera validation failed!" << endl;
        }
    } else {
        cerr << "Failed to retrieve camera details." << endl;
        return 1;
    }

    return 0;
}
Key Notes & Customization Tips
  • Sysfs Path Reliability: The example assumes your udev-mapped device name exists in /sys/class/video4linux/ (udev maintains these links by default). If this fails, you can run udevadm info -q path -n /dev/camera_one in the terminal to get the exact sysfs path, then adjust the videoSysLink variable accordingly.
  • Serial Number Edge Case: Not all USB cameras expose a serial number. Adjust the validateCamera function to either skip serial checks for such devices or mark them as invalid, depending on your security requirements.
  • Permissions: You'll need to run the compiled binary with sudo (or adjust device permissions via udev) to access sysfs files and device nodes.
  • Compilation: Build with g++ using: g++ camera_validator.cpp -o camera_validator

内容的提问来源于stack exchange,提问作者Rich

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:56:48