Here's a patch against the current 2.5 bk tree, followed bk a "bk send
-wgzip_uu", to update ov511 to version 1.53. Please apply.
Summary of changes:
ov511.c:
NEW FEATURES:
- Support for upcoming videodev rewrite.
- Added tables mapping enum values to strings; Palettes and other
variables are
now printed symbolically.
BUG FIXES:
- URB errors should cause interrupt handler to return
CLEANUPS:
- Changed memmove() to memcpy() when obviously safe to do so.
- Removed unnecessary calls to usb_driver_release_interface()
- Removed comments on module parameters (see ov511.txt instead)
- Consolidated unlink code into ov51x_unlink_isoc()
- ov51x_do_dealloc() is used to handle error cases in ov51x_alloc()
- Eliminated ov51x_v4l1_init_done() and ov51x_v4l1_write()
- Eliminated redundant error messages and cleaned up error paths in
i2c code
ov511.h:
- Fixed PDEBUG() macro for GCC >= 3.0.3
- Changed buffers to unsigned char (could otherwise lead to trouble under
certain achitectures )
- Replaced *_list types with generic type and lookup inline function
ov511.txt:
- Update "led" parameter docs
--
Mark McClelland
[EMAIL PROTECTED]
# This is a BitKeeper generated patch for the following project:
# Project Name: greg k-h's linux 2.5 USB kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.364 -> 1.365
# drivers/usb/ov511.h 1.7 -> 1.8
# Documentation/usb/ov511.txt 1.3 -> 1.4
# drivers/usb/ov511.c 1.16 -> 1.17
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 02/03/02 [EMAIL PROTECTED] 1.365
# Update ov511 driver to version 1.53
# --------------------------------------------
#
diff -Nru a/Documentation/usb/ov511.txt b/Documentation/usb/ov511.txt
--- a/Documentation/usb/ov511.txt Sat Mar 2 17:12:46 2002
+++ b/Documentation/usb/ov511.txt Sat Mar 2 17:12:46 2002
@@ -182,9 +182,9 @@
DEFAULT: 1 (Always on)
DESC: Controls whether the LED (the little light) on the front of the camera
is always off (0), always on (1), or only on when driver is open (2).
- This is only supported with the OV511+ chipset, and even then only on
- some cameras (ones that actually have the LED wired to the control pin,
- and not just hardwired to be on all the time).
+ This is not supported with the OV511, and might only work with certain
+ cameras (ones that actually have the LED wired to the control pin, and
+ not just hard-wired to be on all the time).
NAME: dump_bridge
TYPE: integer (Boolean)
diff -Nru a/drivers/usb/ov511.c b/drivers/usb/ov511.c
--- a/drivers/usb/ov511.c Sat Mar 2 17:12:46 2002
+++ b/drivers/usb/ov511.c Sat Mar 2 17:12:46 2002
@@ -10,6 +10,8 @@
* Changes by Claudio Matsuoka <[EMAIL PROTECTED]>
* Original SAA7111A code by Dave Perks <[EMAIL PROTECTED]>
* Kernel I2C interface adapted from nt1003 driver
+ * URB error messages from pwc driver by Nemosoft
+ * generic_ioctl() code from videodev.c by Gerd Knorr and Alan Cox
*
* Based on the Linux CPiA driver written by Peter Pregler,
* Scott J. Bertin and Johannes Erdfelt.
@@ -53,22 +55,35 @@
#include <asm/cpufeature.h>
#endif
+/* A new implementation of the V4L 1 API exists that gives drivers direct
+ * access to file_operations. The old API is compatible with all 2.2 and 2.4
+ * kernels, and all 2.5 kernels through 2.5.5 (at least).
+ *
+ * Remove this #define to enable the new API
+ *
+ * Note: This has nothing to do with the V4L 2 API.
+ */
+#define OV511_OLD_V4L
+
#include "ov511.h"
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.52 for Linux 2.5"
+#define DRIVER_VERSION "v1.53 for Linux 2.5"
#define EMAIL "[EMAIL PROTECTED]"
#define DRIVER_AUTHOR "Mark McClelland <[EMAIL PROTECTED]> & Bret Wallach \
& Orion Sky Lawlor <[EMAIL PROTECTED]> & Kevin Moore & Charl P. Botha \
<[EMAIL PROTECTED]> & Claudio Matsuoka <[EMAIL PROTECTED]>"
-#define DRIVER_DESC "OV511 USB Camera Driver"
+#define DRIVER_DESC "ov511 USB Camera Driver"
#define OV511_I2C_RETRIES 3
#define ENABLE_Y_QUANTABLE 1
#define ENABLE_UV_QUANTABLE 1
+/* If you change this, you must also change the MODULE_PARM definition */
+#define OV511_MAX_UNIT_VIDEO 16
+
/* Pixel count * 3 bytes for RGB */
#define MAX_FRAME_SIZE(w, h) ((w) * (h) * 3)
#define MAX_DATA_SIZE(w, h) (MAX_FRAME_SIZE(w, h) + sizeof(struct timeval))
@@ -78,128 +93,55 @@
#define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM)
-/* PARAMETER VARIABLES: */
-/* (See ov511.txt for detailed descriptions of these.) */
-
-/* Sensor automatically changes brightness */
-static int autobright = 1;
-
-/* Sensor automatically changes gain */
-static int autogain = 1;
-
-/* Sensor automatically changes exposure */
-static int autoexp = 1;
-
-/* 0=no debug messages
- * 1=init/detection/unload and other significant messages,
- * 2=some warning messages
- * 3=config/control function calls
- * 4=most function calls and data parsing messages
- * 5=highly repetitive mesgs
- * NOTE: This should be changed to 0, 1, or 2 for production kernels
- */
-static int debug; /* = 0 */
-
-/* Fix vertical misalignment of red and blue at 640x480 */
-static int fix_rgb_offset; /* = 0 */
-
-/* Snapshot mode enabled flag */
-static int snapshot; /* = 0 */
-
-/* Force image to be read in RGB instead of BGR. This option allow
- * programs that expect RGB data (e.g. gqcam) to work with this driver. */
-static int force_rgb; /* = 0 */
-
-/* Number of seconds before inactive buffers are deallocated */
-static int buf_timeout = 5;
-
-/* Number of cameras to stream from simultaneously */
-static int cams = 1;
-
-/* Enable compression. Needs a fast (>300 MHz) CPU. */
-static int compress; /* = 0 */
-
-/* Display test pattern - doesn't work yet either */
-static int testpat; /* = 0 */
-
-/* Setting this to 1 will make the sensor output GBR422 instead of YUV420. Only
- * affects RGB24 mode. */
-static int sensor_gbr; /* = 0 */
-
-/* Dump raw pixel data. */
-static int dumppix; /* = 0 */
-
-/* LED policy. Only works on some OV511+ cameras. 0=off, 1=on (default), 2=auto
- * (on when open) */
-static int led = 1;
-
-/* Set this to 1 to dump the bridge register contents after initialization */
-static int dump_bridge; /* = 0 */
-
-/* Set this to 1 to dump the sensor register contents after initialization */
-static int dump_sensor; /* = 0 */
-
-/* Temporary option for debugging "works, but no image" problem. Prints the
- * first 12 bytes of data (potentially a packet header) in each isochronous
- * data frame. */
-static int printph; /* = 0 */
-
-/* Compression parameters - I'm not exactly sure what these do yet */
-static int phy = 0x1f;
-static int phuv = 0x05;
-static int pvy = 0x06;
-static int pvuv = 0x06;
-static int qhy = 0x14;
-static int qhuv = 0x03;
-static int qvy = 0x04;
-static int qvuv = 0x04;
-
-/* Light frequency. Set to 50 or 60 (Hz), or zero for default settings */
-static int lightfreq; /* = 0 */
+/**********************************************************************
+ * Module Parameters
+ * (See ov511.txt for detailed descriptions of these)
+ **********************************************************************/
-/* Set this to 1 to enable banding filter by default. Compensates for
- * alternating horizontal light/dark bands caused by (usually fluorescent)
- * lights */
-static int bandingfilter; /* = 0 */
+/* These variables (and all static globals) default to zero */
+static int autobright = 1;
+static int autogain = 1;
+static int autoexp = 1;
+static int debug;
+static int fix_rgb_offset;
+static int snapshot;
+static int force_rgb;
+static int buf_timeout = 5;
+static int cams = 1;
+static int compress;
+static int testpat;
+static int sensor_gbr;
+static int dumppix;
+static int led = 1;
+static int dump_bridge;
+static int dump_sensor;
+static int printph;
+static int phy = 0x1f;
+static int phuv = 0x05;
+static int pvy = 0x06;
+static int pvuv = 0x06;
+static int qhy = 0x14;
+static int qhuv = 0x03;
+static int qvy = 0x04;
+static int qvuv = 0x04;
+static int lightfreq;
+static int bandingfilter;
/* Pixel clock divisor */
-static int clockdiv = -1;
+static int clockdiv = -1;
/* Isoc packet size */
-static int packetsize = -1;
+static int packetsize = -1;
/* Frame drop register (16h) */
-static int framedrop = -1;
+static int framedrop = -1;
-/* Allows picture settings (brightness, hue, etc...) to take effect immediately,
- * even in the middle of a frame. This reduces the time to change settings, but
- * can ruin frames during the change. Only affects OmniVision sensors. */
-static int fastset; /* = 0 */
-
-/* Forces the palette to a specific value. If an application requests a
- * different palette, it will be rejected. */
-static int force_palette; /* = 0 */
-
-/* Set tuner type, if not autodetected */
-static int tuner = -1;
-
-/* Allows proper exposure of objects that are illuminated from behind. Only
- * affects OmniVision sensors. */
-static int backlight; /* = 0 */
-
-/* If you change this, you must also change the MODULE_PARM definition */
-#define OV511_MAX_UNIT_VIDEO 16
-
-/* Allows specified minor numbers to be forced. They will be assigned in the
- * order that devices are detected. Note that you cannot specify 0 as a minor
- * number. If you do not specify any, the next available one will be used. This
- * requires kernel 2.4.5 or later. */
+static int fastset;
+static int force_palette;
+static int tuner = -1;
+static int backlight;
static int unit_video[OV511_MAX_UNIT_VIDEO];
-
-/* Remove zero-padding from uncompressed incoming data. This will compensate for
- * the blocks of corruption that appear when the camera cannot keep up with the
- * speed of the USB bus (eg. at low frame resolutions) */
-static int remove_zeros; /* = 0 */
+static int remove_zeros;
MODULE_PARM(autobright, "i");
MODULE_PARM_DESC(autobright, "Sensor automatically changes brightness");
@@ -289,6 +231,10 @@
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
+/**********************************************************************
+ * Miscellaneous Globals
+ **********************************************************************/
+
static struct usb_driver ov511_driver;
static struct ov51x_decomp_ops *ov511_decomp_ops;
@@ -303,20 +249,28 @@
/* MMX support is present in kernel and CPU. Checked upon decomp module load. */
static int ov51x_mmx_available;
-/* Function prototypes */
-static void ov51x_clear_snapshot(struct usb_ov511 *);
-static int ov51x_check_snapshot(struct usb_ov511 *);
-static inline int sensor_get_picture(struct usb_ov511 *,
- struct video_picture *);
-static int sensor_get_exposure(struct usb_ov511 *, unsigned char *);
-static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long);
+static __devinitdata struct usb_device_id device_table [] = {
+ { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) },
+ { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) },
+ { USB_DEVICE(VEND_OMNIVISION, PROD_OV518) },
+ { USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) },
+ { USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, device_table);
+
+static unsigned char yQuanTable511[] = OV511_YQUANTABLE;
+static unsigned char uvQuanTable511[] = OV511_UVQUANTABLE;
+static unsigned char yQuanTable518[] = OV518_YQUANTABLE;
+static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE;
/**********************************************************************
- * List of known OV511-based cameras
+ * Symbolic Names
**********************************************************************/
-static struct cam_list clist[] = {
+/* Known OV511-based cameras */
+static struct symbolic_list camlist[] = {
{ 0, "Generic Camera (no ID)" },
{ 1, "Mustek WCam 3X" },
{ 3, "D-Link DSB-C300" },
@@ -336,43 +290,73 @@
{ -1, NULL }
};
-static __devinitdata struct usb_device_id device_table [] = {
- { USB_DEVICE(VEND_OMNIVISION, PROD_OV511) },
- { USB_DEVICE(VEND_OMNIVISION, PROD_OV511PLUS) },
- { USB_DEVICE(VEND_OMNIVISION, PROD_OV518) },
- { USB_DEVICE(VEND_OMNIVISION, PROD_OV518PLUS) },
- { USB_DEVICE(VEND_MATTEL, PROD_ME2CAM) },
- { } /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE (usb, device_table);
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
-static struct palette_list plist[] = {
+/* Video4Linux1 Palettes */
+static struct symbolic_list v4l1_plist[] = {
{ VIDEO_PALETTE_GREY, "GREY" },
- { VIDEO_PALETTE_HI240, "HI240" },
- { VIDEO_PALETTE_RGB565, "RGB565" },
+ { VIDEO_PALETTE_HI240, "HI240" },
+ { VIDEO_PALETTE_RGB565, "RGB565" },
{ VIDEO_PALETTE_RGB24, "RGB24" },
{ VIDEO_PALETTE_RGB32, "RGB32" },
- { VIDEO_PALETTE_RGB555, "RGB555" },
- { VIDEO_PALETTE_YUV422, "YUV422" },
- { VIDEO_PALETTE_YUYV, "YUYV" },
- { VIDEO_PALETTE_UYVY, "UYVY" },
- { VIDEO_PALETTE_YUV420, "YUV420" },
- { VIDEO_PALETTE_YUV411, "YUV411" },
- { VIDEO_PALETTE_RAW, "RAW" },
+ { VIDEO_PALETTE_RGB555, "RGB555" },
+ { VIDEO_PALETTE_YUV422, "YUV422" },
+ { VIDEO_PALETTE_YUYV, "YUYV" },
+ { VIDEO_PALETTE_UYVY, "UYVY" },
+ { VIDEO_PALETTE_YUV420, "YUV420" },
+ { VIDEO_PALETTE_YUV411, "YUV411" },
+ { VIDEO_PALETTE_RAW, "RAW" },
{ VIDEO_PALETTE_YUV422P,"YUV422P" },
{ VIDEO_PALETTE_YUV411P,"YUV411P" },
{ VIDEO_PALETTE_YUV420P,"YUV420P" },
{ VIDEO_PALETTE_YUV410P,"YUV410P" },
{ -1, NULL }
};
-#endif
-static unsigned char yQuanTable511[] = OV511_YQUANTABLE;
-static unsigned char uvQuanTable511[] = OV511_UVQUANTABLE;
-static unsigned char yQuanTable518[] = OV518_YQUANTABLE;
-static unsigned char uvQuanTable518[] = OV518_UVQUANTABLE;
+static struct symbolic_list brglist[] = {
+ { BRG_OV511, "OV511" },
+ { BRG_OV511PLUS, "OV511+" },
+ { BRG_OV518, "OV518" },
+ { BRG_OV518PLUS, "OV518+" },
+ { -1, NULL }
+};
+
+static struct symbolic_list senlist[] = {
+ { SEN_OV76BE, "OV76BE" },
+ { SEN_OV7610, "OV7610" },
+ { SEN_OV7620, "OV7620" },
+ { SEN_OV7620AE, "OV7620AE" },
+ { SEN_OV6620, "OV6620" },
+ { SEN_OV6630, "OV6630" },
+ { SEN_OV6630AE, "OV6630AE" },
+ { SEN_OV6630AF, "OV6630AF" },
+ { SEN_OV8600, "OV8600" },
+ { SEN_KS0127, "KS0127" },
+ { SEN_KS0127B, "KS0127B" },
+ { SEN_SAA7111A, "SAA7111A" },
+ { -1, NULL }
+};
+
+/* URB error codes: */
+static struct symbolic_list urb_errlist[] = {
+ { -ENOSR, "Buffer error (overrun)" },
+ { -EPIPE, "Stalled (device not responding)" },
+ { -EOVERFLOW, "Babble (bad cable?)" },
+ { -EPROTO, "Bit-stuff error (bad cable?)" },
+ { -EILSEQ, "CRC/Timeout" },
+ { -ETIMEDOUT, "NAK (device does not respond)" },
+ { -1, NULL }
+};
+
+/**********************************************************************
+ * Prototypes
+ **********************************************************************/
+
+static void ov51x_clear_snapshot(struct usb_ov511 *);
+static int ov51x_check_snapshot(struct usb_ov511 *);
+static inline int sensor_get_picture(struct usb_ov511 *,
+ struct video_picture *);
+static int sensor_get_exposure(struct usb_ov511 *, unsigned char *);
+static int ov51x_control_ioctl(struct inode *, struct file *, unsigned int,
+ unsigned long);
/**********************************************************************
*
@@ -455,7 +439,7 @@
void *data)
{
char *out = page;
- int i, j, len;
+ int i, len;
struct usb_ov511 *ov = data;
struct video_picture p;
unsigned char exp;
@@ -471,8 +455,7 @@
out += sprintf(out, "driver_version : %s\n", DRIVER_VERSION);
out += sprintf(out, "custom_id : %d\n", ov->customid);
- out += sprintf(out, "model : %s\n", ov->desc ?
- clist[ov->desc].description : "unknown");
+ out += sprintf(out, "model : %s\n", ov->desc);
out += sprintf(out, "streaming : %s\n", YES_NO(ov->streaming));
out += sprintf(out, "grabbing : %s\n", YES_NO(ov->grabbing));
out += sprintf(out, "compress : %s\n", YES_NO(ov->compress));
@@ -493,36 +476,16 @@
ov->frame[i].depth);
out += sprintf(out, " size : %d %d\n",
ov->frame[i].width, ov->frame[i].height);
- out += sprintf(out, " format : ");
- for (j = 0; plist[j].num >= 0; j++) {
- if (plist[j].num == ov->frame[i].format) {
- out += sprintf(out, "%s\n", plist[j].name);
- break;
- }
- }
- if (plist[j].num < 0)
- out += sprintf(out, "unknown\n");
+ out += sprintf(out, " format : %s\n",
+ symbolic(v4l1_plist, ov->frame[i].format));
out += sprintf(out, " data_buffer : 0x%p\n",
ov->frame[i].data);
}
out += sprintf(out, "snap_enabled : %s\n", YES_NO(ov->snap_enabled));
out += sprintf(out, "bridge : %s\n",
- ov->bridge == BRG_OV511 ? "OV511" :
- ov->bridge == BRG_OV511PLUS ? "OV511+" :
- ov->bridge == BRG_OV518 ? "OV518" :
- ov->bridge == BRG_OV518PLUS ? "OV518+" :
- "unknown");
+ symbolic(brglist, ov->bridge));
out += sprintf(out, "sensor : %s\n",
- ov->sensor == SEN_OV6620 ? "OV6620" :
- ov->sensor == SEN_OV6630 ? "OV6630" :
- ov->sensor == SEN_OV7610 ? "OV7610" :
- ov->sensor == SEN_OV7620 ? "OV7620" :
- ov->sensor == SEN_OV7620AE ? "OV7620AE" :
- ov->sensor == SEN_OV8600 ? "OV8600" :
- ov->sensor == SEN_KS0127 ? "KS0127" :
- ov->sensor == SEN_KS0127B ? "KS0127B" :
- ov->sensor == SEN_SAA7111A ? "SAA7111A" :
- "unknown");
+ symbolic(senlist, ov->sensor));
out += sprintf(out, "packet_size : %d\n", ov->packet_size);
out += sprintf(out, "framebuffer : 0x%p\n", ov->fbuf);
@@ -728,7 +691,7 @@
up(&ov->cbuf_lock);
if (rc < 0)
- err("reg write: error %d", rc);
+ err("reg write: error %d: %s", rc, symbolic(urb_errlist, rc));
return rc;
}
@@ -750,7 +713,7 @@
PDEBUG(5, "0x%02X:0x%02X", reg, ov->cbuf[0]);
if (rc < 0)
- err("reg read: error %d", rc);
+ err("reg read: error %d: %s", rc, symbolic(urb_errlist, rc));
else
rc = ov->cbuf[0];
@@ -809,7 +772,8 @@
up(&ov->cbuf_lock);
if (rc < 0)
- err("reg write multiple: error %d", rc);
+ err("reg write multiple: error %d: %s", rc,
+ symbolic(urb_errlist, rc));
return rc;
}
@@ -941,21 +905,17 @@
/* Select camera register */
rc = reg_w(ov, R51x_I2C_SADDR_3, reg);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
/* Write "value" to I2C data port of OV511 */
rc = reg_w(ov, R51x_I2C_DATA, value);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
/* Initiate 3-byte write cycle */
rc = reg_w(ov, R518_I2C_CTL, 0x01);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
return 0;
-
-error:
- err("ov518 i2c write: error %d", rc);
- return rc;
}
/* NOTE: Do not call this function directly! */
@@ -972,19 +932,19 @@
for (retries = OV511_I2C_RETRIES; ; ) {
/* Select camera register */
rc = reg_w(ov, R51x_I2C_SADDR_3, reg);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
/* Write "value" to I2C data port of OV511 */
rc = reg_w(ov, R51x_I2C_DATA, value);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
/* Initiate 3-byte write cycle */
rc = reg_w(ov, R511_I2C_CTL, 0x01);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
do rc = reg_r(ov, R511_I2C_CTL);
while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
if ((rc&2) == 0) /* Ack? */
break;
@@ -994,16 +954,11 @@
#endif
if (--retries < 0) {
err("i2c write retries exhausted");
- rc = -1;
- goto error;
+ return -1;
}
}
return 0;
-
-error:
- err("i2c write: error %d", rc);
- return rc;
}
/* NOTE: Do not call this function directly!
@@ -1018,25 +973,21 @@
/* Select camera register */
rc = reg_w(ov, R51x_I2C_SADDR_2, reg);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
/* Initiate 2-byte write cycle */
rc = reg_w(ov, R518_I2C_CTL, 0x03);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
/* Initiate 2-byte read cycle */
rc = reg_w(ov, R518_I2C_CTL, 0x05);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
value = reg_r(ov, R51x_I2C_DATA);
PDEBUG(5, "0x%02X:0x%02X", reg, value);
return value;
-
-error:
- err("ov518 i2c read: error %d", rc);
- return rc;
}
/* NOTE: Do not call this function directly!
@@ -1050,15 +1001,15 @@
for (retries = OV511_I2C_RETRIES; ; ) {
/* Select camera register */
rc = reg_w(ov, R51x_I2C_SADDR_2, reg);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
/* Initiate 2-byte write cycle */
rc = reg_w(ov, R511_I2C_CTL, 0x03);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
do rc = reg_r(ov, R511_I2C_CTL);
while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
if ((rc&2) == 0) /* Ack? */
break;
@@ -1068,8 +1019,7 @@
if (--retries < 0) {
err("i2c write retries exhausted");
- rc = -1;
- goto error;
+ return -1;
}
}
@@ -1077,23 +1027,22 @@
for (retries = OV511_I2C_RETRIES; ; ) {
/* Initiate 2-byte read cycle */
rc = reg_w(ov, R511_I2C_CTL, 0x05);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
do rc = reg_r(ov, R511_I2C_CTL);
while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
if ((rc&2) == 0) /* Ack? */
break;
/* I2C abort */
rc = reg_w(ov, R511_I2C_CTL, 0x10);
- if (rc < 0) goto error;
+ if (rc < 0) return rc;
if (--retries < 0) {
err("i2c read retries exhausted");
- rc = -1;
- goto error;
+ return -1;
}
}
@@ -1104,13 +1053,9 @@
/* This is needed to make i2c_w() work */
rc = reg_w(ov, R511_I2C_CTL, 0x05);
if (rc < 0)
- goto error;
+ return rc;
return value;
-
-error:
- err("i2c read: error %d", rc);
- return rc;
}
/* returns: negative is error, pos or zero is data */
@@ -1315,22 +1260,17 @@
while (pRegvals->bus != OV511_DONE_BUS) {
if (pRegvals->bus == OV511_REG_BUS) {
if ((rc = reg_w(ov, pRegvals->reg, pRegvals->val)) < 0)
- goto error;
+ return rc;
} else if (pRegvals->bus == OV511_I2C_BUS) {
if ((rc = i2c_w(ov, pRegvals->reg, pRegvals->val)) < 0)
- goto error;
+ return rc;
} else {
err("Bad regval array");
- rc = -1;
- goto error;
+ return -1;
}
pRegvals++;
}
return 0;
-
-error:
- err("write regvals: error %d", rc);
- return rc;
}
#ifdef OV511_DEBUG
@@ -2398,13 +2338,13 @@
{
switch (palette) {
case VIDEO_PALETTE_GREY: return 8;
+ case VIDEO_PALETTE_YUV420: return 12;
+ case VIDEO_PALETTE_YUV420P: return 12; /* Planar */
case VIDEO_PALETTE_RGB565: return 16;
case VIDEO_PALETTE_RGB24: return 24;
case VIDEO_PALETTE_YUV422: return 16;
case VIDEO_PALETTE_YUYV: return 16;
- case VIDEO_PALETTE_YUV420: return 12;
case VIDEO_PALETTE_YUV422P: return 16; /* Planar */
- case VIDEO_PALETTE_YUV420P: return 12; /* Planar */
default: return 0; /* Invalid format */
}
}
@@ -3479,6 +3419,7 @@
int ret = ov->decomp_ops->decomp_400(
pIn0,
pOut0,
+ frame->compbuf,
frame->rawwidth,
frame->rawheight,
frame->bytes_recvd);
@@ -3487,6 +3428,7 @@
int ret = ov->decomp_ops->decomp_420(
pIn0,
pOut0,
+ frame->compbuf,
frame->rawwidth,
frame->rawheight,
frame->bytes_recvd);
@@ -3686,7 +3628,7 @@
memset(frame->data, 0,
MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));
PDEBUG(4, "Dumping %d bytes", frame->bytes_recvd);
- memmove(frame->data, frame->rawdata, frame->bytes_recvd);
+ memcpy(frame->data, frame->rawdata, frame->bytes_recvd);
return;
}
@@ -3723,7 +3665,7 @@
/* Deinterlace frame, if necessary */
if (ov->sensor == SEN_SAA7111A && frame->rawheight == 480) {
- memmove(frame->rawdata, frame->tempdata,
+ memcpy(frame->rawdata, frame->tempdata,
MAX_RAW_DATA_SIZE(frame->width, frame->height));
deinterlace(frame, RAWFMT_YUV420, frame->rawdata,
frame->tempdata);
@@ -3751,18 +3693,19 @@
break;
case VIDEO_PALETTE_YUV420:
case VIDEO_PALETTE_YUV420P:
- memmove(frame->data, frame->tempdata,
+ memcpy(frame->data, frame->tempdata,
MAX_RAW_DATA_SIZE(frame->width, frame->height));
break;
case VIDEO_PALETTE_YUV422P:
/* Data is converted in place, so copy it in advance */
- memmove(frame->data, frame->tempdata,
+ memcpy(frame->data, frame->tempdata,
MAX_RAW_DATA_SIZE(frame->width, frame->height));
yuv420p_to_yuv422p(frame, frame->data);
break;
default:
- err("Cannot convert data to this format");
+ err("Cannot convert data to %s",
+ symbolic(v4l1_plist, frame->format));
}
if (fix_rgb_offset)
@@ -3899,7 +3842,7 @@
if (dumppix == 2) {
frame->bytes_recvd += n - 1;
if (frame->bytes_recvd <= max_raw)
- memmove(frame->rawdata + frame->bytes_recvd - (n - 1),
+ memcpy(frame->rawdata + frame->bytes_recvd - (n - 1),
in, n - 1);
else
PDEBUG(3, "Raw data buffer overrun!! (%d)",
@@ -3907,7 +3850,7 @@
} else if (!frame->compressed && !remove_zeros) {
frame->bytes_recvd += num;
if (frame->bytes_recvd <= max_raw)
- memmove(frame->rawdata + frame->bytes_recvd - num,
+ memcpy(frame->rawdata + frame->bytes_recvd - num,
in + offset, num);
else
PDEBUG(3, "Raw data buffer overrun!! (%d)",
@@ -3916,7 +3859,7 @@
int b, read = 0, allzero, copied = 0;
if (offset) {
frame->bytes_recvd += 32 - offset; // Bytes out
- memmove(frame->rawdata, in + offset, 32 - offset);
+ memcpy(frame->rawdata, in + offset, 32 - offset);
read += 32;
}
@@ -3934,7 +3877,7 @@
} else {
if (frame->bytes_recvd + copied + 32 <= max_raw)
{
- memmove(frame->rawdata
+ memcpy(frame->rawdata
+ frame->bytes_recvd + copied,
in + read, 32);
copied += 32;
@@ -4056,7 +3999,7 @@
if (dumppix == 2) {
frame->bytes_recvd += n;
if (frame->bytes_recvd <= max_raw)
- memmove(frame->rawdata + frame->bytes_recvd - n, in, n);
+ memcpy(frame->rawdata + frame->bytes_recvd - n, in, n);
else
PDEBUG(3, "Raw data buffer overrun!! (%d)",
frame->bytes_recvd - max_raw);
@@ -4086,7 +4029,7 @@
} else {
if (frame->bytes_recvd + copied + 8 <= max_raw)
{
- memmove(frame->rawdata
+ memcpy(frame->rawdata
+ frame->bytes_recvd + copied,
in + read, 8);
copied += 8;
@@ -4105,13 +4048,15 @@
{
int i;
struct usb_ov511 *ov;
+ struct ov511_sbuf *sbuf;
if (!urb->context) {
PDEBUG(4, "no context");
return;
}
- ov = (struct usb_ov511 *) urb->context;
+ sbuf = urb->context;
+ ov = sbuf->ov;
if (!ov || !ov->dev || !ov->user) {
PDEBUG(4, "no device, or not open");
@@ -4123,8 +4068,20 @@
return;
}
+ if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
+ PDEBUG(4, "URB unlinked");
+ return;
+ }
+
+ if (urb->status != -EINPROGRESS && urb->status != 0) {
+ err("ERROR: urb->status=%d: %s", urb->status,
+ symbolic(urb_errlist, urb->status));
+ return;
+ }
+
/* Copy the data received into our frame buffer */
- PDEBUG(5, "Moving %d packets", urb->number_of_packets);
+ PDEBUG(5, "sbuf[%d]: Moving %d packets", sbuf->n,
+ urb->number_of_packets);
for (i = 0; i < urb->number_of_packets; i++) {
/* Warning: Don't call *_move_data() if no frame active! */
if (ov->curframe >= 0) {
@@ -4225,14 +4182,13 @@
for (n = 0; n < OV511_NUMSBUF; n++) {
urb = usb_alloc_urb(FRAMES_PER_DESC, GFP_KERNEL);
-
if (!urb) {
err("init isoc: usb_alloc_urb ret. NULL");
return -ENOMEM;
}
ov->sbuf[n].urb = urb;
urb->dev = ov->dev;
- urb->context = ov;
+ urb->context = &ov->sbuf[n];
urb->pipe = usb_rcvisocpipe(ov->dev, OV511_ENDPOINT_ADDRESS);
urb->transfer_flags = USB_ISO_ASAP;
urb->transfer_buffer = ov->sbuf[n].data;
@@ -4262,10 +4218,23 @@
}
static void
-ov51x_stop_isoc(struct usb_ov511 *ov)
+ov51x_unlink_isoc(struct usb_ov511 *ov)
{
int n;
+ /* Unschedule all of the iso td's */
+ for (n = OV511_NUMSBUF - 1; n >= 0; n--) {
+ if (ov->sbuf[n].urb) {
+ usb_unlink_urb(ov->sbuf[n].urb);
+ usb_free_urb(ov->sbuf[n].urb);
+ ov->sbuf[n].urb = NULL;
+ }
+ }
+}
+
+static void
+ov51x_stop_isoc(struct usb_ov511 *ov)
+{
if (!ov->streaming || !ov->dev)
return;
@@ -4275,15 +4244,7 @@
ov->streaming = 0;
- /* Unschedule all of the iso td's */
- for (n = OV511_NUMSBUF - 1; n >= 0; n--) {
- if (ov->sbuf[n].urb) {
- ov->sbuf[n].urb->next = NULL;
- usb_unlink_urb(ov->sbuf[n].urb);
- usb_free_urb(ov->sbuf[n].urb);
- ov->sbuf[n].urb = NULL;
- }
- }
+ ov51x_unlink_isoc(ov);
}
static int
@@ -4337,6 +4298,55 @@
*
***************************************************************************/
+/*
+ * - You must acquire buf_lock before entering this function.
+ * - Because this code will free any non-null pointer, you must be sure to null
+ * them if you explicitly free them somewhere else!
+ */
+static void
+ov51x_do_dealloc(struct usb_ov511 *ov)
+{
+ int i;
+ PDEBUG(4, "entered");
+
+ if (ov->fbuf) {
+ rvfree(ov->fbuf, OV511_NUMFRAMES
+ * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));
+ ov->fbuf = NULL;
+ }
+
+ if (ov->rawfbuf) {
+ vfree(ov->rawfbuf);
+ ov->rawfbuf = NULL;
+ }
+
+ if (ov->tempfbuf) {
+ vfree(ov->tempfbuf);
+ ov->tempfbuf = NULL;
+ }
+
+ for (i = 0; i < OV511_NUMSBUF; i++) {
+ if (ov->sbuf[i].data) {
+ kfree(ov->sbuf[i].data);
+ ov->sbuf[i].data = NULL;
+ }
+ }
+
+ for (i = 0; i < OV511_NUMFRAMES; i++) {
+ ov->frame[i].data = NULL;
+ ov->frame[i].rawdata = NULL;
+ ov->frame[i].tempdata = NULL;
+ if (ov->frame[i].compbuf) {
+ free_page((unsigned long) ov->frame[i].compbuf);
+ ov->frame[i].compbuf = NULL;
+ }
+ }
+
+ PDEBUG(4, "buffer memory deallocated");
+ ov->buf_state = BUF_NOT_ALLOCATED;
+ PDEBUG(4, "leaving");
+}
+
static int
ov51x_alloc(struct usb_ov511 *ov)
{
@@ -4362,40 +4372,23 @@
goto error;
ov->rawfbuf = vmalloc(raw_bufsize);
- if (!ov->rawfbuf) {
- rvfree(ov->fbuf, data_bufsize);
- ov->fbuf = NULL;
+ if (!ov->rawfbuf)
goto error;
- }
+
memset(ov->rawfbuf, 0, raw_bufsize);
ov->tempfbuf = vmalloc(raw_bufsize);
- if (!ov->tempfbuf) {
- vfree(ov->rawfbuf);
- ov->rawfbuf = NULL;
- rvfree(ov->fbuf, data_bufsize);
- ov->fbuf = NULL;
+ if (!ov->tempfbuf)
goto error;
- }
+
memset(ov->tempfbuf, 0, raw_bufsize);
for (i = 0; i < OV511_NUMSBUF; i++) {
ov->sbuf[i].data = kmalloc(FRAMES_PER_DESC *
MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL);
- if (!ov->sbuf[i].data) {
- while (--i) {
- kfree(ov->sbuf[i].data);
- ov->sbuf[i].data = NULL;
- }
- vfree(ov->tempfbuf);
- ov->tempfbuf = NULL;
- vfree(ov->rawfbuf);
- ov->rawfbuf = NULL;
- rvfree(ov->fbuf, data_bufsize);
- ov->fbuf = NULL;
-
+ if (!ov->sbuf[i].data)
goto error;
- }
+
PDEBUG(4, "sbuf[%d] @ %p", i, ov->sbuf[i].data);
}
@@ -4405,6 +4398,12 @@
+ i * MAX_RAW_DATA_SIZE(w, h);
ov->frame[i].tempdata = ov->tempfbuf
+ i * MAX_RAW_DATA_SIZE(w, h);
+
+ ov->frame[i].compbuf =
+ (unsigned char *) __get_free_page(GFP_KERNEL);
+ if (!ov->frame[i].compbuf)
+ goto error;
+
PDEBUG(4, "frame[%d] @ %p", i, ov->frame[i].data);
}
@@ -4414,57 +4413,12 @@
PDEBUG(4, "leaving");
return 0;
error:
- ov->buf_state = BUF_NOT_ALLOCATED;
+ ov51x_do_dealloc(ov);
up(&ov->buf_lock);
PDEBUG(4, "errored");
return -ENOMEM;
}
-/*
- * - You must acquire buf_lock before entering this function.
- * - Because this code will free any non-null pointer, you must be sure to null
- * them if you explicitly free them somewhere else!
- */
-static void
-ov51x_do_dealloc(struct usb_ov511 *ov)
-{
- int i;
- PDEBUG(4, "entered");
-
- if (ov->fbuf) {
- rvfree(ov->fbuf, OV511_NUMFRAMES
- * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight));
- ov->fbuf = NULL;
- }
-
- if (ov->rawfbuf) {
- vfree(ov->rawfbuf);
- ov->rawfbuf = NULL;
- }
-
- if (ov->tempfbuf) {
- vfree(ov->tempfbuf);
- ov->tempfbuf = NULL;
- }
-
- for (i = 0; i < OV511_NUMSBUF; i++) {
- if (ov->sbuf[i].data) {
- kfree(ov->sbuf[i].data);
- ov->sbuf[i].data = NULL;
- }
- }
-
- for (i = 0; i < OV511_NUMFRAMES; i++) {
- ov->frame[i].data = NULL;
- ov->frame[i].rawdata = NULL;
- ov->frame[i].tempdata = NULL;
- }
-
- PDEBUG(4, "buffer memory deallocated");
- ov->buf_state = BUF_NOT_ALLOCATED;
- PDEBUG(4, "leaving");
-}
-
static void
ov51x_buf_callback(unsigned long data)
{
@@ -4513,9 +4467,16 @@
*
***************************************************************************/
+#ifdef OV511_OLD_V4L
static int
ov51x_v4l1_open(struct video_device *vdev, int flags)
{
+#else
+static int
+ov51x_v4l1_open(struct inode *inode, struct file *file)
+{
+ struct video_device *vdev = video_devdata(file);
+#endif
struct usb_ov511 *ov = vdev->priv;
int err, i;
@@ -4567,9 +4528,16 @@
return err;
}
+#ifdef OV511_OLD_V4L
static void
ov51x_v4l1_close(struct video_device *vdev)
{
+#else
+static int
+ov51x_v4l1_close(struct inode *inode, struct file *file)
+{
+ struct video_device *vdev = video_devdata(file);
+#endif
struct usb_ov511 *ov = vdev->priv;
PDEBUG(4, "ov511_close");
@@ -4602,32 +4570,19 @@
kfree(ov);
ov = NULL;
}
-}
-
-static int
-ov51x_v4l1_init_done(struct video_device *vdev)
-{
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
- create_proc_ov511_cam(vdev->priv);
-#endif
+#ifdef OV511_OLD_V4L
+ return;
+#else
return 0;
-}
-
-static long
-ov51x_v4l1_write(struct video_device *vdev, const char *buf,
- unsigned long count, int noblock)
-{
- return -EINVAL;
+#endif
}
/* Do not call this function directly! */
static int
-ov51x_v4l1_ioctl_internal(struct video_device *vdev, unsigned int cmd,
+ov51x_v4l1_ioctl_internal(struct usb_ov511 *ov, unsigned int cmd,
void *arg)
{
- struct usb_ov511 *ov = vdev->priv;
-
PDEBUG(5, "IOCtl: 0x%X", cmd);
if (!ov->dev)
@@ -4636,95 +4591,79 @@
switch (cmd) {
case VIDIOCGCAP:
{
- struct video_capability b;
+ struct video_capability *b = arg;
PDEBUG(4, "VIDIOCGCAP");
- memset(&b, 0, sizeof(b));
- sprintf(b.name, "%s USB Camera",
- ov->bridge == BRG_OV511 ? "OV511" :
- ov->bridge == BRG_OV511PLUS ? "OV511+" :
- ov->bridge == BRG_OV518 ? "OV518" :
- ov->bridge == BRG_OV518PLUS ? "OV518+" :
- "unknown");
- b.type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
+ memset(b, 0, sizeof(struct video_capability));
+ sprintf(b->name, "%s USB Camera",
+ symbolic(brglist, ov->bridge));
+ b->type = VID_TYPE_CAPTURE | VID_TYPE_SUBCAPTURE;
if (ov->has_tuner)
- b.type |= VID_TYPE_TUNER;
- b.channels = ov->num_inputs;
- b.audios = ov->has_audio_proc ? 1:0;
- b.maxwidth = ov->maxwidth;
- b.maxheight = ov->maxheight;
- b.minwidth = ov->minwidth;
- b.minheight = ov->minheight;
+ b->type |= VID_TYPE_TUNER;
+ b->channels = ov->num_inputs;
+ b->audios = ov->has_audio_proc ? 1:0;
+ b->maxwidth = ov->maxwidth;
+ b->maxheight = ov->maxheight;
+ b->minwidth = ov->minwidth;
+ b->minheight = ov->minheight;
- if (copy_to_user(arg, &b, sizeof(b)))
- return -EFAULT;
-
return 0;
}
case VIDIOCGCHAN:
{
- struct video_channel v;
+ struct video_channel *v = arg;
PDEBUG(4, "VIDIOCGCHAN");
- if (copy_from_user(&v, arg, sizeof(v)))
- return -EFAULT;
-
- if ((unsigned)(v.channel) >= ov->num_inputs) {
- err("Invalid channel (%d)", v.channel);
+ if ((unsigned)(v->channel) >= ov->num_inputs) {
+ err("Invalid channel (%d)", v->channel);
return -EINVAL;
}
- v.norm = ov->norm;
- v.type = (ov->has_tuner) ? VIDEO_TYPE_TV : VIDEO_TYPE_CAMERA;
- v.flags = (ov->has_tuner) ? VIDEO_VC_TUNER : 0;
- v.flags |= (ov->has_audio_proc) ? VIDEO_VC_AUDIO : 0;
-// v.flags |= (ov->has_decoder) ? VIDEO_VC_NORM : 0;
- v.tuners = (ov->has_tuner) ? 1:0;
- decoder_get_input_name(ov, v.channel, v.name);
+ v->norm = ov->norm;
+ v->type = (ov->has_tuner) ? VIDEO_TYPE_TV : VIDEO_TYPE_CAMERA;
+ v->flags = (ov->has_tuner) ? VIDEO_VC_TUNER : 0;
+ v->flags |= (ov->has_audio_proc) ? VIDEO_VC_AUDIO : 0;
+// v->flags |= (ov->has_decoder) ? VIDEO_VC_NORM : 0;
+ v->tuners = (ov->has_tuner) ? 1:0;
+ decoder_get_input_name(ov, v->channel, v->name);
- if (copy_to_user(arg, &v, sizeof(v)))
- return -EFAULT;
-
return 0;
}
case VIDIOCSCHAN:
{
- struct video_channel v;
+ struct video_channel *v = arg;
int err;
PDEBUG(4, "VIDIOCSCHAN");
- if (copy_from_user(&v, arg, sizeof(v)))
- return -EFAULT;
-
/* Make sure it's not a camera */
if (!ov->has_decoder) {
- if (v.channel == 0)
+ if (v->channel == 0)
return 0;
else
return -EINVAL;
}
- if (v.norm != VIDEO_MODE_PAL &&
- v.norm != VIDEO_MODE_NTSC &&
- v.norm != VIDEO_MODE_SECAM &&
- v.norm != VIDEO_MODE_AUTO) {
- err("Invalid norm (%d)", v.norm);
+ if (v->norm != VIDEO_MODE_PAL &&
+ v->norm != VIDEO_MODE_NTSC &&
+ v->norm != VIDEO_MODE_SECAM &&
+ v->norm != VIDEO_MODE_AUTO) {
+ err("Invalid norm (%d)", v->norm);
return -EINVAL;
}
- if ((unsigned)(v.channel) >= ov->num_inputs) {
- err("Invalid channel (%d)", v.channel);
+ if ((unsigned)(v->channel) >= ov->num_inputs) {
+ err("Invalid channel (%d)", v->channel);
return -EINVAL;
}
- err = decoder_set_input(ov, v.channel);
+ err = decoder_set_input(ov, v->channel);
if (err)
return err;
- err = decoder_set_norm(ov, v.norm);
+ err = decoder_set_norm(ov, v->norm);
if (err)
return err;
@@ -4732,43 +4671,37 @@
}
case VIDIOCGPICT:
{
- struct video_picture p;
+ struct video_picture *p = arg;
PDEBUG(4, "VIDIOCGPICT");
- memset(&p, 0, sizeof(p));
-
- if (sensor_get_picture(ov, &p))
+ memset(p, 0, sizeof(struct video_picture));
+ if (sensor_get_picture(ov, p))
return -EIO;
- if (copy_to_user(arg, &p, sizeof(p)))
- return -EFAULT;
-
return 0;
}
case VIDIOCSPICT:
{
- struct video_picture p;
+ struct video_picture *p = arg;
int i;
PDEBUG(4, "VIDIOCSPICT");
- if (copy_from_user(&p, arg, sizeof(p)))
- return -EFAULT;
-
- if (!get_depth(p.palette))
+ if (!get_depth(p->palette))
return -EINVAL;
- if (sensor_set_picture(ov, &p))
+ if (sensor_set_picture(ov, p))
return -EIO;
- if (force_palette && p.palette != force_palette) {
- info("Palette rejected (%d)", p.palette);
+ if (force_palette && p->palette != force_palette) {
+ info("Palette rejected (%s)",
+ symbolic(v4l1_plist, p->palette));
return -EINVAL;
}
// FIXME: Format should be independent of frames
- if (p.palette != ov->frame[0].format) {
+ if (p->palette != ov->frame[0].format) {
PDEBUG(4, "Detected format change");
/* If we're collecting previous frame wait
@@ -4777,79 +4710,73 @@
if (signal_pending(current)) return -EINTR;
mode_init_regs(ov, ov->frame[0].width,
- ov->frame[0].height, p.palette, ov->sub_flag);
+ ov->frame[0].height, p->palette, ov->sub_flag);
}
- PDEBUG(4, "Setting depth=%d, palette=%d", p.depth, p.palette);
+ PDEBUG(4, "Setting depth=%d, palette=%s",
+ p->depth, symbolic(v4l1_plist, p->palette));
+
for (i = 0; i < OV511_NUMFRAMES; i++) {
- ov->frame[i].depth = p.depth;
- ov->frame[i].format = p.palette;
+ ov->frame[i].depth = p->depth;
+ ov->frame[i].format = p->palette;
}
return 0;
}
case VIDIOCGCAPTURE:
{
- int vf;
+ int *vf = arg;
PDEBUG(4, "VIDIOCGCAPTURE");
- if (copy_from_user(&vf, arg, sizeof(vf)))
- return -EFAULT;
- ov->sub_flag = vf;
+ ov->sub_flag = *vf;
return 0;
}
case VIDIOCSCAPTURE:
{
- struct video_capture vc;
+ struct video_capture *vc = arg;
PDEBUG(4, "VIDIOCSCAPTURE");
- if (copy_from_user(&vc, arg, sizeof(vc)))
- return -EFAULT;
- if (vc.flags)
+ if (vc->flags)
return -EINVAL;
- if (vc.decimation)
+ if (vc->decimation)
return -EINVAL;
- vc.x &= ~3L;
- vc.y &= ~1L;
- vc.y &= ~31L;
-
- if (vc.width == 0)
- vc.width = 32;
-
- vc.height /= 16;
- vc.height *= 16;
- if (vc.height == 0)
- vc.height = 16;
-
- ov->subx = vc.x;
- ov->suby = vc.y;
- ov->subw = vc.width;
- ov->subh = vc.height;
+ vc->x &= ~3L;
+ vc->y &= ~1L;
+ vc->y &= ~31L;
+
+ if (vc->width == 0)
+ vc->width = 32;
+
+ vc->height /= 16;
+ vc->height *= 16;
+ if (vc->height == 0)
+ vc->height = 16;
+
+ ov->subx = vc->x;
+ ov->suby = vc->y;
+ ov->subw = vc->width;
+ ov->subh = vc->height;
return 0;
}
case VIDIOCSWIN:
{
- struct video_window vw;
+ struct video_window *vw = arg;
int i, result;
- if (copy_from_user(&vw, arg, sizeof(vw)))
- return -EFAULT;
-
- PDEBUG(4, "VIDIOCSWIN: width=%d, height=%d",
- vw.width, vw.height);
+ PDEBUG(4, "VIDIOCSWIN: %dx%d", vw->width, vw->height);
#if 0
- if (vw.flags)
+ if (vw->flags)
return -EINVAL;
- if (vw.clipcount)
+ if (vw->clipcount)
return -EINVAL;
- if (vw.height != ov->maxheight)
+ if (vw->height != ov->maxheight)
return -EINVAL;
- if (vw.width != ov->maxwidth)
+ if (vw->width != ov->maxwidth)
return -EINVAL;
#endif
@@ -4858,140 +4785,132 @@
interruptible_sleep_on(&ov->wq);
if (signal_pending(current)) return -EINTR;
- result = mode_init_regs(ov, vw.width, vw.height,
+ result = mode_init_regs(ov, vw->width, vw->height,
ov->frame[0].format, ov->sub_flag);
if (result < 0)
return result;
for (i = 0; i < OV511_NUMFRAMES; i++) {
- ov->frame[i].width = vw.width;
- ov->frame[i].height = vw.height;
+ ov->frame[i].width = vw->width;
+ ov->frame[i].height = vw->height;
}
return 0;
}
case VIDIOCGWIN:
{
- struct video_window vw;
-
- memset(&vw, 0, sizeof(vw));
- vw.x = 0; /* FIXME */
- vw.y = 0;
- vw.width = ov->frame[0].width;
- vw.height = ov->frame[0].height;
- vw.flags = 30;
+ struct video_window *vw = arg;
- PDEBUG(4, "VIDIOCGWIN: %dx%d", vw.width, vw.height);
+ memset(vw, 0, sizeof(struct video_window));
+ vw->x = 0; /* FIXME */
+ vw->y = 0;
+ vw->width = ov->frame[0].width;
+ vw->height = ov->frame[0].height;
+ vw->flags = 30;
- if (copy_to_user(arg, &vw, sizeof(vw)))
- return -EFAULT;
+ PDEBUG(4, "VIDIOCGWIN: %dx%d", vw->width, vw->height);
return 0;
}
case VIDIOCGMBUF:
{
- struct video_mbuf vm;
+ struct video_mbuf *vm = arg;
int i;
PDEBUG(4, "VIDIOCGMBUF");
- memset(&vm, 0, sizeof(vm));
- vm.size = OV511_NUMFRAMES
- * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight);
- vm.frames = OV511_NUMFRAMES;
+ memset(vm, 0, sizeof(struct video_mbuf));
+ vm->size = OV511_NUMFRAMES
+ * MAX_DATA_SIZE(ov->maxwidth, ov->maxheight);
+ vm->frames = OV511_NUMFRAMES;
- vm.offsets[0] = 0;
+ vm->offsets[0] = 0;
for (i = 1; i < OV511_NUMFRAMES; i++) {
- vm.offsets[i] = vm.offsets[i-1]
+ vm->offsets[i] = vm->offsets[i-1]
+ MAX_DATA_SIZE(ov->maxwidth, ov->maxheight);
}
- if (copy_to_user((void *)arg, (void *)&vm, sizeof(vm)))
- return -EFAULT;
-
return 0;
}
case VIDIOCMCAPTURE:
{
- struct video_mmap vm;
+ struct video_mmap *vm = arg;
int ret, depth;
+ unsigned int f = vm->frame;
- if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm)))
- return -EFAULT;
+ PDEBUG(4, "VIDIOCMCAPTURE: frame: %d, %dx%d, %s", f, vm->width,
+ vm->height, symbolic(v4l1_plist, vm->format));
- PDEBUG(4, "CMCAPTURE");
- PDEBUG(4, "frame: %d, size: %dx%d, format: %d",
- vm.frame, vm.width, vm.height, vm.format);
-
- depth = get_depth(vm.format);
+ depth = get_depth(vm->format);
if (!depth) {
- err("VIDIOCMCAPTURE: invalid format (%d)", vm.format);
+ err("VIDIOCMCAPTURE: invalid format (%s)",
+ symbolic(v4l1_plist, vm->format));
return -EINVAL;
}
- if ((unsigned)vm.frame >= OV511_NUMFRAMES) {
- err("VIDIOCMCAPTURE: invalid frame (%d)", vm.frame);
+ if (f >= OV511_NUMFRAMES) {
+ err("VIDIOCMCAPTURE: invalid frame (%d)", f);
return -EINVAL;
}
- if (vm.width > ov->maxwidth
- || vm.height > ov->maxheight) {
+ if (vm->width > ov->maxwidth
+ || vm->height > ov->maxheight) {
err("VIDIOCMCAPTURE: requested dimensions too big");
return -EINVAL;
}
- if (ov->frame[vm.frame].grabstate == FRAME_GRABBING) {
+ if (ov->frame[f].grabstate == FRAME_GRABBING) {
PDEBUG(4, "VIDIOCMCAPTURE: already grabbing");
return -EBUSY;
}
- if (force_palette && vm.format != force_palette) {
- info("palette rejected (%d)", vm.format);
+ if (force_palette && (vm->format != force_palette)) {
+ info("palette rejected (%s)",
+ symbolic(v4l1_plist, vm->format));
return -EINVAL;
}
- if ((ov->frame[vm.frame].width != vm.width) ||
- (ov->frame[vm.frame].height != vm.height) ||
- (ov->frame[vm.frame].format != vm.format) ||
- (ov->frame[vm.frame].sub_flag != ov->sub_flag) ||
- (ov->frame[vm.frame].depth != depth)) {
+ if ((ov->frame[f].width != vm->width) ||
+ (ov->frame[f].height != vm->height) ||
+ (ov->frame[f].format != vm->format) ||
+ (ov->frame[f].sub_flag != ov->sub_flag) ||
+ (ov->frame[f].depth != depth)) {
PDEBUG(4, "VIDIOCMCAPTURE: change in image parameters");
/* If we're collecting previous frame wait
before changing modes */
interruptible_sleep_on(&ov->wq);
if (signal_pending(current)) return -EINTR;
- ret = mode_init_regs(ov, vm.width, vm.height,
- vm.format, ov->sub_flag);
+ ret = mode_init_regs(ov, vm->width, vm->height,
+ vm->format, ov->sub_flag);
#if 0
if (ret < 0) {
PDEBUG(1, "Got error while initializing regs ");
return ret;
}
#endif
- ov->frame[vm.frame].width = vm.width;
- ov->frame[vm.frame].height = vm.height;
- ov->frame[vm.frame].format = vm.format;
- ov->frame[vm.frame].sub_flag = ov->sub_flag;
- ov->frame[vm.frame].depth = depth;
+ ov->frame[f].width = vm->width;
+ ov->frame[f].height = vm->height;
+ ov->frame[f].format = vm->format;
+ ov->frame[f].sub_flag = ov->sub_flag;
+ ov->frame[f].depth = depth;
}
/* Mark it as ready */
- ov->frame[vm.frame].grabstate = FRAME_READY;
+ ov->frame[f].grabstate = FRAME_READY;
- PDEBUG(4, "VIDIOCMCAPTURE: renewing frame %d", vm.frame);
+ PDEBUG(4, "VIDIOCMCAPTURE: renewing frame %d", f);
- return ov51x_new_frame(ov, vm.frame);
+ return ov51x_new_frame(ov, f);
}
case VIDIOCSYNC:
{
- int fnum, rc;
+ unsigned int fnum = *((unsigned int *) arg);
struct ov511_frame *frame;
+ int rc;
- if (copy_from_user((void *)&fnum, arg, sizeof(int)))
- return -EFAULT;
- if ((unsigned)fnum >= OV511_NUMFRAMES) {
+ if (fnum >= OV511_NUMFRAMES) {
err("VIDIOCSYNC: invalid frame (%d)", fnum);
return -EINVAL;
}
@@ -5053,124 +4972,105 @@
}
case VIDIOCGFBUF:
{
- struct video_buffer vb;
+ struct video_buffer *vb = arg;
- PDEBUG(4, "VIDIOCSCHAN");
+ PDEBUG(4, "VIDIOCGFBUF");
- memset(&vb, 0, sizeof(vb));
- vb.base = NULL; /* frame buffer not supported, not used */
-
- if (copy_to_user((void *)arg, (void *)&vb, sizeof(vb)))
- return -EFAULT;
+ memset(vb, 0, sizeof(struct video_buffer));
return 0;
}
case VIDIOCGUNIT:
{
- struct video_unit vu;
+ struct video_unit *vu = arg;
PDEBUG(4, "VIDIOCGUNIT");
- memset(&vu, 0, sizeof(vu));
-
- vu.video = ov->vdev.minor; /* Video minor */
- vu.vbi = VIDEO_NO_UNIT; /* VBI minor */
- vu.radio = VIDEO_NO_UNIT; /* Radio minor */
- vu.audio = VIDEO_NO_UNIT; /* Audio minor */
- vu.teletext = VIDEO_NO_UNIT; /* Teletext minor */
+ memset(vu, 0, sizeof(struct video_unit));
- if (copy_to_user((void *)arg, (void *)&vu, sizeof(vu)))
- return -EFAULT;
+ vu->video = ov->vdev.minor;
+ vu->vbi = VIDEO_NO_UNIT;
+ vu->radio = VIDEO_NO_UNIT;
+ vu->audio = VIDEO_NO_UNIT;
+ vu->teletext = VIDEO_NO_UNIT;
return 0;
}
case VIDIOCGTUNER:
{
- struct video_tuner v;
+ struct video_tuner *v = arg;
PDEBUG(4, "VIDIOCGTUNER");
- if (copy_from_user(&v, arg, sizeof(v)))
- return -EFAULT;
-
- if (!ov->has_tuner || v.tuner) // Only tuner 0
+ if (!ov->has_tuner || v->tuner) // Only tuner 0
return -EINVAL;
- strcpy(v.name, "Television");
+ strcpy(v->name, "Television");
// FIXME: Need a way to get the real values
- v.rangelow = 0;
- v.rangehigh = ~0;
+ v->rangelow = 0;
+ v->rangehigh = ~0;
- v.flags = VIDEO_TUNER_PAL | VIDEO_TUNER_NTSC |
- VIDEO_TUNER_SECAM;
- v.mode = 0; /* FIXME: Not sure what this is yet */
- v.signal = 0xFFFF; /* unknown */
+ v->flags = VIDEO_TUNER_PAL | VIDEO_TUNER_NTSC
+ | VIDEO_TUNER_SECAM;
+ v->mode = 0; /* FIXME: Not sure what this is yet */
+ v->signal = 0xFFFF; /* unknown */
- call_i2c_clients(ov, cmd, &v);
-
- if (copy_to_user(arg, &v, sizeof(v)))
- return -EFAULT;
+ call_i2c_clients(ov, cmd, v);
return 0;
}
case VIDIOCSTUNER:
{
- struct video_tuner v;
+ struct video_tuner *v = arg;
int err;
PDEBUG(4, "VIDIOCSTUNER");
- if (copy_from_user(&v, arg, sizeof(v)))
- return -EFAULT;
-
/* Only no or one tuner for now */
- if (!ov->has_tuner || v.tuner)
+ if (!ov->has_tuner || v->tuner)
return -EINVAL;
/* and it only has certain valid modes */
- if (v.mode != VIDEO_MODE_PAL &&
- v.mode != VIDEO_MODE_NTSC &&
- v.mode != VIDEO_MODE_SECAM) return -EOPNOTSUPP;
+ if (v->mode != VIDEO_MODE_PAL &&
+ v->mode != VIDEO_MODE_NTSC &&
+ v->mode != VIDEO_MODE_SECAM)
+ return -EOPNOTSUPP;
/* Is this right/necessary? */
- err = decoder_set_norm(ov, v.mode);
+ err = decoder_set_norm(ov, v->mode);
if (err)
return err;
- call_i2c_clients(ov, cmd, &v);
+ call_i2c_clients(ov, cmd, v);
return 0;
}
case VIDIOCGFREQ:
{
- unsigned long v = ov->freq;
+ unsigned long v = *((unsigned long *) arg);
PDEBUG(4, "VIDIOCGFREQ");
if (!ov->has_tuner)
return -EINVAL;
+
+ v = ov->freq;
#if 0
/* FIXME: this is necessary for testing */
v = 46*16;
#endif
- if (copy_to_user(arg, &v, sizeof(v)))
- return -EFAULT;
-
return 0;
}
case VIDIOCSFREQ:
{
- unsigned long v;
+ unsigned long v = *((unsigned long *) arg);
+
+ PDEBUG(4, "VIDIOCSFREQ: %lx", v);
if (!ov->has_tuner)
return -EINVAL;
- if (copy_from_user(&v, arg, sizeof(v)))
- return -EFAULT;
-
- PDEBUG(4, "VIDIOCSFREQ: %lx", v);
-
ov->freq = v;
call_i2c_clients(ov, cmd, &v);
@@ -5190,25 +5090,110 @@
return 0;
}
+#ifdef OV511_OLD_V4L
+/* This is implemented as video_generic_ioctl() in the new V4L's videodev.c */
+int
+ov51x_v4l1_generic_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
+{
+ char sbuf[128];
+ void *mbuf = NULL;
+ void *parg = NULL;
+ int err = -EINVAL;
+
+ /* Copy arguments into temp kernel buffer */
+ switch (_IOC_DIR(cmd)) {
+ case _IOC_NONE:
+ parg = arg;
+ break;
+ case _IOC_READ: /* some v4l ioctls are marked wrong ... */
+ case _IOC_WRITE:
+ case (_IOC_WRITE | _IOC_READ):
+ if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
+ parg = sbuf;
+ } else {
+ /* too big to allocate from stack */
+ mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
+ if (NULL == mbuf)
+ return -ENOMEM;
+ parg = mbuf;
+ }
+
+ err = -EFAULT;
+ if (copy_from_user(parg, arg, _IOC_SIZE(cmd)))
+ goto out;
+ break;
+ }
+
+ err = ov51x_v4l1_ioctl_internal(vdev->priv, cmd, parg);
+ if (err == -ENOIOCTLCMD)
+ err = -EINVAL;
+ if (err < 0)
+ goto out;
+
+ /* Copy results into user buffer */
+ switch (_IOC_DIR(cmd))
+ {
+ case _IOC_READ:
+ case (_IOC_WRITE | _IOC_READ):
+ if (copy_to_user(arg, parg, _IOC_SIZE(cmd)))
+ err = -EFAULT;
+ break;
+ }
+
+out:
+ if (mbuf)
+ kfree(mbuf);
+ return err;
+}
+
static int
ov51x_v4l1_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
{
+ struct usb_ov511 *ov = vdev->priv;
int rc;
+
+ if (down_interruptible(&ov->lock))
+ return -EINTR;
+
+ rc = ov51x_v4l1_generic_ioctl(vdev, cmd, arg);
+
+ up(&ov->lock);
+ return rc;
+}
+
+#else /* If new V4L API */
+
+static int
+ov51x_v4l1_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, void *arg)
+{
+ struct video_device *vdev = video_devdata(file);
struct usb_ov511 *ov = vdev->priv;
+ int rc;
if (down_interruptible(&ov->lock))
return -EINTR;
- rc = ov51x_v4l1_ioctl_internal(vdev, cmd, arg);
+ rc = ov51x_v4l1_ioctl_internal(ov, cmd, arg);
up(&ov->lock);
return rc;
}
+#endif /* OV511_OLD_V4L */
+#ifdef OV511_OLD_V4L
static inline long
ov51x_v4l1_read(struct video_device *vdev, char *buf, unsigned long count,
int noblock)
{
+#else
+static inline int
+ov51x_v4l1_read(struct file *file, char *buf, size_t cnt, loff_t *ppos)
+{
+ struct video_device *vdev = video_devdata(file);
+ int noblock = file->f_flags&O_NONBLOCK;
+ unsigned long count = cnt;
+#endif
struct usb_ov511 *ov = vdev->priv;
int i, rc = 0, frmx = -1;
struct ov511_frame *frame;
@@ -5357,12 +5342,23 @@
return rc;
}
-static int
+static int
+#ifdef OV511_OLD_V4L
ov51x_v4l1_mmap(struct vm_area_struct *vma, struct video_device *vdev,
const char *adr, unsigned long size)
{
- struct usb_ov511 *ov = vdev->priv;
unsigned long start = (unsigned long)adr;
+
+#else /* New V4L API */
+
+ov51x_v4l1_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct video_device *vdev = video_devdata(file);
+ unsigned long start = vma->vm_start;
+ unsigned long size = vma->vm_end - vma->vm_start;
+#endif /* OV511_OLD_V4L */
+
+ struct usb_ov511 *ov = vdev->priv;
unsigned long page, pos;
if (ov->dev == NULL)
@@ -5398,6 +5394,7 @@
return 0;
}
+#ifdef OV511_OLD_V4L
static struct video_device vdev_template = {
owner: THIS_MODULE,
name: "OV511 USB Camera",
@@ -5406,12 +5403,32 @@
open: ov51x_v4l1_open,
close: ov51x_v4l1_close,
read: ov51x_v4l1_read,
- write: ov51x_v4l1_write,
ioctl: ov51x_v4l1_ioctl,
mmap: ov51x_v4l1_mmap,
- initialize: ov51x_v4l1_init_done,
};
+#else /* New V4L API */
+
+static struct file_operations ov511_fops = {
+ owner: THIS_MODULE,
+ open: ov51x_v4l1_open,
+ release: ov51x_v4l1_close,
+ read: ov51x_v4l1_read,
+ mmap: ov51x_v4l1_mmap,
+ ioctl: video_generic_ioctl,
+ llseek: no_llseek,
+};
+
+static struct video_device vdev_template = {
+ owner: THIS_MODULE,
+ name: "OV511 USB Camera",
+ type: VID_TYPE_CAPTURE,
+ hardware: VID_HARDWARE_OV511,
+ fops: &ov511_fops,
+ kernel_ioctl: ov51x_v4l1_ioctl,
+};
+#endif /* OV511_OLD_V4L */
+
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
static int
ov51x_control_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
@@ -5996,19 +6013,18 @@
if (rc < 0) {
err("Error detecting sensor type");
return -1;
- } else if ((rc & 3) == 0) {
- info("Sensor is an OV6630");
+ }
+
+ if ((rc & 3) == 0)
ov->sensor = SEN_OV6630;
- } else if ((rc & 3) == 1) {
- info("Sensor is an OV6620");
+ else if ((rc & 3) == 1)
ov->sensor = SEN_OV6620;
- } else if ((rc & 3) == 2) {
- info("Sensor is an OV6630AE");
+ else if ((rc & 3) == 2)
ov->sensor = SEN_OV6630;
- } else if ((rc & 3) == 3) {
- info("Sensor is an OV6630AF");
+ else if ((rc & 3) == 3)
ov->sensor = SEN_OV6630;
- }
+
+ info("Sensor is an %s", symbolic(senlist, ov->sensor));
/* Set sensor-specific vars */
ov->maxwidth = 352;
@@ -6187,8 +6203,6 @@
static int
ov511_configure(struct usb_ov511 *ov)
{
- int i;
-
static struct ov511_regvals aRegvalsInit511[] = {
{ OV511_REG_BUS, R51x_SYS_RESET, 0x7f },
{ OV511_REG_BUS, R51x_SYS_INIT, 0x01 },
@@ -6230,24 +6244,18 @@
goto error;
}
- ov->desc = -1;
PDEBUG (1, "CustomID = %d", ov->customid);
- for (i = 0; clist[i].id >= 0; i++) {
- if (ov->customid == clist[i].id) {
- info("model: %s", clist[i].description);
- ov->desc = i;
- break;
- }
- }
+ ov->desc = symbolic(camlist, ov->customid);
+ info("model: %s", ov->desc);
- if (clist[i].id == -1) {
+ if (0 == strcmp(ov->desc, NOT_DEFINED_STR)) {
err("Camera type (%d) not recognized", ov->customid);
err("Please notify " EMAIL " of the name,");
err("manufacturer, model, and this number of your camera.");
err("Also include the output of the detection process.");
}
- if (clist[i].id == 6) { /* USB Life TV (NTSC) */
+ if (ov->customid == 6) { /* USB Life TV (NTSC) */
ov->tuner_type = 8; /* Temic 4036FY5 3X 1981 */
}
@@ -6520,29 +6528,24 @@
switch (dev->descriptor.idProduct) {
case PROD_OV511:
- info("USB OV511 camera found");
ov->bridge = BRG_OV511;
ov->bclass = BCL_OV511;
break;
case PROD_OV511PLUS:
- info("USB OV511+ camera found");
ov->bridge = BRG_OV511PLUS;
ov->bclass = BCL_OV511;
break;
case PROD_OV518:
- info("USB OV518 camera found");
ov->bridge = BRG_OV518;
ov->bclass = BCL_OV518;
break;
case PROD_OV518PLUS:
- info("USB OV518+ camera found");
ov->bridge = BRG_OV518PLUS;
ov->bclass = BCL_OV518;
break;
case PROD_ME2CAM:
if (dev->descriptor.idVendor != VEND_MATTEL)
goto error;
- info("Intel Play Me2Cam (OV511+) found");
ov->bridge = BRG_OV511PLUS;
ov->bclass = BCL_OV511;
break;
@@ -6551,6 +6554,8 @@
goto error_dealloc;
}
+ info("USB %s video device found", symbolic(brglist, ov->bridge));
+
/* Workaround for some applications that want data in RGB
* instead of BGR. */
if (force_rgb)
@@ -6584,6 +6589,12 @@
init_waitqueue_head(&ov->frame[i].wq);
}
+ for (i = 0; i < OV511_NUMSBUF; i++) {
+ ov->sbuf[i].ov = ov;
+ spin_lock_init(&ov->sbuf[i].lock);
+ ov->sbuf[i].n = i;
+ }
+
/* Unnecessary? (This is done on open(). Need to make sure variables
* are properly initialized without this before removing it, though). */
if (ov51x_set_default_params(ov) < 0)
@@ -6618,11 +6629,13 @@
info("Device registered on minor %d", ov->vdev.minor);
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
+ create_proc_ov511_cam(ov);
+#endif
+
return ov;
error:
- err("Camera initialization failed");
-
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
/* Safe to call even if entry doesn't exist */
destroy_proc_ov511_cam(ov);
@@ -6635,9 +6648,6 @@
up(&ov->cbuf_lock);
}
- usb_driver_release_interface(&ov511_driver,
- &dev->actconfig->interface[ov->iface]);
-
error_dealloc:
if (ov) {
kfree(ov);
@@ -6645,6 +6655,7 @@
}
error_out:
+ err("Camera initialization failed");
return NULL;
}
@@ -6677,22 +6688,12 @@
ov->streaming = 0;
- /* Unschedule all of the iso td's */
- for (n = OV511_NUMSBUF - 1; n >= 0; n--) {
- if (ov->sbuf[n].urb) {
- ov->sbuf[n].urb->next = NULL;
- usb_unlink_urb(ov->sbuf[n].urb);
- usb_free_urb(ov->sbuf[n].urb);
- ov->sbuf[n].urb = NULL;
- }
- }
+ ov51x_unlink_isoc(ov);
#if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS)
destroy_proc_ov511_cam(ov);
#endif
- usb_driver_release_interface(&ov511_driver,
- &ov->dev->actconfig->interface[ov->iface]);
ov->dev = NULL;
/* Free the memory */
diff -Nru a/drivers/usb/ov511.h b/drivers/usb/ov511.h
--- a/drivers/usb/ov511.h Sat Mar 2 17:12:46 2002
+++ b/drivers/usb/ov511.h Sat Mar 2 17:12:46 2002
@@ -10,8 +10,8 @@
#ifdef OV511_DEBUG
#define PDEBUG(level, fmt, args...) \
- if (debug >= (level)) info("[" __PRETTY_FUNCTION__ ":%d] " fmt,\
- __LINE__ , ## args)
+ if (debug >= (level)) info("[%s:%d] " fmt, \
+ __PRETTY_FUNCTION__, __LINE__ , ## args)
#else
#define PDEBUG(level, fmt, args...) do {} while(0)
#endif
@@ -243,6 +243,16 @@
#define OV511_ENDPOINT_ADDRESS 1 /* Isoc endpoint number */
+#define OV511_NUMFRAMES 2
+#if OV511_NUMFRAMES > VIDEO_MAX_FRAME
+ #error "OV511_NUMFRAMES is too high"
+#endif
+
+#define OV511_NUMSBUF 2
+
+/* Control transfers use up to 4 bytes */
+#define OV511_CBUF_SIZE 4
+
/* Bridge types */
enum {
BRG_UNKNOWN,
@@ -376,9 +386,14 @@
struct ov511_i2c_struct)
/* ------------- End IOCTL interface -------------- */
+struct usb_ov511; /* Forward declaration */
+
struct ov511_sbuf {
- char *data;
+ struct usb_ov511 *ov;
+ unsigned char *data;
struct urb *urb;
+ spinlock_t lock;
+ int n;
};
enum {
@@ -401,9 +416,10 @@
struct ov511_frame {
int framenum; /* Index of this frame */
- char *data; /* Frame buffer */
- char *tempdata; /* Temp buffer for multi-stage conversions */
- char *rawdata; /* Raw camera data buffer */
+ unsigned char *data; /* Frame buffer */
+ unsigned char *tempdata; /* Temp buffer for multi-stage conversions */
+ unsigned char *rawdata; /* Raw camera data buffer */
+ unsigned char *compbuf; /* Temp buffer for decompressor */
int depth; /* Bytes per pixel */
int width; /* Width application is expecting */
@@ -428,27 +444,20 @@
int snapshot; /* True if frame was a snapshot */
};
-#define DECOMP_INTERFACE_VER 2
+#define DECOMP_INTERFACE_VER 3
/* Compression module operations */
struct ov51x_decomp_ops {
- int (*decomp_400)(unsigned char *, unsigned char *, int, int, int);
- int (*decomp_420)(unsigned char *, unsigned char *, int, int, int);
- int (*decomp_422)(unsigned char *, unsigned char *, int, int, int);
+ int (*decomp_400)(unsigned char *, unsigned char *, unsigned char *,
+ int, int, int);
+ int (*decomp_420)(unsigned char *, unsigned char *, unsigned char *,
+ int, int, int);
+ int (*decomp_422)(unsigned char *, unsigned char *, unsigned char *,
+ int, int, int);
void (*decomp_lock)(void);
void (*decomp_unlock)(void);
};
-#define OV511_NUMFRAMES 2
-#if OV511_NUMFRAMES > VIDEO_MAX_FRAME
- #error "OV511_NUMFRAMES is too high"
-#endif
-
-#define OV511_NUMSBUF 2
-
-/* Control transfers use up to 4 bytes */
-#define OV511_CBUF_SIZE 4
-
struct usb_ov511 {
struct video_device vdev;
@@ -456,7 +465,7 @@
struct usb_device *dev;
int customid;
- int desc;
+ char *desc;
unsigned char iface;
/* Determined by sensor type */
@@ -490,9 +499,9 @@
int lightfreq; /* Power (lighting) frequency */
int bandfilt; /* Banding filter enabled flag */
- char *fbuf; /* Videodev buffer area */
- char *tempfbuf; /* Temporary (intermediate) buffer area */
- char *rawfbuf; /* Raw camera data buffer area */
+ unsigned char *fbuf; /* Videodev buffer area */
+ unsigned char *tempfbuf; /* Temporary (intermediate) buffer area */
+ unsigned char *rawfbuf; /* Raw camera data buffer area */
int sub_flag; /* Pix Array subcapture on flag */
int subx; /* Pix Array subcapture x offset */
@@ -556,15 +565,28 @@
struct semaphore cbuf_lock;
};
-struct cam_list {
- int id;
- char *description;
-};
-
-struct palette_list {
+/* Used to represent a list of values and their respective symbolic names */
+struct symbolic_list {
int num;
char *name;
};
+
+#define NOT_DEFINED_STR "Unknown"
+
+/* Returns the name of the matching element in the symbolic_list array. The
+ * end of the list must be marked with an element that has a NULL name.
+ */
+static inline char *
+symbolic(struct symbolic_list list[], int num)
+{
+ int i;
+
+ for (i = 0; list[i].name != NULL; i++)
+ if (list[i].num == num)
+ return (list[i].name);
+
+ return (NOT_DEFINED_STR);
+}
struct mode_list_518 {
int width;
This BitKeeper patch contains the following changesets:
1.365
## Wrapped with gzip_uu ##
begin 664 bkpatch12652
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
M7^043_I7&E(M@FV1[&Z44\@*#R-@^+U_D->5)@35-Q9%3<>1="B1(;U?C
M@FTYEK!Y1]A641F`!;B(9<O`:"O;(JJ[$":[\G*^MF(37UO-[TI6GMPMT.KD
M[9]L<P1PZV!.'^L++`._\@8T7<$'V#P`YX']<,+^1Z<J#=\?Z5W=>->QX]<"
M:YE@4!"O",PLY]`U@8I],M,X/($!C\M];[.^C&66E11YKC,51/TUU^D#)M0H
M_7'>]RC['@M]][)OG0#)_JGLSS,?6Q=9LV@WEN4^"/WH'E;EOK`J$.'^M[9K
M[VT:V>)_NY_"%,$F55L2)W;LL$4J>;#10L)-`^QJ05::1[$:QU%>A;O<^]GO
M>8T]=FQ:T%XDF-8^,YXY,W/FS'G\P(/+K?-RT%8V'"2]0>OJ0Z_?-)],OSR9
MH@B_DU[PCV(YH8;J\N5Z<GU$DF1ZV;$J94(P602K2;1;;HG(YLW*94(D''R4
M416YBBP;VTI5X8E\E-8]J0+[_J1$2^T&`^$O,`-IQFD\Z]G-AD^/O/&>4B/D
M-X72S=F=:A'%U0^W9[PFDG:)C0V^0;FN]<`)=&4C0NDD1]3^KO",XE;XB,*/
M?R$[CH%VW&[OCS<=,M?2FZ_T1G[1E?%8>L:#TR8I0Y(H]?%RP.U5X<X[S$7Q
M4A^LOE</77TBU5R1:JD!A^3]V(<:TSR7SD^O4M6O<_NPD&G8AK`LA+T'%+HI
M.S8[&C]H<U0-$K<VATU24$J%Q\8ET[-':@/\Y2E"*ENHQ!VKDP5(EGIP5OU$
ME5C-]3B"5LHL^\+Q2F<?DO%TI6[9<_D$#85Z1%HD4%OD`CZ<W#=R26VR!PSG
M^93G^I2]+_-3:I$YI\:D#NS<8Y0ZD'@@X=L6B3=/'+'JV$QT):T&5V`IA:45
M*[39_@:BX,H9F]9H'M:QFL7,J=5B57N.6G5F`>AJ=6$OD'M*R9Y+\PUIWHV;
MCUEIODC)1%.4E&_?S(2_"8VL5-*EO+HLQ7H2B)%L]OFG\YOU^%J,G1<FC<!_
M-;Q\^;+7?Z5:X"N&5_>*54MM4@YURY1RN?H9Y?)@+FPVF'IV([Z\I8<5GR4Q
M#\O`+N%;FC0YJ1)F%A(G8]3Z5$0<*V%RIL4::E$%7NR/+E@W+<L$.!PKYXG+
M'^UQ!6=?F$C;9-^1!IWT-D=9]AJRYQH.L=/(8:7&R><'),G1&"9'8Y8H5F^3
MOAP2:7JKWLU#0B471)>&0<BMP9-;0]$JET4^[%RV_^1ZEM2S\D^T9/NN9\O9
M'5X=>/_2"2>[5\YT3Z*%)/*%C:!0R:<:-$FJ@D@MU\T1S)BB#HJ[Y@<AI;^,
MXIR<D9Z$%5#RT80:]*ID*_7$<.)Y2=P2M9<OJ=IVQ::31,K,22+.DI-]8ED%
M0E<JN`4J0/?EN^XQQ3Q6'(Z5K#AQ<`P=V\5F6/XB1TQ6*/J_)V6F:SM8^M"Q
MG=:Q1AVM<[:*[5(?VQ5^#-N03[DDW:<1;8[\Y>$(TL1#2FGX?!$IT7\O8Z
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
;_C]%"+9HLPLOKEVK,IE6K:/_`6,&Y8G09```
`
end