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
nexedi
linux
Commits
7cf654b1
Commit
7cf654b1
authored
Feb 10, 2002
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
patch by Simon Evans <spse@secret.org.uk> that adds a Konica USB webcam driver
parent
1a3cb06f
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
764 additions
and
4 deletions
+764
-4
drivers/usb/Config.help
drivers/usb/Config.help
+15
-0
drivers/usb/Config.in
drivers/usb/Config.in
+1
-0
drivers/usb/Makefile
drivers/usb/Makefile
+1
-0
drivers/usb/konicawc.c
drivers/usb/konicawc.c
+737
-0
drivers/usb/usbvideo.c
drivers/usb/usbvideo.c
+8
-4
drivers/usb/usbvideo.h
drivers/usb/usbvideo.h
+2
-0
No files found.
drivers/usb/Config.help
View file @
7cf654b1
...
...
@@ -505,6 +505,21 @@ CONFIG_USB_DABUSB
The module will be called dabusb.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_KONICAWC
Say Y here if you want support for webcams based on a Konica
chipset. This is known to work with the Intel YC76 webcam.
This driver uses the Video For Linux API. You must enable
(Y or M in config) Video For Linux (under Character Devices)
to use this driver. Information on this API and pointers to
"v4l" programs may be found on the WWW at
<http://roadrunner.swansea.uk.linux.org/v4l.shtml>.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called konicawc.o. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
CONFIG_USB_USBNET
This driver supports network links over USB with USB "Network"
or "data transfer" cables, often used to network laptops to PCs.
...
...
drivers/usb/Config.in
View file @
7cf654b1
...
...
@@ -80,6 +80,7 @@ else
dep_tristate ' USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)' CONFIG_USB_VICAM $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL
dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
dep_tristate ' USB Konica Webcam support' CONFIG_USB_KONICAWC $CONFIG_USB $CONFIG_VIDEO_DEV
fi
comment 'USB Network adaptors'
...
...
drivers/usb/Makefile
View file @
7cf654b1
...
...
@@ -64,6 +64,7 @@ obj-$(CONFIG_USB_ACM) += acm.o
obj-$(CONFIG_USB_PRINTER)
+=
printer.o
obj-$(CONFIG_USB_AUDIO)
+=
audio.o
obj-$(CONFIG_USB_IBMCAM)
+=
ibmcam.o usbvideo.o ultracam.o
obj-$(CONFIG_USB_KONICAWC)
+=
konicawc.o usbvideo.o
obj-$(CONFIG_USB_PWC)
+=
pwc.o
obj-$(CONFIG_USB_DC2XX)
+=
dc2xx.o
obj-$(CONFIG_USB_MDC800)
+=
mdc800.o
...
...
drivers/usb/konicawc.c
0 → 100644
View file @
7cf654b1
/*
* $Id: konicawc.c,v 1.12 2002/02/07 23:18:53 spse Exp $
*
* konicawc.c - konica webcam driver
*
* Author: Simon Evans <spse@secret.org.uk>
*
* Copyright (C) 2002 Simon Evans
*
* Licence: GPL
*
* Driver for USB webcams based on Konica chipset. This
* chipset is used in Intel YC76 camera.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#define DEBUG
#include "usbvideo.h"
#define MAX_BRIGHTNESS 108
#define MAX_CONTRAST 108
#define MAX_SATURATION 108
#define MAX_SHARPNESS 108
#define MAX_WHITEBAL 363
#define MAX_CAMERAS 1
enum
ctrl_req
{
SetWhitebal
=
0x01
,
SetBrightness
=
0x02
,
SetSharpness
=
0x03
,
SetContrast
=
0x04
,
SetSaturation
=
0x05
,
};
enum
frame_sizes
{
SIZE_160X130
=
0
,
SIZE_176X144
=
1
,
SIZE_320X240
=
2
,
};
static
usbvideo_t
*
cams
;
/* Some default values for inital camera settings,
can be set by modprobe */
static
int
debug
;
static
enum
frame_sizes
size
;
static
int
brightness
=
MAX_BRIGHTNESS
/
2
;
static
int
contrast
=
MAX_CONTRAST
/
2
;
static
int
saturation
=
MAX_SATURATION
/
2
;
static
int
sharpness
=
MAX_SHARPNESS
/
2
;
static
int
whitebal
=
3
*
(
MAX_WHITEBAL
/
4
);
struct
konicawc
{
u8
brightness
;
/* camera uses 0 - 9, x11 for real value */
u8
contrast
;
/* as above */
u8
saturation
;
/* as above */
u8
sharpness
;
/* as above */
u8
white_bal
;
/* 0 - 33, x11 for real value */
u8
fps
;
/* Stored as fps * 3 */
u8
size
;
/* Frame Size */
int
height
;
int
width
;
struct
urb
*
sts_urb
[
USBVIDEO_NUMFRAMES
];
u8
sts_buf
[
USBVIDEO_NUMFRAMES
][
FRAMES_PER_DESC
];
struct
urb
*
last_data_urb
;
int
lastframe
;
};
#define konicawc_set_misc(uvd, req, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, req, value, index, NULL, 0)
#define konicawc_get_misc(uvd, req, value, index, buf, sz) konicawc_ctrl_msg(uvd, USB_DIR_IN, req, value, index, buf, sz)
#define konicawc_set_value(uvd, value, index) konicawc_ctrl_msg(uvd, USB_DIR_OUT, 2, value, index, NULL, 0)
static
int
konicawc_ctrl_msg
(
uvd_t
*
uvd
,
u8
dir
,
u8
request
,
u16
value
,
u16
index
,
void
*
buf
,
int
len
)
{
int
retval
=
usb_control_msg
(
uvd
->
dev
,
dir
?
usb_rcvctrlpipe
(
uvd
->
dev
,
0
)
:
usb_sndctrlpipe
(
uvd
->
dev
,
0
),
request
,
0x40
|
dir
,
value
,
index
,
buf
,
len
,
HZ
);
return
retval
<
0
?
retval
:
0
;
}
static
int
konicawc_setup_on_open
(
uvd_t
*
uvd
)
{
struct
konicawc
*
cam
=
(
struct
konicawc
*
)
uvd
->
user_data
;
konicawc_set_misc
(
uvd
,
0x2
,
0
,
0x0b
);
dbg
(
"setting brightness to %d (%d)"
,
cam
->
brightness
,
cam
->
brightness
*
11
);
konicawc_set_value
(
uvd
,
cam
->
brightness
,
SetBrightness
);
dbg
(
"setting white balance to %d (%d)"
,
cam
->
white_bal
,
cam
->
white_bal
*
11
);
konicawc_set_value
(
uvd
,
cam
->
white_bal
,
SetWhitebal
);
dbg
(
"setting contrast to %d (%d)"
,
cam
->
contrast
,
cam
->
contrast
*
11
);
konicawc_set_value
(
uvd
,
cam
->
brightness
,
SetBrightness
);
dbg
(
"setting saturation to %d (%d)"
,
cam
->
saturation
,
cam
->
saturation
*
11
);
konicawc_set_value
(
uvd
,
cam
->
saturation
,
SetSaturation
);
dbg
(
"setting sharpness to %d (%d)"
,
cam
->
sharpness
,
cam
->
sharpness
*
11
);
konicawc_set_value
(
uvd
,
cam
->
sharpness
,
SetSharpness
);
dbg
(
"setting size %d"
,
cam
->
size
);
switch
(
cam
->
size
)
{
case
0
:
konicawc_set_misc
(
uvd
,
0x2
,
0xa
,
0x08
);
break
;
case
1
:
konicawc_set_misc
(
uvd
,
0x2
,
4
,
0x08
);
break
;
case
2
:
konicawc_set_misc
(
uvd
,
0x2
,
5
,
0x08
);
break
;
}
konicawc_set_misc
(
uvd
,
0x2
,
1
,
0x0b
);
cam
->
lastframe
=
-
1
;
return
0
;
}
static
int
konicawc_compress_iso
(
uvd_t
*
uvd
,
struct
urb
*
dataurb
,
struct
urb
*
stsurb
)
{
char
*
cdata
;
int
i
,
totlen
=
0
;
unsigned
char
*
status
=
stsurb
->
transfer_buffer
;
int
keep
=
0
,
discard
=
0
,
bad
=
0
;
static
int
buttonsts
=
0
;
for
(
i
=
0
;
i
<
dataurb
->
number_of_packets
;
i
++
)
{
int
button
=
buttonsts
;
unsigned
char
sts
;
int
n
=
dataurb
->
iso_frame_desc
[
i
].
actual_length
;
int
st
=
dataurb
->
iso_frame_desc
[
i
].
status
;
cdata
=
dataurb
->
transfer_buffer
+
dataurb
->
iso_frame_desc
[
i
].
offset
;
/* Detect and ignore errored packets */
if
(
st
<
0
)
{
if
(
debug
>=
1
)
err
(
"Data error: packet=%d. len=%d. status=%d."
,
i
,
n
,
st
);
uvd
->
stats
.
iso_err_count
++
;
continue
;
}
/* Detect and ignore empty packets */
if
(
n
<=
0
)
{
uvd
->
stats
.
iso_skip_count
++
;
continue
;
}
/* See what the status data said about the packet */
sts
=
*
(
status
+
stsurb
->
iso_frame_desc
[
i
].
offset
);
/* sts: 0x80-0xff: frame start with frame number (ie 0-7f)
* otherwise:
* bit 0 0:drop packet (padding data)
* 1 keep packet
*
* bit 4 0 button not clicked
* 1 button clicked
* button is used to `take a picture' (in software)
*/
if
(
sts
<
0x80
)
{
button
=
sts
&
0x40
;
sts
&=
~
0x40
;
}
/* work out the button status, but dont do
anything with it for now */
if
(
button
!=
buttonsts
)
{
dbg
(
"button: %sclicked"
,
button
?
""
:
"un"
);
buttonsts
=
button
;
}
if
(
sts
==
0x01
)
{
/* drop frame */
discard
++
;
continue
;
}
if
((
sts
>
0x01
)
&&
(
sts
<
0x80
))
{
info
(
"unknown status %2.2x"
,
sts
);
bad
++
;
continue
;
}
keep
++
;
if
(
*
(
status
+
i
)
&
0x80
)
{
/* frame start */
unsigned
char
marker
[]
=
{
0
,
0xff
,
0
,
0x00
};
if
(
debug
>
1
)
dbg
(
"Adding Marker packet = %d, frame = %2.2x"
,
i
,
*
(
status
+
i
));
marker
[
3
]
=
*
(
status
+
i
)
-
0x80
;
RingQueue_Enqueue
(
&
uvd
->
dp
,
marker
,
4
);
totlen
+=
4
;
}
totlen
+=
n
;
/* Little local accounting */
if
(
debug
>
5
)
dbg
(
"Adding packet %d, bytes = %d"
,
i
,
n
);
RingQueue_Enqueue
(
&
uvd
->
dp
,
cdata
,
n
);
}
if
(
debug
>
8
)
{
dbg
(
"finished: keep = %d discard = %d bad = %d added %d bytes"
,
keep
,
discard
,
bad
,
totlen
);
}
return
totlen
;
}
static
void
konicawc_isoc_irq
(
struct
urb
*
urb
)
{
int
i
,
len
=
0
;
uvd_t
*
uvd
=
urb
->
context
;
struct
konicawc
*
cam
=
(
struct
konicawc
*
)
uvd
->
user_data
;
/* We don't want to do anything if we are about to be removed! */
if
(
!
CAMERA_IS_OPERATIONAL
(
uvd
))
return
;
if
(
urb
->
actual_length
>
32
)
{
cam
->
last_data_urb
=
urb
;
return
;
}
if
(
!
uvd
->
streaming
)
{
if
(
debug
>=
1
)
info
(
"Not streaming, but interrupt!"
);
return
;
}
uvd
->
stats
.
urb_count
++
;
if
(
urb
->
actual_length
<=
0
)
goto
urb_done_with
;
/* Copy the data received into ring queue */
if
(
cam
->
last_data_urb
)
{
len
=
konicawc_compress_iso
(
uvd
,
cam
->
last_data_urb
,
urb
);
for
(
i
=
0
;
i
<
FRAMES_PER_DESC
;
i
++
)
{
cam
->
last_data_urb
->
iso_frame_desc
[
i
].
status
=
0
;
cam
->
last_data_urb
->
iso_frame_desc
[
i
].
actual_length
=
0
;
}
cam
->
last_data_urb
=
NULL
;
}
uvd
->
stats
.
urb_length
=
len
;
if
(
len
<=
0
)
{
goto
urb_done_with
;
}
/* Here we got some data */
uvd
->
stats
.
data_count
+=
len
;
RingQueue_WakeUpInterruptible
(
&
uvd
->
dp
);
urb_done_with:
for
(
i
=
0
;
i
<
FRAMES_PER_DESC
;
i
++
)
{
urb
->
iso_frame_desc
[
i
].
status
=
0
;
urb
->
iso_frame_desc
[
i
].
actual_length
=
0
;
}
return
;
}
static
int
konicawc_start_data
(
uvd_t
*
uvd
)
{
struct
usb_device
*
dev
=
uvd
->
dev
;
int
i
,
errFlag
;
struct
konicawc
*
cam
=
(
struct
konicawc
*
)
uvd
->
user_data
;
if
(
!
CAMERA_IS_OPERATIONAL
(
uvd
))
{
err
(
"Camera is not operational"
);
return
-
EFAULT
;
}
uvd
->
curframe
=
-
1
;
/* Alternate interface 1 is is the biggest frame size */
i
=
usb_set_interface
(
dev
,
uvd
->
iface
,
uvd
->
ifaceAltActive
);
if
(
i
<
0
)
{
err
(
"usb_set_interface error"
);
uvd
->
last_error
=
i
;
return
-
EBUSY
;
}
/* We double buffer the Iso lists */
for
(
i
=
0
;
i
<
USBVIDEO_NUMSBUF
;
i
++
)
{
int
j
,
k
;
struct
urb
*
urb
=
uvd
->
sbuf
[
i
].
urb
;
urb
->
dev
=
dev
;
urb
->
context
=
uvd
;
urb
->
pipe
=
usb_rcvisocpipe
(
dev
,
uvd
->
video_endp
);
urb
->
transfer_flags
=
USB_ISO_ASAP
;
urb
->
transfer_buffer
=
uvd
->
sbuf
[
i
].
data
;
urb
->
complete
=
konicawc_isoc_irq
;
urb
->
number_of_packets
=
FRAMES_PER_DESC
;
urb
->
transfer_buffer_length
=
uvd
->
iso_packet_len
*
FRAMES_PER_DESC
;
for
(
j
=
k
=
0
;
j
<
FRAMES_PER_DESC
;
j
++
,
k
+=
uvd
->
iso_packet_len
)
{
urb
->
iso_frame_desc
[
j
].
offset
=
k
;
urb
->
iso_frame_desc
[
j
].
length
=
uvd
->
iso_packet_len
;
}
urb
=
cam
->
sts_urb
[
i
];
urb
->
dev
=
dev
;
urb
->
context
=
uvd
;
urb
->
pipe
=
usb_rcvisocpipe
(
dev
,
uvd
->
video_endp
-
1
);
urb
->
transfer_flags
=
USB_ISO_ASAP
;
urb
->
transfer_buffer
=
cam
->
sts_buf
[
i
];
urb
->
complete
=
konicawc_isoc_irq
;
urb
->
number_of_packets
=
FRAMES_PER_DESC
;
urb
->
transfer_buffer_length
=
FRAMES_PER_DESC
;
for
(
j
=
0
;
j
<
FRAMES_PER_DESC
;
j
++
)
{
urb
->
iso_frame_desc
[
j
].
offset
=
j
;
urb
->
iso_frame_desc
[
j
].
length
=
1
;
}
}
/* Link URBs into a ring so that they invoke each other infinitely */
for
(
i
=
0
;
i
<
USBVIDEO_NUMSBUF
;
i
++
)
{
if
((
i
+
1
)
<
USBVIDEO_NUMSBUF
)
{
cam
->
sts_urb
[
i
]
->
next
=
uvd
->
sbuf
[
i
].
urb
;
uvd
->
sbuf
[
i
].
urb
->
next
=
cam
->
sts_urb
[
i
+
1
];
}
else
{
cam
->
sts_urb
[
i
]
->
next
=
uvd
->
sbuf
[
i
].
urb
;
uvd
->
sbuf
[
i
].
urb
->
next
=
cam
->
sts_urb
[
0
];
}
}
/* Submit all URBs */
for
(
i
=
0
;
i
<
USBVIDEO_NUMSBUF
;
i
++
)
{
errFlag
=
usb_submit_urb
(
uvd
->
sbuf
[
i
].
urb
,
GFP_KERNEL
);
if
(
errFlag
)
err
(
"usb_submit_isoc(%d) ret %d"
,
i
,
errFlag
);
errFlag
=
usb_submit_urb
(
cam
->
sts_urb
[
i
],
GFP_KERNEL
);
if
(
errFlag
)
err
(
"usb_submit_isoc(%d) ret %d"
,
i
,
errFlag
);
}
uvd
->
streaming
=
1
;
if
(
debug
>
1
)
dbg
(
"streaming=1 video_endp=$%02x"
,
uvd
->
video_endp
);
return
0
;
}
static
void
konicawc_stop_data
(
uvd_t
*
uvd
)
{
int
i
,
j
;
struct
konicawc
*
cam
=
(
struct
konicawc
*
)
uvd
->
user_data
;
if
((
uvd
==
NULL
)
||
(
!
uvd
->
streaming
)
||
(
uvd
->
dev
==
NULL
))
return
;
/* Unschedule all of the iso td's */
for
(
i
=
0
;
i
<
USBVIDEO_NUMSBUF
;
i
++
)
{
j
=
usb_unlink_urb
(
uvd
->
sbuf
[
i
].
urb
);
if
(
j
<
0
)
err
(
"usb_unlink_urb() error %d."
,
j
);
j
=
usb_unlink_urb
(
cam
->
sts_urb
[
i
]);
if
(
j
<
0
)
err
(
"usb_unlink_urb() error %d."
,
j
);
}
uvd
->
streaming
=
0
;
if
(
!
uvd
->
remove_pending
)
{
/* Set packet size to 0 */
j
=
usb_set_interface
(
uvd
->
dev
,
uvd
->
iface
,
uvd
->
ifaceAltInactive
);
if
(
j
<
0
)
{
err
(
"usb_set_interface() error %d."
,
j
);
uvd
->
last_error
=
j
;
}
}
}
static
void
konicawc_process_isoc
(
uvd_t
*
uvd
,
usbvideo_frame_t
*
frame
)
{
int
n
;
int
maxline
,
yplanesz
;
struct
konicawc
*
cam
=
(
struct
konicawc
*
)
uvd
->
user_data
;
assert
(
uvd
!=
NULL
);
assert
(
frame
!=
NULL
);
maxline
=
(
cam
->
height
*
cam
->
width
*
3
)
/
(
2
*
384
);
yplanesz
=
cam
->
height
*
cam
->
width
;
if
(
debug
>
5
)
dbg
(
"maxline = %d yplanesz = %d"
,
maxline
,
yplanesz
);
if
(
debug
>
3
)
dbg
(
"Frame state = %d"
,
frame
->
scanstate
);
if
(
frame
->
scanstate
==
ScanState_Scanning
)
{
int
drop
=
0
;
int
curframe
;
int
fdrops
=
0
;
if
(
debug
>
3
)
dbg
(
"Searching for marker, queue len = %d"
,
RingQueue_GetLength
(
&
uvd
->
dp
));
while
(
RingQueue_GetLength
(
&
uvd
->
dp
)
>=
4
)
{
if
((
RING_QUEUE_PEEK
(
&
uvd
->
dp
,
0
)
==
0x00
)
&&
(
RING_QUEUE_PEEK
(
&
uvd
->
dp
,
1
)
==
0xff
)
&&
(
RING_QUEUE_PEEK
(
&
uvd
->
dp
,
2
)
==
0x00
)
&&
(
RING_QUEUE_PEEK
(
&
uvd
->
dp
,
3
)
<
0x80
))
{
curframe
=
RING_QUEUE_PEEK
(
&
uvd
->
dp
,
3
);
if
(
cam
->
lastframe
!=
-
1
)
{
if
(
curframe
<
cam
->
lastframe
)
{
fdrops
=
(
curframe
+
0x80
)
-
cam
->
lastframe
;
}
else
{
fdrops
=
curframe
-
cam
->
lastframe
;
}
fdrops
--
;
if
(
fdrops
)
info
(
"Dropped %d frames (%d -> %d)"
,
fdrops
,
cam
->
lastframe
,
curframe
);
}
cam
->
lastframe
=
curframe
;
frame
->
curline
=
0
;
frame
->
scanstate
=
ScanState_Lines
;
RING_QUEUE_DEQUEUE_BYTES
(
&
uvd
->
dp
,
4
);
break
;
}
RING_QUEUE_DEQUEUE_BYTES
(
&
uvd
->
dp
,
1
);
drop
++
;
}
}
if
(
frame
->
scanstate
==
ScanState_Scanning
)
return
;
/* Try to move data from queue into frame buffer
* We get data in blocks of 384 bytes made up of:
* 256 Y, 64 U, 64 V.
* This needs to be written out as a Y plane, a U plane and a V plane.
*/
while
(
frame
->
curline
<
maxline
&&
(
n
=
RingQueue_GetLength
(
&
uvd
->
dp
))
>=
384
)
{
/* Y */
RingQueue_Dequeue
(
&
uvd
->
dp
,
frame
->
data
+
(
frame
->
curline
*
256
),
256
);
/* U */
RingQueue_Dequeue
(
&
uvd
->
dp
,
frame
->
data
+
yplanesz
+
(
frame
->
curline
*
64
),
64
);
/* V */
RingQueue_Dequeue
(
&
uvd
->
dp
,
frame
->
data
+
(
5
*
yplanesz
)
/
4
+
(
frame
->
curline
*
64
),
64
);
frame
->
seqRead_Length
+=
384
;
frame
->
curline
++
;
}
/* See if we filled the frame */
if
(
frame
->
curline
==
maxline
)
{
if
(
debug
>
5
)
dbg
(
"got whole frame"
);
frame
->
frameState
=
FrameState_Done_Hold
;
frame
->
curline
=
0
;
uvd
->
curframe
=
-
1
;
uvd
->
stats
.
frame_num
++
;
}
}
static
int
konicawc_calculate_fps
(
uvd_t
*
uvd
)
{
struct
konicawc
*
t
=
uvd
->
user_data
;
dbg
(
""
);
return
(
t
->
fps
)
/
3
;
}
static
void
konicawc_configure_video
(
uvd_t
*
uvd
)
{
struct
konicawc
*
cam
=
(
struct
konicawc
*
)
uvd
->
user_data
;
u8
buf
[
2
];
memset
(
&
uvd
->
vpic
,
0
,
sizeof
(
uvd
->
vpic
));
memset
(
&
uvd
->
vpic_old
,
0x55
,
sizeof
(
uvd
->
vpic_old
));
RESTRICT_TO_RANGE
(
brightness
,
0
,
MAX_BRIGHTNESS
);
RESTRICT_TO_RANGE
(
contrast
,
0
,
MAX_CONTRAST
);
RESTRICT_TO_RANGE
(
saturation
,
0
,
MAX_SATURATION
);
RESTRICT_TO_RANGE
(
sharpness
,
0
,
MAX_SHARPNESS
);
RESTRICT_TO_RANGE
(
whitebal
,
0
,
MAX_WHITEBAL
);
cam
->
brightness
=
brightness
/
11
;
cam
->
contrast
=
contrast
/
11
;
cam
->
saturation
=
saturation
/
11
;
cam
->
sharpness
=
sharpness
/
11
;
cam
->
white_bal
=
whitebal
/
11
;
uvd
->
vpic
.
colour
=
108
;
uvd
->
vpic
.
hue
=
108
;
uvd
->
vpic
.
brightness
=
brightness
;
uvd
->
vpic
.
contrast
=
contrast
;
uvd
->
vpic
.
whiteness
=
whitebal
;
uvd
->
vpic
.
depth
=
6
;
uvd
->
vpic
.
palette
=
VIDEO_PALETTE_YUV420P
;
memset
(
&
uvd
->
vcap
,
0
,
sizeof
(
uvd
->
vcap
));
strcpy
(
uvd
->
vcap
.
name
,
"Konica Webcam"
);
uvd
->
vcap
.
type
=
VID_TYPE_CAPTURE
;
uvd
->
vcap
.
channels
=
1
;
uvd
->
vcap
.
audios
=
0
;
uvd
->
vcap
.
maxwidth
=
cam
->
width
;
uvd
->
vcap
.
maxheight
=
cam
->
height
;
uvd
->
vcap
.
minwidth
=
cam
->
width
;
uvd
->
vcap
.
minheight
=
cam
->
height
;
memset
(
&
uvd
->
vchan
,
0
,
sizeof
(
uvd
->
vchan
));
uvd
->
vchan
.
flags
=
0
;
uvd
->
vchan
.
tuners
=
0
;
uvd
->
vchan
.
channel
=
0
;
uvd
->
vchan
.
type
=
VIDEO_TYPE_CAMERA
;
strcpy
(
uvd
->
vchan
.
name
,
"Camera"
);
/* Talk to device */
dbg
(
"device init"
);
if
(
!
konicawc_get_misc
(
uvd
,
0x3
,
0
,
0x10
,
buf
,
2
))
dbg
(
"3,10 -> %2.2x %2.2x"
,
buf
[
0
],
buf
[
1
]);
if
(
!
konicawc_get_misc
(
uvd
,
0x3
,
0
,
0x10
,
buf
,
2
))
dbg
(
"3,10 -> %2.2x %2.2x"
,
buf
[
0
],
buf
[
1
]);
if
(
konicawc_set_misc
(
uvd
,
0x2
,
0
,
0xd
))
dbg
(
"2,0,d failed"
);
dbg
(
"setting initial values"
);
}
static
void
*
konicawc_probe
(
struct
usb_device
*
dev
,
unsigned
int
ifnum
,
const
struct
usb_device_id
*
devid
)
{
uvd_t
*
uvd
=
NULL
;
int
i
,
nas
;
int
actInterface
=-
1
,
inactInterface
=-
1
,
maxPS
=
0
;
unsigned
char
video_ep
=
0
;
if
(
debug
>=
1
)
dbg
(
"konicawc_probe(%p,%u.)"
,
dev
,
ifnum
);
/* We don't handle multi-config cameras */
if
(
dev
->
descriptor
.
bNumConfigurations
!=
1
)
return
NULL
;
info
(
"Konica Webcam (rev. 0x%04x)"
,
dev
->
descriptor
.
bcdDevice
);
/* Validate found interface: must have one ISO endpoint */
nas
=
dev
->
actconfig
->
interface
[
ifnum
].
num_altsetting
;
if
(
debug
>
0
)
info
(
"Number of alternate settings=%d."
,
nas
);
if
(
nas
<
8
)
{
err
(
"Too few alternate settings for this camera!"
);
return
NULL
;
}
/* Validate all alternate settings */
for
(
i
=
0
;
i
<
nas
;
i
++
)
{
const
struct
usb_interface_descriptor
*
interface
;
const
struct
usb_endpoint_descriptor
*
endpoint
;
interface
=
&
dev
->
actconfig
->
interface
[
ifnum
].
altsetting
[
i
];
if
(
interface
->
bNumEndpoints
!=
2
)
{
err
(
"Interface %d. has %u. endpoints!"
,
ifnum
,
(
unsigned
)(
interface
->
bNumEndpoints
));
return
NULL
;
}
endpoint
=
&
interface
->
endpoint
[
1
];
dbg
(
"found endpoint: addr: 0x%2.2x maxps = 0x%4.4x"
,
endpoint
->
bEndpointAddress
,
endpoint
->
wMaxPacketSize
);
if
(
video_ep
==
0
)
video_ep
=
endpoint
->
bEndpointAddress
;
else
if
(
video_ep
!=
endpoint
->
bEndpointAddress
)
{
err
(
"Alternate settings have different endpoint addresses!"
);
return
NULL
;
}
if
((
endpoint
->
bmAttributes
&
0x03
)
!=
0x01
)
{
err
(
"Interface %d. has non-ISO endpoint!"
,
ifnum
);
return
NULL
;
}
if
((
endpoint
->
bEndpointAddress
&
0x80
)
==
0
)
{
err
(
"Interface %d. has ISO OUT endpoint!"
,
ifnum
);
return
NULL
;
}
if
(
endpoint
->
wMaxPacketSize
==
0
)
{
if
(
inactInterface
<
0
)
inactInterface
=
i
;
else
{
err
(
"More than one inactive alt. setting!"
);
return
NULL
;
}
}
else
{
if
(
actInterface
<
0
)
{
actInterface
=
i
;
maxPS
=
endpoint
->
wMaxPacketSize
;
if
(
debug
>
0
)
info
(
"Active setting=%d. maxPS=%d."
,
i
,
maxPS
);
}
else
{
/* Got another active alt. setting */
if
(
maxPS
<
endpoint
->
wMaxPacketSize
)
{
/* This one is better! */
actInterface
=
i
;
maxPS
=
endpoint
->
wMaxPacketSize
;
if
(
debug
>
0
)
{
info
(
"Even better active setting=%d. maxPS=%d."
,
i
,
maxPS
);
}
}
}
}
}
/* Code below may sleep, need to lock module while we are here */
MOD_INC_USE_COUNT
;
uvd
=
usbvideo_AllocateDevice
(
cams
);
if
(
uvd
!=
NULL
)
{
struct
konicawc
*
konicawc_data
=
(
struct
konicawc
*
)(
uvd
->
user_data
);
/* Here uvd is a fully allocated uvd_t object */
for
(
i
=
0
;
i
<
USBVIDEO_NUMSBUF
;
i
++
)
{
konicawc_data
->
sts_urb
[
i
]
=
usb_alloc_urb
(
FRAMES_PER_DESC
);
}
switch
(
size
)
{
case
SIZE_160X130
:
default:
konicawc_data
->
height
=
136
;
konicawc_data
->
width
=
160
;
konicawc_data
->
size
=
SIZE_160X130
;
break
;
case
SIZE_176X144
:
konicawc_data
->
height
=
144
;
konicawc_data
->
width
=
176
;
konicawc_data
->
size
=
SIZE_176X144
;
break
;
case
SIZE_320X240
:
konicawc_data
->
height
=
240
;
konicawc_data
->
width
=
320
;
konicawc_data
->
size
=
SIZE_320X240
;
break
;
}
uvd
->
flags
=
0
;
uvd
->
debug
=
debug
;
uvd
->
dev
=
dev
;
uvd
->
iface
=
ifnum
;
uvd
->
ifaceAltInactive
=
inactInterface
;
uvd
->
ifaceAltActive
=
actInterface
;
uvd
->
video_endp
=
video_ep
;
uvd
->
iso_packet_len
=
maxPS
;
uvd
->
paletteBits
=
1L
<<
VIDEO_PALETTE_YUV420P
;
uvd
->
defaultPalette
=
VIDEO_PALETTE_YUV420P
;
uvd
->
canvas
=
VIDEOSIZE
(
konicawc_data
->
width
,
konicawc_data
->
height
);
uvd
->
videosize
=
uvd
->
canvas
;
/* Initialize konicawc specific data */
konicawc_configure_video
(
uvd
);
i
=
usbvideo_RegisterVideoDevice
(
uvd
);
uvd
->
max_frame_size
=
(
konicawc_data
->
width
*
konicawc_data
->
height
*
3
)
/
2
;
if
(
i
!=
0
)
{
err
(
"usbvideo_RegisterVideoDevice() failed."
);
uvd
=
NULL
;
}
}
MOD_DEC_USE_COUNT
;
return
uvd
;
}
static
int
__init
konicawc_init
(
void
)
{
usbvideo_cb_t
cbTbl
;
memset
(
&
cbTbl
,
0
,
sizeof
(
cbTbl
));
cbTbl
.
probe
=
konicawc_probe
;
cbTbl
.
setupOnOpen
=
konicawc_setup_on_open
;
cbTbl
.
processData
=
konicawc_process_isoc
;
cbTbl
.
getFPS
=
konicawc_calculate_fps
;
cbTbl
.
startDataPump
=
konicawc_start_data
;
cbTbl
.
stopDataPump
=
konicawc_stop_data
;
return
usbvideo_register
(
&
cams
,
MAX_CAMERAS
,
sizeof
(
struct
konicawc
),
"konicawc"
,
&
cbTbl
,
THIS_MODULE
);
}
static
void
__exit
konicawc_cleanup
(
void
)
{
usbvideo_Deregister
(
&
cams
);
}
#if defined(usb_device_id_ver)
static
__devinitdata
struct
usb_device_id
id_table
[]
=
{
{
USB_DEVICE
(
0x04c8
,
0x0720
)
},
/* Intel YC 76 */
{
}
/* Terminating entry */
};
MODULE_DEVICE_TABLE
(
usb
,
id_table
);
#endif
/* defined(usb_device_id_ver) */
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Simon Evans <spse@secret.org.uk>"
);
MODULE_DESCRIPTION
(
"Konica Webcam driver"
);
MODULE_PARM
(
size
,
"i"
);
MODULE_PARM_DESC
(
size
,
"Frame Size 0: 160x136 1: 176x144 2: 320x240"
);
MODULE_PARM
(
brightness
,
"i"
);
MODULE_PARM_DESC
(
brightness
,
"Initial brightness 0 - 108"
);
MODULE_PARM
(
contrast
,
"i"
);
MODULE_PARM_DESC
(
contrast
,
"Initial contrast 0 - 108"
);
MODULE_PARM
(
saturation
,
"i"
);
MODULE_PARM_DESC
(
saturation
,
"Initial saturation 0 - 108"
);
MODULE_PARM
(
sharpness
,
"i"
);
MODULE_PARM_DESC
(
sharpness
,
"Initial brightness 0 - 108"
);
MODULE_PARM
(
whitebal
,
"i"
);
MODULE_PARM_DESC
(
whitebal
,
"Initial white balance 0 - 363"
);
MODULE_PARM
(
debug
,
"i"
);
MODULE_PARM_DESC
(
debug
,
"Debug level: 0-9 (default=0)"
);
module_init
(
konicawc_init
);
module_exit
(
konicawc_cleanup
);
drivers/usb/usbvideo.c
View file @
7cf654b1
...
...
@@ -791,6 +791,10 @@ int usbvideo_register(
cams
->
cb
.
getFrame
=
usbvideo_GetFrame
;
if
(
cams
->
cb
.
disconnect
==
NULL
)
cams
->
cb
.
disconnect
=
usbvideo_Disconnect
;
if
(
cams
->
cb
.
startDataPump
==
NULL
)
cams
->
cb
.
startDataPump
=
usbvideo_StartDataPump
;
if
(
cams
->
cb
.
stopDataPump
==
NULL
)
cams
->
cb
.
stopDataPump
=
usbvideo_StopDataPump
;
#if USES_PROC_FS
/*
* If both /proc fs callbacks are NULL then we assume that the driver
...
...
@@ -963,7 +967,7 @@ void usbvideo_Disconnect(struct usb_device *dev, void *ptr)
uvd
->
remove_pending
=
1
;
/* Now all ISO data will be ignored */
/* At this time we ask to cancel outstanding URBs */
usbvideo_StopDataPump
(
uvd
);
GET_CALLBACK
(
uvd
,
stopDataPump
)
(
uvd
);
for
(
i
=
0
;
i
<
USBVIDEO_NUMSBUF
;
i
++
)
usb_free_urb
(
uvd
->
sbuf
[
i
].
urb
);
...
...
@@ -1299,7 +1303,7 @@ int usbvideo_v4l_open(struct video_device *dev, int flags)
if
(
errCode
==
0
)
{
/* Start data pump if we have valid endpoint */
if
(
uvd
->
video_endp
!=
0
)
errCode
=
usbvideo_StartDataPump
(
uvd
);
errCode
=
GET_CALLBACK
(
uvd
,
startDataPump
)
(
uvd
);
if
(
errCode
==
0
)
{
if
(
VALID_CALLBACK
(
uvd
,
setupOnOpen
))
{
if
(
uvd
->
debug
>
1
)
...
...
@@ -1349,8 +1353,8 @@ void usbvideo_v4l_close(struct video_device *dev)
if
(
uvd
->
debug
>
1
)
info
(
"%s($%p)"
,
proc
,
dev
);
down
(
&
uvd
->
lock
);
usbvideo_StopDataPump
(
uvd
);
down
(
&
uvd
->
lock
);
GET_CALLBACK
(
uvd
,
stopDataPump
)
(
uvd
);
usbvideo_rvfree
(
uvd
->
fbuf
,
uvd
->
fbuf_size
);
uvd
->
fbuf
=
NULL
;
RingQueue_Free
(
&
uvd
->
dp
);
...
...
drivers/usb/usbvideo.h
View file @
7cf654b1
...
...
@@ -269,6 +269,8 @@ typedef struct {
int
(
*
getFrame
)(
uvd_t
*
,
int
);
int
(
*
procfs_read
)(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
);
int
(
*
procfs_write
)(
struct
file
*
file
,
const
char
*
buffer
,
unsigned
long
count
,
void
*
data
);
int
(
*
startDataPump
)(
uvd_t
*
uvd
);
void
(
*
stopDataPump
)(
uvd_t
*
uvd
);
}
usbvideo_cb_t
;
struct
s_usbvideo_t
{
...
...
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