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
...
@@ -505,6 +505,21 @@ CONFIG_USB_DABUSB
The module will be called dabusb.o. If you want to compile it as a
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>.
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
CONFIG_USB_USBNET
This driver supports network links over USB with USB "Network"
This driver supports network links over USB with USB "Network"
or "data transfer" cables, often used to network laptops to PCs.
or "data transfer" cables, often used to network laptops to PCs.
...
...
drivers/usb/Config.in
View file @
7cf654b1
...
@@ -80,6 +80,7 @@ else
...
@@ -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 ' 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 ' 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 ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB
dep_tristate ' USB Konica Webcam support' CONFIG_USB_KONICAWC $CONFIG_USB $CONFIG_VIDEO_DEV
fi
fi
comment 'USB Network adaptors'
comment 'USB Network adaptors'
...
...
drivers/usb/Makefile
View file @
7cf654b1
...
@@ -64,6 +64,7 @@ obj-$(CONFIG_USB_ACM) += acm.o
...
@@ -64,6 +64,7 @@ obj-$(CONFIG_USB_ACM) += acm.o
obj-$(CONFIG_USB_PRINTER)
+=
printer.o
obj-$(CONFIG_USB_PRINTER)
+=
printer.o
obj-$(CONFIG_USB_AUDIO)
+=
audio.o
obj-$(CONFIG_USB_AUDIO)
+=
audio.o
obj-$(CONFIG_USB_IBMCAM)
+=
ibmcam.o usbvideo.o ultracam.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_PWC)
+=
pwc.o
obj-$(CONFIG_USB_DC2XX)
+=
dc2xx.o
obj-$(CONFIG_USB_DC2XX)
+=
dc2xx.o
obj-$(CONFIG_USB_MDC800)
+=
mdc800.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(
...
@@ -791,6 +791,10 @@ int usbvideo_register(
cams
->
cb
.
getFrame
=
usbvideo_GetFrame
;
cams
->
cb
.
getFrame
=
usbvideo_GetFrame
;
if
(
cams
->
cb
.
disconnect
==
NULL
)
if
(
cams
->
cb
.
disconnect
==
NULL
)
cams
->
cb
.
disconnect
=
usbvideo_Disconnect
;
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 USES_PROC_FS
/*
/*
* If both /proc fs callbacks are NULL then we assume that the driver
* 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)
...
@@ -963,7 +967,7 @@ void usbvideo_Disconnect(struct usb_device *dev, void *ptr)
uvd
->
remove_pending
=
1
;
/* Now all ISO data will be ignored */
uvd
->
remove_pending
=
1
;
/* Now all ISO data will be ignored */
/* At this time we ask to cancel outstanding URBs */
/* At this time we ask to cancel outstanding URBs */
usbvideo_StopDataPump
(
uvd
);
GET_CALLBACK
(
uvd
,
stopDataPump
)
(
uvd
);
for
(
i
=
0
;
i
<
USBVIDEO_NUMSBUF
;
i
++
)
for
(
i
=
0
;
i
<
USBVIDEO_NUMSBUF
;
i
++
)
usb_free_urb
(
uvd
->
sbuf
[
i
].
urb
);
usb_free_urb
(
uvd
->
sbuf
[
i
].
urb
);
...
@@ -1299,7 +1303,7 @@ int usbvideo_v4l_open(struct video_device *dev, int flags)
...
@@ -1299,7 +1303,7 @@ int usbvideo_v4l_open(struct video_device *dev, int flags)
if
(
errCode
==
0
)
{
if
(
errCode
==
0
)
{
/* Start data pump if we have valid endpoint */
/* Start data pump if we have valid endpoint */
if
(
uvd
->
video_endp
!=
0
)
if
(
uvd
->
video_endp
!=
0
)
errCode
=
usbvideo_StartDataPump
(
uvd
);
errCode
=
GET_CALLBACK
(
uvd
,
startDataPump
)
(
uvd
);
if
(
errCode
==
0
)
{
if
(
errCode
==
0
)
{
if
(
VALID_CALLBACK
(
uvd
,
setupOnOpen
))
{
if
(
VALID_CALLBACK
(
uvd
,
setupOnOpen
))
{
if
(
uvd
->
debug
>
1
)
if
(
uvd
->
debug
>
1
)
...
@@ -1349,8 +1353,8 @@ void usbvideo_v4l_close(struct video_device *dev)
...
@@ -1349,8 +1353,8 @@ void usbvideo_v4l_close(struct video_device *dev)
if
(
uvd
->
debug
>
1
)
if
(
uvd
->
debug
>
1
)
info
(
"%s($%p)"
,
proc
,
dev
);
info
(
"%s($%p)"
,
proc
,
dev
);
down
(
&
uvd
->
lock
);
down
(
&
uvd
->
lock
);
usbvideo_StopDataPump
(
uvd
);
GET_CALLBACK
(
uvd
,
stopDataPump
)
(
uvd
);
usbvideo_rvfree
(
uvd
->
fbuf
,
uvd
->
fbuf_size
);
usbvideo_rvfree
(
uvd
->
fbuf
,
uvd
->
fbuf_size
);
uvd
->
fbuf
=
NULL
;
uvd
->
fbuf
=
NULL
;
RingQueue_Free
(
&
uvd
->
dp
);
RingQueue_Free
(
&
uvd
->
dp
);
...
...
drivers/usb/usbvideo.h
View file @
7cf654b1
...
@@ -269,6 +269,8 @@ typedef struct {
...
@@ -269,6 +269,8 @@ typedef struct {
int
(
*
getFrame
)(
uvd_t
*
,
int
);
int
(
*
getFrame
)(
uvd_t
*
,
int
);
int
(
*
procfs_read
)(
char
*
page
,
char
**
start
,
off_t
off
,
int
count
,
int
*
eof
,
void
*
data
);
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
(
*
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
;
}
usbvideo_cb_t
;
struct
s_usbvideo_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