ChangeSet 1.842.46.15, 2002/11/27 09:46:14-08:00, [EMAIL PROTECTED]
[PATCH] [PATCH] PWC 8.9
After a little absence, here's a patch to bring the Philips Webcam driver up
to version 8.9 (skipping 8.8 which has been available as a download on my
website for a while).
This patch is against 2.5.49, and includes some of the following:
* New USB IDs for Logitech and Visionite webcams.
* Better URB link/unlink sequence when opening/closing device
and switching resolutions.
* Adding probe for CCD/CMOS sensor type.
* Removed remnants of YUV420 palette stuff.
Also updated the description in 'Kconfig'.
diff -Nru a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig
--- a/drivers/usb/media/Kconfig Wed Nov 27 12:49:43 2002
+++ b/drivers/usb/media/Kconfig Wed Nov 27 12:49:43 2002
@@ -120,15 +120,26 @@
tristate "USB Philips Cameras"
depends on USB && VIDEO_DEV
---help---
- Say Y or M here if you want to use one of these Philips USB webcams:
- PCA645, PCA646, PCVC675, PCVC680, PCVC690, PCVC730, PCVC740, or
- the Askey VC010. The PCA635, PCVC665 and PCVC720 are not supported
- by this driver and never will be.
+ Say Y or M here if you want to use one of these Philips & OEM
+ webcams:
+ * Philips PCA645, PCA646
+ * Philips PCVC675, PCVC680, PCVC690
+ * Philips PCVC730, PCVC740, PCVC750
+ * Askey VC010
+ * Logitech QuickCam Pro 3000, 4000, 'Zoom' and 'Notebook'
+ * Samsung MPC-C10, MPC-C30
+ * Creative Webcam 5
+ * SOTECT Afina Eye
+ * Visionite VCS-UC300, VCS-UM100
+
+ The PCA635, PCVC665 and PCVC720 are not supported by this driver
+ and never will be, but the 665 and 720 are supported by other
+ drivers.
- This driver has an optional plugin, which is distributed as a binary
- module only. It contains code that allow you to use higher
- resolutions and framerates but may not be distributed as source.
- But even without this plugin you can these cams for most
+ This driver has an optional plugin (called PWCX), which is
+ distributed as a binary module only. It contains code that allow you
+ to use higher resolutions and framerates but may not be distributed
+ as source. But even without this plugin you can these cams for most
applications.
See <file:Documentation/usb/philips.txt> for more information and
diff -Nru a/drivers/usb/media/pwc-ctrl.c b/drivers/usb/media/pwc-ctrl.c
--- a/drivers/usb/media/pwc-ctrl.c Wed Nov 27 12:49:43 2002
+++ b/drivers/usb/media/pwc-ctrl.c Wed Nov 27 12:49:43 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);
@@ -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;
@@ -1279,7 +1270,6 @@
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;
}
@@ -1363,12 +1353,10 @@
case VIDIOCPWCPROBE:
{
- struct pwc_probe probe;
+ struct pwc_probe *probe = arg;
- strcpy(probe.name, pdev->vdev->name);
- probe.type = pdev->type;
- if (copy_to_user(arg, &probe, sizeof(probe)))
- ret = -EFAULT;
+ strcpy(probe->name, pdev->vdev->name);
+ probe->type = pdev->type;
break;
}
diff -Nru a/drivers/usb/media/pwc-if.c b/drivers/usb/media/pwc-if.c
--- a/drivers/usb/media/pwc-if.c Wed Nov 27 12:49:43 2002
+++ b/drivers/usb/media/pwc-if.c Wed Nov 27 12:49:43 2002
@@ -1,6 +1,6 @@
/* Linux driver for Philips webcam
USB and Video4Linux interface part.
- (C) 1999-2001 Nemosoft Unv.
+ (C) 1999-2002 Nemosoft Unv.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -42,32 +42,31 @@
- 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>
#include <linux/vmalloc.h>
#include <linux/wrapper.h>
-#include <linux/mm.h>
#include <asm/io.h>
#include "pwc.h"
#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 */
static struct usb_device_id pwc_device_table [] = {
- { USB_DEVICE(0x0471, 0x0302) },
+ { USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
{ USB_DEVICE(0x0471, 0x0303) },
{ USB_DEVICE(0x0471, 0x0304) },
{ USB_DEVICE(0x0471, 0x0307) },
@@ -76,12 +75,17 @@
{ USB_DEVICE(0x0471, 0x0310) },
{ USB_DEVICE(0x0471, 0x0311) },
{ USB_DEVICE(0x0471, 0x0312) },
- { USB_DEVICE(0x069A, 0x0001) },
- { USB_DEVICE(0x046D, 0x08b0) },
- { USB_DEVICE(0x055D, 0x9000) },
+ { USB_DEVICE(0x069A, 0x0001) }, /* Askey */
+ { USB_DEVICE(0x046D, 0x08b0) }, /* Logitech QuickCam Pro 3000 */
+ { USB_DEVICE(0x046D, 0x08b1) }, /* Logitech QuickCam for Notebooks */
+ { 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) },
- { USB_DEVICE(0x04CC, 0x8116) },
+ { USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
+ { USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
+ { USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */
+ { USB_DEVICE(0x0d81, 0x1900) },
{ }
};
MODULE_DEVICE_TABLE(usb, pwc_device_table);
@@ -106,7 +110,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 */
+static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
static struct {
int type;
@@ -167,7 +171,7 @@
succeeded. The pwc_device struct links back to both structures.
When a device is unplugged while in use it will be removed from the
- list of known USB devices; I also de-register as a V4L device, but
+ list of known USB devices; I also de-register it as a V4L device, but
unfortunately I can't free the memory since the struct is still in use
by the file descriptor. This free-ing is then deferend until the first
opportunity. Crude, but it works.
@@ -240,7 +244,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 +319,9 @@
for (; i < MAX_IMAGES; i++)
pdev->image_ptr[i] = NULL;
- Trace(TRACE_MEMORY, "Leaving pwc_allocate_buffers().\n");
+ kbuf = NULL;
+
+ Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n");
return 0;
}
@@ -369,6 +375,7 @@
rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
}
pdev->image_data = NULL;
+
Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
}
@@ -570,12 +577,10 @@
pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
}
-/* 2001-10-14: The YUV420 is still there, but you can only set it from within
- a program (YUV420P being the default) */
+/* 2002-10-11: YUV420P is the only palette remaining. */
static int pwc_set_palette(struct pwc_device *pdev, int pal)
{
- if ( pal == VIDEO_PALETTE_YUV420
- || pal == VIDEO_PALETTE_YUV420P
+ if ( pal == VIDEO_PALETTE_YUV420P
#if PWC_DEBUG
|| pal == VIDEO_PALETTE_RAW
#endif
@@ -613,7 +618,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) {
@@ -686,9 +691,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.
@@ -705,7 +723,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 */
@@ -741,17 +759,23 @@
} /* .. 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)
wake_up_interruptible(&pdev->frameq);
urb->dev = pdev->udev;
- usb_submit_urb(urb, GFP_ATOMIC);
+ i = usb_submit_urb(urb, GFP_ATOMIC);
+ if (i != 0)
+ Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
}
@@ -762,7 +786,6 @@
int i, j, ret;
struct usb_host_interface *idesc;
- int cur_alt;
if (pdev == NULL)
return -EFAULT;
@@ -770,12 +793,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;
@@ -792,7 +814,13 @@
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, GFP_KERNEL);
if (urb == NULL) {
@@ -801,6 +829,7 @@
break;
}
pdev->sbuf[i].urb = urb;
+ Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb);
}
if (ret) {
/* De-allocate in reverse order */
@@ -812,8 +841,7 @@
}
return ret;
}
-
-
+
/* init URB structure */
for (i = 0; i < MAX_ISO_BUFS; i++) {
urb = pdev->sbuf[i].urb;
@@ -829,7 +857,7 @@
urb->start_frame = 0;
urb->number_of_packets = ISO_FRAMES_PER_DESC;
for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
- urb->iso_frame_desc[j].offset = j * pdev->vmax_packet_size;
+ urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
}
}
@@ -840,11 +868,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;
}
@@ -852,21 +881,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)
@@ -881,11 +923,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 transfer in
+pwc_try_video_mode.\n");
+ pdev->drop_frames++; /* try to avoid garbage during switch */
return ret;
}
@@ -921,7 +962,7 @@
struct video_device *vdev = video_devdata(file);
struct pwc_device *pdev;
- Trace(TRACE_OPEN, "video_open called(0x%p).\n", vdev);
+ Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
pdev = (struct pwc_device *)vdev->priv;
if (pdev == NULL)
@@ -932,10 +973,30 @@
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) {
+ /* Query CMOS sensor type */
+ const char *sensor_type = NULL;
+
+ i = pwc_get_cmos_sensor(pdev);
+ switch(i) {
+ case -1: /* Unknown, show nothing */; break;
+ case 0x00: sensor_type = "Hyundai CMOS sensor"; break;
+ case 0x20: sensor_type = "Sony CCD sensor + TDA8787"; break;
+ case 0x2E: sensor_type = "Sony CCD sensor + Exas 98L59";
+break;
+ case 0x2F: sensor_type = "Sony CCD sensor + ADI 9804"; break;
+ case 0x30: sensor_type = "Sharp CCD sensor + TDA8787"; break;
+ case 0x3E: sensor_type = "Sharp CCD sensor + Exas 98L59";
+break;
+ case 0x3F: sensor_type = "Sharp CCD sensor + ADI 9804"; break;
+ 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;
+ }
+ if (sensor_type != NULL)
+ Info("This %s camera is equipped with a %s (%d).\n",
+pdev->vdev->name, sensor_type, i);
+ }
}
/* Turn on camera */
@@ -1000,12 +1061,6 @@
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);
@@ -1023,7 +1078,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;
}
@@ -1034,15 +1089,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)
@@ -1050,15 +1102,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) {
- /* 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)
@@ -1077,6 +1128,7 @@
if (pdev->unplugged)
wake_up(&pdev->remove_ok);
file->private_data = NULL;
+ Trace(TRACE_OPEN, "<< video_close()\n");
return 0;
}
@@ -1514,7 +1566,6 @@
Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
pdev = vdev->priv;
- /* FIXME - audit mmap during a read */
pos = (unsigned long)pdev->image_data;
while (size > 0) {
page = kvirt_to_pa(pos);
@@ -1547,14 +1598,14 @@
int vendor_id, product_id, type_id;
int i, hint;
int video_nr = -1; /* default: use next available device */
- char serial_number[30];
+ char serial_number[30], *name;
free_mem_leak();
/* Check if we can handle this device */
- Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n",
- udev->descriptor.idVendor, udev->descriptor.idProduct,
- intf->altsetting->desc.bInterfaceNumber);
+ Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n",
+ udev->descriptor.idVendor, udev->descriptor.idProduct,
+ intf->altsetting->desc.bInterfaceNumber);
/* the interfaces are probed one by one. We are only interested in the
video interface (0) now.
@@ -1570,38 +1621,47 @@
switch (product_id) {
case 0x0302:
Info("Philips PCA645VC USB webcam detected.\n");
+ name = "Philips 645 webcam";
type_id = 645;
break;
case 0x0303:
Info("Philips PCA646VC USB webcam detected.\n");
+ name = "Philips 646 webcam";
type_id = 646;
break;
case 0x0304:
Info("Askey VC010 type 2 USB webcam detected.\n");
+ name = "Askey VC010 webcam";
type_id = 646;
break;
case 0x0307:
Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
+ name = "Philips 675 webcam";
type_id = 675;
break;
case 0x0308:
Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
+ name = "Philips 680 webcam";
type_id = 680;
break;
case 0x030C:
Info("Philips PCVC690K (Vesta Pro Scan) USB webcam
detected.\n");
+ name = "Philips 690 webcam";
type_id = 690;
break;
case 0x0310:
Info("Philips PCVC730K (ToUCam Fun) USB webcam detected.\n");
+ name = "Philips 730 webcam";
type_id = 730;
break;
case 0x0311:
Info("Philips PCVC740K (ToUCam Pro) USB webcam detected.\n");
+ name = "Philips 740 webcam";
type_id = 740;
break;
case 0x0312:
Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam
detected.\n");
+ name = "Philips 750 webcam";
type_id = 750;
break;
default:
@@ -1613,6 +1673,7 @@
switch(product_id) {
case 0x0001:
Info("Askey VC010 type 1 USB webcam detected.\n");
+ name = "Askey VC010 webcam";
type_id = 645;
break;
default:
@@ -1623,9 +1684,25 @@
else if (vendor_id == 0x046d) {
switch(product_id) {
case 0x08b0:
- Info("Logitech QuickCam 3000 Pro detected.\n");
+ 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 Noteboos USB webcam detected.\n");
+ name = "Logitech QuickCam Notebook";
+ 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; /* ?? unknown sensor */
+ break;
default:
return -ENODEV;
break;
@@ -1639,10 +1716,12 @@
switch(product_id) {
case 0x9000:
Info("Samsung MPC-C10 USB webcam detected.\n");
+ name = "Samsung MPC-C10";
type_id = 675;
break;
case 0x9001:
Info("Samsung MPC-C30 USB webcam detected.\n");
+ name = "Samsung MPC-C30";
type_id = 675;
break;
default:
@@ -1654,6 +1733,7 @@
switch(product_id) {
case 0x400c:
Info("Creative Labs Webcam 5 detected.\n");
+ name = "Creative Labs Webcam 5";
type_id = 730;
break;
default:
@@ -1664,7 +1744,8 @@
else if (vendor_id == 0x04cc) {
switch(product_id) {
case 0x8116:
- Info("SOTEC CMS-001 USB webcam detected.\n");
+ Info("Sotec Afina Eye USB webcam detected.\n");
+ name = "Sotec Afina Eye";
type_id = 730;
break;
default:
@@ -1672,7 +1753,25 @@
break;
}
}
- else return -ENODEV; /* Not Philips, Askey, Logitech, Samsung, Creative or
SOTEC, for sure. */
+ else if (vendor_id == 0x0d81) {
+ switch(product_id) {
+ case 0x1900:
+ Info("Visionite VCS-UC300 USB webcam detected.\n");
+ name = "Visionite VCS-UC300";
+ type_id = 740; /* CCD sensor */
+ break;
+ case 0x1910:
+ Info("Visionite VCS-UM100 USB webcam detected.\n");
+ name = "Visionite VCS-UM100";
+ type_id = 730; /* CMOS sensor */
+ break;
+ default:
+ return -ENODEV;
+ break;
+ }
+ }
+ else
+ return -ENODEV; /* Not any of the know types; but the list keeps
+growing. */
memset(serial_number, 0, 30);
usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
@@ -1706,7 +1805,7 @@
return -ENOMEM;
}
memcpy(vdev, &pwc_template, sizeof(pwc_template));
- sprintf(vdev->name, "Philips %d webcam", pdev->type);
+ strcpy(vdev->name, name);
SET_MODULE_OWNER(vdev);
pdev->vdev = vdev;
vdev->priv = pdev;
@@ -1714,7 +1813,6 @@
pdev->release = udev->descriptor.bcdDevice;
Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
-
/* Now search device_hint[] table for a match, so we can hint a node number. */
for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
if (((device_hint[hint].type == -1) || (device_hint[hint].type ==
pdev->type)) &&
@@ -1761,40 +1859,41 @@
dev_set_drvdata (&intf->dev, NULL);
if (pdev == NULL) {
Err("pwc_disconnect() Called without private pointer.\n");
- goto out_err;
+ goto disconnect_out;
}
if (pdev->udev == NULL) {
Err("pwc_disconnect() already called for %p\n", pdev);
- goto out_err;
+ goto disconnect_out;
}
if (pdev->udev != interface_to_usbdev(intf)) {
Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
- goto out_err;
+ goto disconnect_out;
}
#ifdef PWC_MAGIC
if (pdev->magic != PWC_MAGIC) {
Err("pwc_disconnect() Magic number failed. Consult your scrolls and
try again.\n");
- goto out_err;
+ goto disconnect_out;
}
-#endif
-
+#endif
+
pdev->unplugged = 1;
if (pdev->vdev != NULL) {
- video_unregister_device(pdev->vdev);
+ Trace(TRACE_PROBE, "Unregistering video device.\n");
+ video_unregister_device(pdev->vdev);
if (pdev->vopen) {
Info("Disconnected while device/video is open!\n");
-
+
/* Wake up any processes that might be waiting for
a frame, let them return an error condition
*/
wake_up(&pdev->frameq);
-
+
/* Wait until we get a 'go' from _close(). This used
to have a gigantic race condition, since we kfree()
- stuff here, but we have to wait until close()
- is finished.
+ stuff here, but we have to wait until close()
+ is finished.
*/
-
+
Trace(TRACE_PROBE, "Sleeping on remove_ok.\n");
add_wait_queue(&pdev->remove_ok, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
@@ -1808,26 +1907,25 @@
}
else {
/* Normal disconnect; remove from available devices */
- Trace(TRACE_PROBE, "Unregistering video device normally.\n");
kfree(pdev->vdev);
pdev->vdev = NULL;
}
}
+disconnect_out:
/* search device_hint[] table if we occupy a slot, by any chance */
for (hint = 0; hint < MAX_DEV_HINTS; hint++)
if (device_hint[hint].pdev == pdev)
device_hint[hint].pdev = NULL;
pdev->udev = NULL;
-out_err:
unlock_kernel();
kfree(pdev);
}
/* *grunt* We have to do atoi ourselves :-( */
-static int pwc_atoi(char *s)
+static int pwc_atoi(const char *s)
{
int k = 0;
@@ -1872,7 +1970,7 @@
MODULE_PARM(dev_hint, "0-10s");
MODULE_PARM_DESC(dev_hint, "Device node hints");
-MODULE_DESCRIPTION("Philips USB webcam driver");
+MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
MODULE_AUTHOR("Nemosoft Unv. <[EMAIL PROTECTED]>");
MODULE_LICENSE("GPL");
@@ -1882,11 +1980,12 @@
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, the Creative WebCam 5 and the SOTEC CMS-001.\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) {
- if (fps < 5 || fps > 30) {
- Err("Framerate out of bounds (5-30).\n");
+ if (fps < 4 || fps > 30) {
+ Err("Framerate out of bounds (4-30).\n");
return -EINVAL;
}
default_fps = fps;
@@ -1938,9 +2037,9 @@
if (power_save)
Info("Enabling power save on open/close.\n");
if (leds[0] >= 0)
- led_on = leds[0] / 100;
+ led_on = leds[0];
if (leds[1] >= 0)
- led_off = leds[1] / 100;
+ led_off = leds[1];
/* Big device node whoopla. Basicly, it allows you to assign a
device node (/dev/videoX) to a camera, based on its type
@@ -1999,7 +2098,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 -Nru a/drivers/usb/media/pwc-misc.c b/drivers/usb/media/pwc-misc.c
--- a/drivers/usb/media/pwc-misc.c Wed Nov 27 12:49:43 2002
+++ b/drivers/usb/media/pwc-misc.c Wed Nov 27 12:49:43 2002
@@ -1,6 +1,6 @@
/* Linux driver for Philips webcam
Various miscellaneous functions and tables.
- (C) 1999-2001 Nemosoft Unv. ([EMAIL PROTECTED])
+ (C) 1999-2002 Nemosoft Unv. ([EMAIL PROTECTED])
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff -Nru a/drivers/usb/media/pwc-uncompress.c b/drivers/usb/media/pwc-uncompress.c
--- a/drivers/usb/media/pwc-uncompress.c Wed Nov 27 12:49:43 2002
+++ b/drivers/usb/media/pwc-uncompress.c Wed Nov 27 12:49:43 2002
@@ -1,6 +1,6 @@
/* Linux driver for Philips webcam
Decompression frontend.
- (C) 1999-2001 Nemosoft Unv. ([EMAIL PROTECTED])
+ (C) 1999-2002 Nemosoft Unv. ([EMAIL PROTECTED])
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -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 -Nru a/drivers/usb/media/pwc-uncompress.h b/drivers/usb/media/pwc-uncompress.h
--- a/drivers/usb/media/pwc-uncompress.h Wed Nov 27 12:49:43 2002
+++ b/drivers/usb/media/pwc-uncompress.h Wed Nov 27 12:49:43 2002
@@ -1,4 +1,4 @@
-/* (C) 1999-2001 Nemosoft Unv. ([EMAIL PROTECTED])
+/* (C) 1999-2002 Nemosoft Unv. ([EMAIL PROTECTED])
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff -Nru a/drivers/usb/media/pwc.h b/drivers/usb/media/pwc.h
--- a/drivers/usb/media/pwc.h Wed Nov 27 12:49:43 2002
+++ b/drivers/usb/media/pwc.h Wed Nov 27 12:49:43 2002
@@ -60,8 +60,8 @@
/* Version block */
#define PWC_MAJOR 8
-#define PWC_MINOR 7
-#define PWC_VERSION "8.7"
+#define PWC_MINOR 9
+#define PWC_VERSION "8.9"
#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 SF.net email is sponsored by: Get the new Palm Tungsten T
handheld. Power & Color in a compact size!
http://ads.sourceforge.net/cgi-bin/redirect.pl?palm0002en
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel