From 96eb5089dc3c25c4bf0d8336faef9627b89032d0 Mon Sep 17 00:00:00 2001 From: aflinta Date: Tue, 7 Jan 2003 08:00:46 +0000 Subject: [PATCH] - latest pwc drivers Changed files: linux-2.4.20-pwc.patch -> 1.1 --- linux-2.4.20-pwc.patch | 829 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 829 insertions(+) create mode 100644 linux-2.4.20-pwc.patch diff --git a/linux-2.4.20-pwc.patch b/linux-2.4.20-pwc.patch new file mode 100644 index 00000000..2f20b170 --- /dev/null +++ b/linux-2.4.20-pwc.patch @@ -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 + #include ++#include + #include + #include + #include +@@ -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. "); + 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 -- 2.44.0