Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
d7b09335
Commit
d7b09335
authored
Mar 04, 2002
by
Mark W. McClelland
Committed by
Linus Torvalds
Mar 04, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update USB ov511 driver to version 1.53
parent
cf16aaca
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1015 additions
and
1064 deletions
+1015
-1064
Documentation/usb/ov511.txt
Documentation/usb/ov511.txt
+3
-3
drivers/usb/ov511.c
drivers/usb/ov511.c
+960
-1031
drivers/usb/ov511.h
drivers/usb/ov511.h
+52
-30
No files found.
Documentation/usb/ov511.txt
View file @
d7b09335
...
...
@@ -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 o
n
some cameras (ones that actually have the LED wired to the control pin,
and not just hard
wired to be on all the time).
This is
not supported with the OV511, and might only work with certai
n
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)
...
...
drivers/usb/ov511.c
View file @
d7b09335
/*
* OmniVision OV511 Camera-to-USB Bridge Driver
*
* Copyright (c) 1999-200
1
Mark W. McClelland
* Copyright (c) 1999-200
2
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 "
OV
511 USB Camera Driver"
#define DRIVER_DESC "
ov
511 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 camera
s
*
Symbolic Name
s
**********************************************************************/
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
*
ov
511
)
create_proc_ov511_cam
(
struct
usb_ov511
*
ov
)
{
char
dirname
[
4
];
char
dirname
[
10
];
if
(
!
ov511_proc_entry
||
!
ov
511
)
if
(
!
ov511_proc_entry
||
!
ov
)
return
;
/* Create per-device directory */
s
printf
(
dirname
,
"%d"
,
ov511
->
vdev
.
minor
);
s
nprintf
(
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
);
ov
511
->
proc_button
=
create_proc_read_entry
(
"button"
,
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
ov
511
->
proc_devdir
,
ov511_read_proc_button
,
ov
511
);
if
(
!
ov
511
->
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
();
ov
511
->
proc_control
=
create_proc_entry
(
"control"
,
S_IFREG
|
S_IRUGO
|
S_IWUSR
,
ov511
->
proc_devdir
);
if
(
!
ov
511
->
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
*
ov
511
)
destroy_proc_ov511_cam
(
struct
usb_ov511
*
ov
)
{
char
dirname
[
4
];
char
dirname
[
10
];
if
(
!
ov
511
||
!
ov511
->
proc_devdir
)
if
(
!
ov
||
!
ov
->
proc_devdir
)
return
;
s
printf
(
dirname
,
"%d"
,
ov511
->
vdev
.
minor
);
s
nprintf
(
dirname
,
10
,
"%d"
,
ov
->
vdev
.
minor
);
/* Destroy "control" entry */
if
(
ov
511
->
proc_control
)
{
if
(
ov
->
proc_control
)
{
PDEBUG
(
4
,
"destroying /proc/video/ov511/%s/control"
,
dirname
);
remove_proc_entry
(
"control"
,
ov
511
->
proc_devdir
);
ov
511
->
proc_control
=
NULL
;
remove_proc_entry
(
"control"
,
ov
->
proc_devdir
);
ov
->
proc_control
=
NULL
;
}
/* Destroy "button" entry */
if
(
ov
511
->
proc_button
)
{
if
(
ov
->
proc_button
)
{
PDEBUG
(
4
,
"destroying /proc/video/ov511/%s/button"
,
dirname
);
remove_proc_entry
(
"button"
,
ov
511
->
proc_devdir
);
ov
511
->
proc_button
=
NULL
;
remove_proc_entry
(
"button"
,
ov
->
proc_devdir
);
ov
->
proc_button
=
NULL
;
}
/* Destroy "info" entry */
if
(
ov
511
->
proc_info
)
{
if
(
ov
->
proc_info
)
{
PDEBUG
(
4
,
"destroying /proc/video/ov511/%s/info"
,
dirname
);
remove_proc_entry
(
"info"
,
ov
511
->
proc_devdir
);
ov
511
->
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
);
ov
511
->
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 ? (ov
511
->subw >> 3) - 1 : mlist[i].pxcnt;
// lncnt = sub_flag ? (ov
511
->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(ov
511
, 0x12, pxcnt);
// reg_w(ov
511
, 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
);
mem
move
(
frame
->
data
,
frame
->
rawdata
,
frame
->
bytes_recvd
);
mem
cpy
(
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
)
{
mem
move
(
frame
->
rawdata
,
frame
->
tempdata
,
mem
cpy
(
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
:
mem
move
(
frame
->
data
,
frame
->
tempdata
,
mem
cpy
(
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 */
mem
move
(
frame
->
data
,
frame
->
tempdata
,
mem
cpy
(
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
in
t
ov511_move_data
(
struct
usb_ov511
*
ov
,
struct
urb
*
urb
)
static
in
line
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
in
t
ov518_move_data
(
struct
usb_ov511
*
ov
,
struct
urb
*
urb
)
static
in
line
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
;
ov
51x_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
*
vde
v
,
unsigned
int
cmd
,
ov51x_v4l1_ioctl_internal
(
struct
usb_ov511
*
o
v
,
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
(
v
w
));
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_windo
w
));
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
,
"VIDIOC
SCHAN
"
);
PDEBUG
(
4
,
"VIDIOC
GFBUF
"
);
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
(
vde
v
,
cmd
,
arg
);
rc
=
ov51x_v4l1_ioctl_internal
(
o
v
,
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
*
ov
511
)
saa7111a_configure
(
struct
usb_ov511
*
ov
)
{
int
rc
;
...
...
@@ -6210,44 +6155,44 @@ saa7111a_configure(struct usb_ov511 *ov511)
#endif
/* Set sensor-specific vars */
ov
511
->
maxwidth
=
640
;
ov
511
->
maxheight
=
480
;
/* Even/Odd fields */
ov
511
->
minwidth
=
320
;
ov
511
->
minheight
=
240
;
/* Even field only */
ov
->
maxwidth
=
640
;
ov
->
maxheight
=
480
;
/* Even/Odd fields */
ov
->
minwidth
=
320
;
ov
->
minheight
=
240
;
/* Even field only */
ov
511
->
has_decoder
=
1
;
ov
511
->
num_inputs
=
8
;
ov
511
->
norm
=
VIDEO_MODE_AUTO
;
ov
511
->
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) */
ov
511
->
brightness
=
0x80
<<
8
;
ov
511
->
contrast
=
0x40
<<
9
;
ov
511
->
colour
=
0x40
<<
9
;
ov
511
->
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
(
ov
511
,
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
(
ov
511
,
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
);
ov
511
->
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
(
ov
511
->
bclass
==
BCL_OV511
)
reg_w
(
ov
511
,
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
->
custom
id
==
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 */
...
...
drivers/usb/ov511.h
View file @
d7b09335
...
...
@@ -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
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment