diff options
Diffstat (limited to 'v4l2-apps')
-rw-r--r-- | v4l2-apps/libv4l/ChangeLog | 3 | ||||
-rw-r--r-- | v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 77 |
2 files changed, 63 insertions, 17 deletions
diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog index 21d60dabb..9b029d68b 100644 --- a/v4l2-apps/libv4l/ChangeLog +++ b/v4l2-apps/libv4l/ChangeLog @@ -2,6 +2,9 @@ libv4l-0.5.10 ------------- * sn9c20x cams have occasional bad jpeg frames, drop these to avoid the flickering effect they cause, by: Brian Johnson <brijohn@gmail.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 libv4l-0.5.9 ------------ 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 && |