summaryrefslogtreecommitdiff
path: root/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
diff options
context:
space:
mode:
authorhans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain>2009-03-27 10:39:24 +0100
committerhans@rhel5-devel.localdomain <hans@rhel5-devel.localdomain>2009-03-27 10:39:24 +0100
commit4f4f2f81fd16cc9a8b777452b64b3b2ffb4d819c (patch)
tree13e8e642bdc66456f29adb1eea815f7ce275c9fa /v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c
parent6880d6f23b93031ceab3ce0952359c77d124a89f (diff)
downloadmediapointer-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.c77
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 &&