I'm working on a embedded Linux system (yocto) and I'm trying to simply get a list of the camera USB video devices (webcams) numbers with the related connected USB port from a C program.
I'm able to get the devices list with vendor ID and connected port doing this:
void usbdevs()
{
libusb_device*** list=NULL;
libusb_context *context = NULL;
ssize_t count;
uint8_t port;
char ncameras=0;
libusb_init(&context);
count = libusb_get_device_list(context,&list);
for(int i=0; i < MAX_NUM_CAMS; i++)
usb_dev_list[i]=0;
for (size_t idx = 0; idx < count; ++idx) {
libusb_device *device = list[idx];
struct libusb_device_descriptor desc = {0};
libusb_get_device_descriptor(device, &desc);
port = libusb_get_port_number(device);
printf("Vendor:Device = %04x:%04x Port: %d\n", desc.idVendor, desc.idProduct,port);
}
libusb_free_device_list(list, count);
libusb_exit(context);
}
What I need now is to know (from the C application) what v4l2 device number is related to the USB camera port, eg. I've got two webcam (same vendor ID) connected which appear as /dev/video0 and /dev/video1 respectively and I can get the connected port for each one using the above code, but,
how can I know which ports are connected each one?
I tried to get information from the devices using ioctl calls as it is recommended in this question but when I run the code:
int checkvideodev()
{
int fd;
struct video_capability video_cap;
struct video_window video_win;
struct video_picture video_pic;
if((fd = open("/dev/video0", O_RDONLY)) == -1){
perror("cam_info: Can't open device");
return 1;
}
if(xioctl(fd, VIDIOCGCAP, &video_cap) == -1)
perror("cam_info: Can't get capabilities");
else {
printf("Name:\t\t '%s'\n", video_cap.name);
printf("Minimum size:\t%d x %d\n", video_cap.minwidth, video_cap.minheight);
printf("Maximum size:\t%d x %d\n", video_cap.maxwidth, video_cap.maxheight);
}
if(xioctl(fd, VIDIOCGWIN, &video_win) == -1)
perror("cam_info: Can't get window information");
else
printf("Current size:\t%d x %d\n", video_win.width, video_win.height);
if(xioctl(fd, VIDIOCGPICT, &video_pic) == -1)
perror("cam_info: Can't get picture information");
else
printf("Current depth:\t%d\n", video_pic.depth);
close(fd);
return 0;
}
I've got the next errors:
cam_info: Can't get capabilities: Inappropriate ioctl for device
cam_info: Can't get window information: Inappropriate ioctl for device
cam_info: Can't get picture information: Inappropriate ioctl for device
If I'm checking through command line for instance I can get the capabilities without issues running:
v4l2-ctl --device /dev/video0 --list-formats-ext
Any ideas how can this be done?
I don't know if this specifically answers your question, but you can get useful information by globbing certain patterns under /dev or /sys, for example this will return the full device path (including PCI bus) of each video device,
#include <glob.h>
#include <unistd.h>
void list_videos() {
int i;
glob_t globbuf;
if (glob("/sys/class/video4linux/video*", 0, NULL, &globbuf) != 0) {
perror("glob");
return;
}
for (i=0; i < globbuf.gl_pathc; i++) {
char buf[256] = {};
if (readlink(globbuf.gl_pathv[i], buf, sizeof(buf)-1) > 0) {
puts(buf);
}
}
}
On one system with 2 cameras this prints,
../../devices/pci0000:00/0000:00:14.0/usb2/2-1/2-1.1/2-1.1:1.0/video4linux/video0
../../devices/pci0000:00/0000:00:14.0/usb2/2-3/2-3:1.0/video4linux/video1
Other interesting glob strings include /dev/v4l/by-id/*
and /dev/v4l/by-path/*
.