Commits

Alex Hixon  committed 92effb4

Patch from Hans de Goede for enabling v-flip on webcams that require it.

Better to have this upstream than downstream. :)
Thanks Hans.

  • Participants
  • Parent commits c2eb609

Comments (0)

Files changed (2)

 #include "config.h"
 #endif
 
+#define R5U870_REG_VFLIP_EX	0x30
+#define R5U870_REG_HFLIP_EX	0x31
+
 static gchar    *firmware       = "ucode/r5u87x-%vid%-%pid%.fw";
 static gboolean force_clear     = FALSE;
 static gboolean no_load         = FALSE;
 }
 
 struct usb_device *
-find_device (const struct device_info devices[], gint *version) {
-    struct device_info devinfo;
+find_device (const struct device_info devices[],
+	     const struct device_info **info) {
+    const struct device_info *devinfo;
     gint i = 0;
     struct usb_bus *busses;
     struct usb_bus *bus;
         
         for (dev = bus->devices; dev; dev = dev->next) {
             do {
-                devinfo = devices[i];
-                if (dev->descriptor.idVendor == devinfo.usb_vendor &&
-                    dev->descriptor.idProduct == devinfo.usb_product &&
+                devinfo = &devices[i];
+                if (dev->descriptor.idVendor == devinfo->usb_vendor &&
+                    dev->descriptor.idProduct == devinfo->usb_product &&
                     dev->descriptor.idVendor != 0) {
                     
-                    *version = devinfo.ucode_version;
+		    *info = devinfo;
                     return dev;
                 }
                 
                 i++;
-            } while (devinfo.usb_vendor != 0);
+            } while (devinfo->usb_vendor != 0);
             
             i = 0;
         }
 }
 
 gint
+r5u87x_image_flip(struct usb_dev_handle *handle, gboolean hflip,
+		  gboolean vflip) {
+    gint res;
+
+    res = usb_control_msg (handle, USB_SEND, 0xc2, hflip, R5U870_REG_HFLIP_EX,
+                NULL, 0, TIMEOUT);
+    if (res < 0) {
+        loader_warn ("Unable to set hflip to %u; res: %d\n", hflip, res);
+        return res;
+    }
+
+    res = usb_control_msg (handle, USB_SEND, 0xc2, vflip, R5U870_REG_VFLIP_EX,
+                NULL, 0, TIMEOUT);
+    if (res < 0) {
+        loader_warn ("Unable to set vflip to %u; res: %d\n", vflip, res);
+        return res;
+    }
+
+    return 0;
+}
+
+gint
 r5u87x_ucode_upload (gint firmware, struct usb_dev_handle *handle, gint size) {
     gint length, remaining, address, index, res;
     unsigned char header[3], payload[1024];
 }
 
 gint
-load_firmware (struct usb_device *dev, const gint ucode_version) {
+load_firmware (struct usb_device *dev, usb_dev_handle *handle,
+               const struct device_info *devinfo) {
     gint fd, res, dev_version;
-    usb_dev_handle *handle;
     struct stat infobuf;
 
     dev_version = 0;
         loader_error ("Failed to get filesize of firmware (%s).\n", firmware);
     }
     
-    // Try the USB device too.
-    if (!(handle = usb_open (dev))) {
-        loader_warn ("Failed to open USB device.\n");
-    }
-    
     // Check to see if there's already stuff on there.
     res = r5u87x_ucode_status (handle);
     if (res < 0) {
         
         if (res < 0) {
             return res;
-        } else if (dev_version != ucode_version && dev_version != 0x0001) {
+        } else if (dev_version != devinfo->ucode_version &&
+		   dev_version != 0x0001) {
             // Clear it out - ucode version and device version don't match.
             loader_warn ("Microcode versions don't match, clearing.\n");
             res = r5u87x_ucode_clear (handle);
         res = r5u87x_ucode_version (handle, &dev_version);
         if (res < 0) {
             return res;
-        } else if (dev_version != ucode_version) {
+        } else if (dev_version != devinfo->ucode_version) {
             loader_warn ("Camera returned unexpected ucode version 0x%04x - "
-                "expected 0x%04x\n", dev_version, ucode_version);
+                "expected 0x%04x\n", dev_version, devinfo->ucode_version);
             return -EBADMSG;
         }
     } else {
 main (gint argc, gchar *argv []) {
     GOptionContext *context;
     GError *error = NULL;
+    const struct device_info *devinfo;
     struct usb_device *dev;
-    gint version = 0;
+    usb_dev_handle *handle;
     
     g_set_prgname ("loader");
     context = g_option_context_new("- Ricoh R5U87x series firmware loader");
     
     loader_msg ("Searching for device...\n");
     
-    dev = find_device (device_table, &version);
+    dev = find_device (device_table, &devinfo);
     
     if (dev == NULL) {
         loader_error ("Failed to find any supported webcams.\n");
     }
     
-    int res = load_firmware (dev, version);
+    if (!(handle = usb_open (dev))) {
+        loader_error ("Failed to open USB device.\n");
+    }
+    
+    int res = load_firmware (dev, handle, devinfo);
     if (res < 0) {
         loader_error ("Failed to upload firmware to device: %s (code %d).\n%s",
             strerror (errno), res,
             dev->descriptor.idVendor, dev->descriptor.idProduct);
     }
     
+    r5u87x_image_flip (handle, devinfo->hflip, devinfo->vflip);
     
     if (reload) {
         gint status;
     int usb_vendor;
     int usb_product;
     int ucode_version;
+    int hflip;
+    int vflip;
 };
 
 struct usb_device*
-find_device (const struct device_info devices[], gint *version);
+find_device (const struct device_info devices[],
+	     const struct device_info **info);
 
 /*
  * Please try to keep this in sync with docs/model_matrix.txt and
  * docs/firmware_matrix.txt
  */
 static const struct device_info device_table[] = {
-    { 0x05CA, 0x1803, 0xFFFF }, // Unknown ucode version.
-    { 0x05CA, 0x1810, 0x0115 },
+    { 0x05CA, 0x1803, 0xFFFF, 0, 0 }, // Unknown ucode version.
+    { 0x05CA, 0x1810, 0x0115, 0, 0 },
     /* 05ca:1812 does not require ucode. */
-    { 0x05CA, 0x1830, 0x0100 },
-    { 0x05CA, 0x1832, 0x0100 },
-    { 0x05CA, 0x1833, 0x0100 },
-    { 0x05CA, 0x1834, 0x0111 },
-    { 0x05CA, 0x1835, 0x0107 },
-    { 0x05CA, 0x1836, 0x0115 },
-    { 0x05CA, 0x1837, 0x0115 }, // Uses copy of 0x1836 ucode.
-    { 0x05CA, 0x1839, 0x0030 },
-    { 0x05CA, 0x183a, 0x0111 },
-    { 0x05CA, 0x183b, 0x0131 },
-    { 0x05CA, 0x183e, 0x0100 },
-    { 0x05CA, 0x1841, 0x0103 },
+    { 0x05CA, 0x1830, 0x0100, 0, 0 },
+    { 0x05CA, 0x1832, 0x0100, 0, 0 },
+    { 0x05CA, 0x1833, 0x0100, 0, 0 },
+    { 0x05CA, 0x1834, 0x0111, 0, 0 },
+    { 0x05CA, 0x1835, 0x0107, 0, 0 },
+    { 0x05CA, 0x1836, 0x0115, 0, 0 },
+    { 0x05CA, 0x1837, 0x0115, 1, 1 }, // Uses copy of 0x1836 ucode.
+    { 0x05CA, 0x1839, 0x0030, 0, 0 },
+    { 0x05CA, 0x183a, 0x0111, 0, 0 },
+    { 0x05CA, 0x183b, 0x0131, 0, 0 },
+    { 0x05CA, 0x183e, 0x0100, 0, 0 },
+    { 0x05CA, 0x1841, 0x0103, 0, 0 },
     
     /*
      * These have been commented out because we don't have the routines
      * to determine which is which yet.
      * 
-     * { 0x05CA, 0x1870, 0x0100 },  // Used for HP Webcam 1000      (1870_1.fw)
-     * { 0x05CA, 0x1870, 0x0112 },  // Used for HP Pavilion dv1xxxx (1870.fw)
+     * { 0x05CA, 0x1870, 0x0100, 0, 0 },  // Used for HP Webcam 1000      (1870_1.fw)
+     * { 0x05CA, 0x1870, 0x0112, 0, 0 },  // Used for HP Pavilion dv1xxxx (1870.fw)
      */
      
      { }