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
097032ac
Commit
097032ac
authored
Jun 29, 2004
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
Merge kroah.com:/home/greg/linux/BK/bleed-2.6
into kroah.com:/home/greg/linux/BK/usb-2.6
parents
4d1ae8c5
bbc53b7d
Changes
34
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
1272 additions
and
736 deletions
+1272
-736
Documentation/usb/philips.txt
Documentation/usb/philips.txt
+60
-27
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.c
+112
-33
drivers/usb/class/cdc-acm.h
drivers/usb/class/cdc-acm.h
+13
-1
drivers/usb/core/hub.c
drivers/usb/core/hub.c
+60
-21
drivers/usb/core/hub.h
drivers/usb/core/hub.h
+2
-0
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/dummy_hcd.c
+27
-16
drivers/usb/gadget/ether.c
drivers/usb/gadget/ether.c
+6
-4
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/file_storage.c
+2
-0
drivers/usb/gadget/inode.c
drivers/usb/gadget/inode.c
+179
-5
drivers/usb/gadget/serial.c
drivers/usb/gadget/serial.c
+2
-0
drivers/usb/gadget/zero.c
drivers/usb/gadget/zero.c
+2
-0
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hcd.c
+18
-11
drivers/usb/host/uhci-debug.c
drivers/usb/host/uhci-debug.c
+1
-1
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.c
+12
-7
drivers/usb/host/uhci-hub.c
drivers/usb/host/uhci-hub.c
+2
-2
drivers/usb/input/hid-tmff.c
drivers/usb/input/hid-tmff.c
+1
-1
drivers/usb/media/Kconfig
drivers/usb/media/Kconfig
+1
-1
drivers/usb/media/konicawc.c
drivers/usb/media/konicawc.c
+1
-1
drivers/usb/media/pwc-ctrl.c
drivers/usb/media/pwc-ctrl.c
+361
-414
drivers/usb/media/pwc-if.c
drivers/usb/media/pwc-if.c
+146
-79
drivers/usb/media/pwc-ioctl.h
drivers/usb/media/pwc-ioctl.h
+69
-19
drivers/usb/media/pwc-misc.c
drivers/usb/media/pwc-misc.c
+37
-13
drivers/usb/media/pwc-uncompress.c
drivers/usb/media/pwc-uncompress.c
+24
-9
drivers/usb/media/pwc-uncompress.h
drivers/usb/media/pwc-uncompress.h
+11
-4
drivers/usb/media/pwc.h
drivers/usb/media/pwc.h
+17
-26
drivers/usb/net/kaweth.c
drivers/usb/net/kaweth.c
+2
-2
drivers/usb/net/pegasus.c
drivers/usb/net/pegasus.c
+0
-4
drivers/usb/serial/generic.c
drivers/usb/serial/generic.c
+33
-0
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.c
+46
-7
drivers/usb/serial/pl2303.h
drivers/usb/serial/pl2303.h
+6
-0
drivers/usb/serial/usb-serial.c
drivers/usb/serial/usb-serial.c
+1
-27
drivers/usb/storage/transport.c
drivers/usb/storage/transport.c
+6
-0
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/unusual_devs.h
+11
-1
fs/aio.c
fs/aio.c
+1
-0
No files found.
Documentation/usb/philips.txt
View file @
097032ac
This file contains some additional information for the Philips webcams.
This file contains some additional information for the Philips and OEM webcams.
E-mail: webcam@smcc.demon.nl Last updated: 2001-09-24
E-mail: webcam@smcc.demon.nl Last updated: 2004-01-19
Site: http://www.smcc.demon.nl/webcam/
The main webpage for the Philips driver is http://www.smcc.demon.nl/webcam/.
It contains a lot of extra information, a FAQ, and the binary plugin
As of this moment, the following cameras are supported:
'PWCX'. This plugin contains decompression routines that allow you to
* Philips PCA645
use higher image sizes and framerates; in addition the webcam uses less
* Philips PCA646
bandwidth on the USB bus (handy if you want to run more than 1 camera
* Philips PCVC675
simultaneously). These routines fall under an NDA, and may therefor not be
* Philips PCVC680
distributed as source; however, its use is completely optional.
* Philips PCVC690
* Philips PCVC720/40
* Philips PCVC730
* Philips PCVC740
* Philips PCVC750
* Askey VC010
* Creative Labs Webcam 5
* Creative Labs Webcam Pro Ex
* Logitech QuickCam 3000 Pro
* Logitech QuickCam 4000 Pro
* Logitech QuickCam Notebook Pro
* Logitech QuickCam Zoom
* Logitech QuickCam Orbit
* Logitech QuickCam Sphere
* Samsung MPC-C10
* Samsung MPC-C30
* Sotec Afina Eye
* AME CU-001
* Visionite VCS-UM100
* Visionite VCS-UC300
The main webpage for the Philips driver is at the address above. It contains
a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin
contains decompression routines that allow you to use higher image sizes and
framerates; in addition the webcam uses less bandwidth on the USB bus (handy
if you want to run more than 1 camera simultaneously). These routines fall
under a NDA, and may therefor not be distributed as source; however, its use
is completely optional.
You can build this code either into your kernel, or as a module. I recommend
You can build this code either into your kernel, or as a module. I recommend
the latter, since it makes troubleshooting a lot easier. The built-in
the latter, since it makes troubleshooting a lot easier. The built-in
...
@@ -27,14 +54,14 @@ fps
...
@@ -27,14 +54,14 @@ fps
Specifies the desired framerate. Is an integer in the range of 4-30.
Specifies the desired framerate. Is an integer in the range of 4-30.
fbufs
fbufs
This param
e
ter specifies the number of internal buffers to use for storing
This paramter specifies the number of internal buffers to use for storing
frames from the cam. This will help if the process that reads images from
frames from the cam. This will help if the process that reads images from
the cam is a bit slow or momentar
ily busy. However, on slow machines it
the cam is a bit slow or momentar
ely busy. However, on slow machines it
only introduces lag, so choose carefully. The default is 3, which is
only introduces lag, so choose carefully. The default is 3, which is
reasonable. You can set it between 2 and 5.
reasonable. You can set it between 2 and 5.
mbufs
mbufs
This is an integer between 1 and
4
. It will tell the module the number of
This is an integer between 1 and
10
. It will tell the module the number of
buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
The default is 2, which is adequate for most applications (double
The default is 2, which is adequate for most applications (double
buffering).
buffering).
...
@@ -45,9 +72,9 @@ mbufs
...
@@ -45,9 +72,9 @@ mbufs
slack when your program is behind. But you need a multi-threaded or
slack when your program is behind. But you need a multi-threaded or
forked program to really take advantage of these buffers.
forked program to really take advantage of these buffers.
The absolute maximum is
4
, but don't set it too high! Every buffer takes
The absolute maximum is
10
, but don't set it too high! Every buffer takes
up
1.22 M
B of RAM, so unless you have a lot of memory setting this to
up
460 K
B of RAM, so unless you have a lot of memory setting this to
something more than
2
is an absolute waste. This memory is only
something more than
4
is an absolute waste. This memory is only
allocated during open(), so nothing is wasted when the camera is not in
allocated during open(), so nothing is wasted when the camera is not in
use.
use.
...
@@ -74,9 +101,10 @@ compression (only useful with the plugin)
...
@@ -74,9 +101,10 @@ compression (only useful with the plugin)
introduce some unwanted artefacts. The default is 2, medium compression.
introduce some unwanted artefacts. The default is 2, medium compression.
See the FAQ on the website for an overview of which modes require
See the FAQ on the website for an overview of which modes require
compression.
compression.
The compression parameter only applies to the Vesta & ToUCam cameras.
The compression parameter does not apply to the 645 and 646 cameras
The 645 and 646 have fixed compression parameters.
and OEM models derived from those (only a few). Most cams honour this
parameter.
leds
leds
This settings takes 2 integers, that define the on/off time for the LED
This settings takes 2 integers, that define the on/off time for the LED
...
@@ -89,14 +117,17 @@ leds
...
@@ -89,14 +117,17 @@ leds
leds=0,0
leds=0,0
the LED never goes on, making it suitable for silent surv
a
illance.
the LED never goes on, making it suitable for silent surv
e
illance.
By default the camera's LED is on solid while in use, and turned off
By default the camera's LED is on solid while in use, and turned off
when the camera is not used anymore.
when the camera is not used anymore.
This parameter works only with the ToUCam range of cameras (730, 740,
This parameter works only with the ToUCam range of cameras (720, 730, 740,
750). For other cameras this command is silently ignored, and the LED
750) and OEMs. For other cameras this command is silently ignored, and
cannot be controlled.
the LED cannot be controlled.
Finally: this parameters does not take effect UNTIL the first time you
open the camera device. Until then, the LED remains on.
dev_hint
dev_hint
A long standing problem with USB devices is their dynamic nature: you
A long standing problem with USB devices is their dynamic nature: you
...
@@ -126,7 +157,7 @@ dev_hint
...
@@ -126,7 +157,7 @@ dev_hint
other cameras will get the first free
other cameras will get the first free
available slot (see below).
available slot (see below).
dev_hint=645:1,680
=
2 The PCA645 camera will get /dev/video1,
dev_hint=645:1,680
:
2 The PCA645 camera will get /dev/video1,
and a PCVC680 /dev/video2.
and a PCVC680 /dev/video2.
dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber
dev_hint=645.0123:3,645.4567:0 The PCA645 camera with serialnumber
...
@@ -176,13 +207,16 @@ trace
...
@@ -176,13 +207,16 @@ trace
64 0x40 Show viewport and image sizes Off
64 0x40 Show viewport and image sizes Off
128 0x80 PWCX debugging Off
For example, to trace the open() & read() fuctions, sum 8 + 4 = 12,
For example, to trace the open() & read() fuctions, sum 8 + 4 = 12,
so you would supply trace=12 during insmod or modprobe. If
so you would supply trace=12 during insmod or modprobe. If
you want to turn the initialization and probing tracing off, set trace=0.
you want to turn the initialization and probing tracing off, set trace=0.
The default value for trace is 35 (0x23).
The default value for trace is 35 (0x23).
Example:
Example:
# modprobe pwc size=cif fps=15 power_save=1
# modprobe pwc size=cif fps=15 power_save=1
...
@@ -192,7 +226,7 @@ cameras. Each camera has its own set of buffers.
...
@@ -192,7 +226,7 @@ cameras. Each camera has its own set of buffers.
size and fps only specify defaults when you open() the device; this is to
size and fps only specify defaults when you open() the device; this is to
accommodate some tools that don't set the size. You can change these
accommodate some tools that don't set the size. You can change these
settings after open() with the Video4Linux ioctl() calls. The default of
settings after open() with the Video4Linux ioctl() calls. The default of
defaults is QCIF size at 10 fps
, BGR order
.
defaults is QCIF size at 10 fps.
The compression parameter is semiglobal; it sets the initial compression
The compression parameter is semiglobal; it sets the initial compression
preference for all camera's, but this parameter can be set per camera with
preference for all camera's, but this parameter can be set per camera with
...
@@ -200,4 +234,3 @@ the VIDIOCPWCSCQUAL ioctl() call.
...
@@ -200,4 +234,3 @@ the VIDIOCPWCSCQUAL ioctl() call.
All parameters are optional.
All parameters are optional.
drivers/usb/class/cdc-acm.c
View file @
097032ac
...
@@ -5,6 +5,7 @@
...
@@ -5,6 +5,7 @@
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
* Copyright (c) 1999 Johannes Erdfelt <johannes@erdfelt.com>
* Copyright (c) 1999 Johannes Erdfelt <johannes@erdfelt.com>
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2000 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (c) 2004 Oliver Neukum <oliver@neukum.name>
*
*
* USB Abstract Control Model driver for USB modems and ISDN adapters
* USB Abstract Control Model driver for USB modems and ISDN adapters
*
*
...
@@ -60,6 +61,7 @@
...
@@ -60,6 +61,7 @@
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
#include <linux/usb.h>
#include <asm/byteorder.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
#include "cdc-acm.h"
#include "cdc-acm.h"
...
@@ -108,7 +110,7 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
...
@@ -108,7 +110,7 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
{
{
struct
acm
*
acm
=
urb
->
context
;
struct
acm
*
acm
=
urb
->
context
;
struct
usb_ctrlrequest
*
dr
=
urb
->
transfer_buffer
;
struct
usb_ctrlrequest
*
dr
=
urb
->
transfer_buffer
;
unsigned
char
*
data
=
(
unsigned
char
*
)(
dr
+
1
)
;
unsigned
char
*
data
;
int
newctrl
;
int
newctrl
;
int
status
;
int
status
;
...
@@ -130,6 +132,7 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
...
@@ -130,6 +132,7 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
if
(
!
ACM_READY
(
acm
))
if
(
!
ACM_READY
(
acm
))
goto
exit
;
goto
exit
;
data
=
(
unsigned
char
*
)(
dr
+
1
);
switch
(
dr
->
bRequest
)
{
switch
(
dr
->
bRequest
)
{
case
ACM_IRQ_NETWORK
:
case
ACM_IRQ_NETWORK
:
...
@@ -139,7 +142,7 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
...
@@ -139,7 +142,7 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
case
ACM_IRQ_LINE_STATE
:
case
ACM_IRQ_LINE_STATE
:
newctrl
=
le16_to_cpu
p
((
__u16
*
)
data
);
newctrl
=
le16_to_cpu
(
get_unaligned
((
__u16
*
)
data
)
);
if
(
acm
->
tty
&&
!
acm
->
clocal
&&
(
acm
->
ctrlin
&
~
newctrl
&
ACM_CTRL_DCD
))
{
if
(
acm
->
tty
&&
!
acm
->
clocal
&&
(
acm
->
ctrlin
&
~
newctrl
&
ACM_CTRL_DCD
))
{
dbg
(
"calling hangup"
);
dbg
(
"calling hangup"
);
...
@@ -172,6 +175,7 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
...
@@ -172,6 +175,7 @@ static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
static
void
acm_read_bulk
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
static
void
acm_read_bulk
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
{
struct
acm
*
acm
=
urb
->
context
;
struct
acm
*
acm
=
urb
->
context
;
dbg
(
"Entering acm_read_bulk with status %d
\n
"
,
urb
->
status
);
if
(
!
ACM_READY
(
acm
))
if
(
!
ACM_READY
(
acm
))
return
;
return
;
...
@@ -190,6 +194,7 @@ static void acm_rx_tasklet(unsigned long _acm)
...
@@ -190,6 +194,7 @@ static void acm_rx_tasklet(unsigned long _acm)
struct
tty_struct
*
tty
=
acm
->
tty
;
struct
tty_struct
*
tty
=
acm
->
tty
;
unsigned
char
*
data
=
urb
->
transfer_buffer
;
unsigned
char
*
data
=
urb
->
transfer_buffer
;
int
i
=
0
;
int
i
=
0
;
dbg
(
"Entering acm_rx_tasklet"
);
if
(
urb
->
actual_length
>
0
&&
!
acm
->
throttle
)
{
if
(
urb
->
actual_length
>
0
&&
!
acm
->
throttle
)
{
for
(
i
=
0
;
i
<
urb
->
actual_length
&&
!
acm
->
throttle
;
i
++
)
{
for
(
i
=
0
;
i
<
urb
->
actual_length
&&
!
acm
->
throttle
;
i
++
)
{
...
@@ -200,14 +205,20 @@ static void acm_rx_tasklet(unsigned long _acm)
...
@@ -200,14 +205,20 @@ static void acm_rx_tasklet(unsigned long _acm)
}
}
tty_insert_flip_char
(
tty
,
data
[
i
],
0
);
tty_insert_flip_char
(
tty
,
data
[
i
],
0
);
}
}
dbg
(
"Handed %d bytes to tty layer"
,
i
+
1
);
tty_flip_buffer_push
(
tty
);
tty_flip_buffer_push
(
tty
);
}
}
spin_lock
(
&
acm
->
throttle_lock
);
if
(
acm
->
throttle
)
{
if
(
acm
->
throttle
)
{
dbg
(
"Throtteling noticed"
);
memmove
(
data
,
data
+
i
,
urb
->
actual_length
-
i
);
memmove
(
data
,
data
+
i
,
urb
->
actual_length
-
i
);
urb
->
actual_length
-=
i
;
urb
->
actual_length
-=
i
;
acm
->
resubmit_to_unthrottle
=
1
;
spin_unlock
(
&
acm
->
throttle_lock
);
return
;
return
;
}
}
spin_unlock
(
&
acm
->
throttle_lock
);
urb
->
actual_length
=
0
;
urb
->
actual_length
=
0
;
urb
->
dev
=
acm
->
dev
;
urb
->
dev
=
acm
->
dev
;
...
@@ -221,6 +232,7 @@ static void acm_rx_tasklet(unsigned long _acm)
...
@@ -221,6 +232,7 @@ static void acm_rx_tasklet(unsigned long _acm)
static
void
acm_write_bulk
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
static
void
acm_write_bulk
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
{
struct
acm
*
acm
=
(
struct
acm
*
)
urb
->
context
;
struct
acm
*
acm
=
(
struct
acm
*
)
urb
->
context
;
dbg
(
"Entering acm_write_bulk with status %d
\n
"
,
urb
->
status
);
if
(
!
ACM_READY
(
acm
))
if
(
!
ACM_READY
(
acm
))
goto
out
;
goto
out
;
...
@@ -237,7 +249,8 @@ static void acm_softint(void *private)
...
@@ -237,7 +249,8 @@ static void acm_softint(void *private)
{
{
struct
acm
*
acm
=
private
;
struct
acm
*
acm
=
private
;
struct
tty_struct
*
tty
=
acm
->
tty
;
struct
tty_struct
*
tty
=
acm
->
tty
;
dbg
(
"Entering acm_softint.
\n
"
);
if
(
!
ACM_READY
(
acm
))
if
(
!
ACM_READY
(
acm
))
return
;
return
;
...
@@ -254,6 +267,7 @@ static void acm_softint(void *private)
...
@@ -254,6 +267,7 @@ static void acm_softint(void *private)
static
int
acm_tty_open
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
static
int
acm_tty_open
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
{
{
struct
acm
*
acm
=
acm_table
[
tty
->
index
];
struct
acm
*
acm
=
acm_table
[
tty
->
index
];
dbg
(
"Entering acm_tty_open.
\n
"
);
if
(
!
acm
||
!
acm
->
dev
)
if
(
!
acm
||
!
acm
->
dev
)
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -279,7 +293,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
...
@@ -279,7 +293,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
goto
bail_out_and_unlink
;
goto
bail_out_and_unlink
;
}
}
acm_set_control
(
acm
,
acm
->
ctrlout
=
ACM_CTRL_DTR
|
ACM_CTRL_RTS
);
if
(
0
>
acm_set_control
(
acm
,
acm
->
ctrlout
=
ACM_CTRL_DTR
|
ACM_CTRL_RTS
))
goto
full_bailout
;
/* force low_latency on so that our tty_push actually forces the data through,
/* force low_latency on so that our tty_push actually forces the data through,
otherwise it is scheduled, and with high data rates data can get lost. */
otherwise it is scheduled, and with high data rates data can get lost. */
...
@@ -290,6 +305,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
...
@@ -290,6 +305,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
up
(
&
open_sem
);
up
(
&
open_sem
);
return
0
;
return
0
;
full_bailout:
usb_unlink_urb
(
acm
->
readurb
);
bail_out_and_unlink:
bail_out_and_unlink:
usb_unlink_urb
(
acm
->
ctrlurb
);
usb_unlink_urb
(
acm
->
ctrlurb
);
bail_out:
bail_out:
...
@@ -327,6 +344,7 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c
...
@@ -327,6 +344,7 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c
{
{
struct
acm
*
acm
=
tty
->
driver_data
;
struct
acm
*
acm
=
tty
->
driver_data
;
int
stat
;
int
stat
;
dbg
(
"Entering acm_tty_write to write %d bytes from %s space,
\n
"
,
count
,
from_user
?
"user"
:
"kernel"
);
if
(
!
ACM_READY
(
acm
))
if
(
!
ACM_READY
(
acm
))
return
-
EINVAL
;
return
-
EINVAL
;
...
@@ -337,11 +355,13 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c
...
@@ -337,11 +355,13 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c
count
=
(
count
>
acm
->
writesize
)
?
acm
->
writesize
:
count
;
count
=
(
count
>
acm
->
writesize
)
?
acm
->
writesize
:
count
;
dbg
(
"Get %d bytes from %s space..."
,
count
,
from_user
?
"user"
:
"kernel"
);
if
(
from_user
)
{
if
(
from_user
)
{
if
(
copy_from_user
(
acm
->
write
urb
->
transfer
_buffer
,
(
void
__user
*
)
buf
,
count
))
if
(
copy_from_user
(
acm
->
write_buffer
,
(
void
__user
*
)
buf
,
count
))
return
-
EFAULT
;
return
-
EFAULT
;
}
else
}
else
memcpy
(
acm
->
writeurb
->
transfer_buffer
,
buf
,
count
);
memcpy
(
acm
->
write_buffer
,
buf
,
count
);
dbg
(
" Successfully copied.
\n
"
);
acm
->
writeurb
->
transfer_buffer_length
=
count
;
acm
->
writeurb
->
transfer_buffer_length
=
count
;
acm
->
writeurb
->
dev
=
acm
->
dev
;
acm
->
writeurb
->
dev
=
acm
->
dev
;
...
@@ -378,7 +398,9 @@ static void acm_tty_throttle(struct tty_struct *tty)
...
@@ -378,7 +398,9 @@ static void acm_tty_throttle(struct tty_struct *tty)
struct
acm
*
acm
=
tty
->
driver_data
;
struct
acm
*
acm
=
tty
->
driver_data
;
if
(
!
ACM_READY
(
acm
))
if
(
!
ACM_READY
(
acm
))
return
;
return
;
spin_lock_bh
(
&
acm
->
throttle_lock
);
acm
->
throttle
=
1
;
acm
->
throttle
=
1
;
spin_unlock_bh
(
&
acm
->
throttle_lock
);
}
}
static
void
acm_tty_unthrottle
(
struct
tty_struct
*
tty
)
static
void
acm_tty_unthrottle
(
struct
tty_struct
*
tty
)
...
@@ -386,9 +408,13 @@ static void acm_tty_unthrottle(struct tty_struct *tty)
...
@@ -386,9 +408,13 @@ static void acm_tty_unthrottle(struct tty_struct *tty)
struct
acm
*
acm
=
tty
->
driver_data
;
struct
acm
*
acm
=
tty
->
driver_data
;
if
(
!
ACM_READY
(
acm
))
if
(
!
ACM_READY
(
acm
))
return
;
return
;
spin_lock_bh
(
&
acm
->
throttle_lock
);
acm
->
throttle
=
0
;
acm
->
throttle
=
0
;
if
(
acm
->
readurb
->
status
!=
-
EINPROGRESS
)
spin_unlock_bh
(
&
acm
->
throttle_lock
);
if
(
acm
->
resubmit_to_unthrottle
)
{
acm
->
resubmit_to_unthrottle
=
0
;
acm_read_bulk
(
acm
->
readurb
,
NULL
);
acm_read_bulk
(
acm
->
readurb
,
NULL
);
}
}
}
static
void
acm_tty_break_ctl
(
struct
tty_struct
*
tty
,
int
state
)
static
void
acm_tty_break_ctl
(
struct
tty_struct
*
tty
,
int
state
)
...
@@ -510,7 +536,11 @@ static int acm_probe (struct usb_interface *intf,
...
@@ -510,7 +536,11 @@ static int acm_probe (struct usb_interface *intf,
struct
acm
*
acm
;
struct
acm
*
acm
;
int
minor
;
int
minor
;
int
ctrlsize
,
readsize
;
int
ctrlsize
,
readsize
;
char
*
buf
;
u8
*
buf
;
u8
ac_management_function
=
0
;
u8
call_management_function
=
0
;
int
call_interface_num
=
-
1
;
int
data_interface_num
;
if
(
!
buffer
)
{
if
(
!
buffer
)
{
err
(
"Wierd descriptor references"
);
err
(
"Wierd descriptor references"
);
...
@@ -531,6 +561,18 @@ static int acm_probe (struct usb_interface *intf,
...
@@ -531,6 +561,18 @@ static int acm_probe (struct usb_interface *intf,
}
}
union_header
=
(
struct
union_desc
*
)
buffer
;
union_header
=
(
struct
union_desc
*
)
buffer
;
break
;
break
;
case
CDC_COUNTRY_TYPE
:
/* maybe somehow export */
break
;
/* for now we ignore it */
case
CDC_AC_MANAGEMENT_TYPE
:
ac_management_function
=
buffer
[
3
];
break
;
case
CDC_CALL_MANAGEMENT_TYPE
:
call_management_function
=
buffer
[
3
];
call_interface_num
=
buffer
[
4
];
if
((
call_management_function
&
3
)
!=
3
)
err
(
"This device cannot do calls on its own. It is no modem."
);
break
;
default:
default:
err
(
"Ignoring extra header"
);
err
(
"Ignoring extra header"
);
break
;
break
;
...
@@ -546,11 +588,14 @@ static int acm_probe (struct usb_interface *intf,
...
@@ -546,11 +588,14 @@ static int acm_probe (struct usb_interface *intf,
}
}
control_interface
=
usb_ifnum_to_if
(
usb_dev
,
union_header
->
bMasterInterface0
);
control_interface
=
usb_ifnum_to_if
(
usb_dev
,
union_header
->
bMasterInterface0
);
data_interface
=
usb_ifnum_to_if
(
usb_dev
,
union_header
->
bSlaveInterface0
);
data_interface
=
usb_ifnum_to_if
(
usb_dev
,
(
data_interface_num
=
union_header
->
bSlaveInterface0
)
);
if
(
!
control_interface
||
!
data_interface
)
{
if
(
!
control_interface
||
!
data_interface
)
{
dev_dbg
(
&
intf
->
dev
,
"no interfaces
\n
"
);
dev_dbg
(
&
intf
->
dev
,
"no interfaces
\n
"
);
return
-
ENODEV
;
return
-
ENODEV
;
}
}
if
(
data_interface_num
!=
call_interface_num
)
dev_dbg
(
&
intf
->
dev
,
"Seperate call control interface. That is not fully supported."
);
if
(
usb_interface_claimed
(
data_interface
))
{
/* valid in this context */
if
(
usb_interface_claimed
(
data_interface
))
{
/* valid in this context */
dev_dbg
(
&
intf
->
dev
,
"The data interface isn't available
\n
"
);
dev_dbg
(
&
intf
->
dev
,
"The data interface isn't available
\n
"
);
...
@@ -598,7 +643,7 @@ static int acm_probe (struct usb_interface *intf,
...
@@ -598,7 +643,7 @@ static int acm_probe (struct usb_interface *intf,
if
(
!
(
acm
=
kmalloc
(
sizeof
(
struct
acm
),
GFP_KERNEL
)))
{
if
(
!
(
acm
=
kmalloc
(
sizeof
(
struct
acm
),
GFP_KERNEL
)))
{
dev_dbg
(
&
intf
->
dev
,
"out of memory (acm kmalloc)
\n
"
);
dev_dbg
(
&
intf
->
dev
,
"out of memory (acm kmalloc)
\n
"
);
return
-
ENOMEM
;
goto
alloc_fail
;
}
}
memset
(
acm
,
0
,
sizeof
(
struct
acm
));
memset
(
acm
,
0
,
sizeof
(
struct
acm
));
...
@@ -609,54 +654,66 @@ static int acm_probe (struct usb_interface *intf,
...
@@ -609,54 +654,66 @@ static int acm_probe (struct usb_interface *intf,
acm
->
data
=
data_interface
;
acm
->
data
=
data_interface
;
acm
->
minor
=
minor
;
acm
->
minor
=
minor
;
acm
->
dev
=
usb_dev
;
acm
->
dev
=
usb_dev
;
acm
->
ctrl_caps
=
ac_management_function
;
acm
->
ctrlsize
=
ctrlsize
;
acm
->
readsize
=
readsize
;
acm
->
bh
.
func
=
acm_rx_tasklet
;
acm
->
bh
.
func
=
acm_rx_tasklet
;
acm
->
bh
.
data
=
(
unsigned
long
)
acm
;
acm
->
bh
.
data
=
(
unsigned
long
)
acm
;
INIT_WORK
(
&
acm
->
work
,
acm_softint
,
acm
);
INIT_WORK
(
&
acm
->
work
,
acm_softint
,
acm
);
spin_lock_init
(
&
acm
->
throttle_lock
);
acm
->
ready_for_write
=
1
;
acm
->
ready_for_write
=
1
;
buf
=
usb_buffer_alloc
(
usb_dev
,
ctrlsize
,
GFP_KERNEL
,
&
acm
->
ctrl_dma
);
if
(
!
buf
)
{
dev_dbg
(
&
intf
->
dev
,
"out of memory (ctrl buffer alloc)
\n
"
);
goto
alloc_fail2
;
}
acm
->
ctrl_buffer
=
buf
;
if
(
!
(
buf
=
kmalloc
(
ctrlsize
+
readsize
+
acm
->
writesize
,
GFP_KERNEL
)))
{
buf
=
usb_buffer_alloc
(
usb_dev
,
readsize
,
GFP_KERNEL
,
&
acm
->
read_dma
);
dev_dbg
(
&
intf
->
dev
,
"out of memory (buf kmalloc)
\n
"
);
if
(
!
buf
)
{
kfree
(
acm
);
dev_dbg
(
&
intf
->
dev
,
"out of memory (read buffer alloc)
\n
"
);
return
-
ENOMEM
;
goto
alloc_fail3
;
}
}
acm
->
read_buffer
=
buf
;
buf
=
usb_buffer_alloc
(
usb_dev
,
acm
->
writesize
,
GFP_KERNEL
,
&
acm
->
write_dma
);
if
(
!
buf
)
{
dev_dbg
(
&
intf
->
dev
,
"out of memory (write buffer alloc)
\n
"
);
goto
alloc_fail4
;
}
acm
->
write_buffer
=
buf
;
acm
->
ctrlurb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
acm
->
ctrlurb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
acm
->
ctrlurb
)
{
if
(
!
acm
->
ctrlurb
)
{
dev_dbg
(
&
intf
->
dev
,
"out of memory (ctrlurb kmalloc)
\n
"
);
dev_dbg
(
&
intf
->
dev
,
"out of memory (ctrlurb kmalloc)
\n
"
);
kfree
(
acm
);
goto
alloc_fail5
;
kfree
(
buf
);
return
-
ENOMEM
;
}
}
acm
->
readurb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
acm
->
readurb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
acm
->
readurb
)
{
if
(
!
acm
->
readurb
)
{
dev_dbg
(
&
intf
->
dev
,
"out of memory (readurb kmalloc)
\n
"
);
dev_dbg
(
&
intf
->
dev
,
"out of memory (readurb kmalloc)
\n
"
);
usb_free_urb
(
acm
->
ctrlurb
);
goto
alloc_fail6
;
kfree
(
acm
);
kfree
(
buf
);
return
-
ENOMEM
;
}
}
acm
->
writeurb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
acm
->
writeurb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
acm
->
writeurb
)
{
if
(
!
acm
->
writeurb
)
{
dev_dbg
(
&
intf
->
dev
,
"out of memory (writeurb kmalloc)
\n
"
);
dev_dbg
(
&
intf
->
dev
,
"out of memory (writeurb kmalloc)
\n
"
);
usb_free_urb
(
acm
->
readurb
);
goto
alloc_fail7
;
usb_free_urb
(
acm
->
ctrlurb
);
kfree
(
acm
);
kfree
(
buf
);
return
-
ENOMEM
;
}
}
usb_fill_int_urb
(
acm
->
ctrlurb
,
usb_dev
,
usb_rcvintpipe
(
usb_dev
,
epctrl
->
bEndpointAddress
),
usb_fill_int_urb
(
acm
->
ctrlurb
,
usb_dev
,
usb_rcvintpipe
(
usb_dev
,
epctrl
->
bEndpointAddress
),
buf
,
ctrlsize
,
acm_ctrl_irq
,
acm
,
epctrl
->
bInterval
);
acm
->
ctrl_buffer
,
ctrlsize
,
acm_ctrl_irq
,
acm
,
epctrl
->
bInterval
);
acm
->
ctrlurb
->
transfer_flags
|=
URB_NO_TRANSFER_DMA_MAP
;
acm
->
ctrlurb
->
transfer_dma
=
acm
->
ctrl_dma
;
usb_fill_bulk_urb
(
acm
->
readurb
,
usb_dev
,
usb_rcvbulkpipe
(
usb_dev
,
epread
->
bEndpointAddress
),
usb_fill_bulk_urb
(
acm
->
readurb
,
usb_dev
,
usb_rcvbulkpipe
(
usb_dev
,
epread
->
bEndpointAddress
),
buf
+=
ctrlsize
,
readsize
,
acm_read_bulk
,
acm
);
acm
->
read_buffer
,
readsize
,
acm_read_bulk
,
acm
);
acm
->
readurb
->
transfer_flags
|=
URB_NO_FSBR
;
acm
->
readurb
->
transfer_flags
|=
URB_NO_FSBR
|
URB_NO_TRANSFER_DMA_MAP
;
acm
->
readurb
->
transfer_dma
=
acm
->
read_dma
;
usb_fill_bulk_urb
(
acm
->
writeurb
,
usb_dev
,
usb_sndbulkpipe
(
usb_dev
,
epwrite
->
bEndpointAddress
),
usb_fill_bulk_urb
(
acm
->
writeurb
,
usb_dev
,
usb_sndbulkpipe
(
usb_dev
,
epwrite
->
bEndpointAddress
),
buf
+=
readsize
,
acm
->
writesize
,
acm_write_bulk
,
acm
);
acm
->
write_buffer
,
acm
->
writesize
,
acm_write_bulk
,
acm
);
acm
->
writeurb
->
transfer_flags
|=
URB_NO_FSBR
;
acm
->
writeurb
->
transfer_flags
|=
URB_NO_FSBR
|
URB_NO_TRANSFER_DMA_MAP
;
acm
->
writeurb
->
transfer_dma
=
acm
->
write_dma
;
dev_info
(
&
intf
->
dev
,
"ttyACM%d: USB ACM device
\n
"
,
minor
);
dev_info
(
&
intf
->
dev
,
"ttyACM%d: USB ACM device
\n
"
,
minor
);
...
@@ -673,17 +730,34 @@ static int acm_probe (struct usb_interface *intf,
...
@@ -673,17 +730,34 @@ static int acm_probe (struct usb_interface *intf,
acm_table
[
minor
]
=
acm
;
acm_table
[
minor
]
=
acm
;
usb_set_intfdata
(
intf
,
acm
);
usb_set_intfdata
(
intf
,
acm
);
return
0
;
return
0
;
alloc_fail7:
usb_free_urb
(
acm
->
readurb
);
alloc_fail6:
usb_free_urb
(
acm
->
ctrlurb
);
alloc_fail5:
usb_buffer_free
(
usb_dev
,
acm
->
writesize
,
acm
->
write_buffer
,
acm
->
write_dma
);
alloc_fail4:
usb_buffer_free
(
usb_dev
,
readsize
,
acm
->
read_buffer
,
acm
->
read_dma
);
alloc_fail3:
usb_buffer_free
(
usb_dev
,
ctrlsize
,
acm
->
ctrl_buffer
,
acm
->
ctrl_dma
);
alloc_fail2:
kfree
(
acm
);
alloc_fail:
return
-
ENOMEM
;
}
}
static
void
acm_disconnect
(
struct
usb_interface
*
intf
)
static
void
acm_disconnect
(
struct
usb_interface
*
intf
)
{
{
struct
acm
*
acm
=
usb_get_intfdata
(
intf
);
struct
acm
*
acm
=
usb_get_intfdata
(
intf
);
struct
usb_device
*
usb_dev
=
interface_to_usbdev
(
intf
);
if
(
!
acm
||
!
acm
->
dev
)
{
if
(
!
acm
||
!
acm
->
dev
)
{
dbg
(
"disconnect on nonexisting interface"
);
dbg
(
"disconnect on nonexisting interface"
);
return
;
return
;
}
}
down
(
&
open_sem
);
acm
->
dev
=
NULL
;
acm
->
dev
=
NULL
;
usb_set_intfdata
(
intf
,
NULL
);
usb_set_intfdata
(
intf
,
NULL
);
...
@@ -693,7 +767,9 @@ static void acm_disconnect(struct usb_interface *intf)
...
@@ -693,7 +767,9 @@ static void acm_disconnect(struct usb_interface *intf)
flush_scheduled_work
();
/* wait for acm_softint */
flush_scheduled_work
();
/* wait for acm_softint */
kfree
(
acm
->
ctrlurb
->
transfer_buffer
);
usb_buffer_free
(
usb_dev
,
acm
->
writesize
,
acm
->
write_buffer
,
acm
->
write_dma
);
usb_buffer_free
(
usb_dev
,
acm
->
readsize
,
acm
->
read_buffer
,
acm
->
read_dma
);
usb_buffer_free
(
usb_dev
,
acm
->
ctrlsize
,
acm
->
ctrl_buffer
,
acm
->
ctrl_dma
);
usb_driver_release_interface
(
&
acm_driver
,
acm
->
data
);
usb_driver_release_interface
(
&
acm_driver
,
acm
->
data
);
...
@@ -704,9 +780,12 @@ static void acm_disconnect(struct usb_interface *intf)
...
@@ -704,9 +780,12 @@ static void acm_disconnect(struct usb_interface *intf)
usb_free_urb
(
acm
->
readurb
);
usb_free_urb
(
acm
->
readurb
);
usb_free_urb
(
acm
->
writeurb
);
usb_free_urb
(
acm
->
writeurb
);
kfree
(
acm
);
kfree
(
acm
);
up
(
&
open_sem
);
return
;
return
;
}
}
up
(
&
open_sem
);
if
(
acm
->
tty
)
if
(
acm
->
tty
)
tty_hangup
(
acm
->
tty
);
tty_hangup
(
acm
->
tty
);
}
}
...
...
drivers/usb/class/cdc-acm.h
View file @
097032ac
...
@@ -86,17 +86,23 @@ struct acm {
...
@@ -86,17 +86,23 @@ struct acm {
struct
usb_interface
*
data
;
/* data interface */
struct
usb_interface
*
data
;
/* data interface */
struct
tty_struct
*
tty
;
/* the corresponding tty */
struct
tty_struct
*
tty
;
/* the corresponding tty */
struct
urb
*
ctrlurb
,
*
readurb
,
*
writeurb
;
/* urbs */
struct
urb
*
ctrlurb
,
*
readurb
,
*
writeurb
;
/* urbs */
u8
*
ctrl_buffer
,
*
read_buffer
,
*
write_buffer
;
/* buffers of urbs */
dma_addr_t
ctrl_dma
,
read_dma
,
write_dma
;
/* dma handles of buffers */
struct
acm_line
line
;
/* line coding (bits, stop, parity) */
struct
acm_line
line
;
/* line coding (bits, stop, parity) */
struct
work_struct
work
;
/* work queue entry for line discipline waking up */
struct
work_struct
work
;
/* work queue entry for line discipline waking up */
struct
tasklet_struct
bh
;
/* rx processing */
struct
tasklet_struct
bh
;
/* rx processing */
spinlock_t
throttle_lock
;
/* synchronize throtteling and read callback */
unsigned
int
ctrlin
;
/* input control lines (DCD, DSR, RI, break, overruns) */
unsigned
int
ctrlin
;
/* input control lines (DCD, DSR, RI, break, overruns) */
unsigned
int
ctrlout
;
/* output control lines (DTR, RTS) */
unsigned
int
ctrlout
;
/* output control lines (DTR, RTS) */
unsigned
int
writesize
;
/* max packet size for the output bulk endpoint */
unsigned
int
writesize
;
/* max packet size for the output bulk endpoint */
unsigned
int
readsize
,
ctrlsize
;
/* buffer sizes for freeing */
unsigned
int
used
;
/* someone has this acm's device open */
unsigned
int
used
;
/* someone has this acm's device open */
unsigned
int
minor
;
/* acm minor number */
unsigned
int
minor
;
/* acm minor number */
unsigned
char
throttle
;
/* throttled by tty layer */
unsigned
char
throttle
;
/* throttled by tty layer */
unsigned
char
clocal
;
/* termios CLOCAL */
unsigned
char
clocal
;
/* termios CLOCAL */
unsigned
char
ready_for_write
;
/* write urb can be used */
unsigned
char
ready_for_write
;
/* write urb can be used */
unsigned
char
resubmit_to_unthrottle
;
/* throtteling has disabled the read urb */
unsigned
int
ctrl_caps
;
/* control capabilities from the class specific header */
};
};
/* "Union Functional Descriptor" from CDC spec 5.2.3.X */
/* "Union Functional Descriptor" from CDC spec 5.2.3.X */
...
@@ -110,6 +116,12 @@ struct union_desc {
...
@@ -110,6 +116,12 @@ struct union_desc {
/* ... and there could be other slave interfaces */
/* ... and there could be other slave interfaces */
}
__attribute__
((
packed
));
}
__attribute__
((
packed
));
#define CDC_UNION_TYPE 0x06
/* class specific descriptor types */
#define CDC_CALL_MANAGEMENT_TYPE 0x01
#define CDC_AC_MANAGEMENT_TYPE 0x02
#define CDC_UNION_TYPE 0x06
#define CDC_COUNTRY_TYPE 0x07
#define CDC_DATA_INTERFACE_TYPE 0x0a
#define CDC_DATA_INTERFACE_TYPE 0x0a
drivers/usb/core/hub.c
View file @
097032ac
...
@@ -1034,7 +1034,7 @@ static inline void show_string(struct usb_device *udev, char *id, int index)
...
@@ -1034,7 +1034,7 @@ static inline void show_string(struct usb_device *udev, char *id, int index)
{}
{}
#endif
#endif
/*
/*
*
* usb_new_device - perform initial device setup (usbcore-internal)
* usb_new_device - perform initial device setup (usbcore-internal)
* @udev: newly addressed device (in ADDRESS state)
* @udev: newly addressed device (in ADDRESS state)
*
*
...
@@ -1333,13 +1333,14 @@ static int hub_set_address(struct usb_device *udev)
...
@@ -1333,13 +1333,14 @@ static int hub_set_address(struct usb_device *udev)
return
retval
;
return
retval
;
}
}
/* reset device, (re)assign address, get device descriptor.
/* Reset device, (re)assign address, get device descriptor.
* device connection is stable, no more debouncing needed.
* Device connection must be stable, no more debouncing needed.
* returns device in USB_STATE_ADDRESS, except on error.
* Returns device in USB_STATE_ADDRESS, except on error.
* on error return, device is no longer usable (ref dropped).
*
*
* caller owns dev->serialize for the device, guarding against
* If this is called for an already-existing device (as part of
* config changes and disconnect processing.
* usb_reset_device), the caller must own the device lock. For a
* newly detected device that is not accessible through any global
* pointers, it's not necessary to lock the device.
*/
*/
static
int
static
int
hub_port_init
(
struct
usb_device
*
hdev
,
struct
usb_device
*
udev
,
int
port
)
hub_port_init
(
struct
usb_device
*
hdev
,
struct
usb_device
*
udev
,
int
port
)
...
@@ -1571,6 +1572,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
...
@@ -1571,6 +1572,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
/* Disconnect any existing devices under this port */
/* Disconnect any existing devices under this port */
if
(
hdev
->
children
[
port
])
if
(
hdev
->
children
[
port
])
usb_disconnect
(
&
hdev
->
children
[
port
]);
usb_disconnect
(
&
hdev
->
children
[
port
]);
clear_bit
(
port
,
hub
->
change_bits
);
if
(
portchange
&
USB_PORT_STAT_C_CONNECTION
)
{
if
(
portchange
&
USB_PORT_STAT_C_CONNECTION
)
{
status
=
hub_port_debounce
(
hdev
,
port
);
status
=
hub_port_debounce
(
hdev
,
port
);
...
@@ -1785,12 +1787,15 @@ static void hub_events(void)
...
@@ -1785,12 +1787,15 @@ static void hub_events(void)
/* deal with port status changes */
/* deal with port status changes */
for
(
i
=
0
;
i
<
hub
->
descriptor
->
bNbrPorts
;
i
++
)
{
for
(
i
=
0
;
i
<
hub
->
descriptor
->
bNbrPorts
;
i
++
)
{
if
(
!
test_and_clear_bit
(
i
+
1
,
hub
->
event_bits
))
connect_change
=
test_bit
(
i
,
hub
->
change_bits
);
if
(
!
test_and_clear_bit
(
i
+
1
,
hub
->
event_bits
)
&&
!
connect_change
)
continue
;
continue
;
ret
=
hub_port_status
(
hdev
,
i
,
&
portstatus
,
&
portchange
);
ret
=
hub_port_status
(
hdev
,
i
,
&
portstatus
,
&
portchange
);
if
(
ret
<
0
)
if
(
ret
<
0
)
continue
;
continue
;
connect_change
=
0
;
if
(
portchange
&
USB_PORT_STAT_C_CONNECTION
)
{
if
(
portchange
&
USB_PORT_STAT_C_CONNECTION
)
{
clear_port_feature
(
hdev
,
clear_port_feature
(
hdev
,
...
@@ -1819,7 +1824,7 @@ static void hub_events(void)
...
@@ -1819,7 +1824,7 @@ static void hub_events(void)
dev_err
(
hub_dev
,
dev_err
(
hub_dev
,
"port %i "
"port %i "
"disabled by hub (EMI?), "
"disabled by hub (EMI?), "
"re-enabling..."
,
"re-enabling...
\n
"
,
i
+
1
);
i
+
1
);
connect_change
=
1
;
connect_change
=
1
;
}
}
...
@@ -1996,23 +2001,34 @@ static int config_descriptors_changed(struct usb_device *udev)
...
@@ -1996,23 +2001,34 @@ static int config_descriptors_changed(struct usb_device *udev)
!=
0
)
{
!=
0
)
{
dev_dbg
(
&
udev
->
dev
,
"config index %d changed (#%d)
\n
"
,
dev_dbg
(
&
udev
->
dev
,
"config index %d changed (#%d)
\n
"
,
index
,
buf
->
bConfigurationValue
);
index
,
buf
->
bConfigurationValue
);
/* FIXME enable this when we can re-enumerate after reset;
break
;
* until then DFU-ish drivers need this and other workarounds
*/
// break;
}
}
}
}
kfree
(
buf
);
kfree
(
buf
);
return
index
!=
udev
->
descriptor
.
bNumConfigurations
;
return
index
!=
udev
->
descriptor
.
bNumConfigurations
;
}
}
/*
/**
* usb_reset_devce - perform a USB port reset to reinitialize a device
* @udev: device to reset (not in SUSPENDED or NOTATTACHED state)
*
* WARNING - don't reset any device unless drivers for all of its
* WARNING - don't reset any device unless drivers for all of its
* interfaces are expecting that reset! Maybe some driver->reset()
* interfaces are expecting that reset! Maybe some driver->reset()
* method should eventually help ensure sufficient cooperation.
* method should eventually help ensure sufficient cooperation.
*
*
* This is the same as usb_reset_device() except that the caller
* Do a port reset, reassign the device's address, and establish its
* already holds dev->serialize. For example, it's safe to use
* former operating configuration. If the reset fails, or the device's
* descriptors change from their values before the reset, or the original
* configuration and altsettings cannot be restored, a flag will be set
* telling khubd to pretend the device has been disconnected and then
* re-connected. All drivers will be unbound, and the device will be
* re-enumerated and probed all over again.
*
* Returns 0 if the reset succeeded, -ENODEV if the device has been
* flagged for logical disconnection, or some other negative error code
* if the reset wasn't even attempted.
*
* The caller must own the device lock. For example, it's safe to use
* this from a driver probe() routine after downloading new firmware.
* this from a driver probe() routine after downloading new firmware.
*/
*/
int
__usb_reset_device
(
struct
usb_device
*
udev
)
int
__usb_reset_device
(
struct
usb_device
*
udev
)
...
@@ -2020,13 +2036,23 @@ int __usb_reset_device(struct usb_device *udev)
...
@@ -2020,13 +2036,23 @@ int __usb_reset_device(struct usb_device *udev)
struct
usb_device
*
parent
=
udev
->
parent
;
struct
usb_device
*
parent
=
udev
->
parent
;
struct
usb_device_descriptor
descriptor
=
udev
->
descriptor
;
struct
usb_device_descriptor
descriptor
=
udev
->
descriptor
;
int
i
,
ret
,
port
=
-
1
;
int
i
,
ret
,
port
=
-
1
;
struct
usb_hub
*
hub
;
if
(
udev
->
state
==
USB_STATE_NOTATTACHED
||
udev
->
state
==
USB_STATE_SUSPENDED
)
{
dev_dbg
(
&
udev
->
dev
,
"device reset not allowed in state %d
\n
"
,
udev
->
state
);
return
-
EINVAL
;
}
/* FIXME: This should be legal for regular hubs. Root hubs may
* have special requirements. */
if
(
udev
->
maxchild
)
{
if
(
udev
->
maxchild
)
{
/* this requires hub- or hcd-specific logic;
/* this requires hub- or hcd-specific logic;
* see hub_reset() and OHCI hc_restart()
* see hub_reset() and OHCI hc_restart()
*/
*/
dev_dbg
(
&
udev
->
dev
,
"%s for hub!
\n
"
,
__FUNCTION__
);
dev_dbg
(
&
udev
->
dev
,
"%s for hub!
\n
"
,
__FUNCTION__
);
return
-
EI
NVAL
;
return
-
EI
SDIR
;
}
}
for
(
i
=
0
;
i
<
parent
->
maxchild
;
i
++
)
for
(
i
=
0
;
i
<
parent
->
maxchild
;
i
++
)
...
@@ -2035,8 +2061,11 @@ int __usb_reset_device(struct usb_device *udev)
...
@@ -2035,8 +2061,11 @@ int __usb_reset_device(struct usb_device *udev)
break
;
break
;
}
}
if
(
port
<
0
)
if
(
port
<
0
)
{
/* If this ever happens, it's very bad */
dev_err
(
&
udev
->
dev
,
"Can't locate device's port!
\n
"
);
return
-
ENOENT
;
return
-
ENOENT
;
}
ret
=
hub_port_init
(
parent
,
udev
,
port
);
ret
=
hub_port_init
(
parent
,
udev
,
port
);
if
(
ret
<
0
)
if
(
ret
<
0
)
...
@@ -2088,8 +2117,18 @@ int __usb_reset_device(struct usb_device *udev)
...
@@ -2088,8 +2117,18 @@ int __usb_reset_device(struct usb_device *udev)
return
0
;
return
0
;
re_enumerate:
re_enumerate:
/* FIXME make some task re-enumerate; don't just mark unusable */
hub_port_disable
(
parent
,
port
);
hub_port_disable
(
parent
,
port
);
hub
=
usb_get_intfdata
(
parent
->
actconfig
->
interface
[
0
]);
set_bit
(
port
,
hub
->
change_bits
);
spin_lock_irq
(
&
hub_event_lock
);
if
(
list_empty
(
&
hub
->
event_list
))
{
list_add_tail
(
&
hub
->
event_list
,
&
hub_event_list
);
wake_up
(
&
khubd_wait
);
}
spin_unlock_irq
(
&
hub_event_lock
);
return
-
ENODEV
;
return
-
ENODEV
;
}
}
EXPORT_SYMBOL
(
__usb_reset_device
);
EXPORT_SYMBOL
(
__usb_reset_device
);
...
...
drivers/usb/core/hub.h
View file @
097032ac
...
@@ -204,6 +204,8 @@ struct usb_hub {
...
@@ -204,6 +204,8 @@ struct usb_hub {
struct
list_head
event_list
;
/* hubs w/data or errs ready */
struct
list_head
event_list
;
/* hubs w/data or errs ready */
unsigned
long
event_bits
[
1
];
/* status change bitmask */
unsigned
long
event_bits
[
1
];
/* status change bitmask */
unsigned
long
change_bits
[
1
];
/* ports with logical connect
status change */
#if USB_MAXCHILDREN > 31
/* 8*sizeof(unsigned long) - 1 */
#if USB_MAXCHILDREN > 31
/* 8*sizeof(unsigned long) - 1 */
#error event_bits[] is too short!
#error event_bits[] is too short!
#endif
#endif
...
...
drivers/usb/gadget/dummy_hcd.c
View file @
097032ac
...
@@ -146,8 +146,6 @@ struct dummy {
...
@@ -146,8 +146,6 @@ struct dummy {
u8
fifo_buf
[
FIFO_SIZE
];
u8
fifo_buf
[
FIFO_SIZE
];
u16
devstatus
;
u16
devstatus
;
struct
hcd_dev
*
hdev
;
/*
/*
* MASTER/HOST side support
* MASTER/HOST side support
*/
*/
...
@@ -159,6 +157,8 @@ struct dummy {
...
@@ -159,6 +157,8 @@ struct dummy {
struct
completion
released
;
struct
completion
released
;
unsigned
resuming
:
1
;
unsigned
resuming
:
1
;
unsigned
long
re_timeout
;
unsigned
long
re_timeout
;
struct
usb_device
*
udev
;
};
};
static
struct
dummy
*
the_controller
;
static
struct
dummy
*
the_controller
;
...
@@ -739,11 +739,9 @@ stop_activity (struct dummy *dum, struct usb_gadget_driver *driver)
...
@@ -739,11 +739,9 @@ stop_activity (struct dummy *dum, struct usb_gadget_driver *driver)
struct
dummy_ep
*
ep
;
struct
dummy_ep
*
ep
;
/* prevent any more requests */
/* prevent any more requests */
dum
->
hdev
=
0
;
dum
->
address
=
0
;
dum
->
address
=
0
;
/* this might not succeed ... */
/* The timer is left running so that outstanding URBs can fail */
del_timer
(
&
dum
->
timer
);
/* nuke any pending requests first, so driver i/o is quiesced */
/* nuke any pending requests first, so driver i/o is quiesced */
list_for_each_entry
(
ep
,
&
dum
->
gadget
.
ep_list
,
ep
.
ep_list
)
list_for_each_entry
(
ep
,
&
dum
->
gadget
.
ep_list
,
ep
.
ep_list
)
...
@@ -784,7 +782,6 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
...
@@ -784,7 +782,6 @@ usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
driver_unregister
(
&
driver
->
driver
);
driver_unregister
(
&
driver
->
driver
);
del_timer_sync
(
&
dum
->
timer
);
return
0
;
return
0
;
}
}
EXPORT_SYMBOL
(
usb_gadget_unregister_driver
);
EXPORT_SYMBOL
(
usb_gadget_unregister_driver
);
...
@@ -825,7 +822,12 @@ static int dummy_urb_enqueue (
...
@@ -825,7 +822,12 @@ static int dummy_urb_enqueue (
dum
=
container_of
(
hcd
,
struct
dummy
,
hcd
);
dum
=
container_of
(
hcd
,
struct
dummy
,
hcd
);
spin_lock_irqsave
(
&
dum
->
lock
,
flags
);
spin_lock_irqsave
(
&
dum
->
lock
,
flags
);
dum
->
hdev
=
urb
->
dev
->
hcpriv
;
if
(
!
dum
->
udev
)
{
dum
->
udev
=
urb
->
dev
;
usb_get_dev
(
dum
->
udev
);
}
else
if
(
unlikely
(
dum
->
udev
!=
urb
->
dev
))
dev_err
(
hardware
,
"usb_device address has changed!
\n
"
);
urb
->
hcpriv
=
dum
;
urb
->
hcpriv
=
dum
;
if
(
usb_pipetype
(
urb
->
pipe
)
==
PIPE_CONTROL
)
if
(
usb_pipetype
(
urb
->
pipe
)
==
PIPE_CONTROL
)
urb
->
error_count
=
1
;
/* mark as a new urb */
urb
->
error_count
=
1
;
/* mark as a new urb */
...
@@ -1032,17 +1034,12 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
...
@@ -1032,17 +1034,12 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
static
void
dummy_timer
(
unsigned
long
_dum
)
static
void
dummy_timer
(
unsigned
long
_dum
)
{
{
struct
dummy
*
dum
=
(
struct
dummy
*
)
_dum
;
struct
dummy
*
dum
=
(
struct
dummy
*
)
_dum
;
struct
hcd_dev
*
hdev
=
dum
->
hdev
;
struct
hcd_dev
*
hdev
;
struct
list_head
*
entry
,
*
tmp
;
struct
list_head
*
entry
,
*
tmp
;
unsigned
long
flags
;
unsigned
long
flags
;
int
limit
,
total
;
int
limit
,
total
;
int
i
;
int
i
;
if
(
!
hdev
)
{
dev_err
(
hardware
,
"timer fired with device gone?
\n
"
);
return
;
}
/* simplistic model for one frame's bandwidth */
/* simplistic model for one frame's bandwidth */
switch
(
dum
->
gadget
.
speed
)
{
switch
(
dum
->
gadget
.
speed
)
{
case
USB_SPEED_LOW
:
case
USB_SPEED_LOW
:
...
@@ -1063,6 +1060,14 @@ static void dummy_timer (unsigned long _dum)
...
@@ -1063,6 +1060,14 @@ static void dummy_timer (unsigned long _dum)
/* look at each urb queued by the host side driver */
/* look at each urb queued by the host side driver */
spin_lock_irqsave
(
&
dum
->
lock
,
flags
);
spin_lock_irqsave
(
&
dum
->
lock
,
flags
);
if
(
!
dum
->
udev
)
{
dev_err
(
hardware
,
"timer fired with no URBs pending?
\n
"
);
spin_unlock_irqrestore
(
&
dum
->
lock
,
flags
);
return
;
}
hdev
=
dum
->
udev
->
hcpriv
;
for
(
i
=
0
;
i
<
DUMMY_ENDPOINTS
;
i
++
)
{
for
(
i
=
0
;
i
<
DUMMY_ENDPOINTS
;
i
++
)
{
if
(
!
ep_name
[
i
])
if
(
!
ep_name
[
i
])
break
;
break
;
...
@@ -1334,7 +1339,11 @@ static void dummy_timer (unsigned long _dum)
...
@@ -1334,7 +1339,11 @@ static void dummy_timer (unsigned long _dum)
/* want a 1 msec delay here */
/* want a 1 msec delay here */
if
(
!
list_empty
(
&
hdev
->
urb_list
))
if
(
!
list_empty
(
&
hdev
->
urb_list
))
mod_timer
(
&
dum
->
timer
,
jiffies
+
1
);
mod_timer
(
&
dum
->
timer
,
jiffies
+
msecs_to_jiffies
(
1
));
else
{
usb_put_dev
(
dum
->
udev
);
dum
->
udev
=
NULL
;
}
spin_unlock_irqrestore
(
&
dum
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
dum
->
lock
,
flags
);
}
}
...
@@ -1571,10 +1580,12 @@ show_urbs (struct device *dev, char *buf)
...
@@ -1571,10 +1580,12 @@ show_urbs (struct device *dev, char *buf)
struct
urb
*
urb
;
struct
urb
*
urb
;
size_t
size
=
0
;
size_t
size
=
0
;
unsigned
long
flags
;
unsigned
long
flags
;
struct
hcd_dev
*
hdev
;
spin_lock_irqsave
(
&
dum
->
lock
,
flags
);
spin_lock_irqsave
(
&
dum
->
lock
,
flags
);
if
(
dum
->
hdev
)
{
if
(
dum
->
udev
)
{
list_for_each_entry
(
urb
,
&
dum
->
hdev
->
urb_list
,
urb_list
)
{
hdev
=
dum
->
udev
->
hcpriv
;
list_for_each_entry
(
urb
,
&
hdev
->
urb_list
,
urb_list
)
{
size_t
temp
;
size_t
temp
;
temp
=
show_urb
(
buf
,
PAGE_SIZE
-
size
,
urb
);
temp
=
show_urb
(
buf
,
PAGE_SIZE
-
size
,
urb
);
...
...
drivers/usb/gadget/ether.c
View file @
097032ac
...
@@ -234,7 +234,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
...
@@ -234,7 +234,7 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
/* For CDC-incapable hardware, choose the simple cdc subset.
/* For CDC-incapable hardware, choose the simple cdc subset.
* Anything that talks bulk (without notable bugs) can do this.
* Anything that talks bulk (without notable bugs) can do this.
*/
*/
#ifdef CONFIG_USB_GADGET_PXA
#ifdef CONFIG_USB_GADGET_PXA
2XX
#define DEV_CONFIG_SUBSET
#define DEV_CONFIG_SUBSET
#endif
#endif
...
@@ -1597,6 +1597,8 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
...
@@ -1597,6 +1597,8 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
/* respond with data transfer before status phase? */
/* respond with data transfer before status phase? */
if
(
value
>=
0
)
{
if
(
value
>=
0
)
{
req
->
length
=
value
;
req
->
length
=
value
;
req
->
zero
=
value
<
ctrl
->
wLength
&&
(
value
%
gadget
->
ep0
->
maxpacket
)
==
0
;
value
=
usb_ep_queue
(
gadget
->
ep0
,
req
,
GFP_ATOMIC
);
value
=
usb_ep_queue
(
gadget
->
ep0
,
req
,
GFP_ATOMIC
);
if
(
value
<
0
)
{
if
(
value
<
0
)
{
DEBUG
(
dev
,
"ep_queue --> %d
\n
"
,
value
);
DEBUG
(
dev
,
"ep_queue --> %d
\n
"
,
value
);
...
@@ -2373,6 +2375,7 @@ eth_bind (struct usb_gadget *gadget)
...
@@ -2373,6 +2375,7 @@ eth_bind (struct usb_gadget *gadget)
EP_OUT_NAME
=
ep
->
name
;
EP_OUT_NAME
=
ep
->
name
;
ep
->
driver_data
=
ep
;
/* claim */
ep
->
driver_data
=
ep
;
/* claim */
#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
/* CDC Ethernet control interface doesn't require a status endpoint.
/* CDC Ethernet control interface doesn't require a status endpoint.
* Since some hosts expect one, try to allocate one anyway.
* Since some hosts expect one, try to allocate one anyway.
*/
*/
...
@@ -2386,13 +2389,12 @@ eth_bind (struct usb_gadget *gadget)
...
@@ -2386,13 +2389,12 @@ eth_bind (struct usb_gadget *gadget)
"can't run RNDIS on %s
\n
"
,
"can't run RNDIS on %s
\n
"
,
gadget
->
name
);
gadget
->
name
);
return
-
ENODEV
;
return
-
ENODEV
;
#ifdef DEV_CONFIG_CDC
}
else
if
(
cdc
)
{
}
else
if
(
cdc
)
{
control_intf
.
bNumEndpoints
=
0
;
control_intf
.
bNumEndpoints
=
0
;
/* FIXME remove endpoint from descriptor list */
/* FIXME remove endpoint from descriptor list */
#endif
}
}
}
}
#endif
/* one config: cdc, else minimal subset */
/* one config: cdc, else minimal subset */
if
(
!
cdc
)
{
if
(
!
cdc
)
{
...
@@ -2446,7 +2448,7 @@ eth_bind (struct usb_gadget *gadget)
...
@@ -2446,7 +2448,7 @@ eth_bind (struct usb_gadget *gadget)
/* Module params for these addresses should come from ID proms.
/* Module params for these addresses should come from ID proms.
* The host side address is used with CDC and RNDIS, and commonly
* The host side address is used with CDC and RNDIS, and commonly
* end
ups
in a persistent config database.
* end
s up
in a persistent config database.
*/
*/
get_ether_addr
(
dev_addr
,
net
->
dev_addr
);
get_ether_addr
(
dev_addr
,
net
->
dev_addr
);
if
(
cdc
||
rndis
)
{
if
(
cdc
||
rndis
)
{
...
...
drivers/usb/gadget/file_storage.c
View file @
097032ac
...
@@ -1465,6 +1465,8 @@ static int fsg_setup(struct usb_gadget *gadget,
...
@@ -1465,6 +1465,8 @@ static int fsg_setup(struct usb_gadget *gadget,
/* Respond with data/status or defer until later? */
/* Respond with data/status or defer until later? */
if
(
rc
>=
0
&&
rc
!=
DELAYED_STATUS
)
{
if
(
rc
>=
0
&&
rc
!=
DELAYED_STATUS
)
{
fsg
->
ep0req
->
length
=
rc
;
fsg
->
ep0req
->
length
=
rc
;
fsg
->
ep0req
->
zero
=
rc
<
ctrl
->
wLength
&&
(
rc
%
gadget
->
ep0
->
maxpacket
)
==
0
;
fsg
->
ep0req_name
=
(
ctrl
->
bRequestType
&
USB_DIR_IN
?
fsg
->
ep0req_name
=
(
ctrl
->
bRequestType
&
USB_DIR_IN
?
"ep0-in"
:
"ep0-out"
);
"ep0-in"
:
"ep0-out"
);
rc
=
ep0_queue
(
fsg
);
rc
=
ep0_queue
(
fsg
);
...
...
drivers/usb/gadget/inode.c
View file @
097032ac
...
@@ -20,7 +20,7 @@
...
@@ -20,7 +20,7 @@
*/
*/
#define DEBUG 1
/* data to help fault diagnosis */
// #define DEBUG
/* data to help fault diagnosis */
// #define VERBOSE /* extra debug messages (success too) */
// #define VERBOSE /* extra debug messages (success too) */
#include <linux/init.h>
#include <linux/init.h>
...
@@ -44,7 +44,8 @@
...
@@ -44,7 +44,8 @@
* The gadgetfs API maps each endpoint to a file descriptor so that you
* The gadgetfs API maps each endpoint to a file descriptor so that you
* can use standard synchronous read/write calls for I/O. There's some
* can use standard synchronous read/write calls for I/O. There's some
* O_NONBLOCK and O_ASYNC/FASYNC style i/o support. Example usermode
* O_NONBLOCK and O_ASYNC/FASYNC style i/o support. Example usermode
* drivers show how this works in practice.
* drivers show how this works in practice. You can also use AIO to
* eliminate I/O gaps between requests, to help when streaming data.
*
*
* Key parts that must be USB-specific are protocols defining how the
* Key parts that must be USB-specific are protocols defining how the
* read/write operations relate to the hardware state machines. There
* read/write operations relate to the hardware state machines. There
...
@@ -70,7 +71,7 @@
...
@@ -70,7 +71,7 @@
*/
*/
#define DRIVER_DESC "USB Gadget filesystem"
#define DRIVER_DESC "USB Gadget filesystem"
#define DRIVER_VERSION "
20 Aug
2003"
#define DRIVER_VERSION "
18 Nov
2003"
static
const
char
driver_desc
[]
=
DRIVER_DESC
;
static
const
char
driver_desc
[]
=
DRIVER_DESC
;
static
const
char
shortname
[]
=
"gadgetfs"
;
static
const
char
shortname
[]
=
"gadgetfs"
;
...
@@ -539,6 +540,177 @@ static int ep_ioctl (struct inode *inode, struct file *fd,
...
@@ -539,6 +540,177 @@ static int ep_ioctl (struct inode *inode, struct file *fd,
return
status
;
return
status
;
}
}
/*----------------------------------------------------------------------*/
/* ASYNCHRONOUS ENDPOINT I/O OPERATIONS (bulk/intr/iso) */
struct
kiocb_priv
{
struct
usb_request
*
req
;
struct
ep_data
*
epdata
;
void
*
buf
;
char
__user
*
ubuf
;
unsigned
actual
;
};
static
int
ep_aio_cancel
(
struct
kiocb
*
iocb
,
struct
io_event
*
e
)
{
struct
kiocb_priv
*
priv
=
(
void
*
)
&
iocb
->
private
;
struct
ep_data
*
epdata
;
int
value
;
local_irq_disable
();
epdata
=
priv
->
epdata
;
// spin_lock(&epdata->dev->lock);
kiocbSetCancelled
(
iocb
);
if
(
likely
(
epdata
&&
epdata
->
ep
&&
priv
->
req
))
value
=
usb_ep_dequeue
(
epdata
->
ep
,
priv
->
req
);
else
value
=
-
EINVAL
;
// spin_unlock(&epdata->dev->lock);
local_irq_enable
();
aio_put_req
(
iocb
);
return
value
;
}
static
long
ep_aio_read_retry
(
struct
kiocb
*
iocb
)
{
struct
kiocb_priv
*
priv
=
(
void
*
)
&
iocb
->
private
;
int
status
=
priv
->
actual
;
/* we "retry" to get the right mm context for this: */
status
=
copy_to_user
(
priv
->
ubuf
,
priv
->
buf
,
priv
->
actual
);
if
(
unlikely
(
0
!=
status
))
status
=
-
EFAULT
;
else
status
=
priv
->
actual
;
kfree
(
priv
->
buf
);
aio_put_req
(
iocb
);
return
status
;
}
static
void
ep_aio_complete
(
struct
usb_ep
*
ep
,
struct
usb_request
*
req
)
{
struct
kiocb
*
iocb
=
req
->
context
;
struct
kiocb_priv
*
priv
=
(
void
*
)
&
iocb
->
private
;
struct
ep_data
*
epdata
=
priv
->
epdata
;
/* lock against disconnect (and ideally, cancel) */
spin_lock
(
&
epdata
->
dev
->
lock
);
priv
->
req
=
0
;
priv
->
epdata
=
0
;
if
(
NULL
==
iocb
->
ki_retry
||
unlikely
(
0
==
req
->
actual
)
||
unlikely
(
kiocbIsCancelled
(
iocb
)))
{
kfree
(
req
->
buf
);
/* aio_complete() reports bytes-transferred _and_ faults */
if
(
unlikely
(
kiocbIsCancelled
(
iocb
)))
aio_put_req
(
iocb
);
else
aio_complete
(
iocb
,
req
->
actual
?
req
->
actual
:
req
->
status
,
req
->
status
);
}
else
{
/* retry() won't report both; so we hide some faults */
if
(
unlikely
(
0
!=
req
->
status
))
DBG
(
epdata
->
dev
,
"%s fault %d len %d
\n
"
,
ep
->
name
,
req
->
status
,
req
->
actual
);
priv
->
buf
=
req
->
buf
;
priv
->
actual
=
req
->
actual
;
kick_iocb
(
iocb
);
}
spin_unlock
(
&
epdata
->
dev
->
lock
);
usb_ep_free_request
(
ep
,
req
);
put_ep
(
epdata
);
}
static
ssize_t
ep_aio_rwtail
(
struct
kiocb
*
iocb
,
char
*
buf
,
size_t
len
,
struct
ep_data
*
epdata
)
{
struct
kiocb_priv
*
priv
=
(
void
*
)
&
iocb
->
private
;
struct
usb_request
*
req
;
ssize_t
value
;
value
=
get_ready_ep
(
iocb
->
ki_filp
->
f_flags
,
epdata
);
if
(
unlikely
(
value
<
0
))
{
kfree
(
buf
);
return
value
;
}
iocb
->
ki_cancel
=
ep_aio_cancel
;
get_ep
(
epdata
);
priv
->
epdata
=
epdata
;
priv
->
actual
=
0
;
/* each kiocb is coupled to one usb_request, but we can't
* allocate or submit those if the host disconnected.
*/
spin_lock_irq
(
&
epdata
->
dev
->
lock
);
if
(
likely
(
epdata
->
ep
))
{
req
=
usb_ep_alloc_request
(
epdata
->
ep
,
GFP_ATOMIC
);
if
(
likely
(
req
))
{
priv
->
req
=
req
;
req
->
buf
=
buf
;
req
->
length
=
len
;
req
->
complete
=
ep_aio_complete
;
req
->
context
=
iocb
;
value
=
usb_ep_queue
(
epdata
->
ep
,
req
,
GFP_ATOMIC
);
if
(
unlikely
(
0
!=
value
))
usb_ep_free_request
(
epdata
->
ep
,
req
);
}
else
value
=
-
EAGAIN
;
}
else
value
=
-
ENODEV
;
spin_unlock_irq
(
&
epdata
->
dev
->
lock
);
up
(
&
epdata
->
lock
);
if
(
unlikely
(
value
))
put_ep
(
epdata
);
else
value
=
-
EIOCBQUEUED
;
return
value
;
}
static
ssize_t
ep_aio_read
(
struct
kiocb
*
iocb
,
char
__user
*
ubuf
,
size_t
len
,
loff_t
o
)
{
struct
kiocb_priv
*
priv
=
(
void
*
)
&
iocb
->
private
;
struct
ep_data
*
epdata
=
iocb
->
ki_filp
->
private_data
;
char
*
buf
;
if
(
unlikely
(
epdata
->
desc
.
bEndpointAddress
&
USB_DIR_IN
))
return
-
EINVAL
;
buf
=
kmalloc
(
len
,
GFP_KERNEL
);
if
(
unlikely
(
!
buf
))
return
-
ENOMEM
;
iocb
->
ki_retry
=
ep_aio_read_retry
;
priv
->
ubuf
=
ubuf
;
return
ep_aio_rwtail
(
iocb
,
buf
,
len
,
epdata
);
}
static
ssize_t
ep_aio_write
(
struct
kiocb
*
iocb
,
const
char
__user
*
ubuf
,
size_t
len
,
loff_t
o
)
{
struct
ep_data
*
epdata
=
iocb
->
ki_filp
->
private_data
;
char
*
buf
;
if
(
unlikely
(
!
(
epdata
->
desc
.
bEndpointAddress
&
USB_DIR_IN
)))
return
-
EINVAL
;
buf
=
kmalloc
(
len
,
GFP_KERNEL
);
if
(
unlikely
(
!
buf
))
return
-
ENOMEM
;
if
(
unlikely
(
copy_from_user
(
buf
,
ubuf
,
len
)
!=
0
))
{
kfree
(
buf
);
return
-
EFAULT
;
}
return
ep_aio_rwtail
(
iocb
,
buf
,
len
,
epdata
);
}
/*----------------------------------------------------------------------*/
/* used after endpoint configuration */
/* used after endpoint configuration */
static
struct
file_operations
ep_io_operations
=
{
static
struct
file_operations
ep_io_operations
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
...
@@ -547,8 +719,8 @@ static struct file_operations ep_io_operations = {
...
@@ -547,8 +719,8 @@ static struct file_operations ep_io_operations = {
.
ioctl
=
ep_ioctl
,
.
ioctl
=
ep_ioctl
,
.
release
=
ep_release
,
.
release
=
ep_release
,
//
.aio_read = ep_aio_read,
.
aio_read
=
ep_aio_read
,
//
.aio_write = ep_aio_write,
.
aio_write
=
ep_aio_write
,
};
};
/* ENDPOINT INITIALIZATION
/* ENDPOINT INITIALIZATION
...
@@ -1320,6 +1492,8 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
...
@@ -1320,6 +1492,8 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
/* proceed with data transfer and status phases? */
/* proceed with data transfer and status phases? */
if
(
value
>=
0
&&
dev
->
state
!=
STATE_SETUP
)
{
if
(
value
>=
0
&&
dev
->
state
!=
STATE_SETUP
)
{
req
->
length
=
value
;
req
->
length
=
value
;
req
->
zero
=
value
<
ctrl
->
wLength
&&
(
value
%
gadget
->
ep0
->
maxpacket
)
==
0
;
value
=
usb_ep_queue
(
gadget
->
ep0
,
req
,
GFP_ATOMIC
);
value
=
usb_ep_queue
(
gadget
->
ep0
,
req
,
GFP_ATOMIC
);
if
(
value
<
0
)
{
if
(
value
<
0
)
{
DBG
(
dev
,
"ep_queue --> %d
\n
"
,
value
);
DBG
(
dev
,
"ep_queue --> %d
\n
"
,
value
);
...
...
drivers/usb/gadget/serial.c
View file @
097032ac
...
@@ -1573,6 +1573,8 @@ static int gs_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctr
...
@@ -1573,6 +1573,8 @@ static int gs_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctr
/* respond with data transfer before status phase? */
/* respond with data transfer before status phase? */
if
(
ret
>=
0
)
{
if
(
ret
>=
0
)
{
req
->
length
=
ret
;
req
->
length
=
ret
;
req
->
zero
=
ret
<
ctrl
->
wLength
&&
(
ret
%
gadget
->
ep0
->
maxpacket
)
==
0
;
ret
=
usb_ep_queue
(
gadget
->
ep0
,
req
,
GFP_ATOMIC
);
ret
=
usb_ep_queue
(
gadget
->
ep0
,
req
,
GFP_ATOMIC
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
printk
(
KERN_ERR
printk
(
KERN_ERR
...
...
drivers/usb/gadget/zero.c
View file @
097032ac
...
@@ -1037,6 +1037,8 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
...
@@ -1037,6 +1037,8 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
/* respond with data transfer before status phase? */
/* respond with data transfer before status phase? */
if
(
value
>=
0
)
{
if
(
value
>=
0
)
{
req
->
length
=
value
;
req
->
length
=
value
;
req
->
zero
=
value
<
ctrl
->
wLength
&&
(
value
%
gadget
->
ep0
->
maxpacket
)
==
0
;
value
=
usb_ep_queue
(
gadget
->
ep0
,
req
,
GFP_ATOMIC
);
value
=
usb_ep_queue
(
gadget
->
ep0
,
req
,
GFP_ATOMIC
);
if
(
value
<
0
)
{
if
(
value
<
0
)
{
DBG
(
dev
,
"ep_queue --> %d
\n
"
,
value
);
DBG
(
dev
,
"ep_queue --> %d
\n
"
,
value
);
...
...
drivers/usb/host/ehci-hcd.c
View file @
097032ac
...
@@ -425,7 +425,6 @@ static int ehci_start (struct usb_hcd *hcd)
...
@@ -425,7 +425,6 @@ static int ehci_start (struct usb_hcd *hcd)
ehci_mem_cleanup
(
ehci
);
ehci_mem_cleanup
(
ehci
);
return
retval
;
return
retval
;
}
}
writel
(
INTR_MASK
,
&
ehci
->
regs
->
intr_enable
);
writel
(
ehci
->
periodic_dma
,
&
ehci
->
regs
->
frame_list
);
writel
(
ehci
->
periodic_dma
,
&
ehci
->
regs
->
frame_list
);
#ifdef CONFIG_PCI
#ifdef CONFIG_PCI
...
@@ -531,7 +530,8 @@ static int ehci_start (struct usb_hcd *hcd)
...
@@ -531,7 +530,8 @@ static int ehci_start (struct usb_hcd *hcd)
/*
/*
* Start, enabling full USB 2.0 functionality ... usb 1.1 devices
* Start, enabling full USB 2.0 functionality ... usb 1.1 devices
* are explicitly handed to companion controller(s), so no TT is
* are explicitly handed to companion controller(s), so no TT is
* involved with the root hub.
* involved with the root hub. (Except where one is integrated,
* and there's no companion controller unless maybe for USB OTG.)
*/
*/
ehci
->
reboot_notifier
.
notifier_call
=
ehci_reboot
;
ehci
->
reboot_notifier
.
notifier_call
=
ehci_reboot
;
register_reboot_notifier
(
&
ehci
->
reboot_notifier
);
register_reboot_notifier
(
&
ehci
->
reboot_notifier
);
...
@@ -563,6 +563,8 @@ static int ehci_start (struct usb_hcd *hcd)
...
@@ -563,6 +563,8 @@ static int ehci_start (struct usb_hcd *hcd)
goto
done2
;
goto
done2
;
}
}
writel
(
INTR_MASK
,
&
ehci
->
regs
->
intr_enable
);
/* Turn On Interrupts */
create_debug_files
(
ehci
);
create_debug_files
(
ehci
);
return
0
;
return
0
;
...
@@ -573,6 +575,7 @@ static int ehci_start (struct usb_hcd *hcd)
...
@@ -573,6 +575,7 @@ static int ehci_start (struct usb_hcd *hcd)
static
void
ehci_stop
(
struct
usb_hcd
*
hcd
)
static
void
ehci_stop
(
struct
usb_hcd
*
hcd
)
{
{
struct
ehci_hcd
*
ehci
=
hcd_to_ehci
(
hcd
);
struct
ehci_hcd
*
ehci
=
hcd_to_ehci
(
hcd
);
u8
rh_ports
,
port
;
ehci_dbg
(
ehci
,
"stop
\n
"
);
ehci_dbg
(
ehci
,
"stop
\n
"
);
...
@@ -584,7 +587,16 @@ static void ehci_stop (struct usb_hcd *hcd)
...
@@ -584,7 +587,16 @@ static void ehci_stop (struct usb_hcd *hcd)
return
;
return
;
}
}
del_timer_sync
(
&
ehci
->
watchdog
);
del_timer_sync
(
&
ehci
->
watchdog
);
/* Turn off port power on all root hub ports. */
rh_ports
=
HCS_N_PORTS
(
ehci
->
hcs_params
);
for
(
port
=
1
;
port
<=
rh_ports
;
port
++
)
{
ehci_hub_control
(
hcd
,
ClearPortFeature
,
USB_PORT_FEAT_POWER
,
port
,
NULL
,
0
);
}
ehci_reset
(
ehci
);
ehci_reset
(
ehci
);
writel
(
0
,
&
ehci
->
regs
->
intr_enable
);
/* let companion controllers work when we aren't */
/* let companion controllers work when we aren't */
writel
(
0
,
&
ehci
->
regs
->
configured_flag
);
writel
(
0
,
&
ehci
->
regs
->
configured_flag
);
...
@@ -704,12 +716,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
...
@@ -704,12 +716,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
status
=
readl
(
&
ehci
->
regs
->
status
);
status
=
readl
(
&
ehci
->
regs
->
status
);
/* shared irq */
if
(
status
==
0
)
{
spin_unlock
(
&
ehci
->
lock
);
return
IRQ_NONE
;
}
/* e.g. cardbus physical eject */
/* e.g. cardbus physical eject */
if
(
status
==
~
(
u32
)
0
)
{
if
(
status
==
~
(
u32
)
0
)
{
ehci_dbg
(
ehci
,
"device removed
\n
"
);
ehci_dbg
(
ehci
,
"device removed
\n
"
);
...
@@ -717,8 +723,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
...
@@ -717,8 +723,10 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
}
}
status
&=
INTR_MASK
;
status
&=
INTR_MASK
;
if
(
!
status
)
/* irq sharing? */
if
(
!
status
)
{
/* irq sharing? */
goto
done
;
spin_unlock
(
&
ehci
->
lock
);
return
IRQ_NONE
;
}
/* clear (just) interrupts */
/* clear (just) interrupts */
writel
(
status
,
&
ehci
->
regs
->
status
);
writel
(
status
,
&
ehci
->
regs
->
status
);
...
@@ -789,7 +797,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
...
@@ -789,7 +797,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
if
(
bh
)
if
(
bh
)
ehci_work
(
ehci
,
regs
);
ehci_work
(
ehci
,
regs
);
done:
spin_unlock
(
&
ehci
->
lock
);
spin_unlock
(
&
ehci
->
lock
);
return
IRQ_HANDLED
;
return
IRQ_HANDLED
;
}
}
...
...
drivers/usb/host/uhci-debug.c
View file @
097032ac
...
@@ -248,7 +248,7 @@ static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
...
@@ -248,7 +248,7 @@ static int uhci_show_sc(int port, unsigned short status, char *buf, int len)
static
int
uhci_show_status
(
struct
uhci_hcd
*
uhci
,
char
*
buf
,
int
len
)
static
int
uhci_show_status
(
struct
uhci_hcd
*
uhci
,
char
*
buf
,
int
len
)
{
{
char
*
out
=
buf
;
char
*
out
=
buf
;
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
long
io_addr
=
uhci
->
io_addr
;
unsigned
short
usbcmd
,
usbstat
,
usbint
,
usbfrnum
;
unsigned
short
usbcmd
,
usbstat
,
usbint
,
usbfrnum
;
unsigned
int
flbaseadd
;
unsigned
int
flbaseadd
;
unsigned
char
sof
;
unsigned
char
sof
;
...
...
drivers/usb/host/uhci-hcd.c
View file @
097032ac
...
@@ -1762,7 +1762,7 @@ static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
...
@@ -1762,7 +1762,7 @@ static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
static
irqreturn_t
uhci_irq
(
struct
usb_hcd
*
hcd
,
struct
pt_regs
*
regs
)
static
irqreturn_t
uhci_irq
(
struct
usb_hcd
*
hcd
,
struct
pt_regs
*
regs
)
{
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
long
io_addr
=
uhci
->
io_addr
;
unsigned
short
status
;
unsigned
short
status
;
struct
list_head
*
tmp
,
*
head
;
struct
list_head
*
tmp
,
*
head
;
unsigned
int
age
;
unsigned
int
age
;
...
@@ -1835,7 +1835,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
...
@@ -1835,7 +1835,7 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
static
void
reset_hc
(
struct
uhci_hcd
*
uhci
)
static
void
reset_hc
(
struct
uhci_hcd
*
uhci
)
{
{
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
long
io_addr
=
uhci
->
io_addr
;
/* Turn off PIRQ, SMI, and all interrupts. This also turns off
/* Turn off PIRQ, SMI, and all interrupts. This also turns off
* the BIOS's USB Legacy Support.
* the BIOS's USB Legacy Support.
...
@@ -1856,7 +1856,7 @@ static void reset_hc(struct uhci_hcd *uhci)
...
@@ -1856,7 +1856,7 @@ static void reset_hc(struct uhci_hcd *uhci)
static
void
suspend_hc
(
struct
uhci_hcd
*
uhci
)
static
void
suspend_hc
(
struct
uhci_hcd
*
uhci
)
{
{
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
long
io_addr
=
uhci
->
io_addr
;
dev_dbg
(
uhci_dev
(
uhci
),
"%s
\n
"
,
__FUNCTION__
);
dev_dbg
(
uhci_dev
(
uhci
),
"%s
\n
"
,
__FUNCTION__
);
uhci
->
state
=
UHCI_SUSPENDED
;
uhci
->
state
=
UHCI_SUSPENDED
;
...
@@ -1866,7 +1866,7 @@ static void suspend_hc(struct uhci_hcd *uhci)
...
@@ -1866,7 +1866,7 @@ static void suspend_hc(struct uhci_hcd *uhci)
static
void
wakeup_hc
(
struct
uhci_hcd
*
uhci
)
static
void
wakeup_hc
(
struct
uhci_hcd
*
uhci
)
{
{
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
long
io_addr
=
uhci
->
io_addr
;
switch
(
uhci
->
state
)
{
switch
(
uhci
->
state
)
{
case
UHCI_SUSPENDED
:
/* Start the resume */
case
UHCI_SUSPENDED
:
/* Start the resume */
...
@@ -1906,7 +1906,7 @@ static void wakeup_hc(struct uhci_hcd *uhci)
...
@@ -1906,7 +1906,7 @@ static void wakeup_hc(struct uhci_hcd *uhci)
static
int
ports_active
(
struct
uhci_hcd
*
uhci
)
static
int
ports_active
(
struct
uhci_hcd
*
uhci
)
{
{
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
long
io_addr
=
uhci
->
io_addr
;
int
connection
=
0
;
int
connection
=
0
;
int
i
;
int
i
;
...
@@ -1918,7 +1918,7 @@ static int ports_active(struct uhci_hcd *uhci)
...
@@ -1918,7 +1918,7 @@ static int ports_active(struct uhci_hcd *uhci)
static
int
suspend_allowed
(
struct
uhci_hcd
*
uhci
)
static
int
suspend_allowed
(
struct
uhci_hcd
*
uhci
)
{
{
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
long
io_addr
=
uhci
->
io_addr
;
int
i
;
int
i
;
if
(
to_pci_dev
(
uhci_dev
(
uhci
))
->
vendor
!=
PCI_VENDOR_ID_INTEL
)
if
(
to_pci_dev
(
uhci_dev
(
uhci
))
->
vendor
!=
PCI_VENDOR_ID_INTEL
)
...
@@ -1983,7 +1983,7 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
...
@@ -1983,7 +1983,7 @@ static void hc_state_transitions(struct uhci_hcd *uhci)
static
void
start_hc
(
struct
uhci_hcd
*
uhci
)
static
void
start_hc
(
struct
uhci_hcd
*
uhci
)
{
{
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
long
io_addr
=
uhci
->
io_addr
;
int
timeout
=
1000
;
int
timeout
=
1000
;
/*
/*
...
@@ -2261,6 +2261,11 @@ static int uhci_start(struct usb_hcd *hcd)
...
@@ -2261,6 +2261,11 @@ static int uhci_start(struct usb_hcd *hcd)
uhci
->
fl
->
frame
[
i
]
=
cpu_to_le32
(
uhci
->
skelqh
[
irq
]
->
dma_handle
);
uhci
->
fl
->
frame
[
i
]
=
cpu_to_le32
(
uhci
->
skelqh
[
irq
]
->
dma_handle
);
}
}
/*
* Some architectures require a full mb() to enforce completion of
* the memory writes above before the I/O transfers in start_hc().
*/
mb
();
start_hc
(
uhci
);
start_hc
(
uhci
);
init_stall_timer
(
hcd
);
init_stall_timer
(
hcd
);
...
...
drivers/usb/host/uhci-hub.c
View file @
097032ac
...
@@ -36,7 +36,7 @@ static __u8 root_hub_hub_des[] =
...
@@ -36,7 +36,7 @@ static __u8 root_hub_hub_des[] =
static
int
uhci_hub_status_data
(
struct
usb_hcd
*
hcd
,
char
*
buf
)
static
int
uhci_hub_status_data
(
struct
usb_hcd
*
hcd
,
char
*
buf
)
{
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
long
io_addr
=
uhci
->
io_addr
;
int
i
;
int
i
;
*
buf
=
0
;
*
buf
=
0
;
...
@@ -69,7 +69,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
...
@@ -69,7 +69,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
{
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
int
status
,
retval
=
0
,
len
=
0
;
int
status
,
retval
=
0
,
len
=
0
;
unsigned
int
port_addr
=
uhci
->
io_addr
+
USBPORTSC1
+
2
*
(
wIndex
-
1
);
unsigned
long
port_addr
=
uhci
->
io_addr
+
USBPORTSC1
+
2
*
(
wIndex
-
1
);
__u16
wPortChange
,
wPortStatus
;
__u16
wPortChange
,
wPortStatus
;
switch
(
typeReq
)
{
switch
(
typeReq
)
{
...
...
drivers/usb/input/hid-tmff.c
View file @
097032ac
...
@@ -110,7 +110,7 @@ int hid_tmff_init(struct hid_device *hid)
...
@@ -110,7 +110,7 @@ int hid_tmff_init(struct hid_device *hid)
{
{
struct
tmff_device
*
private
;
struct
tmff_device
*
private
;
struct
list_head
*
pos
;
struct
list_head
*
pos
;
struct
hid_input
*
hidinput
=
list_entry
(
&
hid
->
inputs
,
struct
hid_input
,
list
);
struct
hid_input
*
hidinput
=
list_entry
(
hid
->
inputs
.
next
,
struct
hid_input
,
list
);
private
=
kmalloc
(
sizeof
(
struct
tmff_device
),
GFP_KERNEL
);
private
=
kmalloc
(
sizeof
(
struct
tmff_device
),
GFP_KERNEL
);
if
(
!
private
)
if
(
!
private
)
...
...
drivers/usb/media/Kconfig
View file @
097032ac
...
@@ -108,7 +108,7 @@ config USB_OV511
...
@@ -108,7 +108,7 @@ config USB_OV511
config USB_PWC
config USB_PWC
tristate "USB Philips Cameras"
tristate "USB Philips Cameras"
depends on USB && VIDEO_DEV
&& CONFIG_BROKEN
depends on USB && VIDEO_DEV
---help---
---help---
Say Y or M here if you want to use one of these Philips & OEM
Say Y or M here if you want to use one of these Philips & OEM
webcams:
webcams:
...
...
drivers/usb/media/konicawc.c
View file @
097032ac
...
@@ -324,7 +324,7 @@ static void resubmit_urb(struct uvd *uvd, struct urb *urb)
...
@@ -324,7 +324,7 @@ static void resubmit_urb(struct uvd *uvd, struct urb *urb)
}
}
urb
->
dev
=
uvd
->
dev
;
urb
->
dev
=
uvd
->
dev
;
urb
->
status
=
0
;
urb
->
status
=
0
;
ret
=
usb_submit_urb
(
urb
,
GFP_KERNEL
);
ret
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
DEBUG
(
3
,
"submitting urb of length %d"
,
urb
->
transfer_buffer_length
);
DEBUG
(
3
,
"submitting urb of length %d"
,
urb
->
transfer_buffer_length
);
if
(
ret
)
if
(
ret
)
err
(
"usb_submit_urb error (%d)"
,
ret
);
err
(
"usb_submit_urb error (%d)"
,
ret
);
...
...
drivers/usb/media/pwc-ctrl.c
View file @
097032ac
...
@@ -30,6 +30,7 @@
...
@@ -30,6 +30,7 @@
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#endif
#endif
#include <asm/errno.h>
#include <asm/errno.h>
#include <linux/version.h>
#include "pwc.h"
#include "pwc.h"
#include "pwc-ioctl.h"
#include "pwc-ioctl.h"
...
@@ -127,19 +128,19 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
...
@@ -127,19 +128,19 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
/* This tables contains entries for the 675/680/690 (Timon) camera, with
/* This tables contains entries for the 675/680/690 (Timon) camera, with
4 different qualities (no compression, low, medium, high).
4 different qualities (no compression, low, medium, high).
It lists the bandwidth requirements for said mode by its alternate interface
It lists the bandwidth requirements for said mode by its alternate interface
number. An alternate of 0 means that the mode is unavailable.
number. An alternate of 0 means that the mode is unavailable.
There are 6 * 4 * 4 entries:
There are 6 * 4 * 4 entries:
6 different resolutions subqcif, qsif, qcif, sif, cif, vga
6 different resolutions subqcif, qsif, qcif, sif, cif, vga
6 framerates: 5, 10, 15, 20, 25, 30
6 framerates: 5, 10, 15, 20, 25, 30
4 compression modi: none, low, medium, high
4 compression modi: none, low, medium, high
When an uncompressed mode is not available, the next available compressed mode
When an uncompressed mode is not available, the next available compressed mode
will be chosen (unless the decompressor is absent). Sometimes there are only
will be chosen (unless the decompressor is absent). Sometimes there are only
1 or 2 compressed modes available; in that case entries are duplicated.
1 or 2 compressed modes available; in that case entries are duplicated.
*/
*/
struct
Timon_table_entry
struct
Timon_table_entry
{
{
char
alternate
;
/* USB alternate interface */
char
alternate
;
/* USB alternate interface */
unsigned
short
packetsize
;
/* Normal packet size */
unsigned
short
packetsize
;
/* Normal packet size */
...
@@ -147,7 +148,7 @@ struct Timon_table_entry
...
@@ -147,7 +148,7 @@ struct Timon_table_entry
unsigned
char
mode
[
13
];
/* precomputed mode settings for cam */
unsigned
char
mode
[
13
];
/* precomputed mode settings for cam */
};
};
static
struct
Timon_table_entry
Timon_table
[
PSZ_MAX
][
6
][
4
]
=
static
struct
Timon_table_entry
Timon_table
[
PSZ_MAX
][
6
][
4
]
=
{
{
#include "pwc_timon.h"
#include "pwc_timon.h"
};
};
...
@@ -194,7 +195,7 @@ void pwc_hexdump(void *p, int len)
...
@@ -194,7 +195,7 @@ void pwc_hexdump(void *p, int len)
int
i
;
int
i
;
unsigned
char
*
s
;
unsigned
char
*
s
;
char
buf
[
100
],
*
d
;
char
buf
[
100
],
*
d
;
s
=
(
unsigned
char
*
)
p
;
s
=
(
unsigned
char
*
)
p
;
d
=
buf
;
d
=
buf
;
*
d
=
'\0'
;
*
d
=
'\0'
;
...
@@ -230,7 +231,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
...
@@ -230,7 +231,7 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
unsigned
char
buf
[
3
];
unsigned
char
buf
[
3
];
int
ret
,
fps
;
int
ret
,
fps
;
struct
Nala_table_entry
*
pEntry
;
struct
Nala_table_entry
*
pEntry
;
int
frames2frames
[
31
]
=
int
frames2frames
[
31
]
=
{
/* closest match of framerate */
{
/* closest match of framerate */
0
,
0
,
0
,
0
,
4
,
/* 0-4 */
0
,
0
,
0
,
0
,
4
,
/* 0-4 */
5
,
5
,
7
,
7
,
10
,
/* 5-9 */
5
,
5
,
7
,
7
,
10
,
/* 5-9 */
...
@@ -267,9 +268,12 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
...
@@ -267,9 +268,12 @@ static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int fra
Debug
(
"Failed to send video command... %d
\n
"
,
ret
);
Debug
(
"Failed to send video command... %d
\n
"
,
ret
);
return
ret
;
return
ret
;
}
}
if
(
pEntry
->
compressed
&&
pdev
->
decompressor
!=
NULL
)
if
(
pEntry
->
compressed
&&
pdev
->
decompressor
!=
0
&&
pdev
->
vpalette
!=
VIDEO_PALETTE_RAW
)
pdev
->
decompressor
->
init
(
pdev
->
release
,
buf
,
pdev
->
decompress_data
);
pdev
->
decompressor
->
init
(
pdev
->
type
,
pdev
->
release
,
buf
,
pdev
->
decompress_data
);
pdev
->
cmd_len
=
3
;
memcpy
(
pdev
->
cmd_buf
,
buf
,
3
);
/* Set various parameters */
/* Set various parameters */
pdev
->
vframes
=
frames
;
pdev
->
vframes
=
frames
;
pdev
->
vsize
=
size
;
pdev
->
vsize
=
size
;
...
@@ -303,13 +307,13 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
...
@@ -303,13 +307,13 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
if
(
size
==
PSZ_VGA
&&
frames
>
15
)
if
(
size
==
PSZ_VGA
&&
frames
>
15
)
return
-
EINVAL
;
return
-
EINVAL
;
fps
=
(
frames
/
5
)
-
1
;
fps
=
(
frames
/
5
)
-
1
;
/* Find a supported framerate with progressively higher compression ratios
/* Find a supported framerate with progressively higher compression ratios
if the preferred ratio is not available.
if the preferred ratio is not available.
*/
*/
pChoose
=
NULL
;
pChoose
=
NULL
;
if
(
pdev
->
decompressor
==
NULL
)
{
if
(
pdev
->
decompressor
==
NULL
)
{
#if PWC_DEBUG
#if PWC_DEBUG
Debug
(
"Trying to find uncompressed mode.
\n
"
);
Debug
(
"Trying to find uncompressed mode.
\n
"
);
#endif
#endif
pChoose
=
&
Timon_table
[
size
][
fps
][
0
];
pChoose
=
&
Timon_table
[
size
][
fps
][
0
];
...
@@ -319,7 +323,7 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
...
@@ -319,7 +323,7 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
pChoose
=
&
Timon_table
[
size
][
fps
][
compression
];
pChoose
=
&
Timon_table
[
size
][
fps
][
compression
];
if
(
pChoose
->
alternate
!=
0
)
if
(
pChoose
->
alternate
!=
0
)
break
;
break
;
compression
++
;
compression
++
;
}
}
}
}
if
(
pChoose
==
NULL
||
pChoose
->
alternate
==
0
)
if
(
pChoose
==
NULL
||
pChoose
->
alternate
==
0
)
...
@@ -332,9 +336,12 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
...
@@ -332,9 +336,12 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
if
(
pChoose
->
bandlength
>
0
)
if
(
pChoose
->
bandlength
>
0
&&
pdev
->
decompressor
!=
0
&&
pdev
->
vpalette
!=
VIDEO_PALETTE_RAW
)
pdev
->
decompressor
->
init
(
pdev
->
release
,
buf
,
pdev
->
decompress_data
);
pdev
->
decompressor
->
init
(
pdev
->
type
,
pdev
->
release
,
buf
,
pdev
->
decompress_data
);
pdev
->
cmd_len
=
13
;
memcpy
(
pdev
->
cmd_buf
,
buf
,
13
);
/* Set various parameters */
/* Set various parameters */
pdev
->
vframes
=
frames
;
pdev
->
vframes
=
frames
;
pdev
->
vsize
=
size
;
pdev
->
vsize
=
size
;
...
@@ -342,7 +349,7 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
...
@@ -342,7 +349,7 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
pdev
->
valternate
=
pChoose
->
alternate
;
pdev
->
valternate
=
pChoose
->
alternate
;
pdev
->
image
=
pwc_image_sizes
[
size
];
pdev
->
image
=
pwc_image_sizes
[
size
];
pdev
->
vbandlength
=
pChoose
->
bandlength
;
pdev
->
vbandlength
=
pChoose
->
bandlength
;
if
(
pChoose
->
bandlength
>
0
)
if
(
pChoose
->
bandlength
>
0
)
pdev
->
frame_size
=
(
pChoose
->
bandlength
*
pdev
->
image
.
y
)
/
4
;
pdev
->
frame_size
=
(
pChoose
->
bandlength
*
pdev
->
image
.
y
)
/
4
;
else
else
pdev
->
frame_size
=
(
pdev
->
image
.
x
*
pdev
->
image
.
y
*
12
)
/
8
;
pdev
->
frame_size
=
(
pdev
->
image
.
x
*
pdev
->
image
.
y
*
12
)
/
8
;
...
@@ -352,33 +359,54 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
...
@@ -352,33 +359,54 @@ static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int fr
static
inline
int
set_video_mode_Kiara
(
struct
pwc_device
*
pdev
,
int
size
,
int
frames
,
int
compression
,
int
snapshot
)
static
inline
int
set_video_mode_Kiara
(
struct
pwc_device
*
pdev
,
int
size
,
int
frames
,
int
compression
,
int
snapshot
)
{
{
struct
Kiara_table_entry
*
pChoose
;
struct
Kiara_table_entry
*
pChoose
=
0
;
int
fps
,
ret
;
int
fps
,
ret
;
unsigned
char
buf
[
12
];
unsigned
char
buf
[
12
];
struct
Kiara_table_entry
RawEntry
=
{
6
,
773
,
1272
,
{
0xAD
,
0xF4
,
0x10
,
0x27
,
0xB6
,
0x24
,
0x96
,
0x02
,
0x30
,
0x05
,
0x03
,
0x80
}};
if
(
size
>=
PSZ_MAX
||
frames
<
5
||
frames
>
30
||
compression
<
0
||
compression
>
3
)
if
(
size
>=
PSZ_MAX
||
frames
<
5
||
frames
>
30
||
compression
<
0
||
compression
>
3
)
return
-
EINVAL
;
return
-
EINVAL
;
if
(
size
==
PSZ_VGA
&&
frames
>
15
)
if
(
size
==
PSZ_VGA
&&
frames
>
15
)
return
-
EINVAL
;
return
-
EINVAL
;
fps
=
(
frames
/
5
)
-
1
;
fps
=
(
frames
/
5
)
-
1
;
/* Find a supported framerate with progressively higher compression ratios
/* special case: VGA @ 5 fps and snapshot is raw bayer mode */
if the preferred ratio is not available.
if
(
size
==
PSZ_VGA
&&
frames
==
5
&&
snapshot
)
*/
{
pChoose
=
NULL
;
/* Only available in case the raw palette is selected or
if
(
pdev
->
decompressor
==
NULL
)
{
we have the decompressor available. This mode is
#if PWC_DEBUG
only available in compressed form
Debug
(
"Trying to find uncompressed mode.
\n
"
);
*/
#endif
if
(
pdev
->
vpalette
==
VIDEO_PALETTE_RAW
||
pdev
->
decompressor
!=
NULL
)
pChoose
=
&
Kiara_table
[
size
][
fps
][
0
];
{
Info
(
"Choosing VGA/5 BAYER mode (%d).
\n
"
,
pdev
->
vpalette
);
pChoose
=
&
RawEntry
;
}
else
{
Info
(
"VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.
\n
"
);
}
}
}
else
{
else
while
(
compression
<=
3
)
{
{
pChoose
=
&
Kiara_table
[
size
][
fps
][
compression
];
/* Find a supported framerate with progressively higher compression ratios
if
(
pChoose
->
alternate
!=
0
)
if the preferred ratio is not available.
break
;
Skip this step when using RAW modes.
compression
++
;
*/
if
(
pdev
->
decompressor
==
NULL
&&
pdev
->
vpalette
!=
VIDEO_PALETTE_RAW
)
{
#if PWC_DEBUG
Debug
(
"Trying to find uncompressed mode.
\n
"
);
#endif
pChoose
=
&
Kiara_table
[
size
][
fps
][
0
];
}
}
else
{
while
(
compression
<=
3
)
{
pChoose
=
&
Kiara_table
[
size
][
fps
][
compression
];
if
(
pChoose
->
alternate
!=
0
)
break
;
compression
++
;
}
}
}
}
if
(
pChoose
==
NULL
||
pChoose
->
alternate
==
0
)
if
(
pChoose
==
NULL
||
pChoose
->
alternate
==
0
)
return
-
ENOENT
;
/* Not supported. */
return
-
ENOENT
;
/* Not supported. */
...
@@ -393,9 +421,11 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
...
@@ -393,9 +421,11 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
if
(
pChoose
->
bandlength
>
0
)
if
(
pChoose
->
bandlength
>
0
&&
pdev
->
decompressor
!=
0
&&
pdev
->
vpalette
!=
VIDEO_PALETTE_RAW
)
pdev
->
decompressor
->
init
(
pdev
->
release
,
buf
,
pdev
->
decompress_data
);
pdev
->
decompressor
->
init
(
pdev
->
type
,
pdev
->
release
,
buf
,
pdev
->
decompress_data
);
pdev
->
cmd_len
=
12
;
memcpy
(
pdev
->
cmd_buf
,
buf
,
12
);
/* All set and go */
/* All set and go */
pdev
->
vframes
=
frames
;
pdev
->
vframes
=
frames
;
pdev
->
vsize
=
size
;
pdev
->
vsize
=
size
;
...
@@ -403,15 +433,15 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
...
@@ -403,15 +433,15 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
pdev
->
valternate
=
pChoose
->
alternate
;
pdev
->
valternate
=
pChoose
->
alternate
;
pdev
->
image
=
pwc_image_sizes
[
size
];
pdev
->
image
=
pwc_image_sizes
[
size
];
pdev
->
vbandlength
=
pChoose
->
bandlength
;
pdev
->
vbandlength
=
pChoose
->
bandlength
;
if
(
p
Choose
->
bandlength
>
0
)
if
(
p
dev
->
v
bandlength
>
0
)
pdev
->
frame_size
=
(
p
Choose
->
bandlength
*
pdev
->
image
.
y
)
/
4
;
pdev
->
frame_size
=
(
p
dev
->
v
bandlength
*
pdev
->
image
.
y
)
/
4
;
else
else
pdev
->
frame_size
=
(
pdev
->
image
.
x
*
pdev
->
image
.
y
*
12
)
/
8
;
pdev
->
frame_size
=
(
pdev
->
image
.
x
*
pdev
->
image
.
y
*
12
)
/
8
;
pdev
->
frame_size
+=
(
pdev
->
frame_header_size
+
pdev
->
frame_trailer_size
);
return
0
;
return
0
;
}
}
/**
/**
@pdev: device structure
@pdev: device structure
@width: viewport width
@width: viewport width
...
@@ -422,14 +452,17 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
...
@@ -422,14 +452,17 @@ static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int fr
*/
*/
int
pwc_set_video_mode
(
struct
pwc_device
*
pdev
,
int
width
,
int
height
,
int
frames
,
int
compression
,
int
snapshot
)
int
pwc_set_video_mode
(
struct
pwc_device
*
pdev
,
int
width
,
int
height
,
int
frames
,
int
compression
,
int
snapshot
)
{
{
int
ret
,
size
;
int
ret
,
size
;
Trace
(
TRACE_FLOW
,
"set_video_mode(%dx%d @ %d, palette %d).
\n
"
,
width
,
height
,
frames
,
pdev
->
vpalette
);
size
=
pwc_decode_size
(
pdev
,
width
,
height
);
size
=
pwc_decode_size
(
pdev
,
width
,
height
);
if
(
size
<
0
)
{
if
(
size
<
0
)
{
Debug
(
"Could not find suitable size.
\n
"
);
Debug
(
"Could not find suitable size.
\n
"
);
return
-
ERANGE
;
return
-
ERANGE
;
}
}
ret
=
-
EINVAL
;
Debug
(
"decode_size = %d.
\n
"
,
size
);
ret
=
-
EINVAL
;
switch
(
pdev
->
type
)
{
switch
(
pdev
->
type
)
{
case
645
:
case
645
:
case
646
:
case
646
:
...
@@ -441,7 +474,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
...
@@ -441,7 +474,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
case
690
:
case
690
:
ret
=
set_video_mode_Timon
(
pdev
,
size
,
frames
,
compression
,
snapshot
);
ret
=
set_video_mode_Timon
(
pdev
,
size
,
frames
,
compression
,
snapshot
);
break
;
break
;
case
720
:
case
720
:
case
730
:
case
730
:
case
740
:
case
740
:
...
@@ -459,6 +492,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
...
@@ -459,6 +492,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
}
}
pdev
->
view
.
x
=
width
;
pdev
->
view
.
x
=
width
;
pdev
->
view
.
y
=
height
;
pdev
->
view
.
y
=
height
;
pdev
->
frame_total_size
=
pdev
->
frame_size
+
pdev
->
frame_header_size
+
pdev
->
frame_trailer_size
;
pwc_set_image_buffer_size
(
pdev
);
pwc_set_image_buffer_size
(
pdev
);
Trace
(
TRACE_SIZE
,
"Set viewport to %dx%d, image size is %dx%d.
\n
"
,
width
,
height
,
pwc_image_sizes
[
size
].
x
,
pwc_image_sizes
[
size
].
y
);
Trace
(
TRACE_SIZE
,
"Set viewport to %dx%d, image size is %dx%d.
\n
"
,
width
,
height
,
pwc_image_sizes
[
size
].
x
,
pwc_image_sizes
[
size
].
y
);
return
0
;
return
0
;
...
@@ -467,23 +501,33 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
...
@@ -467,23 +501,33 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
void
pwc_set_image_buffer_size
(
struct
pwc_device
*
pdev
)
void
pwc_set_image_buffer_size
(
struct
pwc_device
*
pdev
)
{
{
int
factor
,
i
,
filler
=
0
;
int
i
,
factor
=
0
,
filler
=
0
;
factor
=
6
;
/* for PALETTE_YUV420P */
filler
=
128
;
switch
(
pdev
->
vpalette
)
{
case
VIDEO_PALETTE_YUV420P
:
factor
=
6
;
filler
=
128
;
break
;
case
VIDEO_PALETTE_RAW
:
factor
=
6
;
/* can be uncompressed YUV420P */
filler
=
0
;
break
;
}
/* Set sizes in bytes */
/* Set sizes in bytes */
pdev
->
image
.
size
=
pdev
->
image
.
x
*
pdev
->
image
.
y
*
factor
/
4
;
pdev
->
image
.
size
=
pdev
->
image
.
x
*
pdev
->
image
.
y
*
factor
/
4
;
pdev
->
view
.
size
=
pdev
->
view
.
x
*
pdev
->
view
.
y
*
factor
/
4
;
pdev
->
view
.
size
=
pdev
->
view
.
x
*
pdev
->
view
.
y
*
factor
/
4
;
/* Align offset, or you'll get some very weird results in
/* Align offset, or you'll get some very weird results in
YUV420 mode... x must be multiple of 4 (to get the Y's in
YUV420 mode... x must be multiple of 4 (to get the Y's in
place), and y even (or you'll mixup U & V). This is less of a
place), and y even (or you'll mixup U & V). This is less of a
problem for YUV420P.
problem for YUV420P.
*/
*/
pdev
->
offset
.
x
=
((
pdev
->
view
.
x
-
pdev
->
image
.
x
)
/
2
)
&
0xFFFC
;
pdev
->
offset
.
x
=
((
pdev
->
view
.
x
-
pdev
->
image
.
x
)
/
2
)
&
0xFFFC
;
pdev
->
offset
.
y
=
((
pdev
->
view
.
y
-
pdev
->
image
.
y
)
/
2
)
&
0xFFFE
;
pdev
->
offset
.
y
=
((
pdev
->
view
.
y
-
pdev
->
image
.
y
)
/
2
)
&
0xFFFE
;
/* Fill buffers with gray or black */
/* Fill buffers with gray or black */
for
(
i
=
0
;
i
<
MAX_IMAGES
;
i
++
)
{
for
(
i
=
0
;
i
<
MAX_IMAGES
;
i
++
)
{
if
(
pdev
->
image_ptr
[
i
]
!=
NULL
)
if
(
pdev
->
image_ptr
[
i
]
!=
NULL
)
...
@@ -499,13 +543,8 @@ int pwc_get_brightness(struct pwc_device *pdev)
...
@@ -499,13 +543,8 @@ int pwc_get_brightness(struct pwc_device *pdev)
{
{
char
buf
;
char
buf
;
int
ret
;
int
ret
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
BRIGHTNESS_FORMATTER
,
1
);
GET_LUM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
BRIGHTNESS_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
return
buf
<<
9
;
return
buf
<<
9
;
...
@@ -520,12 +559,7 @@ int pwc_set_brightness(struct pwc_device *pdev, int value)
...
@@ -520,12 +559,7 @@ int pwc_set_brightness(struct pwc_device *pdev, int value)
if
(
value
>
0xffff
)
if
(
value
>
0xffff
)
value
=
0xffff
;
value
=
0xffff
;
buf
=
(
value
>>
9
)
&
0x7f
;
buf
=
(
value
>>
9
)
&
0x7f
;
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
return
SendControlMsg
(
SET_LUM_CTL
,
BRIGHTNESS_FORMATTER
,
1
);
SET_LUM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
BRIGHTNESS_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
}
}
/* CONTRAST */
/* CONTRAST */
...
@@ -534,13 +568,8 @@ int pwc_get_contrast(struct pwc_device *pdev)
...
@@ -534,13 +568,8 @@ int pwc_get_contrast(struct pwc_device *pdev)
{
{
char
buf
;
char
buf
;
int
ret
;
int
ret
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
CONTRAST_FORMATTER
,
1
);
GET_LUM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
CONTRAST_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
return
buf
<<
10
;
return
buf
<<
10
;
...
@@ -555,12 +584,7 @@ int pwc_set_contrast(struct pwc_device *pdev, int value)
...
@@ -555,12 +584,7 @@ int pwc_set_contrast(struct pwc_device *pdev, int value)
if
(
value
>
0xffff
)
if
(
value
>
0xffff
)
value
=
0xffff
;
value
=
0xffff
;
buf
=
(
value
>>
10
)
&
0x3f
;
buf
=
(
value
>>
10
)
&
0x3f
;
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
return
SendControlMsg
(
SET_LUM_CTL
,
CONTRAST_FORMATTER
,
1
);
SET_LUM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
CONTRAST_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
}
}
/* GAMMA */
/* GAMMA */
...
@@ -570,12 +594,7 @@ int pwc_get_gamma(struct pwc_device *pdev)
...
@@ -570,12 +594,7 @@ int pwc_get_gamma(struct pwc_device *pdev)
char
buf
;
char
buf
;
int
ret
;
int
ret
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
GAMMA_FORMATTER
,
1
);
GET_LUM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
GAMMA_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
return
buf
<<
11
;
return
buf
<<
11
;
...
@@ -590,12 +609,7 @@ int pwc_set_gamma(struct pwc_device *pdev, int value)
...
@@ -590,12 +609,7 @@ int pwc_set_gamma(struct pwc_device *pdev, int value)
if
(
value
>
0xffff
)
if
(
value
>
0xffff
)
value
=
0xffff
;
value
=
0xffff
;
buf
=
(
value
>>
11
)
&
0x1f
;
buf
=
(
value
>>
11
)
&
0x1f
;
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
return
SendControlMsg
(
SET_LUM_CTL
,
GAMMA_FORMATTER
,
1
);
SET_LUM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
GAMMA_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
}
}
...
@@ -608,12 +622,7 @@ int pwc_get_saturation(struct pwc_device *pdev)
...
@@ -608,12 +622,7 @@ int pwc_get_saturation(struct pwc_device *pdev)
if
(
pdev
->
type
<
675
)
if
(
pdev
->
type
<
675
)
return
-
1
;
return
-
1
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_CHROM_CTL
,
pdev
->
type
<
730
?
SATURATION_MODE_FORMATTER2
:
SATURATION_MODE_FORMATTER1
,
1
);
GET_CHROM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
pdev
->
type
<
730
?
SATURATION_MODE_FORMATTER2
:
SATURATION_MODE_FORMATTER1
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
return
32768
+
buf
*
327
;
return
32768
+
buf
*
327
;
...
@@ -631,12 +640,7 @@ int pwc_set_saturation(struct pwc_device *pdev, int value)
...
@@ -631,12 +640,7 @@ int pwc_set_saturation(struct pwc_device *pdev, int value)
value
=
0xffff
;
value
=
0xffff
;
/* saturation ranges from -100 to +100 */
/* saturation ranges from -100 to +100 */
buf
=
(
value
-
32768
)
/
327
;
buf
=
(
value
-
32768
)
/
327
;
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
return
SendControlMsg
(
SET_CHROM_CTL
,
pdev
->
type
<
730
?
SATURATION_MODE_FORMATTER2
:
SATURATION_MODE_FORMATTER1
,
1
);
SET_CHROM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
pdev
->
type
<
730
?
SATURATION_MODE_FORMATTER2
:
SATURATION_MODE_FORMATTER1
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
}
}
/* AGC */
/* AGC */
...
@@ -651,12 +655,7 @@ static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
...
@@ -651,12 +655,7 @@ static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
else
else
buf
=
0xff
;
/* fixed */
buf
=
0xff
;
/* fixed */
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
ret
=
SendControlMsg
(
SET_LUM_CTL
,
AGC_MODE_FORMATTER
,
1
);
SET_LUM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
AGC_MODE_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
!
mode
&&
ret
>=
0
)
{
if
(
!
mode
&&
ret
>=
0
)
{
if
(
value
<
0
)
if
(
value
<
0
)
...
@@ -664,12 +663,7 @@ static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
...
@@ -664,12 +663,7 @@ static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
if
(
value
>
0xffff
)
if
(
value
>
0xffff
)
value
=
0xffff
;
value
=
0xffff
;
buf
=
(
value
>>
10
)
&
0x3F
;
buf
=
(
value
>>
10
)
&
0x3F
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
ret
=
SendControlMsg
(
SET_LUM_CTL
,
PRESET_AGC_FORMATTER
,
1
);
SET_LUM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
PRESET_AGC_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
}
}
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
...
@@ -681,22 +675,12 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
...
@@ -681,22 +675,12 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
unsigned
char
buf
;
unsigned
char
buf
;
int
ret
;
int
ret
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
AGC_MODE_FORMATTER
,
1
);
GET_LUM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
AGC_MODE_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
if
(
buf
!=
0
)
{
/* fixed */
if
(
buf
!=
0
)
{
/* fixed */
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
PRESET_AGC_FORMATTER
,
1
);
GET_LUM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
PRESET_AGC_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
if
(
buf
>
0x3F
)
if
(
buf
>
0x3F
)
...
@@ -704,12 +688,7 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
...
@@ -704,12 +688,7 @@ static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
*
value
=
(
buf
<<
10
);
*
value
=
(
buf
<<
10
);
}
}
else
{
/* auto */
else
{
/* auto */
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_STATUS_CTL
,
READ_AGC_FORMATTER
,
1
);
GET_STATUS_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
READ_AGC_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
/* Gah... this value ranges from 0x00 ... 0x9F */
/* Gah... this value ranges from 0x00 ... 0x9F */
...
@@ -732,12 +711,7 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v
...
@@ -732,12 +711,7 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v
else
else
buf
[
0
]
=
0xff
;
/* fixed */
buf
[
0
]
=
0xff
;
/* fixed */
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
ret
=
SendControlMsg
(
SET_LUM_CTL
,
SHUTTER_MODE_FORMATTER
,
1
);
SET_LUM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
SHUTTER_MODE_FORMATTER
,
pdev
->
vcinterface
,
buf
,
1
,
HZ
/
2
);
if
(
!
mode
&&
ret
>=
0
)
{
if
(
!
mode
&&
ret
>=
0
)
{
if
(
value
<
0
)
if
(
value
<
0
)
...
@@ -763,12 +737,7 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v
...
@@ -763,12 +737,7 @@ static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int v
break
;
break
;
}
}
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
ret
=
SendControlMsg
(
SET_LUM_CTL
,
PRESET_SHUTTER_FORMATTER
,
2
);
SET_LUM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
PRESET_SHUTTER_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
2
,
HZ
/
2
);
}
}
return
ret
;
return
ret
;
}
}
...
@@ -787,12 +756,7 @@ int pwc_camera_power(struct pwc_device *pdev, int power)
...
@@ -787,12 +756,7 @@ int pwc_camera_power(struct pwc_device *pdev, int power)
buf
=
0x00
;
/* active */
buf
=
0x00
;
/* active */
else
else
buf
=
0xFF
;
/* power save */
buf
=
0xFF
;
/* power save */
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
return
SendControlMsg
(
SET_STATUS_CTL
,
SET_POWER_SAVE_MODE_FORMATTER
,
1
);
SET_STATUS_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
SET_POWER_SAVE_MODE_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
}
}
...
@@ -801,32 +765,20 @@ int pwc_camera_power(struct pwc_device *pdev, int power)
...
@@ -801,32 +765,20 @@ int pwc_camera_power(struct pwc_device *pdev, int power)
static
inline
int
pwc_restore_user
(
struct
pwc_device
*
pdev
)
static
inline
int
pwc_restore_user
(
struct
pwc_device
*
pdev
)
{
{
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
char
buf
;
/* dummy */
SET_STATUS_CTL
,
return
SendControlMsg
(
SET_STATUS_CTL
,
RESTORE_USER_DEFAULTS_FORMATTER
,
0
);
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
RESTORE_USER_DEFAULTS_FORMATTER
,
pdev
->
vcinterface
,
NULL
,
0
,
HZ
/
2
);
}
}
static
inline
int
pwc_save_user
(
struct
pwc_device
*
pdev
)
static
inline
int
pwc_save_user
(
struct
pwc_device
*
pdev
)
{
{
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
char
buf
;
/* dummy */
SET_STATUS_CTL
,
return
SendControlMsg
(
SET_STATUS_CTL
,
SAVE_USER_DEFAULTS_FORMATTER
,
0
);
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
SAVE_USER_DEFAULTS_FORMATTER
,
pdev
->
vcinterface
,
NULL
,
0
,
HZ
/
2
);
}
}
static
inline
int
pwc_restore_factory
(
struct
pwc_device
*
pdev
)
static
inline
int
pwc_restore_factory
(
struct
pwc_device
*
pdev
)
{
{
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
char
buf
;
/* dummy */
SET_STATUS_CTL
,
return
SendControlMsg
(
SET_STATUS_CTL
,
RESTORE_FACTORY_DEFAULTS_FORMATTER
,
0
);
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
RESTORE_FACTORY_DEFAULTS_FORMATTER
,
pdev
->
vcinterface
,
NULL
,
0
,
HZ
/
2
);
}
}
/* ************************************************* */
/* ************************************************* */
...
@@ -854,12 +806,7 @@ static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
...
@@ -854,12 +806,7 @@ static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
buf
=
mode
&
0x07
;
/* just the lowest three bits */
buf
=
mode
&
0x07
;
/* just the lowest three bits */
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
ret
=
SendControlMsg
(
SET_CHROM_CTL
,
WB_MODE_FORMATTER
,
1
);
SET_CHROM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
WB_MODE_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
...
@@ -871,12 +818,7 @@ static inline int pwc_get_awb(struct pwc_device *pdev)
...
@@ -871,12 +818,7 @@ static inline int pwc_get_awb(struct pwc_device *pdev)
unsigned
char
buf
;
unsigned
char
buf
;
int
ret
;
int
ret
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_CHROM_CTL
,
WB_MODE_FORMATTER
,
1
);
GET_CHROM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
WB_MODE_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
...
@@ -891,34 +833,21 @@ static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
...
@@ -891,34 +833,21 @@ static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
value
=
0
;
value
=
0
;
if
(
value
>
0xffff
)
if
(
value
>
0xffff
)
value
=
0xffff
;
value
=
0xffff
;
/* only the msb is considered */
/* only the msb are considered */
buf
=
value
>>
8
;
buf
=
value
>>
8
;
return
SendControlMsg
(
SET_CHROM_CTL
,
PRESET_MANUAL_RED_GAIN_FORMATTER
,
1
);
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
SET_CHROM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
PRESET_MANUAL_RED_GAIN_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
}
}
static
inline
int
pwc_get_red_gain
(
struct
pwc_device
*
pdev
)
static
inline
int
pwc_get_red_gain
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
{
unsigned
char
buf
;
unsigned
char
buf
;
int
ret
;
int
ret
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_CHROM_CTL
,
PRESET_MANUAL_RED_GAIN_FORMATTER
,
1
);
GET_CHROM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
PRESET_MANUAL_RED_GAIN_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
*
value
=
buf
<<
8
;
return
(
buf
<<
8
)
;
return
0
;
}
}
...
@@ -930,34 +859,21 @@ static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
...
@@ -930,34 +859,21 @@ static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
value
=
0
;
value
=
0
;
if
(
value
>
0xffff
)
if
(
value
>
0xffff
)
value
=
0xffff
;
value
=
0xffff
;
/* only the msb is considered */
/* linear mapping of 0..0xffff to -0x80..0x7f */
buf
=
value
>>
8
;
buf
=
(
value
>>
8
);
return
SendControlMsg
(
SET_CHROM_CTL
,
PRESET_MANUAL_BLUE_GAIN_FORMATTER
,
1
);
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
SET_CHROM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
PRESET_MANUAL_BLUE_GAIN_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
}
}
static
inline
int
pwc_get_blue_gain
(
struct
pwc_device
*
pdev
)
static
inline
int
pwc_get_blue_gain
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
{
unsigned
char
buf
;
unsigned
char
buf
;
int
ret
;
int
ret
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_CHROM_CTL
,
PRESET_MANUAL_BLUE_GAIN_FORMATTER
,
1
);
GET_CHROM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
PRESET_MANUAL_BLUE_GAIN_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
*
value
=
buf
<<
8
;
return
(
buf
<<
8
)
;
return
0
;
}
}
...
@@ -965,40 +881,28 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev)
...
@@ -965,40 +881,28 @@ static inline int pwc_get_blue_gain(struct pwc_device *pdev)
internal red/blue gains, which may be different from the manual
internal red/blue gains, which may be different from the manual
gains set or read above.
gains set or read above.
*/
*/
static
inline
int
pwc_read_red_gain
(
struct
pwc_device
*
pdev
)
static
inline
int
pwc_read_red_gain
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
{
unsigned
char
buf
;
unsigned
char
buf
;
int
ret
;
int
ret
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_STATUS_CTL
,
READ_RED_GAIN_FORMATTER
,
1
);
GET_STATUS_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
READ_RED_GAIN_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
*
value
=
buf
<<
8
;
return
(
buf
<<
8
)
;
return
0
;
}
}
static
inline
int
pwc_read_blue_gain
(
struct
pwc_device
*
pdev
)
static
inline
int
pwc_read_blue_gain
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
{
unsigned
char
buf
;
unsigned
char
buf
;
int
ret
;
int
ret
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_STATUS_CTL
,
READ_BLUE_GAIN_FORMATTER
,
1
);
GET_STATUS_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
READ_BLUE_GAIN_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
*
value
=
buf
<<
8
;
return
(
buf
<<
8
)
;
return
0
;
}
}
...
@@ -1008,28 +912,19 @@ static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
...
@@ -1008,28 +912,19 @@ static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
/* useful range is 0x01..0x20 */
/* useful range is 0x01..0x20 */
buf
=
speed
/
0x7f0
;
buf
=
speed
/
0x7f0
;
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
return
SendControlMsg
(
SET_CHROM_CTL
,
AWB_CONTROL_SPEED_FORMATTER
,
1
);
SET_CHROM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
AWB_CONTROL_SPEED_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
}
}
static
inline
int
pwc_get_wb_speed
(
struct
pwc_device
*
pdev
)
static
inline
int
pwc_get_wb_speed
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
{
unsigned
char
buf
;
unsigned
char
buf
;
int
ret
;
int
ret
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_CHROM_CTL
,
AWB_CONTROL_SPEED_FORMATTER
,
1
);
GET_CHROM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
AWB_CONTROL_SPEED_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
return
(
buf
*
0x7f0
);
*
value
=
buf
*
0x7f0
;
return
0
;
}
}
...
@@ -1039,28 +934,19 @@ static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
...
@@ -1039,28 +934,19 @@ static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
/* useful range is 0x01..0x3F */
/* useful range is 0x01..0x3F */
buf
=
(
delay
>>
10
);
buf
=
(
delay
>>
10
);
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
return
SendControlMsg
(
SET_CHROM_CTL
,
AWB_CONTROL_DELAY_FORMATTER
,
1
);
SET_CHROM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
AWB_CONTROL_DELAY_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
}
}
static
inline
int
pwc_get_wb_delay
(
struct
pwc_device
*
pdev
)
static
inline
int
pwc_get_wb_delay
(
struct
pwc_device
*
pdev
,
int
*
value
)
{
{
unsigned
char
buf
;
unsigned
char
buf
;
int
ret
;
int
ret
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_CHROM_CTL
,
AWB_CONTROL_DELAY_FORMATTER
,
1
);
GET_CHROM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
AWB_CONTROL_DELAY_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
return
(
buf
<<
10
);
*
value
=
buf
<<
10
;
return
0
;
}
}
...
@@ -1115,12 +1001,7 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
...
@@ -1115,12 +1001,7 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
buf
=
0xff
;
/* auto contour on */
buf
=
0xff
;
/* auto contour on */
else
else
buf
=
0x0
;
/* auto contour off */
buf
=
0x0
;
/* auto contour off */
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
ret
=
SendControlMsg
(
SET_LUM_CTL
,
AUTO_CONTOUR_FORMATTER
,
1
);
SET_LUM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
AUTO_CONTOUR_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
...
@@ -1130,12 +1011,7 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
...
@@ -1130,12 +1011,7 @@ static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
contour
=
0xffff
;
contour
=
0xffff
;
buf
=
(
contour
>>
10
);
/* contour preset is [0..3f] */
buf
=
(
contour
>>
10
);
/* contour preset is [0..3f] */
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
ret
=
SendControlMsg
(
SET_LUM_CTL
,
PRESET_CONTOUR_FORMATTER
,
1
);
SET_LUM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
PRESET_CONTOUR_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
return
0
;
return
0
;
...
@@ -1146,26 +1022,16 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
...
@@ -1146,26 +1022,16 @@ static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
unsigned
char
buf
;
unsigned
char
buf
;
int
ret
;
int
ret
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
AUTO_CONTOUR_FORMATTER
,
1
);
GET_LUM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
AUTO_CONTOUR_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
if
(
buf
==
0
)
{
if
(
buf
==
0
)
{
/* auto mode off, query current preset value */
/* auto mode off, query current preset value */
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
PRESET_CONTOUR_FORMATTER
,
1
);
GET_LUM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
PRESET_CONTOUR_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
*
contour
=
(
buf
<<
10
)
;
*
contour
=
buf
<<
10
;
}
}
else
else
*
contour
=
-
1
;
*
contour
=
-
1
;
...
@@ -1181,28 +1047,19 @@ static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
...
@@ -1181,28 +1047,19 @@ static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
buf
=
0xff
;
buf
=
0xff
;
else
else
buf
=
0x0
;
buf
=
0x0
;
return
usb_control_msg
(
pdev
->
udev
,
usb_sndctrlpipe
(
pdev
->
udev
,
0
),
return
SendControlMsg
(
SET_LUM_CTL
,
BACK_LIGHT_COMPENSATION_FORMATTER
,
1
);
SET_LUM_CTL
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
BACK_LIGHT_COMPENSATION_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
}
}
static
inline
int
pwc_get_backlight
(
struct
pwc_device
*
pdev
)
static
inline
int
pwc_get_backlight
(
struct
pwc_device
*
pdev
,
int
*
backlight
)
{
{
int
ret
;
int
ret
;
unsigned
char
buf
;
unsigned
char
buf
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
BACK_LIGHT_COMPENSATION_FORMATTER
,
1
);
GET_LUM_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
BACK_LIGHT_COMPENSATION_FORMATTER
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
return
buf
;
*
backlight
=
buf
;
return
0
;
}
}
...
@@ -1217,7 +1074,7 @@ static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
...
@@ -1217,7 +1074,7 @@ static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
return
SendControlMsg
(
SET_LUM_CTL
,
FLICKERLESS_MODE_FORMATTER
,
1
);
return
SendControlMsg
(
SET_LUM_CTL
,
FLICKERLESS_MODE_FORMATTER
,
1
);
}
}
static
inline
int
pwc_get_flicker
(
struct
pwc_device
*
pdev
)
static
inline
int
pwc_get_flicker
(
struct
pwc_device
*
pdev
,
int
*
flicker
)
{
{
int
ret
;
int
ret
;
unsigned
char
buf
;
unsigned
char
buf
;
...
@@ -1225,7 +1082,8 @@ static inline int pwc_get_flicker(struct pwc_device *pdev)
...
@@ -1225,7 +1082,8 @@ static inline int pwc_get_flicker(struct pwc_device *pdev)
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
FLICKERLESS_MODE_FORMATTER
,
1
);
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
FLICKERLESS_MODE_FORMATTER
,
1
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
return
buf
;
*
flicker
=
buf
;
return
0
;
}
}
...
@@ -1241,7 +1099,7 @@ static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
...
@@ -1241,7 +1099,7 @@ static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
return
SendControlMsg
(
SET_LUM_CTL
,
DYNAMIC_NOISE_CONTROL_FORMATTER
,
1
);
return
SendControlMsg
(
SET_LUM_CTL
,
DYNAMIC_NOISE_CONTROL_FORMATTER
,
1
);
}
}
static
inline
int
pwc_get_dynamic_noise
(
struct
pwc_device
*
pdev
)
static
inline
int
pwc_get_dynamic_noise
(
struct
pwc_device
*
pdev
,
int
*
noise
)
{
{
int
ret
;
int
ret
;
unsigned
char
buf
;
unsigned
char
buf
;
...
@@ -1249,14 +1107,15 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev)
...
@@ -1249,14 +1107,15 @@ static inline int pwc_get_dynamic_noise(struct pwc_device *pdev)
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
DYNAMIC_NOISE_CONTROL_FORMATTER
,
1
);
ret
=
RecvControlMsg
(
GET_LUM_CTL
,
DYNAMIC_NOISE_CONTROL_FORMATTER
,
1
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
return
buf
;
*
noise
=
buf
;
return
0
;
}
}
int
pwc_mpt_reset
(
struct
pwc_device
*
pdev
,
int
flags
)
int
pwc_mpt_reset
(
struct
pwc_device
*
pdev
,
int
flags
)
{
{
unsigned
char
buf
;
unsigned
char
buf
;
buf
=
flags
&
0x03
;
// only lower two bits are currently used
buf
=
flags
&
0x03
;
// only lower two bits are currently used
return
SendControlMsg
(
SET_MPT_CTL
,
PT_RESET_CONTROL_FORMATTER
,
1
);
return
SendControlMsg
(
SET_MPT_CTL
,
PT_RESET_CONTROL_FORMATTER
,
1
);
}
}
...
@@ -1293,7 +1152,7 @@ static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_sta
...
@@ -1293,7 +1152,7 @@ static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_sta
}
}
int
pwc_get_cmos_sensor
(
struct
pwc_device
*
pdev
)
int
pwc_get_cmos_sensor
(
struct
pwc_device
*
pdev
,
int
*
sensor
)
{
{
unsigned
char
buf
;
unsigned
char
buf
;
int
ret
=
-
1
,
request
;
int
ret
=
-
1
,
request
;
...
@@ -1305,24 +1164,60 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev)
...
@@ -1305,24 +1164,60 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev)
else
else
request
=
SENSOR_TYPE_FORMATTER2
;
request
=
SENSOR_TYPE_FORMATTER2
;
ret
=
usb_control_msg
(
pdev
->
udev
,
usb_rcvctrlpipe
(
pdev
->
udev
,
0
),
ret
=
RecvControlMsg
(
GET_STATUS_CTL
,
request
,
1
);
GET_STATUS_CTL
,
USB_DIR_IN
|
USB_TYPE_VENDOR
|
USB_RECIP_DEVICE
,
request
,
pdev
->
vcinterface
,
&
buf
,
1
,
HZ
/
2
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
if
(
pdev
->
type
<
675
)
if
(
pdev
->
type
<
675
)
return
buf
|
0x100
;
*
sensor
=
buf
|
0x100
;
else
else
return
buf
;
*
sensor
=
buf
;
return
0
;
}
}
/* End of Add-Ons */
/* End of Add-Ons */
/* ************************************************* */
/* ************************************************* */
/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
ioctl() calls. With 2.4, you have to do tedious copy_from_user()
and copy_to_user() calls. With these macros we circumvent this,
and let me maintain only one source file. The functionality is
exactly the same otherwise.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
/* define local variable for arg */
#define ARG_DEF(ARG_type, ARG_name)\
ARG_type *ARG_name = arg;
/* copy arg to local variable */
#define ARG_IN(ARG_name)
/* nothing */
/* argument itself (referenced) */
#define ARGR(ARG_name) (*ARG_name)
/* argument address */
#define ARGA(ARG_name) ARG_name
/* copy local variable to arg */
#define ARG_OUT(ARG_name)
/* nothing */
#else
#define ARG_DEF(ARG_type, ARG_name)\
ARG_type ARG_name;
#define ARG_IN(ARG_name)\
if (copy_from_user(&ARG_name, arg, sizeof(ARG_name))) {\
ret = -EFAULT;\
break;\
}
#define ARGR(ARG_name) ARG_name
#define ARGA(ARG_name) &ARG_name
#define ARG_OUT(ARG_name)\
if (copy_to_user(arg, &ARG_name, sizeof(ARG_name))) {\
ret = -EFAULT;\
break;\
}
#endif
int
pwc_ioctl
(
struct
pwc_device
*
pdev
,
unsigned
int
cmd
,
void
*
arg
)
int
pwc_ioctl
(
struct
pwc_device
*
pdev
,
unsigned
int
cmd
,
void
*
arg
)
{
{
int
ret
=
0
;
int
ret
=
0
;
...
@@ -1351,225 +1246,254 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
...
@@ -1351,225 +1246,254 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
case
VIDIOCPWCSCQUAL
:
case
VIDIOCPWCSCQUAL
:
{
{
int
*
qual
=
arg
;
ARG_DEF
(
int
,
qual
)
if
(
*
qual
<
0
||
*
qual
>
3
)
ARG_IN
(
qual
)
if
(
ARGR
(
qual
)
<
0
||
ARGR
(
qual
)
>
3
)
ret
=
-
EINVAL
;
ret
=
-
EINVAL
;
else
else
ret
=
pwc_try_video_mode
(
pdev
,
pdev
->
view
.
x
,
pdev
->
view
.
y
,
pdev
->
vframes
,
*
qual
,
pdev
->
vsnapshot
);
ret
=
pwc_try_video_mode
(
pdev
,
pdev
->
view
.
x
,
pdev
->
view
.
y
,
pdev
->
vframes
,
ARGR
(
qual
)
,
pdev
->
vsnapshot
);
if
(
ret
>=
0
)
if
(
ret
>=
0
)
pdev
->
vcompression
=
*
qual
;
pdev
->
vcompression
=
ARGR
(
qual
)
;
break
;
break
;
}
}
case
VIDIOCPWCGCQUAL
:
case
VIDIOCPWCGCQUAL
:
{
{
int
*
qual
=
arg
;
ARG_DEF
(
int
,
qual
)
*
qual
=
pdev
->
vcompression
;
ARGR
(
qual
)
=
pdev
->
vcompression
;
ARG_OUT
(
qual
)
break
;
break
;
}
}
case
VIDIOCPWCPROBE
:
case
VIDIOCPWCPROBE
:
{
{
struct
pwc_probe
*
probe
=
arg
;
ARG_DEF
(
struct
pwc_probe
,
probe
)
strcpy
(
probe
->
name
,
pdev
->
vdev
.
name
);
strcpy
(
ARGR
(
probe
).
name
,
pdev
->
vdev
->
name
);
probe
->
type
=
pdev
->
type
;
ARGR
(
probe
).
type
=
pdev
->
type
;
ARG_OUT
(
probe
)
break
;
}
case
VIDIOCPWCGSERIAL
:
{
ARG_DEF
(
struct
pwc_serial
,
serial
)
strcpy
(
ARGR
(
serial
).
serial
,
pdev
->
serial
);
ARG_OUT
(
serial
)
break
;
break
;
}
}
case
VIDIOCPWCSAGC
:
case
VIDIOCPWCSAGC
:
{
{
int
*
agc
=
arg
;
ARG_DEF
(
int
,
agc
)
if
(
pwc_set_agc
(
pdev
,
*
agc
<
0
?
1
:
0
,
*
agc
))
ARG_IN
(
agc
)
if
(
pwc_set_agc
(
pdev
,
ARGR
(
agc
)
<
0
?
1
:
0
,
ARGR
(
agc
)))
ret
=
-
EINVAL
;
ret
=
-
EINVAL
;
break
;
break
;
}
}
case
VIDIOCPWCGAGC
:
case
VIDIOCPWCGAGC
:
{
{
int
*
agc
=
arg
;
ARG_DEF
(
int
,
agc
)
if
(
pwc_get_agc
(
pdev
,
agc
))
if
(
pwc_get_agc
(
pdev
,
ARGA
(
agc
)
))
ret
=
-
EINVAL
;
ret
=
-
EINVAL
;
ARG_OUT
(
agc
)
break
;
break
;
}
}
case
VIDIOCPWCSSHUTTER
:
case
VIDIOCPWCSSHUTTER
:
{
{
int
*
shutter_speed
=
arg
;
ARG_DEF
(
int
,
shutter_speed
)
ret
=
pwc_set_shutter_speed
(
pdev
,
*
shutter_speed
<
0
?
1
:
0
,
*
shutter_speed
);
ARG_IN
(
shutter_speed
)
ret
=
pwc_set_shutter_speed
(
pdev
,
ARGR
(
shutter_speed
)
<
0
?
1
:
0
,
ARGR
(
shutter_speed
));
break
;
break
;
}
}
case
VIDIOCPWCSAWB
:
case
VIDIOCPWCSAWB
:
{
{
struct
pwc_whitebalance
*
wb
=
arg
;
ARG_DEF
(
struct
pwc_whitebalance
,
wb
)
ret
=
pwc_set_awb
(
pdev
,
wb
->
mode
);
ARG_IN
(
wb
)
if
(
ret
>=
0
&&
wb
->
mode
==
PWC_WB_MANUAL
)
{
ret
=
pwc_set_awb
(
pdev
,
ARGR
(
wb
).
mode
);
pwc_set_red_gain
(
pdev
,
wb
->
manual_red
);
if
(
ret
>=
0
&&
ARGR
(
wb
).
mode
==
PWC_WB_MANUAL
)
{
pwc_set_blue_gain
(
pdev
,
wb
->
manual_blue
);
pwc_set_red_gain
(
pdev
,
ARGR
(
wb
).
manual_red
);
pwc_set_blue_gain
(
pdev
,
ARGR
(
wb
).
manual_blue
);
}
}
break
;
break
;
}
}
case
VIDIOCPWCGAWB
:
case
VIDIOCPWCGAWB
:
{
{
struct
pwc_whitebalance
*
wb
=
arg
;
ARG_DEF
(
struct
pwc_whitebalance
,
wb
)
memset
(
wb
,
0
,
sizeof
(
*
wb
));
memset
(
ARGA
(
wb
),
0
,
sizeof
(
struct
pwc_whitebalance
));
wb
->
mode
=
pwc_get_awb
(
pdev
);
ARGR
(
wb
).
mode
=
pwc_get_awb
(
pdev
);
if
(
wb
->
mode
<
0
)
if
(
ARGR
(
wb
).
mode
<
0
)
ret
=
-
EINVAL
;
ret
=
-
EINVAL
;
else
{
else
{
if
(
wb
->
mode
==
PWC_WB_MANUAL
)
{
if
(
ARGR
(
wb
).
mode
==
PWC_WB_MANUAL
)
{
wb
->
manual_red
=
pwc_get_red_gain
(
pdev
);
ret
=
pwc_get_red_gain
(
pdev
,
&
ARGR
(
wb
).
manual_red
);
wb
->
manual_blue
=
pwc_get_blue_gain
(
pdev
);
if
(
ret
<
0
)
break
;
ret
=
pwc_get_blue_gain
(
pdev
,
&
ARGR
(
wb
).
manual_blue
);
if
(
ret
<
0
)
break
;
}
}
if
(
wb
->
mode
==
PWC_WB_AUTO
)
{
if
(
ARGR
(
wb
).
mode
==
PWC_WB_AUTO
)
{
wb
->
read_red
=
pwc_read_red_gain
(
pdev
);
ret
=
pwc_read_red_gain
(
pdev
,
&
ARGR
(
wb
).
read_red
);
wb
->
read_blue
=
pwc_read_blue_gain
(
pdev
);
if
(
ret
<
0
)
break
;
ret
=
pwc_read_blue_gain
(
pdev
,
&
ARGR
(
wb
).
read_blue
);
if
(
ret
<
0
)
break
;
}
}
}
}
ARG_OUT
(
wb
)
break
;
break
;
}
}
case
VIDIOCPWCSAWBSPEED
:
case
VIDIOCPWCSAWBSPEED
:
{
{
struct
pwc_wb_speed
*
wbs
=
arg
;
ARG_DEF
(
struct
pwc_wb_speed
,
wbs
)
if
(
wbs
->
control_speed
>
0
)
{
if
(
ARGR
(
wbs
).
control_speed
>
0
)
{
ret
=
pwc_set_wb_speed
(
pdev
,
wbs
->
control_speed
);
ret
=
pwc_set_wb_speed
(
pdev
,
ARGR
(
wbs
).
control_speed
);
}
}
if
(
wbs
->
control_delay
>
0
)
{
if
(
ARGR
(
wbs
).
control_delay
>
0
)
{
ret
=
pwc_set_wb_delay
(
pdev
,
wbs
->
control_delay
);
ret
=
pwc_set_wb_delay
(
pdev
,
ARGR
(
wbs
).
control_delay
);
}
}
break
;
break
;
}
}
case
VIDIOCPWCGAWBSPEED
:
case
VIDIOCPWCGAWBSPEED
:
{
{
struct
pwc_wb_speed
*
wbs
=
arg
;
ARG_DEF
(
struct
pwc_wb_speed
,
wbs
)
ret
=
pwc_get_wb_speed
(
pdev
);
ret
=
pwc_get_wb_speed
(
pdev
,
&
ARGR
(
wbs
).
control_speed
);
if
(
ret
<
0
)
if
(
ret
<
0
)
break
;
break
;
wbs
->
control_speed
=
ret
;
ret
=
pwc_get_wb_delay
(
pdev
,
&
ARGR
(
wbs
).
control_delay
);
ret
=
pwc_get_wb_delay
(
pdev
);
if
(
ret
<
0
)
if
(
ret
<
0
)
break
;
break
;
wbs
->
control_delay
=
ret
;
ARG_OUT
(
wbs
)
break
;
break
;
}
}
case
VIDIOCPWCSLED
:
case
VIDIOCPWCSLED
:
{
{
struct
pwc_leds
*
leds
=
arg
;
ARG_DEF
(
struct
pwc_leds
,
leds
)
ret
=
pwc_set_leds
(
pdev
,
leds
->
led_on
,
leds
->
led_off
);
ARG_IN
(
leds
)
ret
=
pwc_set_leds
(
pdev
,
ARGR
(
leds
).
led_on
,
ARGR
(
leds
).
led_off
);
break
;
break
;
}
}
case
VIDIOCPWCGLED
:
case
VIDIOCPWCGLED
:
{
{
struct
pwc_leds
*
leds
=
arg
;
ARG_DEF
(
struct
pwc_leds
,
leds
)
ret
=
pwc_get_leds
(
pdev
,
&
leds
->
led_on
,
&
leds
->
led_off
);
ret
=
pwc_get_leds
(
pdev
,
&
ARGR
(
leds
).
led_on
,
&
ARGR
(
leds
).
led_off
);
ARG_OUT
(
leds
)
break
;
break
;
}
}
case
VIDIOCPWCSCONTOUR
:
case
VIDIOCPWCSCONTOUR
:
{
{
int
*
contour
=
arg
;
ARG_DEF
(
int
,
contour
)
ret
=
pwc_set_contour
(
pdev
,
*
contour
);
ARG_IN
(
contour
)
ret
=
pwc_set_contour
(
pdev
,
ARGR
(
contour
));
break
;
break
;
}
}
case
VIDIOCPWCGCONTOUR
:
case
VIDIOCPWCGCONTOUR
:
{
{
int
*
contour
=
arg
;
ARG_DEF
(
int
,
contour
)
ret
=
pwc_get_contour
(
pdev
,
contour
);
ret
=
pwc_get_contour
(
pdev
,
ARGA
(
contour
));
ARG_OUT
(
contour
)
break
;
break
;
}
}
case
VIDIOCPWCSBACKLIGHT
:
case
VIDIOCPWCSBACKLIGHT
:
{
{
int
*
backlight
=
arg
;
ARG_DEF
(
int
,
backlight
)
ret
=
pwc_set_backlight
(
pdev
,
*
backlight
);
ARG_IN
(
backlight
)
ret
=
pwc_set_backlight
(
pdev
,
ARGR
(
backlight
));
break
;
break
;
}
}
case
VIDIOCPWCGBACKLIGHT
:
case
VIDIOCPWCGBACKLIGHT
:
{
{
int
*
backlight
=
arg
;
ARG_DEF
(
int
,
backlight
)
ret
=
pwc_get_backlight
(
pdev
);
ret
=
pwc_get_backlight
(
pdev
,
ARGA
(
backlight
));
if
(
ret
>=
0
)
ARG_OUT
(
backlight
)
*
backlight
=
ret
;
break
;
break
;
}
}
case
VIDIOCPWCSFLICKER
:
case
VIDIOCPWCSFLICKER
:
{
{
int
*
flicker
=
arg
;
ARG_DEF
(
int
,
flicker
)
ret
=
pwc_set_flicker
(
pdev
,
*
flicker
);
ARG_IN
(
flicker
)
ret
=
pwc_set_flicker
(
pdev
,
ARGR
(
flicker
));
break
;
break
;
}
}
case
VIDIOCPWCGFLICKER
:
case
VIDIOCPWCGFLICKER
:
{
{
int
*
flicker
=
arg
;
ARG_DEF
(
int
,
flicker
)
ret
=
pwc_get_flicker
(
pdev
);
ret
=
pwc_get_flicker
(
pdev
,
ARGA
(
flicker
));
if
(
ret
>=
0
)
ARG_OUT
(
flicker
)
*
flicker
=
ret
;
break
;
break
;
}
}
case
VIDIOCPWCSDYNNOISE
:
case
VIDIOCPWCSDYNNOISE
:
{
{
int
*
dynnoise
=
arg
;
ARG_DEF
(
int
,
dynnoise
)
ret
=
pwc_set_dynamic_noise
(
pdev
,
*
dynnoise
);
ARG_IN
(
dynnoise
)
ret
=
pwc_set_dynamic_noise
(
pdev
,
ARGR
(
dynnoise
));
break
;
break
;
}
}
case
VIDIOCPWCGDYNNOISE
:
case
VIDIOCPWCGDYNNOISE
:
{
{
int
*
dynnoise
=
arg
;
ARG_DEF
(
int
,
dynnoise
)
ret
=
pwc_get_dynamic_noise
(
pdev
);
ret
=
pwc_get_dynamic_noise
(
pdev
,
ARGA
(
dynnoise
));
if
(
ret
<
0
)
ARG_OUT
(
dynnoise
);
break
;
*
dynnoise
=
ret
;
break
;
break
;
}
}
case
VIDIOCPWCGREALSIZE
:
case
VIDIOCPWCGREALSIZE
:
{
{
struct
pwc_imagesize
*
size
=
arg
;
ARG_DEF
(
struct
pwc_imagesize
,
size
)
size
->
width
=
pdev
->
image
.
x
;
ARGR
(
size
).
width
=
pdev
->
image
.
x
;
size
->
height
=
pdev
->
image
.
y
;
ARGR
(
size
).
height
=
pdev
->
image
.
y
;
ARG_OUT
(
size
)
break
;
break
;
}
}
case
VIDIOCPWCMPTRESET
:
case
VIDIOCPWCMPTRESET
:
{
{
int
*
flags
=
arg
;
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
{
{
ret
=
pwc_mpt_reset
(
pdev
,
*
flags
);
ARG_DEF
(
int
,
flags
)
ARG_IN
(
flags
)
ret
=
pwc_mpt_reset
(
pdev
,
ARGR
(
flags
));
if
(
ret
>=
0
)
if
(
ret
>=
0
)
{
{
pdev
->
pan_angle
=
0
;
pdev
->
pan_angle
=
0
;
...
@@ -1582,11 +1506,15 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
...
@@ -1582,11 +1506,15 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
}
}
break
;
break
;
}
}
case
VIDIOCPWCMPTGRANGE
:
case
VIDIOCPWCMPTGRANGE
:
{
{
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
{
{
memcpy
(
arg
,
&
pdev
->
angle_range
,
sizeof
(
struct
pwc_mpt_range
));
ARG_DEF
(
struct
pwc_mpt_range
,
range
)
ARGR
(
range
)
=
pdev
->
angle_range
;
ARG_OUT
(
range
)
}
}
else
else
{
{
...
@@ -1597,23 +1525,25 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
...
@@ -1597,23 +1525,25 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
case
VIDIOCPWCMPTSANGLE
:
case
VIDIOCPWCMPTSANGLE
:
{
{
struct
pwc_mpt_angles
*
angles
=
arg
;
int
new_pan
,
new_tilt
;
int
new_pan
,
new_tilt
;
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
{
{
ARG_DEF
(
struct
pwc_mpt_angles
,
angles
)
ARG_IN
(
angles
)
/* The camera can only set relative angles, so
/* The camera can only set relative angles, so
do some calculations when getting an absolute angle .
do some calculations when getting an absolute angle .
*/
*/
if
(
angles
->
absolute
)
if
(
ARGR
(
angles
).
absolute
)
{
{
new_pan
=
angles
->
pan
;
new_pan
=
ARGR
(
angles
).
pan
;
new_tilt
=
angles
->
tilt
;
new_tilt
=
ARGR
(
angles
).
tilt
;
}
}
else
else
{
{
new_pan
=
pdev
->
pan_angle
+
angles
->
pan
;
new_pan
=
pdev
->
pan_angle
+
ARGR
(
angles
).
pan
;
new_tilt
=
pdev
->
tilt_angle
+
angles
->
tilt
;
new_tilt
=
pdev
->
tilt_angle
+
ARGR
(
angles
).
tilt
;
}
}
/* check absolute ranges */
/* check absolute ranges */
if
(
new_pan
<
pdev
->
angle_range
.
pan_min
||
if
(
new_pan
<
pdev
->
angle_range
.
pan_min
||
...
@@ -1649,17 +1579,19 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
...
@@ -1649,17 +1579,19 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
ret
=
-
ENXIO
;
ret
=
-
ENXIO
;
}
}
break
;
break
;
}
}
case
VIDIOCPWCMPTGANGLE
:
case
VIDIOCPWCMPTGANGLE
:
{
{
struct
pwc_mpt_angles
*
angles
=
arg
;
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
{
{
angles
->
absolute
=
1
;
ARG_DEF
(
struct
pwc_mpt_angles
,
angles
)
angles
->
pan
=
pdev
->
pan_angle
;
angles
->
tilt
=
pdev
->
tilt_angle
;
ARGR
(
angles
).
absolute
=
1
;
ARGR
(
angles
).
pan
=
pdev
->
pan_angle
;
ARGR
(
angles
).
tilt
=
pdev
->
tilt_angle
;
ARG_OUT
(
angles
)
}
}
else
else
{
{
...
@@ -1670,19 +1602,34 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
...
@@ -1670,19 +1602,34 @@ int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
case
VIDIOCPWCMPTSTATUS
:
case
VIDIOCPWCMPTSTATUS
:
{
{
struct
pwc_mpt_status
*
status
=
arg
;
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
if
(
pdev
->
features
&
FEATURE_MOTOR_PANTILT
)
{
{
ret
=
pwc_mpt_get_status
(
pdev
,
status
);
ARG_DEF
(
struct
pwc_mpt_status
,
status
)
ret
=
pwc_mpt_get_status
(
pdev
,
ARGA
(
status
));
ARG_OUT
(
status
)
}
}
else
else
{
{
ret
=
-
ENXIO
;
ret
=
-
ENXIO
;
}
}
break
;
break
;
}
}
case
VIDIOCPWCGVIDCMD
:
{
ARG_DEF
(
struct
pwc_video_command
,
cmd
);
ARGR
(
cmd
).
type
=
pdev
->
type
;
ARGR
(
cmd
).
release
=
pdev
->
release
;
ARGR
(
cmd
).
command_len
=
pdev
->
cmd_len
;
memcpy
(
&
ARGR
(
cmd
).
command_buf
,
pdev
->
cmd_buf
,
pdev
->
cmd_len
);
ARGR
(
cmd
).
bandlength
=
pdev
->
vbandlength
;
ARGR
(
cmd
).
frame_size
=
pdev
->
frame_size
;
ARG_OUT
(
cmd
)
break
;
}
default:
default:
ret
=
-
ENOIOCTLCMD
;
ret
=
-
ENOIOCTLCMD
;
break
;
break
;
...
...
drivers/usb/media/pwc-if.c
View file @
097032ac
/* Linux driver for Philips webcam
/* Linux driver for Philips webcam
USB and Video4Linux interface part.
USB and Video4Linux interface part.
(C) 1999-200
3
Nemosoft Unv.
(C) 1999-200
4
Nemosoft Unv.
This program is free software; you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
...
@@ -42,7 +42,7 @@
...
@@ -42,7 +42,7 @@
- Alistar Moire: QuickCam 3000 Pro device/product ID
- Alistar Moire: QuickCam 3000 Pro device/product ID
- Tony Hoyle: Creative Labs Webcam 5 device/product ID
- Tony Hoyle: Creative Labs Webcam 5 device/product ID
- Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
- Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
- Jk Fang: S
OTEC
Afina Eye ID
- Jk Fang: S
otec
Afina Eye ID
- Xavier Roche: QuickCam Pro 4000 ID
- Xavier Roche: QuickCam Pro 4000 ID
- Jens Knudsen: QuickCam Zoom ID
- Jens Knudsen: QuickCam Zoom ID
- J. Debert: QuickCam for Notebooks ID
- J. Debert: QuickCam for Notebooks ID
...
@@ -90,6 +90,7 @@ static struct usb_device_id pwc_device_table [] = {
...
@@ -90,6 +90,7 @@ static struct usb_device_id pwc_device_table [] = {
{
USB_DEVICE
(
0x041E
,
0x400C
)
},
/* Creative Webcam 5 */
{
USB_DEVICE
(
0x041E
,
0x400C
)
},
/* Creative Webcam 5 */
{
USB_DEVICE
(
0x041E
,
0x4011
)
},
/* Creative Webcam Pro Ex */
{
USB_DEVICE
(
0x041E
,
0x4011
)
},
/* Creative Webcam Pro Ex */
{
USB_DEVICE
(
0x04CC
,
0x8116
)
},
/* Afina Eye */
{
USB_DEVICE
(
0x04CC
,
0x8116
)
},
/* Afina Eye */
{
USB_DEVICE
(
0x06BE
,
0x8116
)
},
/* new Afina Eye */
{
USB_DEVICE
(
0x0d81
,
0x1910
)
},
/* Visionite */
{
USB_DEVICE
(
0x0d81
,
0x1910
)
},
/* Visionite */
{
USB_DEVICE
(
0x0d81
,
0x1900
)
},
{
USB_DEVICE
(
0x0d81
,
0x1900
)
},
{
}
{
}
...
@@ -151,7 +152,9 @@ static struct video_device pwc_template = {
...
@@ -151,7 +152,9 @@ static struct video_device pwc_template = {
.
name
=
"Philips Webcam"
,
/* Filled in later */
.
name
=
"Philips Webcam"
,
/* Filled in later */
.
type
=
VID_TYPE_CAPTURE
,
.
type
=
VID_TYPE_CAPTURE
,
.
hardware
=
VID_HARDWARE_PWC
,
.
hardware
=
VID_HARDWARE_PWC
,
.
release
=
video_device_release
,
.
fops
=
&
pwc_fops
,
.
fops
=
&
pwc_fops
,
.
minor
=
-
1
,
};
};
/***************************************************************************/
/***************************************************************************/
...
@@ -258,7 +261,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
...
@@ -258,7 +261,7 @@ static int pwc_allocate_buffers(struct pwc_device *pdev)
return
-
ENXIO
;
return
-
ENXIO
;
}
}
#endif
#endif
/* Allocate Isochronous pipe buffers */
/* Allocate Isochron
u
ous pipe buffers */
for
(
i
=
0
;
i
<
MAX_ISO_BUFS
;
i
++
)
{
for
(
i
=
0
;
i
<
MAX_ISO_BUFS
;
i
++
)
{
if
(
pdev
->
sbuf
[
i
].
data
==
NULL
)
{
if
(
pdev
->
sbuf
[
i
].
data
==
NULL
)
{
kbuf
=
kmalloc
(
ISO_BUFFER_SIZE
,
GFP_KERNEL
);
kbuf
=
kmalloc
(
ISO_BUFFER_SIZE
,
GFP_KERNEL
);
...
@@ -443,7 +446,7 @@ static inline int pwc_next_fill_frame(struct pwc_device *pdev)
...
@@ -443,7 +446,7 @@ static inline int pwc_next_fill_frame(struct pwc_device *pdev)
{
{
int
ret
;
int
ret
;
unsigned
long
flags
;
unsigned
long
flags
;
ret
=
0
;
ret
=
0
;
spin_lock_irqsave
(
&
pdev
->
ptrlock
,
flags
);
spin_lock_irqsave
(
&
pdev
->
ptrlock
,
flags
);
if
(
pdev
->
fill_frame
!=
NULL
)
{
if
(
pdev
->
fill_frame
!=
NULL
)
{
...
@@ -488,7 +491,7 @@ static inline int pwc_next_fill_frame(struct pwc_device *pdev)
...
@@ -488,7 +491,7 @@ static inline int pwc_next_fill_frame(struct pwc_device *pdev)
/**
/**
\brief Reset all buffers, pointers and lists, except for the image_used[] buffer.
\brief Reset all buffers, pointers and lists, except for the image_used[] buffer.
If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble.
If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble.
*/
*/
static
void
pwc_reset_buffers
(
struct
pwc_device
*
pdev
)
static
void
pwc_reset_buffers
(
struct
pwc_device
*
pdev
)
...
@@ -525,7 +528,7 @@ static int pwc_handle_frame(struct pwc_device *pdev)
...
@@ -525,7 +528,7 @@ static int pwc_handle_frame(struct pwc_device *pdev)
{
{
int
ret
=
0
;
int
ret
=
0
;
unsigned
long
flags
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
pdev
->
ptrlock
,
flags
);
spin_lock_irqsave
(
&
pdev
->
ptrlock
,
flags
);
/* First grab our read_frame; this is removed from all lists, so
/* First grab our read_frame; this is removed from all lists, so
we can release the lock after this without problems */
we can release the lock after this without problems */
...
@@ -548,7 +551,7 @@ static int pwc_handle_frame(struct pwc_device *pdev)
...
@@ -548,7 +551,7 @@ static int pwc_handle_frame(struct pwc_device *pdev)
Trace
(
TRACE_SEQUENCE
,
"Decompressing frame %d
\n
"
,
pdev
->
read_frame
->
sequence
);
Trace
(
TRACE_SEQUENCE
,
"Decompressing frame %d
\n
"
,
pdev
->
read_frame
->
sequence
);
#endif
#endif
/* Decompression is a lenghty process, so it's outside of the lock.
/* Decompression is a lenghty process, so it's outside of the lock.
This gives the isoc_handler the opportunity to fill more frames
This gives the isoc_handler the opportunity to fill more frames
in the mean time.
in the mean time.
*/
*/
spin_unlock_irqrestore
(
&
pdev
->
ptrlock
,
flags
);
spin_unlock_irqrestore
(
&
pdev
->
ptrlock
,
flags
);
...
@@ -643,7 +646,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
...
@@ -643,7 +646,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
else
{
else
{
fillptr
=
fbuf
->
data
+
fbuf
->
filled
;
fillptr
=
fbuf
->
data
+
fbuf
->
filled
;
}
}
/* Reset ISOC error counter. We did get here, after all. */
/* Reset ISOC error counter. We did get here, after all. */
pdev
->
visoc_errors
=
0
;
pdev
->
visoc_errors
=
0
;
...
@@ -662,8 +665,8 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
...
@@ -662,8 +665,8 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
pdev
->
vsync
=
2
;
pdev
->
vsync
=
2
;
/* ...copy data to frame buffer, if possible */
/* ...copy data to frame buffer, if possible */
if
(
flen
+
fbuf
->
filled
>
pdev
->
frame_size
)
{
if
(
flen
+
fbuf
->
filled
>
pdev
->
frame_
total_
size
)
{
Trace
(
TRACE_FLOW
,
"Frame buffer overflow (flen = %d, frame_
size = %d).
\n
"
,
flen
,
pdev
->
frame
_size
);
Trace
(
TRACE_FLOW
,
"Frame buffer overflow (flen = %d, frame_
total_size = %d).
\n
"
,
flen
,
pdev
->
frame_total
_size
);
pdev
->
vsync
=
0
;
/* Hmm, let's wait for an EOF (end-of-frame) */
pdev
->
vsync
=
0
;
/* Hmm, let's wait for an EOF (end-of-frame) */
pdev
->
vframes_error
++
;
pdev
->
vframes_error
++
;
}
}
...
@@ -728,7 +731,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
...
@@ -728,7 +731,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
pdev
->
drop_frames
--
;
pdev
->
drop_frames
--
;
else
{
else
{
/* Check for underflow first */
/* Check for underflow first */
if
(
fbuf
->
filled
<
pdev
->
frame_size
)
{
if
(
fbuf
->
filled
<
pdev
->
frame_
total_
size
)
{
Trace
(
TRACE_FLOW
,
"Frame buffer underflow (%d bytes); discarded.
\n
"
,
fbuf
->
filled
);
Trace
(
TRACE_FLOW
,
"Frame buffer underflow (%d bytes); discarded.
\n
"
,
fbuf
->
filled
);
pdev
->
vframes_error
++
;
pdev
->
vframes_error
++
;
}
}
...
@@ -817,7 +820,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
...
@@ -817,7 +820,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
if
(
pdev
->
vmax_packet_size
<
0
||
pdev
->
vmax_packet_size
>
ISO_MAX_FRAME_SIZE
)
{
if
(
pdev
->
vmax_packet_size
<
0
||
pdev
->
vmax_packet_size
>
ISO_MAX_FRAME_SIZE
)
{
Err
(
"Failed to find packet size for video endpoint in current alternate setting.
\n
"
);
Err
(
"Failed to find packet size for video endpoint in current alternate setting.
\n
"
);
return
-
ENFILE
;
/* Odd error, that should be notic
e
able */
return
-
ENFILE
;
/* Odd error, that should be noticable */
}
}
/* Set alternate interface */
/* Set alternate interface */
...
@@ -874,7 +877,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
...
@@ -874,7 +877,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
if
(
ret
)
if
(
ret
)
Err
(
"isoc_init() submit_urb %d failed with error %d
\n
"
,
i
,
ret
);
Err
(
"isoc_init() submit_urb %d failed with error %d
\n
"
,
i
,
ret
);
else
else
Trace
(
TRACE_
OPEN
,
"URB 0x%p submitted.
\n
"
,
pdev
->
sbuf
[
i
].
urb
);
Trace
(
TRACE_
MEMORY
,
"URB 0x%p submitted.
\n
"
,
pdev
->
sbuf
[
i
].
urb
);
}
}
/* All is done... */
/* All is done... */
...
@@ -886,7 +889,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
...
@@ -886,7 +889,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
static
void
pwc_isoc_cleanup
(
struct
pwc_device
*
pdev
)
static
void
pwc_isoc_cleanup
(
struct
pwc_device
*
pdev
)
{
{
int
i
;
int
i
;
Trace
(
TRACE_OPEN
,
">> pwc_isoc_cleanup()
\n
"
);
Trace
(
TRACE_OPEN
,
">> pwc_isoc_cleanup()
\n
"
);
if
(
pdev
==
NULL
)
if
(
pdev
==
NULL
)
return
;
return
;
...
@@ -937,9 +940,9 @@ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_f
...
@@ -937,9 +940,9 @@ int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_f
Trace
(
TRACE_FLOW
,
"pwc_set_video_mode attempt 2 failed.
\n
"
);
Trace
(
TRACE_FLOW
,
"pwc_set_video_mode attempt 2 failed.
\n
"
);
}
}
}
}
if
(
start
==
0
)
if
(
start
==
0
)
{
{
if
(
pwc_isoc_init
(
pdev
)
<
0
)
if
(
pwc_isoc_init
(
pdev
)
<
0
)
{
{
Info
(
"Failed to restart ISOC transfers in pwc_try_video_mode.
\n
"
);
Info
(
"Failed to restart ISOC transfers in pwc_try_video_mode.
\n
"
);
ret
=
-
EAGAIN
;
/* let's try again, who knows if it works a second time */
ret
=
-
EAGAIN
;
/* let's try again, who knows if it works a second time */
...
@@ -972,27 +975,31 @@ static int pwc_video_open(struct inode *inode, struct file *file)
...
@@ -972,27 +975,31 @@ static int pwc_video_open(struct inode *inode, struct file *file)
Trace
(
TRACE_OPEN
,
"Doing first time initialization.
\n
"
);
Trace
(
TRACE_OPEN
,
"Doing first time initialization.
\n
"
);
pdev
->
usb_init
=
1
;
pdev
->
usb_init
=
1
;
if
(
pwc_trace
&
TRACE_OPEN
)
{
if
(
pwc_trace
&
TRACE_OPEN
)
{
/* Query sensor type */
/* Query sensor type */
const
char
*
sensor_type
=
NULL
;
const
char
*
sensor_type
=
NULL
;
int
ret
;
i
=
pwc_get_cmos_sensor
(
pdev
);
ret
=
pwc_get_cmos_sensor
(
pdev
,
&
i
);
switch
(
i
)
{
if
(
ret
>=
0
)
case
-
1
:
/* Unknown, show nothing */
;
break
;
{
case
0x00
:
sensor_type
=
"Hyundai CMOS sensor"
;
break
;
switch
(
i
)
{
case
0x20
:
sensor_type
=
"Sony CCD sensor + TDA8787"
;
break
;
case
0x00
:
sensor_type
=
"Hyundai CMOS sensor"
;
break
;
case
0x2E
:
sensor_type
=
"Sony CCD sensor + Exas 98L59"
;
break
;
case
0x20
:
sensor_type
=
"Sony CCD sensor + TDA8787"
;
break
;
case
0x2F
:
sensor_type
=
"Sony CCD sensor + ADI 9804"
;
break
;
case
0x2E
:
sensor_type
=
"Sony CCD sensor + Exas 98L59"
;
break
;
case
0x30
:
sensor_type
=
"Sharp CCD sensor + TDA8787"
;
break
;
case
0x2F
:
sensor_type
=
"Sony CCD sensor + ADI 9804"
;
break
;
case
0x3E
:
sensor_type
=
"Sharp CCD sensor + Exas 98L59"
;
break
;
case
0x30
:
sensor_type
=
"Sharp CCD sensor + TDA8787"
;
break
;
case
0x3F
:
sensor_type
=
"Sharp CCD sensor + ADI 9804"
;
break
;
case
0x3E
:
sensor_type
=
"Sharp CCD sensor + Exas 98L59"
;
break
;
case
0x40
:
sensor_type
=
"UPA 1021 sensor"
;
break
;
case
0x3F
:
sensor_type
=
"Sharp CCD sensor + ADI 9804"
;
break
;
case
0x100
:
sensor_type
=
"VGA sensor"
;
break
;
case
0x40
:
sensor_type
=
"UPA 1021 sensor"
;
break
;
case
0x101
:
sensor_type
=
"PAL MR sensor"
;
break
;
case
0x100
:
sensor_type
=
"VGA sensor"
;
break
;
default:
sensor_type
=
"unknown type of sensor"
;
break
;
case
0x101
:
sensor_type
=
"PAL MR sensor"
;
break
;
default:
sensor_type
=
"unknown type of sensor"
;
break
;
}
}
}
if
(
sensor_type
!=
NULL
)
if
(
sensor_type
!=
NULL
)
Info
(
"This %s camera is equipped with a %s (%d).
\n
"
,
pdev
->
vdev
.
name
,
sensor_type
,
i
);
Info
(
"This %s camera is equipped with a %s (%d).
\n
"
,
pdev
->
vdev
->
name
,
sensor_type
,
i
);
}
}
}
}
...
@@ -1037,6 +1044,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
...
@@ -1037,6 +1044,7 @@ static int pwc_video_open(struct inode *inode, struct file *file)
/* Set some defaults */
/* Set some defaults */
pdev
->
vsnapshot
=
0
;
pdev
->
vsnapshot
=
0
;
/* Start iso pipe for video; first try the last used video size
/* Start iso pipe for video; first try the last used video size
(or the default one); if that fails try QCIF/10 or QSIF/10;
(or the default one); if that fails try QCIF/10 or QSIF/10;
it that fails too, give up.
it that fails too, give up.
...
@@ -1090,7 +1098,7 @@ static int pwc_video_close(struct inode *inode, struct file *file)
...
@@ -1090,7 +1098,7 @@ static int pwc_video_close(struct inode *inode, struct file *file)
/* Dump statistics, but only if a reasonable amount of frames were
/* Dump statistics, but only if a reasonable amount of frames were
processed (to prevent endless log-entries in case of snap-shot
processed (to prevent endless log-entries in case of snap-shot
programs)
programs)
*/
*/
if
(
pdev
->
vframe_count
>
20
)
if
(
pdev
->
vframe_count
>
20
)
Info
(
"Closing video device: %d frames received, dumped %d frames, %d frames with errors.
\n
"
,
pdev
->
vframe_count
,
pdev
->
vframes_dumped
,
pdev
->
vframes_error
);
Info
(
"Closing video device: %d frames received, dumped %d frames, %d frames with errors.
\n
"
,
pdev
->
vframe_count
,
pdev
->
vframes_dumped
,
pdev
->
vframes_error
);
...
@@ -1111,7 +1119,7 @@ static int pwc_video_close(struct inode *inode, struct file *file)
...
@@ -1111,7 +1119,7 @@ static int pwc_video_close(struct inode *inode, struct file *file)
Info
(
"Failed to set LED on/off time.
\n
"
);
Info
(
"Failed to set LED on/off time.
\n
"
);
if
(
power_save
)
{
if
(
power_save
)
{
i
=
pwc_camera_power
(
pdev
,
0
);
i
=
pwc_camera_power
(
pdev
,
0
);
if
(
i
<
0
)
if
(
i
<
0
)
Err
(
"Failed to power down camera (%d)
\n
"
,
i
);
Err
(
"Failed to power down camera (%d)
\n
"
,
i
);
}
}
}
}
...
@@ -1139,6 +1147,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
...
@@ -1139,6 +1147,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
struct
pwc_device
*
pdev
;
struct
pwc_device
*
pdev
;
int
noblock
=
file
->
f_flags
&
O_NONBLOCK
;
int
noblock
=
file
->
f_flags
&
O_NONBLOCK
;
DECLARE_WAITQUEUE
(
wait
,
current
);
DECLARE_WAITQUEUE
(
wait
,
current
);
int
bytes_to_read
;
Trace
(
TRACE_READ
,
"video_read(0x%p, %p, %d) called.
\n
"
,
vdev
,
buf
,
count
);
Trace
(
TRACE_READ
,
"video_read(0x%p, %p, %d) called.
\n
"
,
vdev
,
buf
,
count
);
if
(
vdev
==
NULL
)
if
(
vdev
==
NULL
)
...
@@ -1175,20 +1184,25 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
...
@@ -1175,20 +1184,25 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
}
}
remove_wait_queue
(
&
pdev
->
frameq
,
&
wait
);
remove_wait_queue
(
&
pdev
->
frameq
,
&
wait
);
set_current_state
(
TASK_RUNNING
);
set_current_state
(
TASK_RUNNING
);
/* Decompress and release frame */
/* Decompress and release frame */
if
(
pwc_handle_frame
(
pdev
))
if
(
pwc_handle_frame
(
pdev
))
return
-
EFAULT
;
return
-
EFAULT
;
}
}
Trace
(
TRACE_READ
,
"Copying data to user space.
\n
"
);
Trace
(
TRACE_READ
,
"Copying data to user space.
\n
"
);
if
(
pdev
->
vpalette
==
VIDEO_PALETTE_RAW
)
bytes_to_read
=
pdev
->
frame_size
;
else
bytes_to_read
=
pdev
->
view
.
size
;
/* copy bytes to user space; we allow for partial reads */
/* copy bytes to user space; we allow for partial reads */
if
(
count
+
pdev
->
image_read_pos
>
pdev
->
view
.
size
)
if
(
count
+
pdev
->
image_read_pos
>
bytes_to_read
)
count
=
pdev
->
view
.
size
-
pdev
->
image_read_pos
;
count
=
bytes_to_read
-
pdev
->
image_read_pos
;
if
(
copy_to_user
(
buf
,
pdev
->
image_ptr
[
pdev
->
fill_image
]
+
pdev
->
image_read_pos
,
count
))
if
(
copy_to_user
(
buf
,
pdev
->
image_ptr
[
pdev
->
fill_image
]
+
pdev
->
image_read_pos
,
count
))
return
-
EFAULT
;
return
-
EFAULT
;
pdev
->
image_read_pos
+=
count
;
pdev
->
image_read_pos
+=
count
;
if
(
pdev
->
image_read_pos
>=
pdev
->
view
.
size
)
{
/* All data has been read */
if
(
pdev
->
image_read_pos
>=
bytes_to_read
)
{
/* All data has been read */
pdev
->
image_read_pos
=
0
;
pdev
->
image_read_pos
=
0
;
pwc_next_image
(
pdev
);
pwc_next_image
(
pdev
);
}
}
...
@@ -1260,7 +1274,7 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
...
@@ -1260,7 +1274,7 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
}
}
case
VIDIOCSCHAN
:
case
VIDIOCSCHAN
:
{
{
/* The spec says the argument is an integer, but
/* The spec says the argument is an integer, but
the bttv driver uses a video_channel arg, which
the bttv driver uses a video_channel arg, which
makes sense becasue it also has the norm flag.
makes sense becasue it also has the norm flag.
...
@@ -1278,8 +1292,6 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
...
@@ -1278,8 +1292,6 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
struct
video_picture
*
p
=
arg
;
struct
video_picture
*
p
=
arg
;
int
val
;
int
val
;
p
->
colour
=
0x8000
;
p
->
hue
=
0x8000
;
val
=
pwc_get_brightness
(
pdev
);
val
=
pwc_get_brightness
(
pdev
);
if
(
val
>=
0
)
if
(
val
>=
0
)
p
->
brightness
=
val
;
p
->
brightness
=
val
;
...
@@ -1302,11 +1314,11 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
...
@@ -1302,11 +1314,11 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
else
else
p
->
colour
=
0xffff
;
p
->
colour
=
0xffff
;
p
->
depth
=
24
;
p
->
depth
=
24
;
p
->
palette
=
VIDEO_PALETTE_YUV420P
;
p
->
palette
=
pdev
->
vpalette
;
p
->
hue
=
0xFFFF
;
/* N/A */
p
->
hue
=
0xFFFF
;
/* N/A */
break
;
break
;
}
}
case
VIDIOCSPICT
:
case
VIDIOCSPICT
:
{
{
struct
video_picture
*
p
=
arg
;
struct
video_picture
*
p
=
arg
;
...
@@ -1318,13 +1330,22 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
...
@@ -1318,13 +1330,22 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
is used exactly once in the uncompress
is used exactly once in the uncompress
routine.
routine.
*/
*/
if
(
p
->
palette
&&
p
->
palette
!=
VIDEO_PALETTE_YUV420P
)
{
return
-
EINVAL
;
}
pwc_set_brightness
(
pdev
,
p
->
brightness
);
pwc_set_brightness
(
pdev
,
p
->
brightness
);
pwc_set_contrast
(
pdev
,
p
->
contrast
);
pwc_set_contrast
(
pdev
,
p
->
contrast
);
pwc_set_gamma
(
pdev
,
p
->
whiteness
);
pwc_set_gamma
(
pdev
,
p
->
whiteness
);
pwc_set_saturation
(
pdev
,
p
->
colour
);
pwc_set_saturation
(
pdev
,
p
->
colour
);
if
(
p
->
palette
&&
p
->
palette
!=
pdev
->
vpalette
)
{
switch
(
p
->
palette
)
{
case
VIDEO_PALETTE_YUV420P
:
case
VIDEO_PALETTE_RAW
:
pdev
->
vpalette
=
p
->
palette
;
return
pwc_try_video_mode
(
pdev
,
pdev
->
image
.
x
,
pdev
->
image
.
y
,
pdev
->
vframes
,
pdev
->
vcompression
,
pdev
->
vsnapshot
);
break
;
default:
return
-
EINVAL
;
break
;
}
}
break
;
break
;
}
}
...
@@ -1398,13 +1419,23 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
...
@@ -1398,13 +1419,23 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
various palettes... The driver doesn't support
various palettes... The driver doesn't support
such small images, so I'm working around it.
such small images, so I'm working around it.
*/
*/
if
(
vm
->
format
&&
vm
->
format
!=
VIDEO_PALETTE_YUV420P
)
if
(
vm
->
format
)
return
-
EINVAL
;
{
switch
(
vm
->
format
)
{
case
VIDEO_PALETTE_YUV420P
:
case
VIDEO_PALETTE_RAW
:
break
;
default:
return
-
EINVAL
;
break
;
}
}
if
((
vm
->
width
!=
pdev
->
view
.
x
||
vm
->
height
!=
pdev
->
view
.
y
)
&&
if
((
vm
->
width
!=
pdev
->
view
.
x
||
vm
->
height
!=
pdev
->
view
.
y
)
&&
(
vm
->
width
>=
pdev
->
view_min
.
x
&&
vm
->
height
>=
pdev
->
view_min
.
y
))
{
(
vm
->
width
>=
pdev
->
view_min
.
x
&&
vm
->
height
>=
pdev
->
view_min
.
y
))
{
int
ret
;
int
ret
;
Trace
(
TRACE_OPEN
,
"VIDIOCMCAPTURE: changing size to please xawtv :-(.
\n
"
);
Trace
(
TRACE_OPEN
,
"VIDIOCMCAPTURE: changing size to please xawtv :-(.
\n
"
);
ret
=
pwc_try_video_mode
(
pdev
,
vm
->
width
,
vm
->
height
,
pdev
->
vframes
,
pdev
->
vcompression
,
pdev
->
vsnapshot
);
ret
=
pwc_try_video_mode
(
pdev
,
vm
->
width
,
vm
->
height
,
pdev
->
vframes
,
pdev
->
vcompression
,
pdev
->
vsnapshot
);
if
(
ret
)
if
(
ret
)
...
@@ -1523,7 +1554,7 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
...
@@ -1523,7 +1554,7 @@ static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
{
{
struct
video_unit
*
vu
=
arg
;
struct
video_unit
*
vu
=
arg
;
vu
->
video
=
pdev
->
vdev
.
minor
&
0x3F
;
vu
->
video
=
pdev
->
vdev
->
minor
&
0x3F
;
vu
->
audio
=
-
1
;
/* not known yet */
vu
->
audio
=
-
1
;
/* not known yet */
vu
->
vbi
=
-
1
;
vu
->
vbi
=
-
1
;
vu
->
radio
=
-
1
;
vu
->
radio
=
-
1
;
...
@@ -1636,12 +1667,12 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
...
@@ -1636,12 +1667,12 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
type_id
=
690
;
type_id
=
690
;
break
;
break
;
case
0x0310
:
case
0x0310
:
Info
(
"Philips PCVC730K (ToUCam Fun) USB webcam detected.
\n
"
);
Info
(
"Philips PCVC730K (ToUCam Fun)
/PCVC830 (ToUCam II)
USB webcam detected.
\n
"
);
name
=
"Philips 730 webcam"
;
name
=
"Philips 730 webcam"
;
type_id
=
730
;
type_id
=
730
;
break
;
break
;
case
0x0311
:
case
0x0311
:
Info
(
"Philips PCVC740K (ToUCam Pro) USB webcam detected.
\n
"
);
Info
(
"Philips PCVC740K (ToUCam Pro)
/PCVC840 (ToUCam II)
USB webcam detected.
\n
"
);
name
=
"Philips 740 webcam"
;
name
=
"Philips 740 webcam"
;
type_id
=
740
;
type_id
=
740
;
break
;
break
;
...
@@ -1755,17 +1786,44 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
...
@@ -1755,17 +1786,44 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
break
;
break
;
}
}
}
}
else
if
(
vendor_id
==
0x04cc
)
{
else
if
(
vendor_id
==
0x04cc
)
{
switch
(
product_id
)
{
switch
(
product_id
)
{
case
0x8116
:
case
0x8116
:
Info
(
"Sotec Afina Eye USB webcam detected.
\n
"
);
Info
(
"Sotec Afina Eye USB webcam detected.
\n
"
);
name
=
"Sotec Afina Eye"
;
name
=
"Sotec Afina Eye"
;
type_id
=
730
;
type_id
=
730
;
break
;
break
;
default:
return
-
ENODEV
;
break
;
}
}
else
if
(
vendor_id
==
0x06be
)
{
switch
(
product_id
)
{
case
0x8116
:
/* Basicly the same as the Sotec Afina Eye */
Info
(
"AME CU-001 USB webcam detected.
\n
"
);
name
=
"AME CU-001"
;
type_id
=
730
;
break
;
default:
return
-
ENODEV
;
break
;
}
}
else
if
(
vendor_id
==
0x06be
)
{
switch
(
product_id
)
{
case
0x8116
:
/* This is essentially the same cam as the Sotec Afina Eye */
Info
(
"AME Co. Afina Eye USB webcam detected.
\n
"
);
name
=
"AME Co. Afina Eye"
;
type_id
=
750
;
break
;
default:
default:
return
-
ENODEV
;
return
-
ENODEV
;
break
;
break
;
}
}
}
}
else
if
(
vendor_id
==
0x0d81
)
{
else
if
(
vendor_id
==
0x0d81
)
{
switch
(
product_id
)
{
switch
(
product_id
)
{
...
@@ -1804,6 +1862,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
...
@@ -1804,6 +1862,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pdev
->
type
=
type_id
;
pdev
->
type
=
type_id
;
pdev
->
vsize
=
default_size
;
pdev
->
vsize
=
default_size
;
pdev
->
vframes
=
default_fps
;
pdev
->
vframes
=
default_fps
;
strcpy
(
pdev
->
serial
,
serial_number
);
pdev
->
features
=
features
;
pdev
->
features
=
features
;
if
(
vendor_id
==
0x046D
&&
product_id
==
0x08B5
)
if
(
vendor_id
==
0x046D
&&
product_id
==
0x08B5
)
{
{
...
@@ -1815,8 +1874,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
...
@@ -1815,8 +1874,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pdev
->
angle_range
.
pan_max
=
7000
;
pdev
->
angle_range
.
pan_max
=
7000
;
pdev
->
angle_range
.
tilt_min
=
-
3000
;
pdev
->
angle_range
.
tilt_min
=
-
3000
;
pdev
->
angle_range
.
tilt_max
=
2500
;
pdev
->
angle_range
.
tilt_max
=
2500
;
pdev
->
angle_range
.
zoom_min
=
-
1
;
pdev
->
angle_range
.
zoom_max
=
-
1
;
}
}
init_MUTEX
(
&
pdev
->
modlock
);
init_MUTEX
(
&
pdev
->
modlock
);
...
@@ -1826,11 +1883,19 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
...
@@ -1826,11 +1883,19 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
init_waitqueue_head
(
&
pdev
->
frameq
);
init_waitqueue_head
(
&
pdev
->
frameq
);
pdev
->
vcompression
=
pwc_preferred_compression
;
pdev
->
vcompression
=
pwc_preferred_compression
;
memcpy
(
&
pdev
->
vdev
,
&
pwc_template
,
sizeof
(
pwc_template
));
/* Allocate video_device structure */
strcpy
(
pdev
->
vdev
.
name
,
name
);
pdev
->
vdev
=
video_device_alloc
();
pdev
->
vdev
.
owner
=
THIS_MODULE
;
if
(
pdev
->
vdev
==
0
)
pdev
->
vdev
.
priv
=
pdev
;
{
Err
(
"Err, cannot allocate video_device struture. Failing probe."
);
kfree
(
pdev
);
return
-
ENOMEM
;
}
memcpy
(
pdev
->
vdev
,
&
pwc_template
,
sizeof
(
pwc_template
));
strcpy
(
pdev
->
vdev
->
name
,
name
);
pdev
->
vdev
->
owner
=
THIS_MODULE
;
video_set_drvdata
(
pdev
->
vdev
,
pdev
);
pdev
->
release
=
udev
->
descriptor
.
bcdDevice
;
pdev
->
release
=
udev
->
descriptor
.
bcdDevice
;
Trace
(
TRACE_PROBE
,
"Release: %04x
\n
"
,
pdev
->
release
);
Trace
(
TRACE_PROBE
,
"Release: %04x
\n
"
,
pdev
->
release
);
...
@@ -1848,15 +1913,16 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
...
@@ -1848,15 +1913,16 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
}
}
}
}
pdev
->
vdev
.
release
=
video_device_release
;
pdev
->
vdev
->
release
=
video_device_release
;
i
=
video_register_device
(
&
pdev
->
vdev
,
VFL_TYPE_GRABBER
,
video_nr
);
i
=
video_register_device
(
pdev
->
vdev
,
VFL_TYPE_GRABBER
,
video_nr
);
if
(
i
<
0
)
{
if
(
i
<
0
)
{
Err
(
"Failed to register as video device (%d).
\n
"
,
i
);
Err
(
"Failed to register as video device (%d).
\n
"
,
i
);
video_device_release
(
pdev
->
vdev
);
/* Drip... drip... drip... */
kfree
(
pdev
);
/* Oops, no memory leaks please */
kfree
(
pdev
);
/* Oops, no memory leaks please */
return
-
EIO
;
return
-
EIO
;
}
}
else
{
else
{
Info
(
"Registered as /dev/video%d.
\n
"
,
pdev
->
vdev
.
minor
&
0x3F
);
Info
(
"Registered as /dev/video%d.
\n
"
,
pdev
->
vdev
->
minor
&
0x3F
);
}
}
/* occupy slot */
/* occupy slot */
...
@@ -1894,14 +1960,14 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
...
@@ -1894,14 +1960,14 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
Err
(
"pwc_disconnect() Magic number failed. Consult your scrolls and try again.
\n
"
);
Err
(
"pwc_disconnect() Magic number failed. Consult your scrolls and try again.
\n
"
);
goto
disconnect_out
;
goto
disconnect_out
;
}
}
#endif
#endif
/* We got unplugged; this is signalled by an EPIPE error code */
/* We got unplugged; this is signalled by an EPIPE error code */
if
(
pdev
->
vopen
)
{
if
(
pdev
->
vopen
)
{
Info
(
"Disconnected while webcam is in use!
\n
"
);
Info
(
"Disconnected while webcam is in use!
\n
"
);
pdev
->
error_status
=
EPIPE
;
pdev
->
error_status
=
EPIPE
;
}
}
/* Alert waiting processes */
/* Alert waiting processes */
wake_up_interruptible
(
&
pdev
->
frameq
);
wake_up_interruptible
(
&
pdev
->
frameq
);
/* Wait until device is closed */
/* Wait until device is closed */
...
@@ -1909,7 +1975,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
...
@@ -1909,7 +1975,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
schedule
();
schedule
();
/* Device is now closed, so we can safely unregister it */
/* Device is now closed, so we can safely unregister it */
Trace
(
TRACE_PROBE
,
"Unregistering video device in disconnect().
\n
"
);
Trace
(
TRACE_PROBE
,
"Unregistering video device in disconnect().
\n
"
);
video_unregister_device
(
&
pdev
->
vdev
);
video_unregister_device
(
pdev
->
vdev
);
/* Free memory (don't set pdev to 0 just yet) */
/* Free memory (don't set pdev to 0 just yet) */
kfree
(
pdev
);
kfree
(
pdev
);
...
@@ -1928,7 +1994,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
...
@@ -1928,7 +1994,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
static
int
pwc_atoi
(
const
char
*
s
)
static
int
pwc_atoi
(
const
char
*
s
)
{
{
int
k
=
0
;
int
k
=
0
;
k
=
0
;
k
=
0
;
while
(
*
s
!=
'\0'
&&
*
s
>=
'0'
&&
*
s
<=
'9'
)
{
while
(
*
s
!=
'\0'
&&
*
s
>=
'0'
&&
*
s
<=
'9'
)
{
k
=
10
*
k
+
(
*
s
-
'0'
);
k
=
10
*
k
+
(
*
s
-
'0'
);
...
@@ -1971,7 +2037,7 @@ MODULE_PARM(dev_hint, "0-20s");
...
@@ -1971,7 +2037,7 @@ MODULE_PARM(dev_hint, "0-20s");
MODULE_PARM_DESC
(
dev_hint
,
"Device node hints"
);
MODULE_PARM_DESC
(
dev_hint
,
"Device node hints"
);
MODULE_DESCRIPTION
(
"Philips & OEM USB webcam driver"
);
MODULE_DESCRIPTION
(
"Philips & OEM USB webcam driver"
);
MODULE_AUTHOR
(
"Nemosoft Unv. <
nemosoft
@smcc.demon.nl>"
);
MODULE_AUTHOR
(
"Nemosoft Unv. <
webcam
@smcc.demon.nl>"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
static
int
__init
usb_pwc_init
(
void
)
static
int
__init
usb_pwc_init
(
void
)
...
@@ -1979,9 +2045,10 @@ static int __init usb_pwc_init(void)
...
@@ -1979,9 +2045,10 @@ static int __init usb_pwc_init(void)
int
i
,
sz
;
int
i
,
sz
;
char
*
sizenames
[
PSZ_MAX
]
=
{
"sqcif"
,
"qsif"
,
"qcif"
,
"sif"
,
"cif"
,
"vga"
};
char
*
sizenames
[
PSZ_MAX
]
=
{
"sqcif"
,
"qsif"
,
"qcif"
,
"sif"
,
"cif"
,
"vga"
};
Info
(
"Philips PCA645/646 + PCVC675/680/690 + PCVC730/740/750 webcam module version "
PWC_VERSION
" loaded.
\n
"
);
Info
(
"Philips webcam module version "
PWC_VERSION
" loaded.
\n
"
);
Info
(
"Also supports the Askey VC010, various Logitech QuickCams, Samsung MPC-C10 and MPC-C30,
\n
"
);
Info
(
"Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.
\n
"
);
Info
(
"the Creative WebCam 5, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.
\n
"
);
Info
(
"Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,
\n
"
);
Info
(
"the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.
\n
"
);
if
(
fps
)
{
if
(
fps
)
{
if
(
fps
<
4
||
fps
>
30
)
{
if
(
fps
<
4
||
fps
>
30
)
{
...
@@ -1991,7 +2058,7 @@ static int __init usb_pwc_init(void)
...
@@ -1991,7 +2058,7 @@ static int __init usb_pwc_init(void)
default_fps
=
fps
;
default_fps
=
fps
;
Info
(
"Default framerate set to %d.
\n
"
,
default_fps
);
Info
(
"Default framerate set to %d.
\n
"
,
default_fps
);
}
}
if
(
size
)
{
if
(
size
)
{
/* string; try matching with array */
/* string; try matching with array */
for
(
sz
=
0
;
sz
<
PSZ_MAX
;
sz
++
)
{
for
(
sz
=
0
;
sz
<
PSZ_MAX
;
sz
++
)
{
...
@@ -2041,12 +2108,12 @@ static int __init usb_pwc_init(void)
...
@@ -2041,12 +2108,12 @@ static int __init usb_pwc_init(void)
if
(
leds
[
1
]
>=
0
)
if
(
leds
[
1
]
>=
0
)
led_off
=
leds
[
1
];
led_off
=
leds
[
1
];
/* Big device node whoopla. Basic
ally, it allows you to assign a
/* Big device node whoopla. Basic
ly, it allows you to assign a
device node (/dev/videoX) to a camera, based on its type
device node (/dev/videoX) to a camera, based on its type
& serial number. The format is [type[.serialnumber]:]node.
& serial number. The format is [type[.serialnumber]:]node.
Any camera that isn't matched by these rules gets the next
Any camera that isn't matched by these rules gets the next
available free device node.
available free device node.
*/
*/
for
(
i
=
0
;
i
<
MAX_DEV_HINTS
;
i
++
)
{
for
(
i
=
0
;
i
<
MAX_DEV_HINTS
;
i
++
)
{
char
*
s
,
*
colon
,
*
dot
;
char
*
s
,
*
colon
,
*
dot
;
...
...
drivers/usb/media/pwc-ioctl.h
View file @
097032ac
#ifndef PWC_IOCTL_H
#ifndef PWC_IOCTL_H
#define PWC_IOCTL_H
#define PWC_IOCTL_H
/* (C) 2001-200
3
Nemosoft Unv. webcam@smcc.demon.nl
/* (C) 2001-200
4
Nemosoft Unv. webcam@smcc.demon.nl
This program is free software; you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
the Free Software Foundation; either version 2 of the License, or
...
@@ -18,19 +18,24 @@
...
@@ -18,19 +18,24 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
*/
/* This is pwc-ioctl.h belonging to PWC 8.10 */
/* This is pwc-ioctl.h belonging to PWC 8.12.1
It contains structures and defines to communicate from user space
directly to the driver.
*/
/*
/*
Changes
Changes
2001/08/03 Alvarado Added ioctl constants to access methods for
2001/08/03 Alvarado Added ioctl constants to access methods for
changing white balance and red/blue gains
changing white balance and red/blue gains
2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE
2002/12/15 G. H. Fernandez-Toribio VIDIOCGREALSIZE
2003/12/13 Nemosft Unv. Some modifications to make interfacing to
PWCX easier
*/
*/
/* These are private ioctl() commands, specific for the Philips webcams.
/* These are private ioctl() commands, specific for the Philips webcams.
They contain functions not found in other webcams, and settings not
They contain functions not found in other webcams, and settings not
specified in the Video4Linux API.
specified in the Video4Linux API.
The #define names are built up like follows:
The #define names are built up like follows:
VIDIOC VIDeo IOCtl prefix
VIDIOC VIDeo IOCtl prefix
PWC Philps WebCam
PWC Philps WebCam
...
@@ -40,13 +45,21 @@
...
@@ -40,13 +45,21 @@
*/
*/
/* Enumeration of image sizes */
#define PSZ_SQCIF 0x00
#define PSZ_QSIF 0x01
#define PSZ_QCIF 0x02
#define PSZ_SIF 0x03
#define PSZ_CIF 0x04
#define PSZ_VGA 0x05
#define PSZ_MAX 6
/* The frame rate is encoded in the video_window.flags parameter using
/* The frame rate is encoded in the video_window.flags parameter using
the upper 16 bits, since some flags are defined nowadays. The following
the upper 16 bits, since some flags are defined nowadays. The following
defines provide a mask and shift to filter out this value.
defines provide a mask and shift to filter out this value.
In 'Snapshot' mode the camera freezes its automatic exposure and colour
In 'Snapshot' mode the camera freezes its automatic exposure and colour
balance controls.
balance controls.
*/
*/
#define PWC_FPS_SHIFT 16
#define PWC_FPS_SHIFT 16
...
@@ -55,14 +68,26 @@
...
@@ -55,14 +68,26 @@
#define PWC_FPS_SNAPSHOT 0x00400000
#define PWC_FPS_SNAPSHOT 0x00400000
/* structure for transfering x & y coordinates */
struct
pwc_coord
{
int
x
,
y
;
/* guess what */
int
size
;
/* size, or offset */
};
/* Used with VIDIOCPWCPROBE */
struct
pwc_probe
struct
pwc_probe
{
{
char
name
[
32
];
char
name
[
32
];
int
type
;
int
type
;
};
};
struct
pwc_serial
{
char
serial
[
30
];
/* String with serial number. Contains terminating 0 */
};
/* pwc_whitebalance.mode values */
/* pwc_whitebalance.mode values */
#define PWC_WB_INDOOR 0
#define PWC_WB_INDOOR 0
#define PWC_WB_OUTDOOR 1
#define PWC_WB_OUTDOOR 1
...
@@ -78,7 +103,6 @@ struct pwc_probe
...
@@ -78,7 +103,6 @@ struct pwc_probe
otherwise undefined.
otherwise undefined.
'read_red' and 'read_blue' are read-only.
'read_red' and 'read_blue' are read-only.
*/
*/
struct
pwc_whitebalance
struct
pwc_whitebalance
{
{
int
mode
;
int
mode
;
...
@@ -117,7 +141,7 @@ struct pwc_imagesize
...
@@ -117,7 +141,7 @@ struct pwc_imagesize
#define PWC_MPT_TILT 0x02
#define PWC_MPT_TILT 0x02
#define PWC_MPT_TIMEOUT 0x04
/* for status */
#define PWC_MPT_TIMEOUT 0x04
/* for status */
/* Set angles; when absolute
= 1
, the angle is absolute and the
/* Set angles; when absolute
!= 0
, the angle is absolute and the
driver calculates the relative offset for you. This can only
driver calculates the relative offset for you. This can only
be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
absolute angles.
absolute angles.
...
@@ -127,18 +151,14 @@ struct pwc_mpt_angles
...
@@ -127,18 +151,14 @@ struct pwc_mpt_angles
int
absolute
;
/* write-only */
int
absolute
;
/* write-only */
int
pan
;
/* degrees * 100 */
int
pan
;
/* degrees * 100 */
int
tilt
;
/* degress * 100 */
int
tilt
;
/* degress * 100 */
int
zoom
;
/* N/A, set to -1 */
};
};
/* Range of angles of the camera, both horizontally and vertically.
/* Range of angles of the camera, both horizontally and vertically.
The zoom is not used, maybe in the future...
*/
*/
struct
pwc_mpt_range
struct
pwc_mpt_range
{
{
int
pan_min
,
pan_max
;
/* degrees * 100 */
int
pan_min
,
pan_max
;
/* degrees * 100 */
int
tilt_min
,
tilt_max
;
int
tilt_min
,
tilt_max
;
int
zoom_min
,
zoom_max
;
/* -1, -1 */
};
};
struct
pwc_mpt_status
struct
pwc_mpt_status
...
@@ -149,6 +169,30 @@ struct pwc_mpt_status
...
@@ -149,6 +169,30 @@ struct pwc_mpt_status
};
};
/* This is used for out-of-kernel decompression. With it, you can get
all the necessary information to initialize and use the decompressor
routines in standalone applications.
*/
struct
pwc_video_command
{
int
type
;
/* camera type (645, 675, 730, etc.) */
int
release
;
/* release number */
int
size
;
/* one of PSZ_* */
int
alternate
;
int
command_len
;
/* length of USB video command */
unsigned
char
command_buf
[
13
];
/* Actual USB video command */
int
bandlength
;
/* >0 = compressed */
int
frame_size
;
/* Size of one (un)compressed frame */
};
/* Flags for PWCX subroutines. Not all modules honour all flags. */
#define PWCX_FLAG_PLANAR 0x0001
#define PWCX_FLAG_BAYER 0x0008
/* IOCTL definitions */
/* Restore user settings */
/* Restore user settings */
#define VIDIOCPWCRUSER _IO('v', 192)
#define VIDIOCPWCRUSER _IO('v', 192)
/* Save user settings */
/* Save user settings */
...
@@ -169,16 +213,19 @@ struct pwc_mpt_status
...
@@ -169,16 +213,19 @@ struct pwc_mpt_status
#define VIDIOCPWCGCQUAL _IOR('v', 195, int)
#define VIDIOCPWCGCQUAL _IOR('v', 195, int)
/* Retrieve serial number of camera */
#define VIDIOCPWCGSERIAL _IOR('v', 198, struct pwc_serial)
/* This is a probe function; since so many devices are supported, it
/* This is a probe function; since so many devices are supported, it
becomes difficult to include all the names in programs that want to
becomes difficult to include all the names in programs that want to
check for the enhanced Philips stuff. So in stead, try this PROBE;
check for the enhanced Philips stuff. So in stead, try this PROBE;
it returns a structure with the original name, and the corresponding
it returns a structure with the original name, and the corresponding
Philips type.
Philips type.
To use, fill the structure with zeroes, call PROBE and if that succeeds,
To use, fill the structure with zeroes, call PROBE and if that succeeds,
compare the name with that returned from VIDIOCGCAP; they should be the
compare the name with that returned from VIDIOCGCAP; they should be the
same. If so, you can be assured it is a Philips (OEM) cam and the type
same. If so, you can be assured it is a Philips (OEM) cam and the type
is valid.
is valid.
*/
*/
#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe)
#define VIDIOCPWCPROBE _IOR('v', 199, struct pwc_probe)
/* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
/* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
...
@@ -225,5 +272,8 @@ struct pwc_mpt_status
...
@@ -225,5 +272,8 @@ struct pwc_mpt_status
#define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles)
#define VIDIOCPWCMPTSANGLE _IOW('v', 212, struct pwc_mpt_angles)
#define VIDIOCPWCMPTGANGLE _IOR('v', 212, struct pwc_mpt_angles)
#define VIDIOCPWCMPTGANGLE _IOR('v', 212, struct pwc_mpt_angles)
#define VIDIOCPWCMPTSTATUS _IOR('v', 213, struct pwc_mpt_status)
#define VIDIOCPWCMPTSTATUS _IOR('v', 213, struct pwc_mpt_status)
/* Get the USB set-video command; needed for initializing libpwcx */
#define VIDIOCPWCGVIDCMD _IOR('v', 215, struct pwc_video_command)
#endif
#endif
drivers/usb/media/pwc-misc.c
View file @
097032ac
...
@@ -15,13 +15,13 @@
...
@@ -15,13 +15,13 @@
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
*/
#include <linux/slab.h>
#include <linux/slab.h>
#include "pwc.h"
#include "pwc.h"
struct
pwc_coord
pwc_image_sizes
[
PSZ_MAX
]
=
struct
pwc_coord
pwc_image_sizes
[
PSZ_MAX
]
=
{
{
{
128
,
96
,
0
},
{
128
,
96
,
0
},
{
160
,
120
,
0
},
{
160
,
120
,
0
},
...
@@ -36,11 +36,30 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height)
...
@@ -36,11 +36,30 @@ int pwc_decode_size(struct pwc_device *pdev, int width, int height)
{
{
int
i
,
find
;
int
i
,
find
;
/* Make sure we don't go beyond our max size */
/* Make sure we don't go beyond our max size.
if
(
width
>
pdev
->
view_max
.
x
||
height
>
pdev
->
view_max
.
y
)
NB: we have different limits for RAW and normal modes. In case
return
-
1
;
you don't have the decompressor loaded or use RAW mode,
the maximum viewable size is smaller.
*/
if
(
pdev
->
vpalette
==
VIDEO_PALETTE_RAW
)
{
if
(
width
>
pdev
->
abs_max
.
x
||
height
>
pdev
->
abs_max
.
y
)
{
Debug
(
"VIDEO_PALETTE_RAW: going beyond abs_max.
\n
"
);
return
-
1
;
}
}
else
{
if
(
width
>
pdev
->
view_max
.
x
||
height
>
pdev
->
view_max
.
y
)
{
Debug
(
"VIDEO_PALETTE_ not RAW: going beyond view_max.
\n
"
);
return
-
1
;
}
}
/* Find the largest size supported by the camera that fits into the
/* Find the largest size supported by the camera that fits into the
requested size.
requested size.
*/
*/
find
=
-
1
;
find
=
-
1
;
for
(
i
=
0
;
i
<
PSZ_MAX
;
i
++
)
{
for
(
i
=
0
;
i
<
PSZ_MAX
;
i
++
)
{
...
@@ -62,6 +81,8 @@ void pwc_construct(struct pwc_device *pdev)
...
@@ -62,6 +81,8 @@ void pwc_construct(struct pwc_device *pdev)
pdev
->
view_min
.
y
=
96
;
pdev
->
view_min
.
y
=
96
;
pdev
->
view_max
.
x
=
352
;
pdev
->
view_max
.
x
=
352
;
pdev
->
view_max
.
y
=
288
;
pdev
->
view_max
.
y
=
288
;
pdev
->
abs_max
.
x
=
352
;
pdev
->
abs_max
.
y
=
288
;
pdev
->
image_mask
=
1
<<
PSZ_SQCIF
|
1
<<
PSZ_QCIF
|
1
<<
PSZ_CIF
;
pdev
->
image_mask
=
1
<<
PSZ_SQCIF
|
1
<<
PSZ_QCIF
|
1
<<
PSZ_CIF
;
pdev
->
vcinterface
=
2
;
pdev
->
vcinterface
=
2
;
pdev
->
vendpoint
=
4
;
pdev
->
vendpoint
=
4
;
...
@@ -77,13 +98,14 @@ void pwc_construct(struct pwc_device *pdev)
...
@@ -77,13 +98,14 @@ void pwc_construct(struct pwc_device *pdev)
if
(
pdev
->
decompressor
!=
NULL
)
{
if
(
pdev
->
decompressor
!=
NULL
)
{
pdev
->
view_max
.
x
=
640
;
pdev
->
view_max
.
x
=
640
;
pdev
->
view_max
.
y
=
480
;
pdev
->
view_max
.
y
=
480
;
pdev
->
image_mask
=
1
<<
PSZ_SQCIF
|
1
<<
PSZ_QSIF
|
1
<<
PSZ_QCIF
|
1
<<
PSZ_SIF
|
1
<<
PSZ_CIF
|
1
<<
PSZ_VGA
;
}
}
else
{
else
{
pdev
->
view_max
.
x
=
352
;
pdev
->
view_max
.
x
=
352
;
pdev
->
view_max
.
y
=
288
;
pdev
->
view_max
.
y
=
288
;
pdev
->
image_mask
=
1
<<
PSZ_SQCIF
|
1
<<
PSZ_QSIF
|
1
<<
PSZ_QCIF
|
1
<<
PSZ_SIF
|
1
<<
PSZ_CIF
;
}
}
pdev
->
image_mask
=
1
<<
PSZ_SQCIF
|
1
<<
PSZ_QSIF
|
1
<<
PSZ_QCIF
|
1
<<
PSZ_SIF
|
1
<<
PSZ_CIF
|
1
<<
PSZ_VGA
;
pdev
->
abs_max
.
x
=
640
;
pdev
->
abs_max
.
y
=
480
;
pdev
->
vcinterface
=
3
;
pdev
->
vcinterface
=
3
;
pdev
->
vendpoint
=
4
;
pdev
->
vendpoint
=
4
;
pdev
->
frame_header_size
=
0
;
pdev
->
frame_header_size
=
0
;
...
@@ -99,24 +121,26 @@ void pwc_construct(struct pwc_device *pdev)
...
@@ -99,24 +121,26 @@ void pwc_construct(struct pwc_device *pdev)
if
(
pdev
->
decompressor
!=
NULL
)
{
if
(
pdev
->
decompressor
!=
NULL
)
{
pdev
->
view_max
.
x
=
640
;
pdev
->
view_max
.
x
=
640
;
pdev
->
view_max
.
y
=
480
;
pdev
->
view_max
.
y
=
480
;
pdev
->
image_mask
=
1
<<
PSZ_QSIF
|
1
<<
PSZ_SIF
|
1
<<
PSZ_VGA
;
}
}
else
{
else
{
/*
Tell CIF, even though SIF really is the maximum, but some tools really need CIF
*/
/*
We use CIF, not SIF since some tools really need CIF. So we cheat a bit.
*/
pdev
->
view_max
.
x
=
352
;
pdev
->
view_max
.
x
=
352
;
pdev
->
view_max
.
y
=
288
;
pdev
->
view_max
.
y
=
288
;
pdev
->
image_mask
=
1
<<
PSZ_QSIF
|
1
<<
PSZ_SIF
;
}
}
pdev
->
image_mask
=
1
<<
PSZ_QSIF
|
1
<<
PSZ_SIF
|
1
<<
PSZ_VGA
;
pdev
->
abs_max
.
x
=
640
;
pdev
->
abs_max
.
y
=
480
;
pdev
->
vcinterface
=
3
;
pdev
->
vcinterface
=
3
;
pdev
->
vendpoint
=
5
;
pdev
->
vendpoint
=
5
;
pdev
->
frame_header_size
=
TOUCAM_HEADER_SIZE
;
pdev
->
frame_header_size
=
TOUCAM_HEADER_SIZE
;
pdev
->
frame_trailer_size
=
TOUCAM_TRAILER_SIZE
;
pdev
->
frame_trailer_size
=
TOUCAM_TRAILER_SIZE
;
break
;
break
;
}
}
pdev
->
vpalette
=
VIDEO_PALETTE_YUV420P
;
/* default */
pdev
->
view_min
.
size
=
pdev
->
view_min
.
x
*
pdev
->
view_min
.
y
;
pdev
->
view_min
.
size
=
pdev
->
view_min
.
x
*
pdev
->
view_min
.
y
;
pdev
->
view_max
.
size
=
pdev
->
view_max
.
x
*
pdev
->
view_max
.
y
;
pdev
->
view_max
.
size
=
pdev
->
view_max
.
x
*
pdev
->
view_max
.
y
;
/* length of image, in YUV format */
/* length of image, in YUV format
; always allocate enough memory.
*/
pdev
->
len_per_image
=
(
pdev
->
view_max
.
size
*
3
)
/
2
;
pdev
->
len_per_image
=
(
pdev
->
abs_max
.
x
*
pdev
->
abs_max
.
y
*
3
)
/
2
;
}
}
drivers/usb/media/pwc-uncompress.c
View file @
097032ac
/* Linux driver for Philips webcam
/* Linux driver for Philips webcam
Decompression frontend.
Decompression frontend.
(C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl)
(C) 1999-2003 Nemosoft Unv. (webcam@smcc.demon.nl)
...
@@ -21,7 +21,9 @@
...
@@ -21,7 +21,9 @@
themselves. It also has a decompressor wrapper function.
themselves. It also has a decompressor wrapper function.
*/
*/
#include <asm/current.h>
#include <asm/types.h>
#include <asm/types.h>
// #include <linux/sched.h>
#include "pwc.h"
#include "pwc.h"
#include "pwc-uncompress.h"
#include "pwc-uncompress.h"
...
@@ -81,7 +83,6 @@ int pwc_decompress(struct pwc_device *pdev)
...
@@ -81,7 +83,6 @@ int pwc_decompress(struct pwc_device *pdev)
u16
*
src
;
u16
*
src
;
u16
*
dsty
,
*
dstu
,
*
dstv
;
u16
*
dsty
,
*
dstu
,
*
dstv
;
if
(
pdev
==
NULL
)
if
(
pdev
==
NULL
)
return
-
EFAULT
;
return
-
EFAULT
;
#if defined(__KERNEL__) && defined(PWC_MAGIC)
#if defined(__KERNEL__) && defined(PWC_MAGIC)
...
@@ -97,16 +98,24 @@ int pwc_decompress(struct pwc_device *pdev)
...
@@ -97,16 +98,24 @@ int pwc_decompress(struct pwc_device *pdev)
image
=
pdev
->
image_ptr
[
pdev
->
fill_image
];
image
=
pdev
->
image_ptr
[
pdev
->
fill_image
];
if
(
!
image
)
if
(
!
image
)
return
-
EFAULT
;
return
-
EFAULT
;
yuv
=
fbuf
->
data
+
pdev
->
frame_header_size
;
/* Skip header */
yuv
=
fbuf
->
data
+
pdev
->
frame_header_size
;
/* Skip header */
if
(
pdev
->
vbandlength
==
0
)
{
/* Raw format; that's easy... */
if
(
pdev
->
vpalette
==
VIDEO_PALETTE_RAW
)
{
memcpy
(
image
,
yuv
,
pdev
->
frame_size
);
return
0
;
}
if
(
pdev
->
vbandlength
==
0
)
{
/* Uncompressed mode. We copy the data into the output buffer,
/* Uncompressed mode. We copy the data into the output buffer,
using the viewport size (which may be larger than the image
using the viewport size (which may be larger than the image
size). Unfortunately we have to do a bit of byte stuffing
size). Unfortunately we have to do a bit of byte stuffing
to get the desired output format/size.
to get the desired output format/size.
*/
*/
/*
/*
* We do some byte shuffling here to go from the
* We do some byte shuffling here to go from the
* native format to YUV420P.
* native format to YUV420P.
*/
*/
src
=
(
u16
*
)
yuv
;
src
=
(
u16
*
)
yuv
;
...
@@ -140,15 +149,21 @@ int pwc_decompress(struct pwc_device *pdev)
...
@@ -140,15 +149,21 @@ int pwc_decompress(struct pwc_device *pdev)
dstu
+=
(
stride
>>
1
);
dstu
+=
(
stride
>>
1
);
}
}
}
}
else
{
else
{
/* Compressed; the decompressor routines will write the data
/* Compressed; the decompressor routines will write the data
in planar format immediately.
in planar format immediately.
*/
*/
int
flags
;
flags
=
PWCX_FLAG_PLANAR
;
if
(
pdev
->
vsize
==
PSZ_VGA
&&
pdev
->
vframes
==
5
&&
pdev
->
vsnapshot
)
flags
|=
PWCX_FLAG_BAYER
;
if
(
pdev
->
decompressor
)
if
(
pdev
->
decompressor
)
pdev
->
decompressor
->
decompress
(
pdev
->
decompressor
->
decompress
(
&
pdev
->
image
,
&
pdev
->
view
,
&
pdev
->
offset
,
&
pdev
->
image
,
&
pdev
->
view
,
&
pdev
->
offset
,
yuv
,
image
,
yuv
,
image
,
1
,
flags
,
pdev
->
decompress_data
,
pdev
->
vbandlength
);
pdev
->
decompress_data
,
pdev
->
vbandlength
);
else
else
return
-
ENXIO
;
/* No such device or address: missing decompressor */
return
-
ENXIO
;
/* No such device or address: missing decompressor */
...
...
drivers/usb/media/pwc-uncompress.h
View file @
097032ac
...
@@ -24,9 +24,15 @@
...
@@ -24,9 +24,15 @@
#define PWC_UNCOMPRESS_H
#define PWC_UNCOMPRESS_H
#include <linux/config.h>
#include <linux/config.h>
#include <linux/linkage.h>
#include <linux/list.h>
#include <linux/list.h>
#include "pwc.h"
#include "pwc-ioctl.h"
/* from pwc-dec.h */
#define PWCX_FLAG_PLANAR 0x0001
/* */
#ifdef __cplusplus
#ifdef __cplusplus
extern
"C"
{
extern
"C"
{
...
@@ -42,10 +48,11 @@ struct pwc_decompressor
...
@@ -42,10 +48,11 @@ struct pwc_decompressor
int
type
;
/* type of camera (645, 680, etc) */
int
type
;
/* type of camera (645, 680, etc) */
int
table_size
;
/* memory needed */
int
table_size
;
/* memory needed */
void
(
*
init
)(
int
release
,
void
*
buffer
,
void
*
table
);
/* Initialization routine; should be called after each set_video_mode */
void
(
*
init
)(
int
type
,
int
release
,
void
*
buffer
,
void
*
table
);
/* Initialization routine; should be called after each set_video_mode */
void
(
*
exit
)(
void
);
/* Cleanup routine */
void
(
*
exit
)(
void
);
/* Cleanup routine */
void
(
*
decompress
)(
struct
pwc_coord
*
image
,
struct
pwc_coord
*
view
,
struct
pwc_coord
*
offset
,
void
(
*
decompress
)(
struct
pwc_coord
*
image
,
struct
pwc_coord
*
view
,
void
*
src
,
void
*
dst
,
int
planar
,
struct
pwc_coord
*
offset
,
void
*
src
,
void
*
dst
,
int
flags
,
void
*
table
,
int
bandlength
);
void
*
table
,
int
bandlength
);
void
(
*
lock
)(
void
);
/* make sure module cannot be unloaded */
void
(
*
lock
)(
void
);
/* make sure module cannot be unloaded */
void
(
*
unlock
)(
void
);
/* release lock on module */
void
(
*
unlock
)(
void
);
/* release lock on module */
...
...
drivers/usb/media/pwc.h
View file @
097032ac
...
@@ -22,15 +22,15 @@
...
@@ -22,15 +22,15 @@
#include <linux/config.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/smp_lock.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
#include <linux/usb.h>
#include <linux/spinlock.h>
#include <linux/videodev.h>
#include <linux/videodev.h>
#include <linux/wait.h>
#include <linux/wait.h>
#include <linux/smp_lock.h>
#include <asm/semaphore.h>
#include <asm/semaphore.h>
#include <asm/errno.h>
#include <asm/errno.h>
#include "pwc-uncompress.h"
#include "pwc-ioctl.h"
#include "pwc-ioctl.h"
/* Defines and structures for the Philips webcam */
/* Defines and structures for the Philips webcam */
...
@@ -65,9 +65,9 @@
...
@@ -65,9 +65,9 @@
#define FEATURE_MOTOR_PANTILT 0x0001
#define FEATURE_MOTOR_PANTILT 0x0001
/* Version block */
/* Version block */
#define PWC_MAJOR
8
#define PWC_MAJOR
9
#define PWC_MINOR
12
#define PWC_MINOR
0
#define PWC_VERSION "
8.12
"
#define PWC_VERSION "
9.0.1
"
#define PWC_NAME "pwc"
#define PWC_NAME "pwc"
/* Turn certain features on/off */
/* Turn certain features on/off */
...
@@ -90,12 +90,6 @@
...
@@ -90,12 +90,6 @@
/* Absolute maximum number of buffers available for mmap() */
/* Absolute maximum number of buffers available for mmap() */
#define MAX_IMAGES 10
#define MAX_IMAGES 10
struct
pwc_coord
{
int
x
,
y
;
/* guess what */
int
size
;
/* size, or offset */
};
/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
struct
pwc_iso_buf
struct
pwc_iso_buf
{
{
...
@@ -118,7 +112,7 @@ struct pwc_frame_buf
...
@@ -118,7 +112,7 @@ struct pwc_frame_buf
struct
pwc_device
struct
pwc_device
{
{
struct
video_device
vdev
;
struct
video_device
*
vdev
;
#ifdef PWC_MAGIC
#ifdef PWC_MAGIC
int
magic
;
int
magic
;
#endif
#endif
...
@@ -128,6 +122,7 @@ struct pwc_device
...
@@ -128,6 +122,7 @@ struct pwc_device
int
type
;
/* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
int
type
;
/* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
int
release
;
/* release number */
int
release
;
/* release number */
int
features
;
/* feature bits */
int
features
;
/* feature bits */
char
serial
[
30
];
/* serial number (string) */
int
error_status
;
/* set when something goes wrong with the cam (unplugged, USB errors) */
int
error_status
;
/* set when something goes wrong with the cam (unplugged, USB errors) */
int
usb_init
;
/* set when the cam has been initialized over USB */
int
usb_init
;
/* set when the cam has been initialized over USB */
...
@@ -137,6 +132,7 @@ struct pwc_device
...
@@ -137,6 +132,7 @@ struct pwc_device
int
vcinterface
;
/* video control interface */
int
vcinterface
;
/* video control interface */
int
valternate
;
/* alternate interface needed */
int
valternate
;
/* alternate interface needed */
int
vframes
,
vsize
;
/* frames-per-second & size (see PSZ_*) */
int
vframes
,
vsize
;
/* frames-per-second & size (see PSZ_*) */
int
vpalette
;
/* palette: 420P, RAW or RGBBAYER */
int
vframe_count
;
/* received frames */
int
vframe_count
;
/* received frames */
int
vframes_dumped
;
/* counter for dumped frames */
int
vframes_dumped
;
/* counter for dumped frames */
int
vframes_error
;
/* frames received in error */
int
vframes_error
;
/* frames received in error */
...
@@ -148,6 +144,9 @@ struct pwc_device
...
@@ -148,6 +144,9 @@ struct pwc_device
char
vsnapshot
;
/* snapshot mode */
char
vsnapshot
;
/* snapshot mode */
char
vsync
;
/* used by isoc handler */
char
vsync
;
/* used by isoc handler */
char
vmirror
;
/* for ToUCaM series */
char
vmirror
;
/* for ToUCaM series */
int
cmd_len
;
unsigned
char
cmd_buf
[
13
];
/* The image acquisition requires 3 to 4 steps:
/* The image acquisition requires 3 to 4 steps:
1. data is gathered in short packets from the USB controller
1. data is gathered in short packets from the USB controller
...
@@ -169,8 +168,9 @@ struct pwc_device
...
@@ -169,8 +168,9 @@ struct pwc_device
struct
pwc_frame_buf
*
full_frames
,
*
full_frames_tail
;
/* all filled frames */
struct
pwc_frame_buf
*
full_frames
,
*
full_frames_tail
;
/* all filled frames */
struct
pwc_frame_buf
*
fill_frame
;
/* frame currently being filled */
struct
pwc_frame_buf
*
fill_frame
;
/* frame currently being filled */
struct
pwc_frame_buf
*
read_frame
;
/* frame currently read by user process */
struct
pwc_frame_buf
*
read_frame
;
/* frame currently read by user process */
int
frame_size
;
int
frame_header_size
,
frame_trailer_size
;
int
frame_header_size
,
frame_trailer_size
;
int
frame_size
;
int
frame_total_size
;
/* including header & trailer */
int
drop_frames
;
int
drop_frames
;
#if PWC_DEBUG
#if PWC_DEBUG
int
sequence
;
/* Debugging aid */
int
sequence
;
/* Debugging aid */
...
@@ -187,7 +187,8 @@ struct pwc_device
...
@@ -187,7 +187,8 @@ struct pwc_device
a gray or black border. view_min <= image <= view <= view_max;
a gray or black border. view_min <= image <= view <= view_max;
*/
*/
int
image_mask
;
/* bitmask of supported sizes */
int
image_mask
;
/* bitmask of supported sizes */
struct
pwc_coord
view_min
,
view_max
;
/* minimum and maximum sizes */
struct
pwc_coord
view_min
,
view_max
;
/* minimum and maximum viewable sizes */
struct
pwc_coord
abs_max
;
/* maximum supported size with compression */
struct
pwc_coord
image
,
view
;
/* image and viewport size */
struct
pwc_coord
image
,
view
;
/* image and viewport size */
struct
pwc_coord
offset
;
/* offset within the viewport */
struct
pwc_coord
offset
;
/* offset within the viewport */
...
@@ -213,16 +214,6 @@ struct pwc_device
...
@@ -213,16 +214,6 @@ struct pwc_device
#endif
#endif
};
};
/* Enumeration of image sizes */
#define PSZ_SQCIF 0x00
#define PSZ_QSIF 0x01
#define PSZ_QCIF 0x02
#define PSZ_SIF 0x03
#define PSZ_CIF 0x04
#define PSZ_VGA 0x05
#define PSZ_MAX 6
#ifdef __cplusplus
#ifdef __cplusplus
extern
"C"
{
extern
"C"
{
...
@@ -259,7 +250,7 @@ extern int pwc_get_saturation(struct pwc_device *pdev);
...
@@ -259,7 +250,7 @@ extern int pwc_get_saturation(struct pwc_device *pdev);
extern
int
pwc_set_saturation
(
struct
pwc_device
*
pdev
,
int
value
);
extern
int
pwc_set_saturation
(
struct
pwc_device
*
pdev
,
int
value
);
extern
int
pwc_set_leds
(
struct
pwc_device
*
pdev
,
int
on_value
,
int
off_value
);
extern
int
pwc_set_leds
(
struct
pwc_device
*
pdev
,
int
on_value
,
int
off_value
);
extern
int
pwc_get_leds
(
struct
pwc_device
*
pdev
,
int
*
on_value
,
int
*
off_value
);
extern
int
pwc_get_leds
(
struct
pwc_device
*
pdev
,
int
*
on_value
,
int
*
off_value
);
extern
int
pwc_get_cmos_sensor
(
struct
pwc_device
*
pdev
);
extern
int
pwc_get_cmos_sensor
(
struct
pwc_device
*
pdev
,
int
*
sensor
);
/* Power down or up the camera; not supported by all models */
/* Power down or up the camera; not supported by all models */
extern
int
pwc_camera_power
(
struct
pwc_device
*
pdev
,
int
power
);
extern
int
pwc_camera_power
(
struct
pwc_device
*
pdev
,
int
power
);
...
...
drivers/usb/net/kaweth.c
View file @
097032ac
...
@@ -62,7 +62,7 @@
...
@@ -62,7 +62,7 @@
#include <asm/semaphore.h>
#include <asm/semaphore.h>
#include <asm/byteorder.h>
#include <asm/byteorder.h>
#
define
DEBUG
#
undef
DEBUG
#ifdef DEBUG
#ifdef DEBUG
#define kaweth_dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" ,##arg)
#define kaweth_dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" ,##arg)
...
@@ -592,7 +592,7 @@ static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs)
...
@@ -592,7 +592,7 @@ static void kaweth_usb_receive(struct urb *urb, struct pt_regs *regs)
struct
sk_buff
*
skb
;
struct
sk_buff
*
skb
;
if
(
unlikely
(
urb
->
status
==
-
ECONNRESET
||
urb
->
status
==
-
ECONNABORTED
))
if
(
unlikely
(
urb
->
status
==
-
ECONNRESET
||
urb
->
status
==
-
ECONNABORTED
||
urb
->
status
==
-
ESHUTDOWN
))
/* we are killed - set a flag and wake the disconnect handler */
/* we are killed - set a flag and wake the disconnect handler */
{
{
kaweth
->
end
=
1
;
kaweth
->
end
=
1
;
...
...
drivers/usb/net/pegasus.c
View file @
097032ac
...
@@ -1137,8 +1137,6 @@ static void pegasus_set_multicast(struct net_device *net)
...
@@ -1137,8 +1137,6 @@ static void pegasus_set_multicast(struct net_device *net)
{
{
pegasus_t
*
pegasus
=
net
->
priv
;
pegasus_t
*
pegasus
=
net
->
priv
;
netif_stop_queue
(
net
);
if
(
net
->
flags
&
IFF_PROMISC
)
{
if
(
net
->
flags
&
IFF_PROMISC
)
{
pegasus
->
eth_regs
[
EthCtrl2
]
|=
RX_PROMISCUOUS
;
pegasus
->
eth_regs
[
EthCtrl2
]
|=
RX_PROMISCUOUS
;
info
(
"%s: Promiscuous mode enabled"
,
net
->
name
);
info
(
"%s: Promiscuous mode enabled"
,
net
->
name
);
...
@@ -1154,8 +1152,6 @@ static void pegasus_set_multicast(struct net_device *net)
...
@@ -1154,8 +1152,6 @@ static void pegasus_set_multicast(struct net_device *net)
pegasus
->
flags
|=
ETH_REGS_CHANGE
;
pegasus
->
flags
|=
ETH_REGS_CHANGE
;
ctrl_callback
(
pegasus
->
ctrl_urb
,
NULL
);
ctrl_callback
(
pegasus
->
ctrl_urb
,
NULL
);
netif_wake_queue
(
net
);
}
}
static
__u8
mii_phy_probe
(
pegasus_t
*
pegasus
)
static
__u8
mii_phy_probe
(
pegasus_t
*
pegasus
)
...
...
drivers/usb/serial/generic.c
View file @
097032ac
...
@@ -53,6 +53,32 @@ struct usb_serial_device_type usb_serial_generic_device = {
...
@@ -53,6 +53,32 @@ struct usb_serial_device_type usb_serial_generic_device = {
.
num_ports
=
1
,
.
num_ports
=
1
,
.
shutdown
=
usb_serial_generic_shutdown
,
.
shutdown
=
usb_serial_generic_shutdown
,
};
};
/* we want to look at all devices, as the vendor/product id can change
* depending on the command line argument */
static
struct
usb_device_id
generic_serial_ids
[]
=
{
{.
driver_info
=
42
},
{}
};
static
int
generic_probe
(
struct
usb_interface
*
interface
,
const
struct
usb_device_id
*
id
)
{
const
struct
usb_device_id
*
id_pattern
;
id_pattern
=
usb_match_id
(
interface
,
generic_device_ids
);
if
(
id_pattern
!=
NULL
)
return
usb_serial_probe
(
interface
,
id
);
return
-
ENODEV
;
}
static
struct
usb_driver
generic_driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"usbserial_generic"
,
.
probe
=
generic_probe
,
.
disconnect
=
usb_serial_disconnect
,
.
id_table
=
generic_serial_ids
,
};
#endif
#endif
int
usb_serial_generic_register
(
int
_debug
)
int
usb_serial_generic_register
(
int
_debug
)
...
@@ -67,6 +93,12 @@ int usb_serial_generic_register (int _debug)
...
@@ -67,6 +93,12 @@ int usb_serial_generic_register (int _debug)
/* register our generic driver with ourselves */
/* register our generic driver with ourselves */
retval
=
usb_serial_register
(
&
usb_serial_generic_device
);
retval
=
usb_serial_register
(
&
usb_serial_generic_device
);
if
(
retval
)
goto
exit
;
retval
=
usb_register
(
&
generic_driver
);
if
(
retval
)
usb_serial_deregister
(
&
usb_serial_generic_device
);
exit:
#endif
#endif
return
retval
;
return
retval
;
}
}
...
@@ -75,6 +107,7 @@ void usb_serial_generic_deregister (void)
...
@@ -75,6 +107,7 @@ void usb_serial_generic_deregister (void)
{
{
#ifdef CONFIG_USB_SERIAL_GENERIC
#ifdef CONFIG_USB_SERIAL_GENERIC
/* remove our generic driver */
/* remove our generic driver */
usb_deregister
(
&
generic_driver
);
usb_serial_deregister
(
&
usb_serial_generic_device
);
usb_serial_deregister
(
&
usb_serial_generic_device
);
#endif
#endif
}
}
...
...
drivers/usb/serial/pl2303.c
View file @
097032ac
...
@@ -62,7 +62,7 @@
...
@@ -62,7 +62,7 @@
/*
/*
* Version Information
* Version Information
*/
*/
#define DRIVER_VERSION "v0.1
0
"
#define DRIVER_VERSION "v0.1
1
"
#define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver"
#define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver"
...
@@ -82,6 +82,7 @@ static struct usb_device_id id_table [] = {
...
@@ -82,6 +82,7 @@ static struct usb_device_id id_table [] = {
{
USB_DEVICE
(
DCU10_VENDOR_ID
,
DCU10_PRODUCT_ID
)
},
{
USB_DEVICE
(
DCU10_VENDOR_ID
,
DCU10_PRODUCT_ID
)
},
{
USB_DEVICE
(
SITECOM_VENDOR_ID
,
SITECOM_PRODUCT_ID
)
},
{
USB_DEVICE
(
SITECOM_VENDOR_ID
,
SITECOM_PRODUCT_ID
)
},
{
USB_DEVICE
(
ALCATEL_VENDOR_ID
,
ALCATEL_PRODUCT_ID
)
},
{
USB_DEVICE
(
ALCATEL_VENDOR_ID
,
ALCATEL_PRODUCT_ID
)
},
{
USB_DEVICE
(
SAMSUNG_VENDOR_ID
,
SAMSUNG_PRODUCT_ID
)
},
{
}
/* Terminating entry */
{
}
/* Terminating entry */
};
};
...
@@ -172,20 +173,38 @@ static struct usb_serial_device_type pl2303_device = {
...
@@ -172,20 +173,38 @@ static struct usb_serial_device_type pl2303_device = {
.
shutdown
=
pl2303_shutdown
,
.
shutdown
=
pl2303_shutdown
,
};
};
enum
pl2303_type
{
type_0
,
/* don't know the difference between type 0 and */
type_1
,
/* type 1, until someone from prolific tells us... */
HX
,
/* HX version of the pl2303 chip */
};
struct
pl2303_private
{
struct
pl2303_private
{
spinlock_t
lock
;
spinlock_t
lock
;
wait_queue_head_t
delta_msr_wait
;
wait_queue_head_t
delta_msr_wait
;
u8
line_control
;
u8
line_control
;
u8
line_status
;
u8
line_status
;
u8
termios_initialized
;
u8
termios_initialized
;
enum
pl2303_type
type
;
};
};
static
int
pl2303_startup
(
struct
usb_serial
*
serial
)
static
int
pl2303_startup
(
struct
usb_serial
*
serial
)
{
{
struct
pl2303_private
*
priv
;
struct
pl2303_private
*
priv
;
enum
pl2303_type
type
=
type_0
;
int
i
;
int
i
;
if
(
serial
->
dev
->
descriptor
.
bDeviceClass
==
0x02
)
type
=
type_0
;
else
if
(
serial
->
dev
->
descriptor
.
bMaxPacketSize0
==
0x40
)
type
=
HX
;
else
if
(
serial
->
dev
->
descriptor
.
bDeviceClass
==
0x00
)
type
=
type_1
;
else
if
(
serial
->
dev
->
descriptor
.
bDeviceClass
==
0xFF
)
type
=
type_1
;
dbg
(
"device type: %d"
,
type
);
for
(
i
=
0
;
i
<
serial
->
num_ports
;
++
i
)
{
for
(
i
=
0
;
i
<
serial
->
num_ports
;
++
i
)
{
priv
=
kmalloc
(
sizeof
(
struct
pl2303_private
),
GFP_KERNEL
);
priv
=
kmalloc
(
sizeof
(
struct
pl2303_private
),
GFP_KERNEL
);
if
(
!
priv
)
if
(
!
priv
)
...
@@ -193,6 +212,7 @@ static int pl2303_startup (struct usb_serial *serial)
...
@@ -193,6 +212,7 @@ static int pl2303_startup (struct usb_serial *serial)
memset
(
priv
,
0x00
,
sizeof
(
struct
pl2303_private
));
memset
(
priv
,
0x00
,
sizeof
(
struct
pl2303_private
));
spin_lock_init
(
&
priv
->
lock
);
spin_lock_init
(
&
priv
->
lock
);
init_waitqueue_head
(
&
priv
->
delta_msr_wait
);
init_waitqueue_head
(
&
priv
->
delta_msr_wait
);
priv
->
type
=
type
;
usb_set_serial_port_data
(
serial
->
port
[
i
],
priv
);
usb_set_serial_port_data
(
serial
->
port
[
i
],
priv
);
}
}
return
0
;
return
0
;
...
@@ -395,20 +415,27 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
...
@@ -395,20 +415,27 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
buf
[
0
],
buf
[
1
],
buf
[
2
],
buf
[
3
],
buf
[
4
],
buf
[
5
],
buf
[
6
]);
buf
[
0
],
buf
[
1
],
buf
[
2
],
buf
[
3
],
buf
[
4
],
buf
[
5
],
buf
[
6
]);
if
(
cflag
&
CRTSCTS
)
{
if
(
cflag
&
CRTSCTS
)
{
i
=
usb_control_msg
(
serial
->
dev
,
usb_sndctrlpipe
(
serial
->
dev
,
0
),
__u16
index
;
VENDOR_WRITE_REQUEST
,
VENDOR_WRITE_REQUEST_TYPE
,
if
(
priv
->
type
==
HX
)
0x0
,
0x41
,
NULL
,
0
,
100
);
index
=
0x61
;
dbg
(
"0x40:0x1:0x0:0x41 %d"
,
i
);
else
index
=
0x41
;
i
=
usb_control_msg
(
serial
->
dev
,
usb_sndctrlpipe
(
serial
->
dev
,
0
),
VENDOR_WRITE_REQUEST
,
VENDOR_WRITE_REQUEST_TYPE
,
0x0
,
index
,
NULL
,
0
,
100
);
dbg
(
"0x40:0x1:0x0:0x%x %d"
,
index
,
i
);
}
}
kfree
(
buf
);
kfree
(
buf
);
}
}
static
int
pl2303_open
(
struct
usb_serial_port
*
port
,
struct
file
*
filp
)
static
int
pl2303_open
(
struct
usb_serial_port
*
port
,
struct
file
*
filp
)
{
{
struct
termios
tmp_termios
;
struct
termios
tmp_termios
;
struct
usb_serial
*
serial
=
port
->
serial
;
struct
usb_serial
*
serial
=
port
->
serial
;
struct
pl2303_private
*
priv
=
usb_get_serial_port_data
(
port
);
unsigned
char
*
buf
;
unsigned
char
*
buf
;
int
result
;
int
result
;
...
@@ -439,6 +466,18 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp)
...
@@ -439,6 +466,18 @@ static int pl2303_open (struct usb_serial_port *port, struct file *filp)
SOUP
(
VENDOR_WRITE_REQUEST_TYPE
,
VENDOR_WRITE_REQUEST
,
0x0404
,
1
);
SOUP
(
VENDOR_WRITE_REQUEST_TYPE
,
VENDOR_WRITE_REQUEST
,
0x0404
,
1
);
FISH
(
VENDOR_READ_REQUEST_TYPE
,
VENDOR_READ_REQUEST
,
0x8484
,
0
);
FISH
(
VENDOR_READ_REQUEST_TYPE
,
VENDOR_READ_REQUEST
,
0x8484
,
0
);
FISH
(
VENDOR_READ_REQUEST_TYPE
,
VENDOR_READ_REQUEST
,
0x8383
,
0
);
FISH
(
VENDOR_READ_REQUEST_TYPE
,
VENDOR_READ_REQUEST
,
0x8383
,
0
);
SOUP
(
VENDOR_WRITE_REQUEST_TYPE
,
VENDOR_WRITE_REQUEST
,
0
,
1
);
SOUP
(
VENDOR_WRITE_REQUEST_TYPE
,
VENDOR_WRITE_REQUEST
,
1
,
0
);
if
(
priv
->
type
==
HX
)
{
/* HX chip */
SOUP
(
VENDOR_WRITE_REQUEST_TYPE
,
VENDOR_WRITE_REQUEST
,
2
,
0x44
);
/* reset upstream data pipes */
SOUP
(
VENDOR_WRITE_REQUEST_TYPE
,
VENDOR_WRITE_REQUEST
,
8
,
0
);
SOUP
(
VENDOR_WRITE_REQUEST_TYPE
,
VENDOR_WRITE_REQUEST
,
9
,
0
);
}
else
{
SOUP
(
VENDOR_WRITE_REQUEST_TYPE
,
VENDOR_WRITE_REQUEST
,
2
,
0x24
);
}
kfree
(
buf
);
kfree
(
buf
);
...
...
drivers/usb/serial/pl2303.h
View file @
097032ac
...
@@ -42,5 +42,11 @@
...
@@ -42,5 +42,11 @@
#define SITECOM_VENDOR_ID 0x6189
#define SITECOM_VENDOR_ID 0x6189
#define SITECOM_PRODUCT_ID 0x2068
#define SITECOM_PRODUCT_ID 0x2068
/* Alcatel OT535/735 USB cable */
#define ALCATEL_VENDOR_ID 0x11f7
#define ALCATEL_VENDOR_ID 0x11f7
#define ALCATEL_PRODUCT_ID 0x02df
#define ALCATEL_PRODUCT_ID 0x02df
/* Samsung I330 phone cradle */
#define SAMSUNG_VENDOR_ID 0x04e8
#define SAMSUNG_PRODUCT_ID 0x8001
drivers/usb/serial/usb-serial.c
View file @
097032ac
...
@@ -355,25 +355,12 @@
...
@@ -355,25 +355,12 @@
#define DRIVER_DESC "USB Serial Driver core"
#define DRIVER_DESC "USB Serial Driver core"
#ifdef CONFIG_USB_SERIAL_GENERIC
/* we want to look at all devices, as the vendor/product id can change
* depending on the command line argument */
static
struct
usb_device_id
generic_serial_ids
[]
=
{
{.
driver_info
=
42
},
{}
};
#endif
/* CONFIG_USB_SERIAL_GENERIC */
/* Driver structure we register with the USB core */
/* Driver structure we register with the USB core */
static
struct
usb_driver
usb_serial_driver
=
{
static
struct
usb_driver
usb_serial_driver
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
name
=
"usbserial"
,
.
name
=
"usbserial"
,
.
probe
=
usb_serial_probe
,
.
probe
=
usb_serial_probe
,
.
disconnect
=
usb_serial_disconnect
,
.
disconnect
=
usb_serial_disconnect
,
#ifdef CONFIG_USB_SERIAL_GENERIC
.
id_table
=
generic_serial_ids
,
#endif
};
};
/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead
...
@@ -1383,22 +1370,9 @@ int usb_serial_register(struct usb_serial_device_type *new_device)
...
@@ -1383,22 +1370,9 @@ int usb_serial_register(struct usb_serial_device_type *new_device)
void
usb_serial_deregister
(
struct
usb_serial_device_type
*
device
)
void
usb_serial_deregister
(
struct
usb_serial_device_type
*
device
)
{
{
struct
usb_serial
*
serial
;
int
i
;
info
(
"USB Serial deregistering driver %s"
,
device
->
name
);
info
(
"USB Serial deregistering driver %s"
,
device
->
name
);
/* clear out the serial_table if the device is attached to a port */
for
(
i
=
0
;
i
<
SERIAL_TTY_MINORS
;
++
i
)
{
serial
=
serial_table
[
i
];
if
((
serial
!=
NULL
)
&&
(
serial
->
type
==
device
))
{
usb_driver_release_interface
(
&
usb_serial_driver
,
serial
->
interface
);
usb_serial_disconnect
(
serial
->
interface
);
}
}
list_del
(
&
device
->
driver_list
);
list_del
(
&
device
->
driver_list
);
usb_serial_bus_deregister
(
device
);
usb_serial_bus_deregister
(
device
);
}
}
...
...
drivers/usb/storage/transport.c
View file @
097032ac
...
@@ -708,6 +708,12 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
...
@@ -708,6 +708,12 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
srb
->
sense_buffer
[
0
]
=
0x0
;
srb
->
sense_buffer
[
0
]
=
0x0
;
}
}
}
}
/* Did we transfer less than the minimum amount required? */
if
(
srb
->
result
==
SAM_STAT_GOOD
&&
srb
->
request_bufflen
-
srb
->
resid
<
srb
->
underflow
)
srb
->
result
=
(
DID_ERROR
<<
16
)
|
(
SUGGEST_RETRY
<<
24
);
return
;
return
;
/* abort processing: the bulk-only transport requires a reset
/* abort processing: the bulk-only transport requires a reset
...
...
drivers/usb/storage/unusual_devs.h
View file @
097032ac
...
@@ -73,6 +73,16 @@ UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
...
@@ -73,6 +73,16 @@ UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001,
US_SC_8070
,
US_PR_SCM_ATAPI
,
init_8200e
,
0
),
US_SC_8070
,
US_PR_SCM_ATAPI
,
init_8200e
,
0
),
#endif
#endif
/* <torsten.scherer@uni-bielefeld.de>: I don't know the name of the bridge
* manufacturer, but I've got an external USB drive by the Revoltec company
* that needs this. otherwise the drive is recognized as /dev/sda, but any
* access to it blocks indefinitely.
*/
UNUSUAL_DEV
(
0x0402
,
0x5621
,
0x0103
,
0x0103
,
"Revoltec"
,
"USB/IDE Bridge (ATA/ATAPI)"
,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
/* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
* Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
* Entry needed for flags: US_FL_FIX_INQUIRY because initial inquiry message
* always fails and confuses drive.
* always fails and confuses drive.
...
@@ -686,7 +696,7 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
...
@@ -686,7 +696,7 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
UNUSUAL_DEV
(
0x097a
,
0x0001
,
0x0000
,
0x0001
,
UNUSUAL_DEV
(
0x097a
,
0x0001
,
0x0000
,
0x0001
,
"Minds@Work"
,
"Minds@Work"
,
"Digital Wallet"
,
"Digital Wallet"
,
US_SC_
SCSI
,
US_PR_CB
,
NULL
,
US_SC_
DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_MODE_XLATE
),
US_FL_MODE_XLATE
),
UNUSUAL_DEV
(
0x0a16
,
0x8888
,
0x0100
,
0x0100
,
UNUSUAL_DEV
(
0x0a16
,
0x8888
,
0x0100
,
0x0100
,
...
...
fs/aio.c
View file @
097032ac
...
@@ -624,6 +624,7 @@ void fastcall kick_iocb(struct kiocb *iocb)
...
@@ -624,6 +624,7 @@ void fastcall kick_iocb(struct kiocb *iocb)
queue_work
(
aio_wq
,
&
ctx
->
wq
);
queue_work
(
aio_wq
,
&
ctx
->
wq
);
}
}
}
}
EXPORT_SYMBOL
(
kick_iocb
);
/* aio_complete
/* aio_complete
* Called when the io request on the given iocb is complete.
* Called when the io request on the given iocb is complete.
...
...
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