diff --git a/c/flipped_webcam/flipped_webcam.c b/c/flipped_webcam/flipped_webcam.c new file mode 100644 index 0000000..5e3d8b2 --- /dev/null +++ b/c/flipped_webcam/flipped_webcam.c @@ -0,0 +1,193 @@ + +// +#include +#include +#include + +struct v4lcontrol_flags_info { + unsigned short vendor_id; + unsigned short product_id; + unsigned short product_mask; + /*const */char *dmi_board_vendor; + /*const */char *dmi_board_name; + /* We could also use the USB manufacturer and product strings some devices have + const char *manufacturer; + const char *product; */ + int flags; + int default_gamma; + /* Some seldom used dmi strings (for notebooks with bogus info in the board + entries, but usefull info elsewhere). We keep this at the end as to not + polute the initalizers for the normal case. */ + /* System (product) vendor / name */ + const char *dmi_system_vendor; + const char *dmi_system_name; + /* Board and System versions */ + const char *dmi_board_version; + const char *dmi_system_version; +}; + +/* Controls */ +enum { + V4LCONTROL_WHITEBALANCE, + V4LCONTROL_HFLIP, + V4LCONTROL_VFLIP, + V4LCONTROL_GAMMA, + /* All fake controls above here are auto enabled when not present in hw */ + V4LCONTROL_AUTO_ENABLE_COUNT, + V4LCONTROL_AUTOGAIN, + V4LCONTROL_AUTOGAIN_TARGET, + V4LCONTROL_COUNT +}; + + +struct v4lcontrol_data { + int fd; /* Device fd */ + int flags; /* Flags for this device */ + int priv_flags; /* Internal use only flags */ + int controls; /* Which controls to use for this device */ + unsigned int *shm_values; /* shared memory control value store */ + unsigned int old_values[V4LCONTROL_COUNT]; /* for controls_changed() */ + /*const */struct v4lcontrol_flags_info/* **/flags_info; +}; + +static void v4lcontrol_get_dmi_string(const char *string, char *buf, int size) +{ + FILE *f; + char *s, sysfs_name[512]; + + snprintf(sysfs_name, sizeof(sysfs_name), + "/sys/class/dmi/id/%s", string); + f = fopen(sysfs_name, "r"); + if (!f) { + /* Try again with a different sysfs path, not sure if this is needed + but we used to look under /sys/devices/virtual/dmi/id in older + libv4l versions, but this did not work with some kernels */ + snprintf(sysfs_name, sizeof(sysfs_name), + "/sys/devices/virtual/dmi/id/%s", string); + f = fopen(sysfs_name, "r"); + if (!f) { + buf[0] = 0; + return; + } + } + + s = fgets(buf, size, f); + if (s) + s[strlen(s) - 1] = 0; + fclose(f); +} + +static int v4lcontrol_get_usb_ids(struct v4lcontrol_data *data, + unsigned short *vendor_id, unsigned short *product_id) +{ + FILE *f; + int i, minor; + struct stat st; + char sysfs_name[512]; + char c, *s, buf[32]; + + if (fstat(data->fd, &st) || !S_ISCHR(st.st_mode)) + return 0; /* Should never happen */ + + /* 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); + + 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/modalias", i); + f = fopen(sysfs_name, "r"); + 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 */ + } + + return 1; +} + +int main(int argc, char *argv[]) +{ + char dmi_board_vendor[512], dmi_board_name[512]; + + unsigned short vendor_id = 0; + unsigned short product_id = 0; + struct v4lcontrol_data *data = calloc(1, sizeof(struct v4lcontrol_data)); + + /* Get DMI board and system strings */ + v4lcontrol_get_dmi_string("board_vendor", dmi_board_vendor, + sizeof(dmi_board_vendor)); + v4lcontrol_get_dmi_string("board_name", dmi_board_name, + sizeof(dmi_board_name)); + + data->flags_info.dmi_board_name = dmi_board_vendor; + data->flags_info.dmi_board_name = dmi_board_name; + + /* Get Bus and Device ids */ + int got_usb_ids = v4lcontrol_get_usb_ids(data, &vendor_id, &product_id); + + if (!got_usb_ids) { + fprintf(stderr, "Sorry, webcamera device not recognised :("); + exit(-1); + } + + puts("If Your PC is a Laptop add this two strings to mediat-tv/v4l-utils/lib/libv4lconvert/control/libv4lcontrol.c:"); + printf(" { 0x%4.4x, 0x%4.4x, 0, \"%s\", \"%s\",\n", vendor_id, product_id, dmi_board_vendor, dmi_board_name); + puts(" V4LCONTROL_HFLIPPED | V4LCONTROL_VFLIPPED },"); + puts("\n"); + puts("Otherwise if Your PC is a Desktop string lines should look like this:"); + printf(" { 0x%4.4x, 0x%4.4x, 0, NULL, NULL,\n", vendor_id, product_id); + puts(" V4LCONTROL_HFLIPPED | V4LCONTROL_VFLIPPED },"); + puts("\n"); + puts("Rebuild the package and send to v4l maintainers Your camera info."); + + return EXIT_SUCCESS; +}//?>