From: Nemosoft Unv. <nemosoft@smcc.demon.nl> To: linux-usb-devel@lists.sourceforge.net Subject: [linux-usb-devel] [PATH] PWC 8.3 Date: Sun, 14 Oct 2001 23:25:24 +0200 Cc: Greg KH <greg@kroah.com> 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. <nemosoft@smcc.demon.nl>"); 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