Commit d7b09335 authored by Mark W. McClelland's avatar Mark W. McClelland Committed by Linus Torvalds

Update USB ov511 driver to version 1.53

parent cf16aaca
......@@ -182,9 +182,9 @@ MODULE PARAMETERS:
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)
......
/*
* OmniVision OV511 Camera-to-USB Bridge Driver
*
* Copyright (c) 1999-2001 Mark W. McClelland
* Copyright (c) 1999-2002 Mark W. McClelland
* Original decompression code Copyright 1998-2000 OmniVision Technologies
* Many improvements by Bret Wallach <bwallac1@san.rr.com>
* Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)
......@@ -10,6 +10,8 @@
* Changes by Claudio Matsuoka <claudio@conectiva.com>
* Original SAA7111A code by Dave Perks <dperks@ibm.net>
* 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.49 for Linux 2.5"
#define DRIVER_VERSION "v1.53 for Linux 2.5"
#define EMAIL "mmcclell@bigfoot.com"
#define DRIVER_AUTHOR "Mark McClelland <mmcclell@bigfoot.com> & Bret Wallach \
& Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \
<cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>"
#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,73 +93,29 @@
#define FATAL_ERROR(rc) ((rc) < 0 && (rc) != -EPERM)
/* PARAMETER VARIABLES: */
/* (See ov511.txt for detailed descriptions of these.) */
/**********************************************************************
* Module Parameters
* (See ov511.txt for detailed descriptions of these)
**********************************************************************/
/* Sensor automatically changes brightness */
/* These variables (and all static globals) default to zero */
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 debug;
static int fix_rgb_offset;
static int snapshot;
static int force_rgb;
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 compress;
static int testpat;
static int sensor_gbr;
static int dumppix;
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 dump_bridge;
static int dump_sensor;
static int printph;
static int phy = 0x1f;
static int phuv = 0x05;
static int pvy = 0x06;
......@@ -153,14 +124,8 @@ 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 */
/* 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 */
static int lightfreq;
static int bandingfilter;
/* Pixel clock divisor */
static int clockdiv = -1;
......@@ -171,35 +136,12 @@ static int packetsize = -1;
/* Frame drop register (16h) */
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 fastset;
static int force_palette;
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 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_AUTHOR(DRIVER_AUTHOR);
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 @@ static int i2c_detect_tries = 5;
/* 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,19 +290,8 @@ static struct cam_list clist[] = {
{ -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" },
......@@ -367,15 +310,58 @@ static struct palette_list plist[] = {
{ 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);
/**********************************************************************
*
* Memory management
*
**********************************************************************/
/* Here we want the physical address of the memory.
......@@ -453,7 +439,7 @@ ov511_read_proc_info(char *page, char **start, off_t off, int count, int *eof,
void *data)
{
char *out = page;
int i, j, len;
int i, len;
struct usb_ov511 *ov = data;
struct video_picture p;
unsigned char exp;
......@@ -469,8 +455,7 @@ ov511_read_proc_info(char *page, char **start, off_t off, int count, int *eof,
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));
......@@ -491,36 +476,16 @@ ov511_read_proc_info(char *page, char **start, off_t off, int count, int *eof,
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);
......@@ -582,89 +547,91 @@ ov511_read_proc_button(char *page, char **start, off_t off, int count, int *eof,
}
static void
create_proc_ov511_cam(struct usb_ov511 *ov511)
create_proc_ov511_cam(struct usb_ov511 *ov)
{
char dirname[4];
char dirname[10];
if (!ov511_proc_entry || !ov511)
if (!ov511_proc_entry || !ov)
return;
/* Create per-device directory */
sprintf(dirname, "%d", ov511->vdev.minor);
snprintf(dirname, 10, "%d", ov->vdev.minor);
PDEBUG(4, "creating /proc/video/ov511/%s/", dirname);
ov511->proc_devdir = create_proc_entry(dirname, S_IFDIR,
ov511_proc_entry);
if (!ov511->proc_devdir)
ov->proc_devdir = create_proc_entry(dirname, S_IFDIR, ov511_proc_entry);
if (!ov->proc_devdir)
return;
ov->proc_devdir->owner = THIS_MODULE;
/* Create "info" entry (human readable device information) */
PDEBUG(4, "creating /proc/video/ov511/%s/info", dirname);
ov511->proc_info = create_proc_read_entry("info",
S_IFREG|S_IRUGO|S_IWUSR, ov511->proc_devdir,
ov511_read_proc_info, ov511);
if (!ov511->proc_info)
ov->proc_info = create_proc_read_entry("info", S_IFREG|S_IRUGO|S_IWUSR,
ov->proc_devdir, ov511_read_proc_info, ov);
if (!ov->proc_info)
return;
ov->proc_info->owner = THIS_MODULE;
/* Don't create it if old snapshot mode on (would cause race cond.) */
if (!snapshot) {
/* Create "button" entry (snapshot button status) */
PDEBUG(4, "creating /proc/video/ov511/%s/button", dirname);
ov511->proc_button = create_proc_read_entry("button",
S_IFREG|S_IRUGO|S_IWUSR, ov511->proc_devdir,
ov511_read_proc_button, ov511);
if (!ov511->proc_button)
ov->proc_button = create_proc_read_entry("button",
S_IFREG|S_IRUGO|S_IWUSR, ov->proc_devdir,
ov511_read_proc_button, ov);
if (!ov->proc_button)
return;
}
ov->proc_button->owner = THIS_MODULE;
/* Create "control" entry (ioctl() interface) */
PDEBUG(4, "creating /proc/video/ov511/%s/control", dirname);
lock_kernel();
ov511->proc_control = create_proc_entry("control",
S_IFREG|S_IRUGO|S_IWUSR, ov511->proc_devdir);
if (!ov511->proc_control) {
ov->proc_control = create_proc_entry("control", S_IFREG|S_IRUGO|S_IWUSR,
ov->proc_devdir);
if (!ov->proc_control) {
unlock_kernel();
return;
}
ov511->proc_control->data = ov511;
ov511->proc_control->proc_fops = &ov511_control_fops;
ov->proc_control->owner = THIS_MODULE;
ov->proc_control->data = ov;
ov->proc_control->proc_fops = &ov511_control_fops;
unlock_kernel();
}
static void
destroy_proc_ov511_cam(struct usb_ov511 *ov511)
destroy_proc_ov511_cam(struct usb_ov511 *ov)
{
char dirname[4];
char dirname[10];
if (!ov511 || !ov511->proc_devdir)
if (!ov || !ov->proc_devdir)
return;
sprintf(dirname, "%d", ov511->vdev.minor);
snprintf(dirname, 10, "%d", ov->vdev.minor);
/* Destroy "control" entry */
if (ov511->proc_control) {
if (ov->proc_control) {
PDEBUG(4, "destroying /proc/video/ov511/%s/control", dirname);
remove_proc_entry("control", ov511->proc_devdir);
ov511->proc_control = NULL;
remove_proc_entry("control", ov->proc_devdir);
ov->proc_control = NULL;
}
/* Destroy "button" entry */
if (ov511->proc_button) {
if (ov->proc_button) {
PDEBUG(4, "destroying /proc/video/ov511/%s/button", dirname);
remove_proc_entry("button", ov511->proc_devdir);
ov511->proc_button = NULL;
remove_proc_entry("button", ov->proc_devdir);
ov->proc_button = NULL;
}
/* Destroy "info" entry */
if (ov511->proc_info) {
if (ov->proc_info) {
PDEBUG(4, "destroying /proc/video/ov511/%s/info", dirname);
remove_proc_entry("info", ov511->proc_devdir);
ov511->proc_info = NULL;
remove_proc_entry("info", ov->proc_devdir);
ov->proc_info = NULL;
}
/* Destroy per-device directory */
PDEBUG(4, "destroying /proc/video/ov511/%s/", dirname);
remove_proc_entry(dirname, ov511_proc_entry);
ov511->proc_devdir = NULL;
ov->proc_devdir = NULL;
}
static void
......@@ -724,7 +691,7 @@ reg_w(struct usb_ov511 *ov, unsigned char reg, unsigned char value)
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;
}
......@@ -746,7 +713,7 @@ reg_r(struct usb_ov511 *ov, unsigned char reg)
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];
......@@ -805,7 +772,8 @@ ov518_reg_w32(struct usb_ov511 *ov, unsigned char reg, u32 val, int n)
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;
}
......@@ -937,21 +905,17 @@ ov518_i2c_write_internal(struct usb_ov511 *ov,
/* 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! */
......@@ -968,19 +932,19 @@ ov511_i2c_write_internal(struct usb_ov511 *ov,
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;
......@@ -990,16 +954,11 @@ ov511_i2c_write_internal(struct usb_ov511 *ov,
#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!
......@@ -1014,25 +973,21 @@ ov518_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
/* 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!
......@@ -1046,15 +1001,15 @@ ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
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;
......@@ -1064,8 +1019,7 @@ ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
if (--retries < 0) {
err("i2c write retries exhausted");
rc = -1;
goto error;
return -1;
}
}
......@@ -1073,23 +1027,22 @@ ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
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;
}
}
......@@ -1100,13 +1053,9 @@ ov511_i2c_read_internal(struct usb_ov511 *ov, unsigned char reg)
/* 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 */
......@@ -1311,22 +1260,17 @@ write_regvals(struct usb_ov511 *ov, struct ov511_regvals * pRegvals)
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
......@@ -2394,13 +2338,13 @@ get_depth(int palette)
{
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 */
}
}
......@@ -2803,11 +2747,11 @@ ov518_mode_init_regs(struct usb_ov511 *ov,
// /* Here I'm assuming that snapshot size == image size.
// * I hope that's always true. --claudio
// */
// pxcnt = sub_flag ? (ov511->subw >> 3) - 1 : mlist[i].pxcnt;
// lncnt = sub_flag ? (ov511->subh >> 3) - 1 : mlist[i].lncnt;
// pxcnt = sub_flag ? (ov->subw >> 3) - 1 : mlist[i].pxcnt;
// lncnt = sub_flag ? (ov->subh >> 3) - 1 : mlist[i].lncnt;
//
// reg_w(ov511, 0x12, pxcnt);
// reg_w(ov511, 0x13, lncnt);
// reg_w(ov, 0x12, pxcnt);
// reg_w(ov, 0x13, lncnt);
/******** Set the mode ********/
......@@ -3475,6 +3419,7 @@ decompress(struct usb_ov511 *ov, struct ov511_frame *frame,
int ret = ov->decomp_ops->decomp_400(
pIn0,
pOut0,
frame->compbuf,
frame->rawwidth,
frame->rawheight,
frame->bytes_recvd);
......@@ -3483,6 +3428,7 @@ decompress(struct usb_ov511 *ov, struct ov511_frame *frame,
int ret = ov->decomp_ops->decomp_420(
pIn0,
pOut0,
frame->compbuf,
frame->rawwidth,
frame->rawheight,
frame->bytes_recvd);
......@@ -3682,7 +3628,7 @@ ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame)
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;
}
......@@ -3719,7 +3665,7 @@ ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame)
/* 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);
......@@ -3747,18 +3693,19 @@ ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame)
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)
......@@ -3771,38 +3718,15 @@ ov51x_postprocess(struct usb_ov511 *ov, struct ov511_frame *frame)
*
**********************************************************************/
static int
ov511_move_data(struct usb_ov511 *ov, struct urb *urb)
static inline void
ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
{
unsigned char *cdata;
int data_size, num, offset, i, totlen = 0;
int aPackNum[FRAMES_PER_DESC];
struct ov511_frame *frame;
int num, offset;
int pnum = in[ov->packet_size - 1]; /* Get packet number */
int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight);
struct ov511_frame *frame = &ov->frame[ov->curframe];
struct timeval *ts;
PDEBUG(5, "Moving %d packets", urb->number_of_packets);
data_size = ov->packet_size - 1;
for (i = 0; i < urb->number_of_packets; i++) {
int n = urb->iso_frame_desc[i].actual_length;
int st = urb->iso_frame_desc[i].status;
urb->iso_frame_desc[i].actual_length = 0;
urb->iso_frame_desc[i].status = 0;
cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
aPackNum[i] = n ? cdata[ov->packet_size - 1] : -1;
if (!n || ov->curframe == -1)
continue;
if (st)
PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st);
frame = &ov->frame[ov->curframe];
/* SOF/EOF packets have 1st to 8th bytes zeroed and the 9th
* byte non-zero. The EOF packet has image width/height in the
* 10th and 11th bytes. The 9th byte is given as follows:
......@@ -3818,47 +3742,40 @@ ov511_move_data(struct usb_ov511 *ov, struct urb *urb)
*/
if (printph) {
info("packet header (%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
cdata[ov->packet_size - 1],
cdata[0], cdata[1], cdata[2], cdata[3], cdata[4], cdata[5],
cdata[6], cdata[7], cdata[8], cdata[9], cdata[10], cdata[11]);
info("ph(%3d): %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
pnum, in[0], in[1], in[2], in[3], in[4], in[5], in[6],
in[7], in[8], in[9], in[10], in[11]);
}
/* Check for SOF/EOF packet */
if ((cdata[0] | cdata[1] | cdata[2] | cdata[3] |
cdata[4] | cdata[5] | cdata[6] | cdata[7]) ||
(~cdata[8] & 0x08))
if ((in[0] | in[1] | in[2] | in[3] | in[4] | in[5] | in[6] | in[7]) ||
(~in[8] & 0x08))
goto check_middle;
/* Frame end */
if (cdata[8] & 0x80) {
if (in[8] & 0x80) {
ts = (struct timeval *)(frame->data
+ MAX_FRAME_SIZE(ov->maxwidth, ov->maxheight));
do_gettimeofday(ts);
/* Get the actual frame size from the EOF header */
frame->rawwidth = ((int)(cdata[9]) + 1) * 8;
frame->rawheight = ((int)(cdata[10]) + 1) * 8;
frame->rawwidth = ((int)(in[9]) + 1) * 8;
frame->rawheight = ((int)(in[10]) + 1) * 8;
PDEBUG(4, "Frame end, curframe = %d, packnum=%d, hw=%d, vw=%d, recvd=%d",
ov->curframe,
(int)(cdata[ov->packet_size - 1]),
frame->rawwidth,
frame->rawheight,
PDEBUG(4, "Frame end, frame=%d, pnum=%d, w=%d, h=%d, recvd=%d",
ov->curframe, pnum, frame->rawwidth, frame->rawheight,
frame->bytes_recvd);
/* Validate the header data */
RESTRICT_TO_RANGE(frame->rawwidth, ov->minwidth, ov->maxwidth);
RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, ov->maxheight);
RESTRICT_TO_RANGE(frame->rawheight, ov->minheight,
ov->maxheight);
/* Don't allow byte count to exceed buffer size */
RESTRICT_TO_RANGE(frame->bytes_recvd,
8,
MAX_RAW_DATA_SIZE(ov->maxwidth,
ov->maxheight));
RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);
if (frame->scanstate == STATE_LINES) {
int iFrameNext;
int nextf;
frame->grabstate = FRAME_DONE; // FIXME: Is this right?
......@@ -3869,17 +3786,17 @@ ov511_move_data(struct usb_ov511 *ov, struct urb *urb)
/* If next frame is ready or grabbing,
* point to it */
iFrameNext = (ov->curframe + 1) % OV511_NUMFRAMES;
if (ov->frame[iFrameNext].grabstate == FRAME_READY
|| ov->frame[iFrameNext].grabstate == FRAME_GRABBING) {
ov->curframe = iFrameNext;
ov->frame[iFrameNext].scanstate = STATE_SCANNING;
nextf = (ov->curframe + 1) % OV511_NUMFRAMES;
if (ov->frame[nextf].grabstate == FRAME_READY
|| ov->frame[nextf].grabstate == FRAME_GRABBING) {
ov->curframe = nextf;
ov->frame[nextf].scanstate = STATE_SCANNING;
} else {
if (frame->grabstate == FRAME_DONE) {
PDEBUG(4, "Frame done! congratulations");
PDEBUG(4, "** Frame done **");
} else {
PDEBUG(4, "Frame not ready? state = %d",
ov->frame[iFrameNext].grabstate);
ov->frame[nextf].grabstate);
}
ov->curframe = -1;
......@@ -3896,40 +3813,23 @@ ov511_move_data(struct usb_ov511 *ov, struct urb *urb)
/* Check to see if it's a snapshot frame */
/* FIXME?? Should the snapshot reset go here? Performance? */
if (cdata[8] & 0x02) {
if (in[8] & 0x02) {
frame->snapshot = 1;
PDEBUG(3, "snapshot detected");
}
frame->scanstate = STATE_LINES;
frame->bytes_recvd = 0;
frame->compressed = cdata[8] & 0x40;
frame->compressed = in[8] & 0x40;
}
check_middle:
/* Are we in a frame? */
if (frame->scanstate != STATE_LINES) {
PDEBUG(5, "Not in a frame; packet skipped");
continue;
}
#if 0
/* Skip packet if first 9 bytes are zero. These are common, so
* we use a less expensive test here instead of later */
if (frame->compressed) {
int b, skip = 1;
for (b = 0; b < 9; b++) {
if (cdata[b])
skip=0;
return;
}
if (skip) {
PDEBUG(5, "Skipping packet (all zero)");
continue;
}
}
#endif
/* If frame start, skip header */
if (frame->bytes_recvd == 0)
offset = 9;
......@@ -3941,37 +3841,32 @@ ov511_move_data(struct usb_ov511 *ov, struct urb *urb)
/* Dump all data exactly as received */
if (dumppix == 2) {
frame->bytes_recvd += n - 1;
if (frame->bytes_recvd <= MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight))
memmove(frame->rawdata + frame->bytes_recvd - (n - 1),
&cdata[0], n - 1);
if (frame->bytes_recvd <= max_raw)
memcpy(frame->rawdata + frame->bytes_recvd - (n - 1),
in, n - 1);
else
PDEBUG(3, "Raw data buffer overrun!! (%d)",
frame->bytes_recvd
- MAX_RAW_DATA_SIZE(ov->maxwidth,
ov->maxheight));
frame->bytes_recvd - max_raw);
} else if (!frame->compressed && !remove_zeros) {
frame->bytes_recvd += num;
if (frame->bytes_recvd <= MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight))
memmove(frame->rawdata + frame->bytes_recvd - num,
&cdata[offset], num);
if (frame->bytes_recvd <= max_raw)
memcpy(frame->rawdata + frame->bytes_recvd - num,
in + offset, num);
else
PDEBUG(3, "Raw data buffer overrun!! (%d)",
frame->bytes_recvd
- MAX_RAW_DATA_SIZE(ov->maxwidth,
ov->maxheight));
frame->bytes_recvd - max_raw);
} else { /* Remove all-zero FIFO lines (aligned 32-byte blocks) */
int b, in = 0, allzero, copied=0;
int b, read = 0, allzero, copied = 0;
if (offset) {
frame->bytes_recvd += 32 - offset; // Bytes out
memmove(frame->rawdata,
&cdata[offset], 32 - offset);
in += 32;
memcpy(frame->rawdata, in + offset, 32 - offset);
read += 32;
}
while (in < n - 1) {
while (read < n - 1) {
allzero = 1;
for (b = 0; b < 32; b++) {
if (cdata[in + b]) {
if (in[read + b]) {
allzero = 0;
break;
}
......@@ -3980,78 +3875,39 @@ ov511_move_data(struct usb_ov511 *ov, struct urb *urb)
if (allzero) {
/* Don't copy it */
} else {
if (frame->bytes_recvd + copied + 32
<= MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight)) {
memmove(frame->rawdata + frame->bytes_recvd + copied,
&cdata[in], 32);
if (frame->bytes_recvd + copied + 32 <= max_raw)
{
memcpy(frame->rawdata
+ frame->bytes_recvd + copied,
in + read, 32);
copied += 32;
} else {
PDEBUG(3, "Raw data buffer overrun!!");
}
}
in += 32;
read += 32;
}
frame->bytes_recvd += copied;
}
}
PDEBUG(5, "pn: %d %d %d %d %d %d %d %d %d %d",
aPackNum[0], aPackNum[1], aPackNum[2], aPackNum[3], aPackNum[4],
aPackNum[5],aPackNum[6], aPackNum[7], aPackNum[8], aPackNum[9]);
return totlen;
}
static int
ov518_move_data(struct usb_ov511 *ov, struct urb *urb)
static inline void
ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
{
unsigned char *cdata;
int i, data_size, totlen = 0;
struct ov511_frame *frame;
int max_raw = MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight);
struct ov511_frame *frame = &ov->frame[ov->curframe];
struct timeval *ts;
PDEBUG(5, "Moving %d packets", urb->number_of_packets);
/* OV518(+) has no packet numbering */
data_size = ov->packet_size;
for (i = 0; i < urb->number_of_packets; i++) {
int n = urb->iso_frame_desc[i].actual_length;
int st = urb->iso_frame_desc[i].status;
urb->iso_frame_desc[i].actual_length = 0;
urb->iso_frame_desc[i].status = 0;
cdata = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
if (!n) {
PDEBUG(4, "Zero-length packet");
continue;
}
if (ov->curframe == -1) {
PDEBUG(4, "No frame currently active");
continue;
}
if (st)
PDEBUG(2, "data error: [%d] len=%d, status=%d", i, n, st);
frame = &ov->frame[ov->curframe];
if (printph) {
info("packet header: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
cdata[0], cdata[1], cdata[2], cdata[3], cdata[4], cdata[5],
cdata[6], cdata[7], cdata[8], cdata[9], cdata[10], cdata[11]);
info("ph: %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x",
in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7],
in[8], in[9], in[10], in[11]);
}
/* A false positive here is likely, until OVT gives me
* the definitive SOF/EOF format */
if ((!(cdata[0] | cdata[1] | cdata[2] | cdata[3] |
cdata[5])) && cdata[6]) {
if ((!(in[0] | in[1] | in[2] | in[3] | in[5])) && in[6]) {
if (frame->scanstate == STATE_LINES) {
PDEBUG(4, "Detected frame end/start");
goto eof;
......@@ -4071,7 +3927,7 @@ ov518_move_data(struct usb_ov511 *ov, struct urb *urb)
PDEBUG(4, "Frame end, curframe = %d, hw=%d, vw=%d, recvd=%d",
ov->curframe,
(int)(cdata[9]), (int)(cdata[10]), frame->bytes_recvd);
(int)(in[9]), (int)(in[10]), frame->bytes_recvd);
// FIXME: Since we don't know the header formats yet,
// there is no way to know what the actual image size is
......@@ -4083,12 +3939,10 @@ ov518_move_data(struct usb_ov511 *ov, struct urb *urb)
RESTRICT_TO_RANGE(frame->rawheight, ov->minheight, ov->maxheight);
/* Don't allow byte count to exceed buffer size */
RESTRICT_TO_RANGE(frame->bytes_recvd,
8,
MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight));
RESTRICT_TO_RANGE(frame->bytes_recvd, 8, max_raw);
if (frame->scanstate == STATE_LINES) {
int iFrameNext;
int nextf;
frame->grabstate = FRAME_DONE; // FIXME: Is this right?
......@@ -4099,35 +3953,33 @@ ov518_move_data(struct usb_ov511 *ov, struct urb *urb)
/* If next frame is ready or grabbing,
* point to it */
iFrameNext = (ov->curframe + 1) % OV511_NUMFRAMES;
if (ov->frame[iFrameNext].grabstate == FRAME_READY
|| ov->frame[iFrameNext].grabstate == FRAME_GRABBING) {
ov->curframe = iFrameNext;
ov->frame[iFrameNext].scanstate = STATE_SCANNING;
frame = &ov->frame[iFrameNext];
nextf = (ov->curframe + 1) % OV511_NUMFRAMES;
if (ov->frame[nextf].grabstate == FRAME_READY
|| ov->frame[nextf].grabstate == FRAME_GRABBING) {
ov->curframe = nextf;
ov->frame[nextf].scanstate = STATE_SCANNING;
frame = &ov->frame[nextf];
} else {
if (frame->grabstate == FRAME_DONE) {
PDEBUG(4, "Frame done! congratulations");
PDEBUG(4, "** Frame done **");
} else {
PDEBUG(4, "Frame not ready? state = %d",
ov->frame[iFrameNext].grabstate);
ov->frame[nextf].grabstate);
}
ov->curframe = -1;
PDEBUG(4, "SOF dropped (no active frame)");
continue; /* Nowhere to store this frame */
return; /* Nowhere to store this frame */
}
}
/* Image corruption caused by misplaced frame->segment = 0
* fixed by carlosf@conectiva.com.br
*/
sof:
PDEBUG(4, "Starting capture on frame %d", frame->framenum);
// Snapshot not reverse-engineered yet.
#if 0
/* Check to see if it's a snapshot frame */
/* FIXME?? Should the snapshot reset go here? Performance? */
if (cdata[8] & 0x02) {
if (in[8] & 0x02) {
frame->snapshot = 1;
PDEBUG(3, "snapshot detected");
}
......@@ -4140,20 +3992,17 @@ ov518_move_data(struct usb_ov511 *ov, struct urb *urb)
/* Are we in a frame? */
if (frame->scanstate != STATE_LINES) {
PDEBUG(4, "scanstate: no SOF yet");
continue;
return;
}
/* Dump all data exactly as received */
if (dumppix == 2) {
frame->bytes_recvd += n;
if (frame->bytes_recvd <= MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight))
memmove(frame->rawdata + frame->bytes_recvd - n,
&cdata[0], n);
if (frame->bytes_recvd <= max_raw)
memcpy(frame->rawdata + frame->bytes_recvd - n, in, n);
else
PDEBUG(3, "Raw data buffer overrun!! (%d)",
frame->bytes_recvd
- MAX_RAW_DATA_SIZE(ov->maxwidth,
ov->maxheight));
frame->bytes_recvd - max_raw);
} else {
/* All incoming data are divided into 8-byte segments. If the
* segment contains all zero bytes, it must be skipped. These
......@@ -4164,12 +4013,12 @@ ov518_move_data(struct usb_ov511 *ov, struct urb *urb)
* skips it later).
*/
int b, in = 0, allzero, copied=0;
int b, read = 0, allzero, copied = 0;
while (in < n) {
while (read < n) {
allzero = 1;
for (b = 0; b < 8; b++) {
if (cdata[in + b]) {
if (in[read + b]) {
allzero = 0;
break;
}
......@@ -4178,36 +4027,36 @@ ov518_move_data(struct usb_ov511 *ov, struct urb *urb)
if (allzero) {
/* Don't copy it */
} else {
if (frame->bytes_recvd + copied + 8
<= MAX_RAW_DATA_SIZE(ov->maxwidth, ov->maxheight)) {
memmove(frame->rawdata + frame->bytes_recvd + copied,
&cdata[in], 8);
if (frame->bytes_recvd + copied + 8 <= max_raw)
{
memcpy(frame->rawdata
+ frame->bytes_recvd + copied,
in + read, 8);
copied += 8;
} else {
PDEBUG(3, "Raw data buffer overrun!!");
}
}
in += 8;
read += 8;
}
frame->bytes_recvd += copied;
}
}
return totlen;
}
static void
ov51x_isoc_irq(struct urb *urb)
{
int len;
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");
......@@ -4219,17 +4068,53 @@ ov51x_isoc_irq(struct urb *urb)
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, "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) {
int n = urb->iso_frame_desc[i].actual_length;
int st = urb->iso_frame_desc[i].status;
unsigned char *cdata;
urb->iso_frame_desc[i].actual_length = 0;
urb->iso_frame_desc[i].status = 0;
cdata = urb->transfer_buffer
+ urb->iso_frame_desc[i].offset;
if (!n) {
PDEBUG(4, "Zero-length packet");
continue;
}
if (st)
PDEBUG(2, "data error: [%d] len=%d, status=%d",
i, n, st);
if (ov->bclass == BCL_OV511)
len = ov511_move_data(ov, urb);
ov511_move_data(ov, cdata, n);
else if (ov->bclass == BCL_OV518)
len = ov518_move_data(ov, urb);
ov518_move_data(ov, cdata, n);
else
err("Unknown bridge device (%d)", ov->bridge);
} else if (waitqueue_active(&ov->wq)) {
wake_up_interruptible(&ov->wq);
}
}
urb->dev = ov->dev;
......@@ -4297,14 +4182,13 @@ ov51x_init_isoc(struct usb_ov511 *ov)
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;
......@@ -4334,23 +4218,13 @@ ov51x_init_isoc(struct usb_ov511 *ov)
}
static void
ov51x_stop_isoc(struct usb_ov511 *ov)
ov51x_unlink_isoc(struct usb_ov511 *ov)
{
int n;
if (!ov->streaming || !ov->dev)
return;
PDEBUG(3, "*** Stopping capture ***");
ov51x_set_packet_size(ov, 0);
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;
......@@ -4358,13 +4232,28 @@ ov51x_stop_isoc(struct usb_ov511 *ov)
}
}
static int
ov51x_new_frame(struct usb_ov511 *ov, int framenum)
static void
ov51x_stop_isoc(struct usb_ov511 *ov)
{
struct ov511_frame *frame;
int newnum;
if (!ov->streaming || !ov->dev)
return;
PDEBUG(4, "ov->curframe = %d, framenum = %d", ov->curframe, framenum);
PDEBUG(3, "*** Stopping capture ***");
ov51x_set_packet_size(ov, 0);
ov->streaming = 0;
ov51x_unlink_isoc(ov);
}
static int
ov51x_new_frame(struct usb_ov511 *ov, int framenum)
{
struct ov511_frame *frame;
int newnum;
PDEBUG(4, "ov->curframe = %d, framenum = %d", ov->curframe, framenum);
if (!ov->dev)
return -1;
......@@ -4409,6 +4298,55 @@ ov51x_new_frame(struct usb_ov511 *ov, int framenum)
*
***************************************************************************/
/*
* - 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)
{
......@@ -4434,40 +4372,23 @@ ov51x_alloc(struct usb_ov511 *ov)
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);
}
......@@ -4477,6 +4398,12 @@ ov51x_alloc(struct usb_ov511 *ov)
+ 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);
}
......@@ -4486,57 +4413,12 @@ ov51x_alloc(struct usb_ov511 *ov)
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)
{
......@@ -4585,9 +4467,16 @@ ov51x_dealloc(struct usb_ov511 *ov, int now)
*
***************************************************************************/
#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;
......@@ -4639,9 +4528,16 @@ ov51x_v4l1_open(struct video_device *vdev, int flags)
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");
......@@ -4674,32 +4570,19 @@ ov51x_v4l1_close(struct video_device *vdev)
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)
......@@ -4708,95 +4591,79 @@ ov51x_v4l1_ioctl_internal(struct video_device *vdev, unsigned int cmd,
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;
if (copy_to_user(arg, &b, sizeof(b)))
return -EFAULT;
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;
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);
if (copy_to_user(arg, &v, sizeof(v)))
return -EFAULT;
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);
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;
......@@ -4804,43 +4671,37 @@ ov51x_v4l1_ioctl_internal(struct video_device *vdev, unsigned int cmd,
}
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
......@@ -4849,79 +4710,73 @@ ov51x_v4l1_ioctl_internal(struct video_device *vdev, unsigned int cmd,
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;
vc->x &= ~3L;
vc->y &= ~1L;
vc->y &= ~31L;
if (vc.width == 0)
vc.width = 32;
if (vc->width == 0)
vc->width = 32;
vc.height /= 16;
vc.height *= 16;
if (vc.height == 0)
vc.height = 16;
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;
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
......@@ -4930,140 +4785,132 @@ ov51x_v4l1_ioctl_internal(struct video_device *vdev, unsigned int cmd,
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;
struct video_window *vw = arg;
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;
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;
PDEBUG(4, "VIDIOCGWIN: %dx%d", vw.width, vw.height);
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
memset(vm, 0, sizeof(struct video_mbuf));
vm->size = OV511_NUMFRAMES
* MAX_DATA_SIZE(ov->maxwidth, ov->maxheight);
vm.frames = OV511_NUMFRAMES;
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, "CMCAPTURE");
PDEBUG(4, "frame: %d, size: %dx%d, format: %d",
vm.frame, vm.width, vm.height, vm.format);
PDEBUG(4, "VIDIOCMCAPTURE: frame: %d, %dx%d, %s", f, vm->width,
vm->height, symbolic(v4l1_plist, 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;
}
......@@ -5125,124 +4972,105 @@ ov51x_v4l1_ioctl_internal(struct video_device *vdev, unsigned int cmd,
}
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);
......@@ -5262,25 +5090,110 @@ ov51x_v4l1_ioctl_internal(struct video_device *vdev, unsigned int cmd,
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;
......@@ -5430,11 +5343,22 @@ ov51x_v4l1_read(struct video_device *vdev, char *buf, unsigned long count,
}
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)
......@@ -5453,7 +5377,8 @@ ov51x_v4l1_mmap(struct vm_area_struct *vma, struct video_device *vdev,
pos = (unsigned long)ov->fbuf;
while (size > 0) {
page = kvirt_to_pa(pos);
if (remap_page_range(vma, start, page, PAGE_SIZE, PAGE_SHARED)) {
if (remap_page_range(vma, start, page, PAGE_SIZE,
PAGE_SHARED)) {
up(&ov->lock);
return -EAGAIN;
}
......@@ -5469,6 +5394,7 @@ ov51x_v4l1_mmap(struct vm_area_struct *vma, struct video_device *vdev,
return 0;
}
#ifdef OV511_OLD_V4L
static struct video_device vdev_template = {
owner: THIS_MODULE,
name: "OV511 USB Camera",
......@@ -5477,12 +5403,32 @@ static struct video_device vdev_template = {
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,
......@@ -5497,7 +5443,7 @@ ov51x_control_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if (!pde)
return -ENOENT;
ov = (struct usb_ov511 *) pde->data;
ov = pde->data;
if (!ov)
return -ENODEV;
......@@ -6067,19 +6013,18 @@ ov6xx0_configure(struct usb_ov511 *ov)
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;
......@@ -6165,7 +6110,7 @@ ks0127_configure(struct usb_ov511 *ov)
/* This initializes the SAA7111A video decoder. */
static int
saa7111a_configure(struct usb_ov511 *ov511)
saa7111a_configure(struct usb_ov511 *ov)
{
int rc;
......@@ -6210,44 +6155,44 @@ saa7111a_configure(struct usb_ov511 *ov511)
#endif
/* Set sensor-specific vars */
ov511->maxwidth = 640;
ov511->maxheight = 480; /* Even/Odd fields */
ov511->minwidth = 320;
ov511->minheight = 240; /* Even field only */
ov->maxwidth = 640;
ov->maxheight = 480; /* Even/Odd fields */
ov->minwidth = 320;
ov->minheight = 240; /* Even field only */
ov511->has_decoder = 1;
ov511->num_inputs = 8;
ov511->norm = VIDEO_MODE_AUTO;
ov511->stop_during_set = 0; /* Decoder guarantees stable image */
ov->has_decoder = 1;
ov->num_inputs = 8;
ov->norm = VIDEO_MODE_AUTO;
ov->stop_during_set = 0; /* Decoder guarantees stable image */
/* Decoder doesn't change these values, so we use these instead of
* acutally reading the registers (which doesn't work) */
ov511->brightness = 0x80 << 8;
ov511->contrast = 0x40 << 9;
ov511->colour = 0x40 << 9;
ov511->hue = 32768;
ov->brightness = 0x80 << 8;
ov->contrast = 0x40 << 9;
ov->colour = 0x40 << 9;
ov->hue = 32768;
PDEBUG(4, "Writing SAA7111A registers");
if (write_regvals(ov511, aRegvalsNormSAA7111A))
if (write_regvals(ov, aRegvalsNormSAA7111A))
return -1;
/* Detect version of decoder. This must be done after writing the
* initial regs or the decoder will lock up. */
rc = i2c_r(ov511, 0x00);
rc = i2c_r(ov, 0x00);
if (rc < 0) {
err("Error detecting sensor version");
return -1;
} else {
info("Sensor is an SAA7111A (version 0x%x)", rc);
ov511->sensor = SEN_SAA7111A;
ov->sensor = SEN_SAA7111A;
}
// FIXME: Fix this for OV518(+)
/* Latch to negative edge of clock. Otherwise, we get incorrect
* colors and jitter in the digital signal. */
if (ov511->bclass == BCL_OV511)
reg_w(ov511, 0x11, 0x00);
if (ov->bclass == BCL_OV511)
reg_w(ov, 0x11, 0x00);
else
warn("SAA7111A not yet supported with OV518/OV518+");
......@@ -6258,8 +6203,6 @@ saa7111a_configure(struct usb_ov511 *ov511)
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 },
......@@ -6301,24 +6244,18 @@ ov511_configure(struct usb_ov511 *ov)
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 */
}
......@@ -6545,7 +6482,6 @@ ov518_configure(struct usb_ov511 *ov)
*
***************************************************************************/
/* 2.2.x compatibility */
static void *
ov51x_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
......@@ -6592,29 +6528,24 @@ ov51x_probe(struct usb_device *dev, unsigned int ifnum,
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;
......@@ -6623,6 +6554,8 @@ ov51x_probe(struct usb_device *dev, unsigned int ifnum,
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)
......@@ -6656,6 +6589,12 @@ ov51x_probe(struct usb_device *dev, unsigned int ifnum,
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)
......@@ -6690,11 +6629,13 @@ ov51x_probe(struct usb_device *dev, unsigned int ifnum,
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);
......@@ -6707,9 +6648,6 @@ ov51x_probe(struct usb_device *dev, unsigned int ifnum,
up(&ov->cbuf_lock);
}
usb_driver_release_interface(&ov511_driver,
&dev->actconfig->interface[ov->iface]);
error_dealloc:
if (ov) {
kfree(ov);
......@@ -6717,6 +6655,7 @@ ov51x_probe(struct usb_device *dev, unsigned int ifnum,
}
error_out:
err("Camera initialization failed");
return NULL;
}
......@@ -6749,22 +6688,12 @@ ov51x_disconnect(struct usb_device *dev, void *ptr)
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 */
......
......@@ -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 {
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_regvals {
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 @@ struct ov511_frame {
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_ov511 {
struct usb_device *dev;
int customid;
int desc;
char *desc;
unsigned char iface;
/* Determined by sensor type */
......@@ -490,9 +499,9 @@ struct usb_ov511 {
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,16 +565,29 @@ struct usb_ov511 {
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;
int height;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment