clinuxlinux-kernelvideo4linux

Video4Linux ioctl error (#25) when attempting to read device information from /dev/video0


I am currently attempting to retrieve device information for a built in web-cam using the following code:

#include <fcntl.h>
#include <unistd.h>
#include <linux/media.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

int main(int argc, char **argv) {
   int fd = open("/dev/video0", O_RDONLY, 0);
   if (fd > 0) {
       struct media_device_info *device_data = (struct media_device_info *) malloc (sizeof(struct media_device_info) * 1);

       if (ioctl(fd, MEDIA_IOC_DEVICE_INFO, device_data) ==  0)
            printf("Media Version: %u\nDriver: %s\nVersion: %d\nSerial: %s\n", (unsigned int) device_data->media_version, device_data->driver, (int) device_data->driver_version, device_data->serial);
        else {
               fprintf(stderr, "Couldn't get device info: %d: %s\n", errno, strerror(errno));
       }

       close(fd);
       free(device_data);
    }

    return 0;
}

When the code executes the else block is entered thus giving the following:

Couldn't get device info: 25: Inappropriate ioctl for device

From this it would seem that the device is being opened in the wrong manner such that ioctl cannot use the file descriptor. I must be missing something; could anyone here help me with regards to opening the /dev/video0 device?

Thanks!

p.s. If this has been answered before elsewhere please let me know. If this question is invalid in anyway then please accept my apologies.


Solution

  • It seems that the /dev/video* devices may be bound to separate /dev/media* devices, and you need to issue your MEDIA_IOC_DEVICE_INFO ioctl against the corresponding /dev/media* device for your /dev/video* device.

    As to how to locate that corresponding device id, the best I have come up with is to search for media* files within the /sys/class/video4linux/video{N}/device directory.

    For example, for a given device /dev/video0 on my system (kernel 4.15.0-34-generic), searching for media* files under /sys/class/video4linux/video0/device turned up media10, which I was then able to use to recover the serial number (open /dev/media10, issue the ioctl command).

    I don't know whether this method of finding the corresponding media devices is consistent across distros/versions/kernels/etc.