diff options
author | hans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain> | 2009-03-27 10:39:24 +0100 |
---|---|---|
committer | hans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain> | 2009-03-27 10:39:24 +0100 |
commit | 4f4f2f81fd16cc9a8b777452b64b3b2ffb4d819c (patch) | |
tree | 13e8e642bdc66456f29adb1eea815f7ce275c9fa /v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | |
parent | 6880d6f23b93031ceab3ce0952359c77d124a89f (diff) | |
download | mediapointer-dvb-s2-4f4f2f81fd16cc9a8b777452b64b3b2ffb4d819c.tar.gz mediapointer-dvb-s2-4f4f2f81fd16cc9a8b777452b64b3b2ffb4d819c.tar.bz2 |
libv4l: Fix upside down detection with certain usb devices
From: Hans de Goede <hdegoede@redhat.com>
* adjust libv4l's upside down cam detection to also work with devices
which have the usb interface as parent instead of the usb device
* fix libv4l upside down detection for the new v4l minor numbering scheme
Priority: normal
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Diffstat (limited to 'v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c')
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 77 |
1 files changed, 60 insertions, 17 deletions
diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c index 5467c695a..f11922f3d 100644 --- a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c @@ -98,30 +98,73 @@ static int v4lconvert_get_flags(int fd) char sysfs_name[512]; unsigned short vendor_id = 0; unsigned short product_id = 0; - int i; + int i, minor; + char c, *s, buf[32]; if (fstat(fd, &st) || !S_ISCHR(st.st_mode)) return 0; /* Should never happen */ - /* Get product ID */ - snprintf(sysfs_name, sizeof(sysfs_name), - "/sys/class/video4linux/video%d/device/idVendor", - minor(st.st_rdev)); - f = fopen(sysfs_name, "r"); - if (!f) - return 0; /* Not an USB device (or no sysfs) */ - i = fscanf(f, "%hx", &vendor_id); - fclose(f); + /* <Sigh> find ourselve in sysfs */ + for (i = 0; i < 256; i++) { + snprintf(sysfs_name, sizeof(sysfs_name), + "/sys/class/video4linux/video%d/dev", i); + f = fopen(sysfs_name, "r"); + if (!f) + continue; + + s = fgets(buf, sizeof(buf), f); + fclose(f); - /* Get product ID */ + if (s && sscanf(buf, "%*d:%d%c", &minor, &c) == 2 && c == '\n' && + minor == minor(st.st_rdev)) + break; + } + if (i == 256) + return 0; /* Not found, sysfs not mounted? */ + + /* Get vendor and product ID */ snprintf(sysfs_name, sizeof(sysfs_name), - "/sys/class/video4linux/video%d/device/idProduct", - minor(st.st_rdev)); + "/sys/class/video4linux/video%d/device/modalias", i); f = fopen(sysfs_name, "r"); - if (!f) - return 0; /* Should never happen */ - i = fscanf(f, "%hx", &product_id); - fclose(f); + if (f) { + s = fgets(buf, sizeof(buf), f); + fclose(f); + + if (!s || + sscanf(s, "usb:v%4hxp%4hx%c", &vendor_id, &product_id, &c) != 3 || + c != 'd') + return 0; /* Not an USB device */ + } else { + /* Try again assuming the device link points to the usb + device instead of the usb interface (bug in older versions + of gspca) */ + + /* Get product ID */ + snprintf(sysfs_name, sizeof(sysfs_name), + "/sys/class/video4linux/video%d/device/idVendor", i); + f = fopen(sysfs_name, "r"); + if (!f) + return 0; /* Not an USB device (or no sysfs) */ + + s = fgets(buf, sizeof(buf), f); + fclose(f); + + if (!s || sscanf(s, "%04hx%c", &vendor_id, &c) != 2 || c != '\n') + return 0; /* Should never happen */ + + /* Get product ID */ + snprintf(sysfs_name, sizeof(sysfs_name), + "/sys/class/video4linux/video%d/device/idProduct", i); + f = fopen(sysfs_name, "r"); + if (!f) + return 0; /* Should never happen */ + + s = fgets(buf, sizeof(buf), f); + fclose(f); + + if (!s || sscanf(s, "%04hx%c", &product_id, &c) != 2 || c != '\n') + return 0; /* Should never happen */ + } for (i = 0; i < ARRAY_SIZE(v4lconvert_flags); i++) if (v4lconvert_flags[i].vendor_id == vendor_id && |