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