]> git.pld-linux.org Git - packages/kernel.git/commitdiff
- latest pwc drivers
authoraflinta <aflinta@pld-linux.org>
Tue, 7 Jan 2003 08:00:46 +0000 (08:00 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    linux-2.4.20-pwc.patch -> 1.1

linux-2.4.20-pwc.patch [new file with mode: 0644]

diff --git a/linux-2.4.20-pwc.patch b/linux-2.4.20-pwc.patch
new file mode 100644 (file)
index 0000000..2f20b17
--- /dev/null
@@ -0,0 +1,829 @@
+diff -urN linux-2.4.20.orig/Documentation/usb/philips.txt linux-2.4.20/Documentation/usb/philips.txt
+--- linux-2.4.20.orig/Documentation/usb/philips.txt    Mon Jan  6 22:16:06 2003
++++ linux-2.4.20/Documentation/usb/philips.txt Mon Dec 16 22:19:15 2002
+@@ -1,13 +1,34 @@
+-This file contains some additional information for the Philips webcams.
+-E-mail: webcam@smcc.demon.nl                        Last updated: 2001-09-24
+-
+-The main webpage for the Philips driver is http://www.smcc.demon.nl/webcam/.
+-It contains a lot of extra information, a FAQ, and the binary plugin
+-'PWCX'. This plugin contains decompression routines that allow you to
+-use higher image sizes and framerates; in addition the webcam uses less
+-bandwidth on the USB bus (handy if you want to run more than 1 camera
+-simultaneously). These routines fall under an NDA, and may therefor not be
+-distributed as source; however, its use is completely optional.
++This file contains some additional information for the Philips and OEM webcams.
++E-mail: webcam@smcc.demon.nl                        Last updated: 2002-11-28
++Site: http://www.smcc.demon.nl/webcam/
++As of this moment, the following cameras are supported:
++ * Philips PCA645
++ * Philips PCA646
++ * Philips PCVC675
++ * Philips PCVC680
++ * Philips PCVC690
++ * Philips PCVC730
++ * Philips PCVC740
++ * Philips PCVC750
++ * Askey VC010
++ * Creative Labs Webcam 5
++ * Logitech QuickCam 3000 Pro
++ * Logitech QuickCam Notebook
++ * Logitech QuickCam 4000 Pro
++ * Logitech QuickCam Zoom
++ * Samsung MPC-C10
++ * Samsung MPC-C30
++ * Sotec Afina Eye
++ * Visionite VCS-UM100
++ * Visionite VCS-UC300
++
++The main webpage for the Philips driver is at the address above. It contains
++a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin
++contains decompression routines that allow you to use higher image sizes and
++framerates; in addition the webcam uses less bandwidth on the USB bus (handy
++if you want to run more than 1 camera simultaneously). These routines fall
++under a NDA, and may therefor not be distributed as source; however, its use
++is completely optional.
+ You can build this code either into your kernel, or as a module. I recommend
+ the latter, since it makes troubleshooting a lot easier. The built-in
+@@ -98,6 +119,9 @@
+    750). For other cameras this command is silently ignored, and the LED
+    cannot be controlled.
++   Finally: this parameters does not take effect UNTIL the first time you
++   open the camera device. Until then, the LED remains on.
++
+ dev_hint
+    A long standing problem with USB devices is their dynamic nature: you
+    never know what device a camera gets assigned; it depends on module load
+@@ -126,7 +150,7 @@
+                                other cameras will get the first free 
+                                available slot (see below).
+-     dev_hint=645:1,680=2      The PCA645 camera will get /dev/video1,
++     dev_hint=645:1,680:2      The PCA645 camera will get /dev/video1,
+                                and a PCVC680 /dev/video2.
+                                
+      dev_hint=645.0123:3,645.4567:0   The PCA645 camera with serialnumber 
+@@ -176,6 +200,7 @@
+       64   0x40   Show viewport and image sizes                       Off
++     128   0x80   PWCX debugging                                      Off
+    For example, to trace the open() & read() fuctions, sum 8 + 4 = 12,
+    so you would supply trace=12 during insmod or modprobe. If
+@@ -189,10 +214,10 @@
+ The fbufs, mbufs and trace parameters are global and apply to all connected
+ cameras. Each camera has its own set of buffers.
+-size, fps, palette only specify defaults when you open() the device; this is
+-to accommodate some tools that don't set the size or colour palette. You can
+-change these settings after open() with the Video4Linux ioctl() calls. The
+-default of defaults is QCIF size at 10 fps, BGR order.
++size and fps only specify defaults when you open() the device; this is to
++accommodate some tools that don't set the size. You can change these
++settings after open() with the Video4Linux ioctl() calls. The default of
++defaults is QCIF size at 10 fps, YUV420 palette order.
+ The compression parameter is semiglobal; it sets the initial compression
+ preference for all camera's, but this parameter can be set per camera with
+@@ -200,4 +225,3 @@
+ All parameters are optional.
+-
+diff -urN linux-2.4.20.orig/drivers/usb/pwc-ctrl.c linux-2.4.20/drivers/usb/pwc-ctrl.c
+--- linux-2.4.20.orig/drivers/usb/pwc-ctrl.c   Mon Jan  6 22:15:48 2003
++++ linux-2.4.20/drivers/usb/pwc-ctrl.c        Mon Dec 16 22:19:15 2002
+@@ -256,8 +256,10 @@
+       memcpy(buf, pEntry->mode, 3);   
+       ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
+-      if (ret < 0)
++      if (ret < 0) {
++              Debug("Failed to send video command... %d\n", ret);
+               return ret;
++      }
+       if (pEntry->compressed && pdev->decompressor != NULL)
+               pdev->decompressor->init(pdev->release, buf, pdev->decompress_data);
+               
+@@ -444,8 +446,8 @@
+                       Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames);
+               else {
+                       Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
+-                      return ret;
+               }
++              return ret;
+       }
+       pdev->view.x = width;
+       pdev->view.y = height;
+@@ -997,7 +999,7 @@
+               &buf, 1, HZ / 2);
+       if (ret < 0)
+-          return ret;
++              return ret;
+       
+       return (buf << 8);
+ }
+@@ -1103,12 +1105,7 @@
+       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, 2, HZ / 2);
++      return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2);
+ }
+ int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
+@@ -1122,13 +1119,7 @@
+               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, 2, HZ / 2);
+-
++      ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2);
+       if (ret < 0)
+               return ret;
+       *on_value = buf[0] * 100;
+@@ -1252,7 +1243,7 @@
+       int ret;
+       unsigned char buf;
+       
+-      ret = RecvControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
++      ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
+       if (ret < 0)
+               return ret;
+       return buf;
+@@ -1276,10 +1267,9 @@
+       int ret;
+       unsigned char buf;
+       
+-      ret = RecvControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
++      ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
+       if (ret < 0)
+               return ret;
+-Debug("pwc_get_dynamic_noise = %d\n", buf);
+       return buf;
+ }
+@@ -1595,6 +1585,16 @@
+               break;
+       }
+       
++      case VIDIOCPWCGREALSIZE:
++      {
++              struct pwc_imagesize size;
++              
++              size.width = pdev->image.x;
++              size.height = pdev->image.y;
++              if (copy_to_user(arg, &size, sizeof(size)))
++                      ret = -EFAULT;
++              break;
++      }       
+       default:
+               ret = -ENOIOCTLCMD;
+diff -urN linux-2.4.20.orig/drivers/usb/pwc-if.c linux-2.4.20/drivers/usb/pwc-if.c
+--- linux-2.4.20.orig/drivers/usb/pwc-if.c     Mon Jan  6 22:15:48 2003
++++ linux-2.4.20/drivers/usb/pwc-if.c  Mon Dec 16 22:19:15 2002
+@@ -42,11 +42,15 @@
+    - Alistar Moire: QuickCam 3000 Pro device/product ID
+    - Tony Hoyle: Creative Labs Webcam 5 device/product ID
+    - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
+-   - Jk Fang: SOTEC device/product ID
++   - Jk Fang: Sotec Afina Eye ID
++   - Xavier Roche: QuickCam Pro 4000 ID
++   - Jens Knudsen: QuickCam Zoom ID
++   - J. Debert: QuickCam for Notebooks ID
+ */
+ #include <linux/errno.h>
+ #include <linux/init.h>
++#include <linux/mm.h>
+ #include <linux/module.h>
+ #include <linux/poll.h>
+ #include <linux/slab.h>
+@@ -58,10 +62,6 @@
+ #include "pwc-ioctl.h"
+ #include "pwc-uncompress.h"
+-#if !defined(MAP_NR)
+-#define MAP_NR(a) virt_to_page(a)
+-#endif
+-
+ /* Function prototypes and driver templates */
+ /* hotplug device table support */
+@@ -76,10 +76,13 @@
+       { USB_DEVICE(0x0471, 0x0311) },
+       { USB_DEVICE(0x0471, 0x0312) },
+       { USB_DEVICE(0x069A, 0x0001) }, /* Askey */
+-      { USB_DEVICE(0x046D, 0x08b0) }, /* Logitech */
++      { USB_DEVICE(0x046D, 0x08b0) }, /* Logitech QuickCam Pro 3000 */
++      { USB_DEVICE(0x046D, 0x08b1) }, /* Logitech QuickCam Notebook Pro */
++      { USB_DEVICE(0x046d, 0x08b2) }, /* Logitech QuickCam Pro 4000 */
++      { USB_DEVICE(0x046d, 0x08b3) }, /* Logitech QuickCam Zoom */
+       { USB_DEVICE(0x055D, 0x9000) }, /* Samsung */
+       { USB_DEVICE(0x055D, 0x9001) },
+-      { USB_DEVICE(0x041E, 0x400C) }, /* Creative */
++      { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
+       { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
+       { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */
+       { USB_DEVICE(0x0d81, 0x1900) },
+@@ -127,7 +130,7 @@
+ static long pwc_video_write(struct video_device *vdev, const char *buf, unsigned long count, int noblock);
+ static unsigned int pwc_video_poll(struct video_device *vdev, struct file *file, poll_table *wait);
+ static int  pwc_video_ioctl(struct video_device *vdev, unsigned int cmd, void *arg);
+-static int  pwc_video_mmap(struct video_device *dev, const char *adr, unsigned long size);
++static int  pwc_video_mmap(struct video_device *vdev, const char *adr, unsigned long size);
+ static struct video_device pwc_template = {
+       owner:          THIS_MODULE,
+@@ -238,7 +241,7 @@
+       int i;
+       void *kbuf;
+-      Trace(TRACE_MEMORY, "Entering allocate_buffers(%p).\n", pdev);
++      Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
+       if (pdev == NULL)
+               return -ENXIO;
+@@ -315,7 +318,7 @@
+       kbuf = NULL;
+         
+-      Trace(TRACE_MEMORY, "Leaving pwc_allocate_buffers().\n");
++      Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n");
+       return 0;
+ }
+@@ -592,7 +595,7 @@
+ /* This gets called for the Isochronous pipe (video). This is done in
+  * interrupt time, so it has to be fast, not crash, and not stall. Neat.
+  */
+-static void pwc_isoc_handler(struct urb *urb)
++static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
+ {
+       struct pwc_device *pdev;
+       int i, fst, flen;
+@@ -612,7 +615,7 @@
+       }
+ #endif
+       if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
+-              Trace(TRACE_OPEN, "pwc_isoc_handler(): URB unlinked.\n");
++              Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
+               return;
+       }
+       if (urb->status != -EINPROGRESS && urb->status != 0) {
+@@ -685,9 +688,22 @@
+ #if PWC_DEBUG
+                                                       Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
+ #endif
+-                                                      pdev->drop_frames = 2;
++                                                      pdev->drop_frames += 2;
+                                                       pdev->vframes_error++;
+                                               }
++                                              if ((ptr[0] ^ pdev->vmirror) & 0x01) {
++                                                      if (ptr[0] & 0x01)
++                                                              Info("Snapshot button pressed.\n");
++                                                      else
++                                                              Info("Snapshot button released.\n");
++                                              }
++                                              if ((ptr[0] ^ pdev->vmirror) & 0x02) {
++                                                      if (ptr[0] & 0x02)
++                                                              Info("Image is mirrored.\n");
++                                                      else
++                                                              Info("Image is normal.\n");
++                                              }
++                                              pdev->vmirror = ptr[0] & 0x03;
+                                               /* Sometimes the trailer of the 730 is still sent as a 4 byte packet 
+                                                  after a short frame; this condition is filtered out specifically. A 4 byte
+                                                  frame doesn't make sense anyway.
+@@ -704,7 +720,7 @@
+                                       /* In case we were instructed to drop the frame, do so silently.
+                                          The buffer pointers are not updated either (but the counters are reset below).
+                                        */
+-                                      if (pdev->drop_frames)
++                                      if (pdev->drop_frames > 0)
+                                               pdev->drop_frames--;
+                                       else {
+                                               /* Check for underflow first */
+@@ -740,10 +756,14 @@
+                       } /* .. flen < last_packet_size */
+                       pdev->vlast_packet_size = flen;
+               } /* ..status == 0 */
+-#ifdef PWC_DEBUG
++#if PWC_DEBUG
+               /* This is normally not interesting to the user, unless you are really debugging something */
+-              else 
+-                      Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
++              else {
++                      static int iso_error = 0;
++                      iso_error++;
++                      if (iso_error < 20)
++                              Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
++              }
+ #endif                        
+       }
+       if (awake)
+@@ -758,7 +778,6 @@
+       int i, j, ret;
+       struct usb_interface_descriptor *idesc;
+-      int cur_alt;
+       if (pdev == NULL)
+               return -EFAULT;
+@@ -766,12 +785,11 @@
+               return 0;
+       pdev->vsync = 0;
+       udev = pdev->udev;
+-      
++
+       /* Get the current alternate interface, adjust packet size */
+       if (!udev->actconfig)
+               return -EFAULT;
+-      cur_alt = udev->actconfig->interface[0].act_altsetting;
+-      idesc = &udev->actconfig->interface[0].altsetting[cur_alt];
++      idesc = &udev->actconfig->interface[0].altsetting[pdev->valternate];
+       if (!idesc)
+               return -EFAULT;
+@@ -783,12 +801,18 @@
+                       break;
+               }
+       
+-      if (pdev->vmax_packet_size < 0) {
++      if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
+               Err("Failed to find packet size for video endpoint in current alternate setting.\n");
+               return -ENFILE; /* Odd error, that should be noticable */
+       }
++      /* Set alternate interface */
+       ret = 0;
++      Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate);
++      ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
++      if (ret < 0)
++              return ret;
++
+       for (i = 0; i < MAX_ISO_BUFS; i++) {
+               urb = usb_alloc_urb(ISO_FRAMES_PER_DESC);
+               if (urb == NULL) {
+@@ -797,6 +821,7 @@
+                       break;
+               }
+               pdev->sbuf[i].urb = urb;
++              Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb);
+       }
+       if (ret) {
+               /* De-allocate in reverse order */
+@@ -808,8 +833,7 @@
+               }
+               return ret;
+       }
+-      
+-      
++
+       /* init URB structure */        
+       for (i = 0; i < MAX_ISO_BUFS; i++) {
+               urb = pdev->sbuf[i].urb;
+@@ -826,7 +850,7 @@
+               urb->number_of_packets = ISO_FRAMES_PER_DESC;
+               for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
+                       urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
+-                      urb->iso_frame_desc[j].length = ISO_MAX_FRAME_SIZE;
++                      urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
+               }
+       }
+@@ -836,11 +860,12 @@
+               if (ret)
+                       Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
+               else
+-                      Trace(TRACE_OPEN, "pwc_isoc_init(): URB submitted.\n");
++                      Trace(TRACE_OPEN, "URB 0x%p submitted.\n", pdev->sbuf[i].urb);
+       }
+-      /* data should stream in now */
++      /* All is done... */
+       pdev->iso_init = 1;
++      Trace(TRACE_OPEN, "<< pwc_isoc_init()\n");
+       return 0;
+ }
+@@ -848,21 +873,34 @@
+ {
+       int i;
+       
++      Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n");
+       if (pdev == NULL)
+               return;
+-      if (!pdev->iso_init)
+-              return;
++
++      /* Unlinking ISOC buffers one by one */
++      for (i = 0; i < MAX_ISO_BUFS; i++) {
++              struct urb *urb;
++
++              urb = pdev->sbuf[i].urb;
++              if (urb != 0) {
++                      if (pdev->iso_init) {
++                              Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb);
++                              usb_unlink_urb(urb);
++                      }
++                      Trace(TRACE_MEMORY, "Freeing URB\n");
++                      usb_free_urb(urb);
++                      pdev->sbuf[i].urb = NULL;
++              }
++      }
++
+       /* Stop camera, but only if we are sure the camera is still there */
+-      if (!pdev->unplugged)
++      if (!pdev->unplugged) {
++              Trace(TRACE_OPEN, "Setting alternate interface 0.\n");
+               usb_set_interface(pdev->udev, 0, 0);
+-      /* Unlinking ISOC buffers one by one */
+-      for (i = MAX_ISO_BUFS - 1; i >= 0; i--) {
+-              pdev->sbuf[i].urb->next = NULL;
+-              usb_unlink_urb(pdev->sbuf[i].urb);
+-              usb_free_urb(pdev->sbuf[i].urb);
+-              pdev->sbuf[i].urb = NULL;
+       }
++
+       pdev->iso_init = 0;
++      Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n");
+ }
+ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
+@@ -876,11 +914,10 @@
+       ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
+       if (ret) /* That failed... restore old mode (we know that worked) */
+               ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+-      else /* Set (new) alternate interface */
+-              ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
+       if (!ret)
+-              ret = pwc_isoc_init(pdev);
+-      pdev->drop_frames = 1; /* try to avoid garbage during switch */
++              if (pwc_isoc_init(pdev) < 0)
++                      Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
++      pdev->drop_frames++; /* try to avoid garbage during switch */
+       return ret;
+ }
+@@ -915,20 +952,19 @@
+       int i;
+       struct pwc_device *pdev;
+-      Trace(TRACE_OPEN, "video_open called(0x%p, 0%o).\n", vdev, mode);
++      Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
+       
+       if (vdev == NULL)
+               BUG();
+       pdev = (struct pwc_device *)vdev->priv;
+       if (pdev == NULL)
+               BUG();
++      if (pdev->vopen)
++              return -EBUSY;
+       
+       down(&pdev->modlock);
+       if (!pdev->usb_init) {
+               Trace(TRACE_OPEN, "Doing first time initialization.\n");
+-              /* Reset camera */
+-              if (usb_set_interface(pdev->udev, 0, 0))
+-                      Info("Failed to set alternate interface to 0.\n");
+               pdev->usb_init = 1;
+               
+               if (pwc_trace & TRACE_OPEN) {
+@@ -948,10 +984,10 @@
+                       case 0x40:  sensor_type = "UPA 1021 sensor"; break;
+                       case 0x100: sensor_type = "VGA sensor"; break;
+                       case 0x101: sensor_type = "PAL MR sensor"; break;
+-                      default:   sensor_type = "unknown type of sensor"; break;
++                      default:    sensor_type = "unknown type of sensor"; break;
+                       }
+                       if (sensor_type != NULL)
+-                              Info("Thes %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i);
++                              Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i);
+               }
+       }
+@@ -1017,16 +1053,9 @@
+               return i;
+       }
+       
+-      i = usb_set_interface(pdev->udev, 0, pdev->valternate);
+-      if (i) {
+-              Trace(TRACE_OPEN, "Failed to set alternate interface = %d.\n", i);
+-              up(&pdev->modlock);
+-              return -EINVAL;
+-      }
+       i = pwc_isoc_init(pdev);
+       if (i) {
+               Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
+-              MOD_DEC_USE_COUNT;
+               up(&pdev->modlock);
+               return i;
+       }
+@@ -1039,7 +1068,7 @@
+       if (pdev->decompressor != NULL)
+               pdev->decompressor->lock();
+       up(&pdev->modlock);
+-      Trace(TRACE_OPEN, "video_open() returning 0.\n");
++      Trace(TRACE_OPEN, "<< video_open() returns 0.\n");
+       return 0;
+ }
+@@ -1049,15 +1078,12 @@
+       struct pwc_device *pdev;
+       int i;
+-      Trace(TRACE_OPEN, "video_close called(0x%p).\n", vdev);
++      Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev);
+       pdev = (struct pwc_device *)vdev->priv;
+       if (pdev->vopen == 0)
+               Info("video_close() called on closed device?\n");
+-      /* Free isoc URBs */
+-      pwc_isoc_cleanup(pdev);
+-
+       /* Dump statistics, but only if a reasonable amount of frames were
+          processed (to prevent endless log-entries in case of snap-shot
+          programs) 
+@@ -1065,21 +1091,14 @@
+       if (pdev->vframe_count > 20)
+               Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
+-      if (pdev->unplugged) {
+-              /* The device was unplugged or some other error occured */
+-              /* We unregister the video_device */
+-              Trace(TRACE_OPEN, "Delayed video device unregistered.\n");
+-              video_unregister_device(pdev->vdev);
+-      }
+-      else {
+-              /* Normal close: stop isochronuous and interrupt endpoint */
+-              Trace(TRACE_OPEN, "Normal close(): setting interface to 0.\n");
+-              usb_set_interface(pdev->udev, 0, 0);
++      /* Free isoc URBs, stop camera */
++      pwc_isoc_cleanup(pdev);
++      if (!pdev->unplugged) {
+               /* 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 */
++                      Info("Failed to set LED on/off time.\n");
++              /* Power down camera to save energy */
+               if (power_save) {
+                       i = pwc_camera_power(pdev, 0);
+                       if (i < 0) 
+@@ -1097,6 +1116,7 @@
+       /* wake up _disconnect() routine */
+       if (pdev->unplugged)
+               wake_up(&pdev->remove_ok);
++      Trace(TRACE_OPEN, "<< video_close()\n");
+ }
+ /*
+@@ -1495,8 +1515,8 @@
+                                       set_current_state(TASK_RUNNING);
+                                       return -ERESTARTSYS;
+                               }
+-                              schedule();
+                               set_current_state(TASK_INTERRUPTIBLE);
++                              schedule();
+                       }
+                       remove_wait_queue(&pdev->frameq, &wait);
+                       set_current_state(TASK_RUNNING);
+@@ -1574,8 +1594,6 @@
+       Trace(TRACE_MEMORY, "mmap(0x%p, 0x%p, %lu) called.\n", vdev, adr, size);
+       pdev = vdev->priv;
+-      /* FIXME - audit mmap during a read */          
+-      /* Nemo: 9 months and 20 kernel revisions later I still don't know what you mean by this :-) */
+       pos = (unsigned long)pdev->image_data;
+       while (size > 0) {
+               page = kvirt_to_pa(pos);
+@@ -1691,10 +1709,25 @@
+       else if (vendor_id == 0x046d) {
+               switch(product_id) {
+               case 0x08b0:
+-                      Info("Logitech QuickCam 3000 Pro USB webcam detected.\n");
+-                      name = "Logitech QuickCam 3000 Pro";
++                      Info("Logitech QuickCam Pro 3000 USB webcam detected.\n");
++                      name = "Logitech QuickCam Pro 3000";
+                       type_id = 730;
+-                      break;
++                      break;
++              case 0x08b1:
++                      Info("Logitech QuickCam for Notebook Pro USB webcam detected.\n");
++                      name = "Logitech QuickCam Notebook Pro";
++                      type_id = 740; /* ?? unknown sensor */
++                      break;
++              case 0x08b2:
++                      Info("Logitech QuickCam 4000 Pro USB webcam detected.\n");
++                      name = "Logitech QuickCam Pro 4000";
++                      type_id = 740; /* CCD sensor */
++                      break;
++              case 0x08b3:
++                      Info("Logitech QuickCam Zoom USB webcam detected.\n");
++                      name = "Logitech QuickCam Zoom";
++                      type_id = 740; /* CCD sensor */
++                      break;
+               default:
+                       return NULL;
+                       break;
+@@ -1868,6 +1901,8 @@
+       
+       pdev->unplugged = 1;
+       if (pdev->vdev != NULL) {
++              Trace(TRACE_PROBE, "Unregistering video device.\n");
++              video_unregister_device(pdev->vdev); 
+               if (pdev->vopen) {
+                       Info("Disconnected while device/video is open!\n");
+                       
+@@ -1895,8 +1930,6 @@
+               }
+               else {
+                       /* Normal disconnect; remove from available devices */
+-                      Trace(TRACE_PROBE, "Unregistering video device normally.\n");
+-                      video_unregister_device(pdev->vdev); 
+                       kfree(pdev->vdev);
+                       pdev->vdev = NULL;
+               }
+@@ -1914,7 +1947,7 @@
+ /* *grunt* We have to do atoi ourselves :-( */
+-static int pwc_atoi(char *s)
++static int pwc_atoi(const char *s)
+ {
+       int k = 0;
+       
+@@ -1959,7 +1992,7 @@
+ MODULE_PARM(dev_hint, "0-10s");
+ MODULE_PARM_DESC(dev_hint, "Device node hints");
+-MODULE_DESCRIPTION("Philips USB webcam driver");
++MODULE_DESCRIPTION("Philips USB & OEM webcam driver");
+ MODULE_AUTHOR("Nemosoft Unv. <nemosoft@smcc.demon.nl>");
+ MODULE_LICENSE("GPL");
+@@ -1969,7 +2002,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 the Askey VC010, Logitech Quickcam 3000 Pro, Samsung MPC-C10 and MPC-C30,\n");
++      Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
+       Info("the Creative WebCam 5, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
+       if (fps) {
+@@ -2087,7 +2120,7 @@
+                                       device_hint[i].serial_number[k] = '\0';
+                               }
+                       }
+-#ifdef PWC_DEBUG              
++#if PWC_DEBUG         
+                       Debug("device_hint[%d]:\n", i);
+                       Debug("  type    : %d\n", device_hint[i].type);
+                       Debug("  serial# : %s\n", device_hint[i].serial_number);
+diff -urN linux-2.4.20.orig/drivers/usb/pwc-ioctl.h linux-2.4.20/drivers/usb/pwc-ioctl.h
+--- linux-2.4.20.orig/drivers/usb/pwc-ioctl.h  Mon Jan  6 22:15:48 2003
++++ linux-2.4.20/drivers/usb/pwc-ioctl.h       Mon Dec 16 22:19:15 2002
+@@ -18,12 +18,13 @@
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+-/*         This is pwc-ioctl.h belonging to PWC 8.6                        */
++/*         This is pwc-ioctl.h belonging to PWC 8.10                        */
+ /* 
+    Changes
+    2001/08/03  Alvarado   Added ioctl constants to access methods for 
+                           changing white balance and red/blue gains
++   2002/12/15  G. H. Fernandez-Toribio   VIDIOCGREALSIZE
+  */
+ /* These are private ioctl() commands, specific for the Philips webcams.
+@@ -104,7 +105,12 @@
+       int led_off;                    /* Led off-time; range = 0..25000  */
+ };
+-
++/* Image size (used with GREALSIZE) */
++struct pwc_imagesize
++{
++      int width;
++      int height;
++};
+  /* Restore user settings */
+ #define VIDIOCPWCRUSER                _IO('v', 192)
+@@ -173,4 +179,7 @@
+ #define VIDIOCPWCSDYNNOISE    _IOW('v', 209, int)
+ #define VIDIOCPWCGDYNNOISE    _IOR('v', 209, int)
++ /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
++#define VIDIOCPWCGREALSIZE    _IOR('v', 210, struct pwc_imagesize)
++ 
+ #endif
+diff -urN linux-2.4.20.orig/drivers/usb/pwc-uncompress.c linux-2.4.20/drivers/usb/pwc-uncompress.c
+--- linux-2.4.20.orig/drivers/usb/pwc-uncompress.c     Mon Jan  6 22:15:48 2003
++++ linux-2.4.20/drivers/usb/pwc-uncompress.c  Mon Dec 16 22:19:15 2002
+@@ -77,7 +77,7 @@
+ {
+       struct pwc_frame_buf *fbuf;
+       int n, line, col, stride;
+-      void *yuv, *image, *dst;
++      void *yuv, *image;
+       u16 *src;
+       u16 *dsty, *dstu, *dstv;
+@@ -114,19 +114,6 @@
+                  to get the desired output format/size.
+                */
+               switch (pdev->vpalette) {
+-              case VIDEO_PALETTE_YUV420:
+-                      /* Calculate byte offsets per line in image & view */
+-                      n   = (pdev->image.x * 3) / 2;
+-                      col = (pdev->view.x  * 3) / 2;
+-                      /* Offset into image */
+-                      dst = image + (pdev->view.x * pdev->offset.y + pdev->offset.x) * 3 / 2;
+-                      for (line = 0; line < pdev->image.y; line++) {
+-                              memcpy(dst, yuv, n);
+-                              yuv += n;
+-                              dst += col;
+-                      }
+-                      break;
+-
+               case VIDEO_PALETTE_YUV420P:
+                       /* 
+                        * We do some byte shuffling here to go from the 
+@@ -163,17 +150,20 @@
+                                       dstu += (stride >> 1);
+                       }
+                       break;
++              default:
++                      Err("Unsupported palette!");
++                      break;
+               }
+       }
+       else { 
+               /* Compressed; the decompressor routines will write the data 
+-                 in interlaced or planar format immediately.
++                 in planar format immediately.
+                */
+               if (pdev->decompressor)
+                       pdev->decompressor->decompress(
+                               &pdev->image, &pdev->view, &pdev->offset,
+-                              yuv, image, 
+-                              pdev->vpalette == VIDEO_PALETTE_YUV420P ? 1 : 0,
++                              yuv, image,
++                              1,
+                               pdev->decompress_data, pdev->vbandlength);
+               else
+                       return -ENXIO; /* No such device or address: missing decompressor */
+diff -urN linux-2.4.20.orig/drivers/usb/pwc.h linux-2.4.20/drivers/usb/pwc.h
+--- linux-2.4.20.orig/drivers/usb/pwc.h        Mon Jan  6 22:15:48 2003
++++ linux-2.4.20/drivers/usb/pwc.h     Mon Dec 16 22:19:15 2002
+@@ -60,8 +60,8 @@
+ /* Version block */
+ #define PWC_MAJOR     8
+-#define PWC_MINOR     6
+-#define PWC_VERSION   "8.6"
++#define PWC_MINOR     8
++#define PWC_VERSION   "8.8"
+ #define PWC_NAME      "pwc"
+ /* Turn certain features on/off */
+@@ -130,7 +130,7 @@
+    int vcinterface;           /* video control interface */
+    int valternate;            /* alternate interface needed */
+    int vframes, vsize;                /* frames-per-second & size (see PSZ_*) */
+-   int vpalette;              /* YUV, RGB24, RGB32, etc */
++   int vpalette;              /* YUV */
+    int vframe_count;          /* received frames */
+    int vframes_dumped;                /* counter for dumped frames */
+    int vframes_error;         /* frames received in error */
+@@ -140,7 +140,8 @@
+    int vbandlength;           /* compressed band length; 0 is uncompressed */
+    char vsnapshot;            /* snapshot mode */
+    char vsync;                        /* used by isoc handler */
+-   
++   char vmirror;              /* for ToUCaM series */
++
+    /* The image acquisition requires 3 to 4 steps:
+       1. data is gathered in short packets from the USB controller
+       2. data is synchronized and packed into a frame buffer
This page took 0.086115 seconds and 4 git commands to generate.