Greetings,

This patch brings the Philips Webcam driver up to version 8.3. It has the 
following changes:

* Adding Samsung C10 and C30 cameras
* Removing palette module parameter
* Fixed typo in ID of QuickCam 3000 Pro
* Adding LED settings (blinking while in use) for ToUCam cameras.
* Turns LED off when camera is not in use.
* Updates documentation to remove some erronuous statements and describes 
the new LED stuff

This is against 2.4.12, but should apply to 2.4.10 as well.

Please apply.

 - Nemosoft
Only in linux-2.4.12/drivers/usb: .depend
diff -aur linux-2.4.12-dist/drivers/usb/pwc-ctrl.c linux-2.4.12/drivers/usb/pwc-ctrl.c
--- linux-2.4.12-dist/drivers/usb/pwc-ctrl.c    Fri Oct 12 00:10:36 2001
+++ linux-2.4.12/drivers/usb/pwc-ctrl.c Sun Oct 14 22:53:33 2001
@@ -495,7 +495,7 @@
 }
 
 
-#ifdef __KERNEL__
+
 /* BRIGHTNESS */
 
 int pwc_get_brightness(struct pwc_device *pdev)
@@ -983,6 +983,7 @@
        
        return (buf << 8);
 }
+
 static inline int pwc_read_blue_gain(struct pwc_device *pdev)
 {
        unsigned char buf;
@@ -1001,43 +1002,55 @@
        return (buf << 8);
 }
 
-/* still unused (it doesn't work yet...) */
-static inline int pwc_set_led(struct pwc_device *pdev, int value)
+int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
 {
-       unsigned char buf;
+       unsigned char buf[2];
 
-       if (value < 0)
-               value = 0;
-       if (value > 0xffff)
-               value = 0xffff;
+       if (pdev->type < 730)
+               return 0;
+       if (on_value < 0)
+               on_value = 0;
+       if (on_value > 0xff)
+               on_value = 0xff;
+       if (off_value < 0)
+               off_value = 0;
+       if (off_value > 0xff)
+               off_value = 0xff;
 
-       buf = (value >> 8);
+       buf[0] = on_value;
+       buf[1] = off_value;
 
        return usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0),
                SET_STATUS_CTL,
                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                LED_FORMATTER,
                pdev->vcinterface,
-               &buf, 1, HZ / 2);
+               &buf, 2, HZ / 2);
 }
 
-/* still unused (it doesn't work yet...) */
-static inline int pwc_get_led(struct pwc_device *pdev)
+int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
 {
-       unsigned char buf;
+       unsigned char buf[2];
        int ret;
        
+       if (pdev->type < 730) {
+               *on_value = -1;
+               *off_value = -1;
+               return 0;
+       }
+
        ret = usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0),
                GET_STATUS_CTL,
                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                LED_FORMATTER,
                pdev->vcinterface,
-               &buf, 1, HZ / 2);
+               &buf, 2, HZ / 2);
 
        if (ret < 0)
-           return ret;
-       
-       return (buf << 8);
+               return ret;
+       *on_value = buf[0];
+       *off_value = buf[1];
+       return 0;
 }
 
  /* End of Add-Ons                                    */
@@ -1167,15 +1180,15 @@
 
         case VIDIOCPWCSLED:
        {
-           int led, ret;
-           if (copy_from_user(&led,arg,sizeof(led)))
-               return -EFAULT;
-           else {
-               /* ret = pwc_set_led(pdev, led); */
-               ret = 0;
+               int ret;
+               struct pwc_leds leds;
+
+               if (copy_from_user(&leds, arg, sizeof(leds)))
+                       return -EFAULT;
+
+               ret = pwc_set_leds(pdev, leds.led_on, leds.led_off);
                if (ret<0)
                    return ret;
-           }
            break;
        }
 
@@ -1184,11 +1197,12 @@
        case VIDIOCPWCGLED:
        {
                int led;
+               struct pwc_leds leds;
                
-               led = pwc_get_led(pdev); 
+               led = pwc_get_leds(pdev, &leds.led_on, &leds.led_off); 
                if (led < 0)
                        return -EINVAL;
-               if (copy_to_user(arg, &led, sizeof(led)))
+               if (copy_to_user(arg, &leds, sizeof(leds)))
                        return -EFAULT;
                break;
        }
@@ -1202,9 +1216,6 @@
        }
        return 0;
 }
-
-#endif
-
 
 
 
diff -aur linux-2.4.12-dist/drivers/usb/pwc-if.c linux-2.4.12/drivers/usb/pwc-if.c
--- linux-2.4.12-dist/drivers/usb/pwc-if.c      Fri Oct 12 00:10:36 2001
+++ linux-2.4.12/drivers/usb/pwc-if.c   Sun Oct 14 23:16:49 2001
@@ -73,7 +73,9 @@
        { USB_DEVICE(0x0471, 0x0311) },
        { USB_DEVICE(0x0471, 0x0312) },
        { USB_DEVICE(0x069A, 0x0001) },
-       { USB_DEVICE(0x046D, 0x0b80) },
+       { USB_DEVICE(0x046D, 0x08b0) },
+       { USB_DEVICE(0x055D, 0x9000) },
+       { USB_DEVICE(0x055D, 0x9001) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, pwc_device_table);
@@ -96,6 +98,7 @@
 static int default_mbufs = 2;  /* Default number of mmap() buffers */
        int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
 static int power_save = 0;
+static int led_on = 1, led_off = 0; /* defaults to LED that is on while in use */
 int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
 
 static struct semaphore mem_lock;
@@ -592,7 +595,8 @@
        pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
 }
 
-/* XXX: 2001-06-17: The YUV420 palette will be phased out soon */
+/* 2001-10-14: The YUV420 is still there, but you can only set it from within 
+   a program (YUV420P being the default) */
 static int pwc_set_palette(struct pwc_device *pdev, int pal)
 {
        if (   pal == VIDEO_PALETTE_YUV420
@@ -947,14 +951,16 @@
                        Info("Failed to set alternate interface to 0.\n");
                pdev->usb_init = 1;
        }
-       else {
-               /* Turn on camera */
-               if (power_save) {
-                       i = pwc_camera_power(pdev, 1);
-                       if (i < 0)
-                               Info("Failed to restore power to the camera! (%d)\n", 
i);
-               }
+
+       /* Turn on camera */
+       if (power_save) {
+               i = pwc_camera_power(pdev, 1);
+               if (i < 0)
+                       Info("Failed to restore power to the camera! (%d)\n", i);
        }
+       /* Set LED on/off time */
+       if (pwc_set_leds(pdev, led_on, led_off) < 0)
+               Info("Failed to set LED on/off time.\n");
 
        /* Find our decompressor, if any */
        pdev->decompressor = pwc_find_decompressor(pdev->type);
@@ -1007,6 +1013,7 @@
                up(&pdev->modlock);
                return i;
        }
+       
        i = usb_set_interface(pdev->udev, 0, pdev->valternate);
        if (i) {
                Trace(TRACE_OPEN, "Failed to set alternate interface = %d.\n", i);
@@ -1066,7 +1073,10 @@
                Trace(TRACE_OPEN, "Normal close(): setting interface to 0.\n");
                usb_set_interface(pdev->udev, 0, 0);
 
-               /* Turn off LED by powering down camera */
+               /* Turn LEDs off */
+               if (pwc_set_leds(pdev, 0, 0) < 0)
+                       Info("Failed to set LED on/off time..\n");
+               /* Power down camere to save energy */
                if (power_save) {
                        i = pwc_camera_power(pdev, 0);
                        if (i < 0) 
@@ -1656,18 +1666,37 @@
                        break;
                }
        }
-        else if (vendor_id == 0x046d) {
-               switch(product_id) {
-               case 0x08b0:
-                       Info("Logitech QuickCam 3000 Pro detected.\n");
-                       type_id = 730;
+       else if (vendor_id == 0x046d) {
+               switch(product_id) {
+               case 0x08b0:
+                       Info("Logitech QuickCam 3000 Pro detected.\n");
+                       type_id = 730;
                        break;
                default:
                        return NULL;
                        break;
                }
         }
-        else return NULL; /* Not Philips or Askey, for sure. */
+       else if (vendor_id == 0x055d) {
+               /* I don't know the difference between the C10 and the C30;
+                  I suppose the difference is the sensor, but both cameras
+                  work equally well with a type_id of 675
+                */
+               switch(product_id) {
+               case 0x9000:
+                       Info("Samsung MPC-C10 USB webcam detected.\n");
+                       type_id = 675;
+                       break;
+               case 0x9001:
+                       Info("Samsung MPC-C30 USB webcam detected.\n");
+                       type_id = 675;
+                       break;
+               default:
+                       return NULL;
+                       break;
+               }
+       }
+       else return NULL; /* Not Philips, Askey, Logitech or Samsung, for sure. */
 
        if (udev->descriptor.bNumConfigurations > 1)
                Info("Warning: more than 1 configuration available.\n");
@@ -1799,19 +1828,17 @@
 
 static char *size = NULL;
 static int fps = 0;
-static char *palette = NULL;
 static int fbufs = 0;
 static int mbufs = 0;
 static int trace = -1;
 static int compression = -1;
+static int leds[2] = { -1, -1 };
 
 MODULE_PARM(video_nr, "i");
 MODULE_PARM(size, "s");
 MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
 MODULE_PARM(fps, "i");
 MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 
5-30");
-MODULE_PARM(palette, "s");
-MODULE_PARM_DESC(palette, "Initial colour format of images. One of yuv420, yuv420p");
 MODULE_PARM(fbufs, "i");
 MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
 MODULE_PARM(mbufs, "i");
@@ -1822,7 +1849,8 @@
 MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
 MODULE_PARM(compression, "i");
 MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) 
to 3 (high compression)");
-
+MODULE_PARM(leds, "2i");
+MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
 MODULE_DESCRIPTION("Philips USB webcam driver");
 MODULE_AUTHOR("Nemosoft Unv. <[EMAIL PROTECTED]>");
 MODULE_LICENSE("GPL");
@@ -1833,7 +1861,7 @@
        char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
 
        Info("Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module 
version " PWC_VERSION " loaded.\n");
-       Info("Also supports Askey VC010 cam.\n");
+       Info("Also supports the Askey VC010, Logitech Quickcam 3000 Pro and the 
+Samsung MPC-C10 and MPC-C30.\n");
 
        if (fps) {
                if (fps < 5 || fps > 30) {
@@ -1858,18 +1886,6 @@
                }
                Info("Default image size set to %s [%dx%d].\n", 
sizenames[default_size], pwc_image_sizes[default_size].x, 
pwc_image_sizes[default_size].y);
        }
-       if (palette) {
-               /* Determine default palette */
-               if (!strcmp(palette, "yuv420"))
-                       default_palette = VIDEO_PALETTE_YUV420;
-               else if (!strcmp(palette, "yuv420p"))
-                       default_palette = VIDEO_PALETTE_YUV420P;
-               else {
-                       Err("Palette not recognized: try palette=yuv420 or 
yuv420p.\n");
-                       return -EINVAL;
-               }
-               Info("Default palette set to %d.\n", default_palette);
-       }
        if (mbufs) {
                if (mbufs < 1 || mbufs > MAX_IMAGES) {
                        Err("Illegal number of mmap() buffers; use a number between 1 
and %d.\n", MAX_IMAGES);
@@ -1900,6 +1916,10 @@
        }
        if (power_save)
                Info("Enabling power save on open/close.\n");
+       if (leds[0] >= 0)
+               led_on = leds[0] / 100;
+       if (leds[1] >= 0)
+               led_off = leds[1] / 100;
 
        init_MUTEX(&mem_lock);
        Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
diff -aur linux-2.4.12-dist/drivers/usb/pwc-ioctl.h 
linux-2.4.12/drivers/usb/pwc-ioctl.h
--- linux-2.4.12-dist/drivers/usb/pwc-ioctl.h   Fri Oct 12 00:10:37 2001
+++ linux-2.4.12/drivers/usb/pwc-ioctl.h        Sun Oct 14 20:48:15 2001
@@ -76,6 +76,15 @@
 };
 
 
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+       int led_on;                     /* Led on-time; range = 0..255 */
+       int led_off;                    /*  */
+};
+
+
+
  /* Restore user settings */
 #define VIDIOCPWCRUSER         _IO('v', 192)
  /* Save user settings */
@@ -107,9 +116,8 @@
 #define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
 
  /* Turn LED on/off ; int range 0..65535 */
-#define VIDIOCPWCSLED           _IOW('v', 205, int)
-
+#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
  /* Get state of LED; int range 0..65535 */
-#define VIDIOCPWCGLED           _IOR('v', 205, int)
+#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
 
 #endif
diff -aur linux-2.4.12-dist/drivers/usb/pwc.h linux-2.4.12/drivers/usb/pwc.h
--- linux-2.4.12-dist/drivers/usb/pwc.h Fri Oct 12 00:10:37 2001
+++ linux-2.4.12/drivers/usb/pwc.h      Sun Oct 14 21:39:14 2001
@@ -60,8 +60,8 @@
 
 /* Version block */
 #define PWC_MAJOR      8
-#define PWC_MINOR      2
-#define PWC_VERSION    "8.2"
+#define PWC_MINOR      3
+#define PWC_VERSION    "8.3"
 #define PWC_NAME       "pwc"
 
 /* Turn certain features on/off */
@@ -245,6 +245,8 @@
 extern int pwc_set_gamma(struct pwc_device *pdev, int value);
 extern int pwc_get_saturation(struct pwc_device *pdev);
 extern int pwc_set_saturation(struct pwc_device *pdev, int value);
+extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
+extern int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value);
 
 /* Power down or up the camera; not supported by all models */
 extern int pwc_camera_power(struct pwc_device *pdev, int power);
Only in linux-2.4.12/drivers/usb/serial: .depend
Only in linux-2.4.12/drivers/usb/storage: .depend
diff -aur linux-2.4.12-dist/Documentation/usb/philips.txt 
linux-2.4.12/Documentation/usb/philips.txt
--- linux-2.4.12-dist/Documentation/usb/philips.txt     Fri Oct 12 00:11:02 2001
+++ linux-2.4.12/Documentation/usb/philips.txt  Sun Oct 14 23:10:27 2001
@@ -22,21 +22,12 @@
 size
    Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
    'vga', for an image size of resp. 128x96, 160x120, 176x144,
-   320x240, 352x288 and 640x480 (of course, only for those cameras that support these 
resolutions).
+   320x240, 352x288 and 640x480 (of course, only for those cameras that 
+   support these resolutions).
 
 fps
    Specifies the desired framerate. Is an integer in the range of 4-30.
 
-palette
-   Specifies the desired colour order that should be delivered by read() and
-   mmap(). The string can be one of yuv420 or yuv420p; however, yuv420 will
-   be phased out, leaving only yuv420p, so this option will disappear
-   entirely.
-
-   Only the native yuv420/yuv420p format is supported by the in kernel driver. 
-   If you want to use other formats with in-kernel conversion download the
-   driver from the URL given. [Alan]
-
 fbufs
    This paramter specifies the number of internal buffers to use for storing 
    frames from the cam. This will help if the process that reads images from 
@@ -88,6 +79,26 @@
       
    The compression parameter only applies to the Vesta & ToUCam cameras.
    The 645 and 646 have fixed compression parameters.      
+
+leds
+   This settings takes 2 integers, that define the on/off time for the LED
+   (in milliseconds). One of the interesting things that you can do with
+   this is let the LED blink while the camera is in use. This:
+
+     leds=500,500
+      
+   will blink the LED once every second. But with:
+
+     leds=0,0
+
+   the LED never goes on, making it suitable for silent survaillance.
+
+   By default the camera's LED is on solid while in use, and turned off
+   when the camera is not used anymore.
+
+   This parameter works only with the ToUCam range of cameras (730, 740,
+   750). For other cameras this command is silently ignored, and the LED
+   cannot be controlled.
 
 trace
    In order to better detect problems, it is now possible to turn on a

Reply via email to