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
6aa909be
Commit
6aa909be
authored
Feb 18, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/jgarzik/net-drivers-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
afe1bcc5
7f6cf788
Changes
26
Show whitespace changes
Inline
Side-by-side
Showing
26 changed files
with
689 additions
and
892 deletions
+689
-892
CREDITS
CREDITS
+8
-0
MAINTAINERS
MAINTAINERS
+8
-0
drivers/usb/Makefile.lib
drivers/usb/Makefile.lib
+3
-0
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.c
+3
-0
drivers/usb/core/message.c
drivers/usb/core/message.c
+14
-5
drivers/usb/core/urb.c
drivers/usb/core/urb.c
+2
-2
drivers/usb/core/usb.c
drivers/usb/core/usb.c
+5
-0
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hcd.c
+18
-1
drivers/usb/host/ehci.h
drivers/usb/host/ehci.h
+2
-0
drivers/usb/input/Kconfig
drivers/usb/input/Kconfig
+4
-5
drivers/usb/input/usbkbd.c
drivers/usb/input/usbkbd.c
+1
-1
drivers/usb/input/usbmouse.c
drivers/usb/input/usbmouse.c
+1
-1
drivers/usb/media/ov511.c
drivers/usb/media/ov511.c
+58
-69
drivers/usb/misc/Kconfig
drivers/usb/misc/Kconfig
+9
-0
drivers/usb/misc/atmsar.c
drivers/usb/misc/atmsar.c
+5
-392
drivers/usb/misc/atmsar.h
drivers/usb/misc/atmsar.h
+0
-8
drivers/usb/misc/speedtouch.c
drivers/usb/misc/speedtouch.c
+447
-305
drivers/usb/net/kaweth.c
drivers/usb/net/kaweth.c
+3
-2
drivers/usb/net/pegasus.h
drivers/usb/net/pegasus.h
+4
-1
drivers/usb/serial/Kconfig
drivers/usb/serial/Kconfig
+4
-0
drivers/usb/serial/console.c
drivers/usb/serial/console.c
+0
-6
drivers/usb/serial/usb-serial.c
drivers/usb/serial/usb-serial.c
+84
-90
drivers/usb/serial/usb-serial.h
drivers/usb/serial/usb-serial.h
+2
-2
drivers/usb/storage/transport.c
drivers/usb/storage/transport.c
+1
-1
include/linux/usb.h
include/linux/usb.h
+2
-0
lib/Makefile
lib/Makefile
+1
-1
No files found.
CREDITS
View file @
6aa909be
...
...
@@ -2746,6 +2746,14 @@ E: wsalamon@tislabs.com
E: wsalamon@nai.com
D: portions of the Linux Security Module (LSM) framework and security modules
N: Duncan Sands
E: duncan.sands@wanadoo.fr
W: http://topo.math.u-psud.fr/~sands
D: Alcatel SpeedTouch USB driver
S: 69 rue Dunois
S: 75013 Paris
S: France
N: Robert Sanders
E: gt8134b@prism.gatech.edu
D: Dosemu
...
...
MAINTAINERS
View file @
6aa909be
...
...
@@ -215,6 +215,14 @@ M: Juergen Fischer <fischer@norbit.de>
L: linux-scsi@vger.kernel.org
S: Maintained
ALCATEL SPEEDTOUCH USB DRIVER
P: Duncan Sands
M: duncan.sands@wanadoo.fr
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
W: http://www.linux-usb.org/SpeedTouch/
S: Maintained
ALPHA PORT
P: Richard Henderson
M: rth@twiddle.net
...
...
drivers/usb/
class/
Makefile.lib
→
drivers/usb/Makefile.lib
View file @
6aa909be
obj-$(CONFIG_USB_CATC)
+=
crc32.o
obj-$(CONFIG_USB_SPEEDTOUCH)
+=
crc32.o
obj-$(CONFIG_USB_USBNET)
+=
crc32.o
drivers/usb/class/cdc-acm.c
View file @
6aa909be
...
...
@@ -606,6 +606,7 @@ static int acm_probe (struct usb_interface *intf,
if
(
!
acm
->
ctrlurb
)
{
err
(
"out of memory"
);
kfree
(
acm
);
kfree
(
buf
);
return
-
ENOMEM
;
}
acm
->
readurb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
...
...
@@ -613,6 +614,7 @@ static int acm_probe (struct usb_interface *intf,
err
(
"out of memory"
);
usb_free_urb
(
acm
->
ctrlurb
);
kfree
(
acm
);
kfree
(
buf
);
return
-
ENOMEM
;
}
acm
->
writeurb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
...
...
@@ -621,6 +623,7 @@ static int acm_probe (struct usb_interface *intf,
usb_free_urb
(
acm
->
readurb
);
usb_free_urb
(
acm
->
ctrlurb
);
kfree
(
acm
);
kfree
(
buf
);
return
-
ENOMEM
;
}
...
...
drivers/usb/core/message.c
View file @
6aa909be
...
...
@@ -219,16 +219,25 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
spin_lock_irqsave
(
&
io
->
lock
,
flags
);
/* In 2.5 we require hcds' endpoint queues not to progress after fault
* reports, until the competion callback (this!) returns. That lets
* reports, until the comp
l
etion callback (this!) returns. That lets
* device driver code (like this routine) unlink queued urbs first,
* if it needs to, since the HC won't work on them at all. So it's
* not possible for page N+1 to overwrite page N, and so on.
*
* That's only for "hard" faults; "soft" faults (unlinks) sometimes
* complete before the HCD can get requests away from hardware,
* though never during cleanup after a hard fault.
*/
if
(
io
->
status
&&
urb
->
actual_length
)
{
err
(
"driver for bus %s dev %s ep %d-%s corrupted data!"
,
io
->
dev
->
bus
->
bus_name
,
io
->
dev
->
devpath
,
if
(
io
->
status
&&
(
io
->
status
!=
-
ECONNRESET
||
urb
->
status
!=
-
ECONNRESET
)
&&
urb
->
actual_length
)
{
dev_err
(
io
->
dev
->
bus
->
controller
,
"dev %s ep%d%s scatterlist error %d/%d
\n
"
,
io
->
dev
->
devpath
,
usb_pipeendpoint
(
urb
->
pipe
),
usb_pipein
(
urb
->
pipe
)
?
"in"
:
"out"
);
usb_pipein
(
urb
->
pipe
)
?
"in"
:
"out"
,
urb
->
status
,
io
->
status
);
// BUG ();
}
...
...
drivers/usb/core/urb.c
View file @
6aa909be
...
...
@@ -195,7 +195,7 @@ int usb_submit_urb(struct urb *urb, int mem_flags)
if
(
!
urb
||
urb
->
hcpriv
||
!
urb
->
complete
)
return
-
EINVAL
;
if
(
!
(
dev
=
urb
->
dev
)
||
!
dev
->
bus
||
dev
->
devnum
<=
0
)
if
(
!
(
dev
=
urb
->
dev
)
||
!
dev
->
present
||
!
dev
->
bus
||
dev
->
devnum
<=
0
)
return
-
ENODEV
;
if
(
!
(
op
=
dev
->
bus
->
op
)
||
!
op
->
submit_urb
)
return
-
ENODEV
;
...
...
@@ -376,7 +376,7 @@ int usb_submit_urb(struct urb *urb, int mem_flags)
*/
int
usb_unlink_urb
(
struct
urb
*
urb
)
{
if
(
urb
&&
urb
->
dev
&&
urb
->
dev
->
bus
&&
urb
->
dev
->
bus
->
op
)
if
(
urb
&&
urb
->
dev
&&
urb
->
dev
->
present
&&
urb
->
dev
->
bus
&&
urb
->
dev
->
bus
->
op
)
return
urb
->
dev
->
bus
->
op
->
unlink_urb
(
urb
);
else
return
-
ENODEV
;
...
...
drivers/usb/core/usb.c
View file @
6aa909be
...
...
@@ -679,6 +679,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus)
memset
(
dev
,
0
,
sizeof
(
*
dev
));
device_initialize
(
&
dev
->
dev
);
dev
->
present
=
1
;
usb_bus_get
(
bus
);
...
...
@@ -854,6 +855,10 @@ void usb_disconnect(struct usb_device **pdev)
}
device_unregister
(
&
dev
->
dev
);
/* mark the device as not present so any further urb submissions for
* this device will fail. */
dev
->
present
=
0
;
/* Decrement the reference count, it'll auto free everything when */
/* it hits 0 which could very well be now */
usb_put_dev
(
dev
);
...
...
drivers/usb/host/ehci-hcd.c
View file @
6aa909be
...
...
@@ -37,7 +37,7 @@
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/reboot.h>
#include <linux/usb.h>
#include <linux/version.h>
...
...
@@ -306,6 +306,19 @@ static int bios_handoff (struct ehci_hcd *ehci, int where, u32 cap)
return
0
;
}
static
int
ehci_reboot
(
struct
notifier_block
*
self
,
unsigned
long
code
,
void
*
null
)
{
struct
ehci_hcd
*
ehci
;
ehci
=
container_of
(
self
,
struct
ehci_hcd
,
reboot_notifier
);
/* make BIOS/etc use companion controller during reboot */
writel
(
0
,
&
ehci
->
regs
->
configured_flag
);
return
0
;
}
/* called by khubd or root hub init threads */
static
int
ehci_start
(
struct
usb_hcd
*
hcd
)
...
...
@@ -464,6 +477,9 @@ static int ehci_start (struct usb_hcd *hcd)
* are explicitly handed to companion controller(s), so no TT is
* involved with the root hub.
*/
ehci
->
reboot_notifier
.
notifier_call
=
ehci_reboot
;
register_reboot_notifier
(
&
ehci
->
reboot_notifier
);
ehci
->
hcd
.
state
=
USB_STATE_READY
;
writel
(
FLAG_CF
,
&
ehci
->
regs
->
configured_flag
);
readl
(
&
ehci
->
regs
->
command
);
/* unblock posted write */
...
...
@@ -520,6 +536,7 @@ static void ehci_stop (struct usb_hcd *hcd)
/* let companion controllers work when we aren't */
writel
(
0
,
&
ehci
->
regs
->
configured_flag
);
unregister_reboot_notifier
(
&
ehci
->
reboot_notifier
);
remove_debug_files
(
ehci
);
...
...
drivers/usb/host/ehci.h
View file @
6aa909be
...
...
@@ -81,8 +81,10 @@ struct ehci_hcd { /* one per controller */
struct
pci_pool
*
sitd_pool
;
/* sitd per split iso urb */
struct
timer_list
watchdog
;
struct
notifier_block
reboot_notifier
;
unsigned
stamp
;
/* irq statistics */
#ifdef EHCI_STATS
struct
ehci_stats
stats
;
# define COUNT(x) do { (x)++; } while (0)
...
...
drivers/usb/input/Kconfig
View file @
6aa909be
...
...
@@ -164,10 +164,9 @@ config USB_POWERMATE
depends on USB && INPUT
---help---
Say Y here if you want to use Griffin PowerMate or Contour Jog devices.
These are stainless steel dials which can measure clockwise and
anticlockwise rotation. The dial also acts as a pushbutton. The base
contains an LED which can be instructed to pulse or to switch to a
particular intensity.
These are aluminum dials which can measure clockwise and anticlockwise
rotation. The dial also acts as a pushbutton. The base contains an LED
which can be instructed to pulse or to switch to a particular intensity.
You can download userspace tools from http://sowerbutts.com/powermate/
...
...
drivers/usb/input/usbkbd.c
View file @
6aa909be
...
...
@@ -355,7 +355,7 @@ static struct usb_device_id usb_kbd_id_table [] = {
MODULE_DEVICE_TABLE
(
usb
,
usb_kbd_id_table
);
static
struct
usb_driver
usb_kbd_driver
=
{
.
name
=
"
keyboar
d"
,
.
name
=
"
usbkb
d"
,
.
probe
=
usb_kbd_probe
,
.
disconnect
=
usb_kbd_disconnect
,
.
id_table
=
usb_kbd_id_table
,
...
...
drivers/usb/input/usbmouse.c
View file @
6aa909be
...
...
@@ -238,7 +238,7 @@ static struct usb_device_id usb_mouse_id_table [] = {
MODULE_DEVICE_TABLE
(
usb
,
usb_mouse_id_table
);
static
struct
usb_driver
usb_mouse_driver
=
{
.
name
=
"usb
_
mouse"
,
.
name
=
"usbmouse"
,
.
probe
=
usb_mouse_probe
,
.
disconnect
=
usb_mouse_disconnect
,
.
id_table
=
usb_mouse_id_table
,
...
...
drivers/usb/media/ov511.c
View file @
6aa909be
/*
* OmniVision OV511 Camera-to-USB Bridge Driver
*
* Copyright (c) 1999-200
2
Mark W. McClelland
* Copyright (c) 1999-200
3
Mark W. McClelland
* Original decompression code Copyright 1998-2000 OmniVision Technologies
* Many improvements by Bret Wallach <bwallac1@san.rr.com>
* Color fixes by by Orion Sky Lawlor <olawlor@acm.org> (2/26/2000)
...
...
@@ -60,7 +60,7 @@
/*
* Version Information
*/
#define DRIVER_VERSION "v1.6
3
for Linux 2.5"
#define DRIVER_VERSION "v1.6
4
for Linux 2.5"
#define EMAIL "mark@alpha.dyndns.org"
#define DRIVER_AUTHOR "Mark McClelland <mark@alpha.dyndns.org> & Bret Wallach \
& Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha \
...
...
@@ -137,7 +137,7 @@ MODULE_PARM_DESC(snapshot, "Enable snapshot mode");
MODULE_PARM
(
cams
,
"i"
);
MODULE_PARM_DESC
(
cams
,
"Number of simultaneous cameras"
);
MODULE_PARM
(
compress
,
"i"
);
MODULE_PARM_DESC
(
compress
,
"Turn on compression
(not reliable yet)
"
);
MODULE_PARM_DESC
(
compress
,
"Turn on compression"
);
MODULE_PARM
(
testpat
,
"i"
);
MODULE_PARM_DESC
(
testpat
,
"Replace image with vertical bar testpattern (only partially working)"
);
...
...
@@ -1349,6 +1349,13 @@ ov51x_restart(struct usb_ov511 *ov)
return
0
;
}
/* Sleeps until no frames are active. Returns !0 if got signal */
static
int
ov51x_wait_frames_inactive
(
struct
usb_ov511
*
ov
)
{
return
wait_event_interruptible
(
ov
->
wq
,
ov
->
curframe
<
0
);
}
/* Resets the hardware snapshot button */
static
void
ov51x_clear_snapshot
(
struct
usb_ov511
*
ov
)
...
...
@@ -2121,7 +2128,7 @@ sensor_get_exposure(struct usb_ov511 *ov, unsigned char *val)
return
0
;
}
#endif
/* CONFIG_
PROC_FS && CONFIG_
VIDEO_PROC_FS */
#endif
/* CONFIG_VIDEO_PROC_FS */
/* Turns on or off the LED. Only has an effect with OV511+/OV518(+) */
static
void
...
...
@@ -2486,8 +2493,6 @@ mode_init_ov_sensor_regs(struct usb_ov511 *ov, int width, int height,
/******** Clock programming ********/
// FIXME: Test this with OV6630
/* The OV6620 needs special handling. This prevents the
* severe banding that normally occurs */
if
(
ov
->
sensor
==
SEN_OV6620
||
ov
->
sensor
==
SEN_OV6630
)
...
...
@@ -2995,6 +3000,7 @@ ov51x_set_default_params(struct usb_ov511 *ov)
ov
->
frame
[
i
].
format
=
force_palette
;
else
ov
->
frame
[
i
].
format
=
VIDEO_PALETTE_YUV420
;
ov
->
frame
[
i
].
depth
=
get_depth
(
ov
->
frame
[
i
].
format
);
}
...
...
@@ -3577,12 +3583,8 @@ ov511_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
if
(
frame
->
scanstate
==
STATE_LINES
)
{
int
nextf
;
frame
->
grabstate
=
FRAME_DONE
;
// FIXME: Is this right?
if
(
waitqueue_active
(
&
frame
->
wq
))
{
frame
->
grabstate
=
FRAME_DONE
;
wake_up_interruptible
(
&
frame
->
wq
);
}
/* If next frame is ready or grabbing,
* point to it */
...
...
@@ -3747,12 +3749,8 @@ ov518_move_data(struct usb_ov511 *ov, unsigned char *in, int n)
if
(
frame
->
scanstate
==
STATE_LINES
)
{
int
nextf
;
frame
->
grabstate
=
FRAME_DONE
;
// FIXME: Is this right?
if
(
waitqueue_active
(
&
frame
->
wq
))
{
frame
->
grabstate
=
FRAME_DONE
;
wake_up_interruptible
(
&
frame
->
wq
);
}
/* If next frame is ready or grabbing,
* point to it */
...
...
@@ -4228,7 +4226,7 @@ ov51x_alloc(struct usb_ov511 *ov)
}
static
void
ov51x_dealloc
(
struct
usb_ov511
*
ov
,
int
now
)
ov51x_dealloc
(
struct
usb_ov511
*
ov
)
{
PDEBUG
(
4
,
"entered"
);
down
(
&
ov
->
buf_lock
);
...
...
@@ -4258,10 +4256,6 @@ ov51x_v4l1_open(struct inode *inode, struct file *file)
if
(
ov
->
user
)
goto
out
;
err
=
ov51x_alloc
(
ov
);
if
(
err
<
0
)
goto
out
;
ov
->
sub_flag
=
0
;
/* In case app doesn't set them... */
...
...
@@ -4283,9 +4277,13 @@ ov51x_v4l1_open(struct inode *inode, struct file *file)
goto
out
;
}
err
=
ov51x_alloc
(
ov
);
if
(
err
<
0
)
goto
out
;
err
=
ov51x_init_isoc
(
ov
);
if
(
err
)
{
ov51x_dealloc
(
ov
,
0
);
ov51x_dealloc
(
ov
);
goto
out
;
}
...
...
@@ -4319,7 +4317,7 @@ ov51x_v4l1_close(struct inode *inode, struct file *file)
ov51x_led_control
(
ov
,
0
);
if
(
ov
->
dev
)
ov51x_dealloc
(
ov
,
0
);
ov51x_dealloc
(
ov
);
up
(
&
ov
->
lock
);
...
...
@@ -4331,7 +4329,7 @@ ov51x_v4l1_close(struct inode *inode, struct file *file)
ov
->
cbuf
=
NULL
;
up
(
&
ov
->
cbuf_lock
);
ov51x_dealloc
(
ov
,
1
);
ov51x_dealloc
(
ov
);
kfree
(
ov
);
ov
=
NULL
;
}
...
...
@@ -4449,7 +4447,7 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
case
VIDIOCSPICT
:
{
struct
video_picture
*
p
=
arg
;
int
i
;
int
i
,
rc
;
PDEBUG
(
4
,
"VIDIOCSPICT"
);
...
...
@@ -4469,10 +4467,9 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
if
(
p
->
palette
!=
ov
->
frame
[
0
].
format
)
{
PDEBUG
(
4
,
"Detected format change"
);
/* If we're collecting previous frame wait
before changing modes */
interruptible_sleep_on
(
&
ov
->
wq
);
if
(
signal_pending
(
current
))
return
-
EINTR
;
rc
=
ov51x_wait_frames_inactive
(
ov
);
if
(
rc
)
return
rc
;
mode_init_regs
(
ov
,
ov
->
frame
[
0
].
width
,
ov
->
frame
[
0
].
height
,
p
->
palette
,
ov
->
sub_flag
);
...
...
@@ -4530,7 +4527,7 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
case
VIDIOCSWIN
:
{
struct
video_window
*
vw
=
arg
;
int
i
,
r
esult
;
int
i
,
r
c
;
PDEBUG
(
4
,
"VIDIOCSWIN: %dx%d"
,
vw
->
width
,
vw
->
height
);
...
...
@@ -4545,15 +4542,14 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
return -EINVAL;
#endif
/* If we're collecting previous frame wait
before changing modes */
interruptible_sleep_on
(
&
ov
->
wq
);
if
(
signal_pending
(
current
))
return
-
EINTR
;
rc
=
ov51x_wait_frames_inactive
(
ov
);
if
(
rc
)
return
rc
;
r
esult
=
mode_init_regs
(
ov
,
vw
->
width
,
vw
->
height
,
r
c
=
mode_init_regs
(
ov
,
vw
->
width
,
vw
->
height
,
ov
->
frame
[
0
].
format
,
ov
->
sub_flag
);
if
(
r
esult
<
0
)
return
r
esult
;
if
(
r
c
<
0
)
return
r
c
;
for
(
i
=
0
;
i
<
OV511_NUMFRAMES
;
i
++
)
{
ov
->
frame
[
i
].
width
=
vw
->
width
;
...
...
@@ -4600,7 +4596,7 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
case
VIDIOCMCAPTURE
:
{
struct
video_mmap
*
vm
=
arg
;
int
r
et
,
depth
;
int
r
c
,
depth
;
unsigned
int
f
=
vm
->
frame
;
PDEBUG
(
4
,
"VIDIOCMCAPTURE: frame: %d, %dx%d, %s"
,
f
,
vm
->
width
,
...
...
@@ -4642,14 +4638,14 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
(
ov
->
frame
[
f
].
depth
!=
depth
))
{
PDEBUG
(
4
,
"VIDIOCMCAPTURE: change in image parameters"
);
/* If we're collecting previous frame wait
before changing modes */
interruptible_sleep_on
(
&
ov
->
wq
)
;
if
(
signal_pending
(
current
))
return
-
EINTR
;
r
et
=
mode_init_regs
(
ov
,
vm
->
width
,
vm
->
height
,
rc
=
ov51x_wait_frames_inactive
(
ov
);
if
(
rc
)
return
rc
;
r
c
=
mode_init_regs
(
ov
,
vm
->
width
,
vm
->
height
,
vm
->
format
,
ov
->
sub_flag
);
#if 0
if (r
et
< 0) {
if (r
c
< 0) {
PDEBUG(1, "Got error while initializing regs ");
return ret;
}
...
...
@@ -4702,18 +4698,15 @@ ov51x_v4l1_ioctl_internal(struct inode *inode, struct file *file,
return
rc
;
if
(
frame
->
grabstate
==
FRAME_ERROR
)
{
int
ret
;
if
((
ret
=
ov51x_new_frame
(
ov
,
fnum
))
<
0
)
return
ret
;
if
((
rc
=
ov51x_new_frame
(
ov
,
fnum
))
<
0
)
return
rc
;
goto
redo
;
}
/* Fall through */
case
FRAME_DONE
:
if
(
ov
->
snap_enabled
&&
!
frame
->
snapshot
)
{
int
ret
;
if
((
ret
=
ov51x_new_frame
(
ov
,
fnum
))
<
0
)
return
ret
;
if
((
rc
=
ov51x_new_frame
(
ov
,
fnum
))
<
0
)
return
rc
;
goto
redo
;
}
...
...
@@ -6089,7 +6082,6 @@ ov518_configure(struct usb_ov511 *ov)
return
-
EBUSY
;
}
/****************************************************************************
*
* USB routines
...
...
@@ -6097,11 +6089,10 @@ ov518_configure(struct usb_ov511 *ov)
***************************************************************************/
static
int
ov51x_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
ov51x_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
struct
usb_device
*
dev
=
interface_to_usbdev
(
intf
);
struct
usb_interface_descriptor
*
i
nterface
;
struct
usb_interface_descriptor
*
i
desc
;
struct
usb_ov511
*
ov
;
int
i
;
int
registered
=
0
;
...
...
@@ -6112,12 +6103,11 @@ ov51x_probe(struct usb_interface *intf,
if
(
dev
->
descriptor
.
bNumConfigurations
!=
1
)
return
-
ENODEV
;
i
nterface
=
&
intf
->
altsetting
[
0
].
desc
;
i
desc
=
&
intf
->
altsetting
[
0
].
desc
;
/* Checking vendor/product should be enough, but what the hell */
if
(
interface
->
bInterfaceClass
!=
0xFF
)
if
(
idesc
->
bInterfaceClass
!=
0xFF
)
return
-
ENODEV
;
if
(
i
nterface
->
bInterfaceSubClass
!=
0x00
)
if
(
i
desc
->
bInterfaceSubClass
!=
0x00
)
return
-
ENODEV
;
if
((
ov
=
kmalloc
(
sizeof
(
*
ov
),
GFP_KERNEL
))
==
NULL
)
{
...
...
@@ -6128,7 +6118,7 @@ ov51x_probe(struct usb_interface *intf,
memset
(
ov
,
0
,
sizeof
(
*
ov
));
ov
->
dev
=
dev
;
ov
->
iface
=
i
nterface
->
bInterfaceNumber
;
ov
->
iface
=
i
desc
->
bInterfaceNumber
;
ov
->
led_policy
=
led
;
ov
->
compress
=
compress
;
ov
->
lightfreq
=
lightfreq
;
...
...
@@ -6272,7 +6262,7 @@ ov51x_probe(struct usb_interface *intf,
error_out:
err
(
"Camera initialization failed"
);
return
-
E
NOMEM
;
return
-
E
IO
;
}
static
void
...
...
@@ -6284,6 +6274,7 @@ ov51x_disconnect(struct usb_interface *intf)
PDEBUG
(
3
,
""
);
usb_set_intfdata
(
intf
,
NULL
);
if
(
!
ov
)
return
;
...
...
@@ -6298,9 +6289,8 @@ ov51x_disconnect(struct usb_interface *intf)
/* This will cause the process to request another frame */
for
(
n
=
0
;
n
<
OV511_NUMFRAMES
;
n
++
)
if
(
waitqueue_active
(
&
ov
->
frame
[
n
].
wq
))
wake_up_interruptible
(
&
ov
->
frame
[
n
].
wq
);
if
(
waitqueue_active
(
&
ov
->
wq
))
wake_up_interruptible
(
&
ov
->
wq
);
ov
->
streaming
=
0
;
...
...
@@ -6317,7 +6307,7 @@ ov51x_disconnect(struct usb_interface *intf)
ov
->
cbuf
=
NULL
;
up
(
&
ov
->
cbuf_lock
);
ov51x_dealloc
(
ov
,
1
);
ov51x_dealloc
(
ov
);
kfree
(
ov
);
ov
=
NULL
;
}
...
...
@@ -6333,7 +6323,6 @@ static struct usb_driver ov511_driver = {
.
disconnect
=
ov51x_disconnect
};
/****************************************************************************
*
* Module routines
...
...
drivers/usb/misc/Kconfig
View file @
6aa909be
...
...
@@ -96,6 +96,15 @@ config USB_LCD
config USB_SPEEDTOUCH
tristate "Alcatel Speedtouch ADSL USB Modem"
depends on USB && ATM
help
Say Y here if you have an Alcatel SpeedTouch USB or SpeedTouch 330
modem. In order to use your modem you will need to install some user
space tools, see <http://www.linux-usb.org/SpeedTouch/> for details.
This code is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called speedtch. If you want to compile it as
a module, say M here and read <file:Documentation/modules.txt>.
config USB_TEST
tristate "USB testing driver (DEVELOPMENT)"
...
...
drivers/usb/misc/atmsar.c
View file @
6aa909be
...
...
@@ -71,6 +71,7 @@
*
*/
#include <linux/crc32.h>
#include "atmsar.h"
/***********************
...
...
@@ -113,200 +114,22 @@
*dest++ = (unsigned char) (header >> 8); \
*dest++ = (unsigned char) (header & 0xff);
/*
* CRC Routines from net/wan/sbni.c)
* table generated by Rocksoft^tm Model CRC Algorithm Table Generation Program V1.0
*/
#define CRC32_REMAINDER CBF43926
#define CRC32_INITIAL 0xffffffff
#define CRC32(c,crc) (crc32tab[((size_t)(crc>>24) ^ (c)) & 0xff] ^ (((crc) << 8)))
unsigned
long
crc32tab
[
256
]
=
{
0x00000000L
,
0x04C11DB7L
,
0x09823B6EL
,
0x0D4326D9L
,
0x130476DCL
,
0x17C56B6BL
,
0x1A864DB2L
,
0x1E475005L
,
0x2608EDB8L
,
0x22C9F00FL
,
0x2F8AD6D6L
,
0x2B4BCB61L
,
0x350C9B64L
,
0x31CD86D3L
,
0x3C8EA00AL
,
0x384FBDBDL
,
0x4C11DB70L
,
0x48D0C6C7L
,
0x4593E01EL
,
0x4152FDA9L
,
0x5F15ADACL
,
0x5BD4B01BL
,
0x569796C2L
,
0x52568B75L
,
0x6A1936C8L
,
0x6ED82B7FL
,
0x639B0DA6L
,
0x675A1011L
,
0x791D4014L
,
0x7DDC5DA3L
,
0x709F7B7AL
,
0x745E66CDL
,
0x9823B6E0L
,
0x9CE2AB57L
,
0x91A18D8EL
,
0x95609039L
,
0x8B27C03CL
,
0x8FE6DD8BL
,
0x82A5FB52L
,
0x8664E6E5L
,
0xBE2B5B58L
,
0xBAEA46EFL
,
0xB7A96036L
,
0xB3687D81L
,
0xAD2F2D84L
,
0xA9EE3033L
,
0xA4AD16EAL
,
0xA06C0B5DL
,
0xD4326D90L
,
0xD0F37027L
,
0xDDB056FEL
,
0xD9714B49L
,
0xC7361B4CL
,
0xC3F706FBL
,
0xCEB42022L
,
0xCA753D95L
,
0xF23A8028L
,
0xF6FB9D9FL
,
0xFBB8BB46L
,
0xFF79A6F1L
,
0xE13EF6F4L
,
0xE5FFEB43L
,
0xE8BCCD9AL
,
0xEC7DD02DL
,
0x34867077L
,
0x30476DC0L
,
0x3D044B19L
,
0x39C556AEL
,
0x278206ABL
,
0x23431B1CL
,
0x2E003DC5L
,
0x2AC12072L
,
0x128E9DCFL
,
0x164F8078L
,
0x1B0CA6A1L
,
0x1FCDBB16L
,
0x018AEB13L
,
0x054BF6A4L
,
0x0808D07DL
,
0x0CC9CDCAL
,
0x7897AB07L
,
0x7C56B6B0L
,
0x71159069L
,
0x75D48DDEL
,
0x6B93DDDBL
,
0x6F52C06CL
,
0x6211E6B5L
,
0x66D0FB02L
,
0x5E9F46BFL
,
0x5A5E5B08L
,
0x571D7DD1L
,
0x53DC6066L
,
0x4D9B3063L
,
0x495A2DD4L
,
0x44190B0DL
,
0x40D816BAL
,
0xACA5C697L
,
0xA864DB20L
,
0xA527FDF9L
,
0xA1E6E04EL
,
0xBFA1B04BL
,
0xBB60ADFCL
,
0xB6238B25L
,
0xB2E29692L
,
0x8AAD2B2FL
,
0x8E6C3698L
,
0x832F1041L
,
0x87EE0DF6L
,
0x99A95DF3L
,
0x9D684044L
,
0x902B669DL
,
0x94EA7B2AL
,
0xE0B41DE7L
,
0xE4750050L
,
0xE9362689L
,
0xEDF73B3EL
,
0xF3B06B3BL
,
0xF771768CL
,
0xFA325055L
,
0xFEF34DE2L
,
0xC6BCF05FL
,
0xC27DEDE8L
,
0xCF3ECB31L
,
0xCBFFD686L
,
0xD5B88683L
,
0xD1799B34L
,
0xDC3ABDEDL
,
0xD8FBA05AL
,
0x690CE0EEL
,
0x6DCDFD59L
,
0x608EDB80L
,
0x644FC637L
,
0x7A089632L
,
0x7EC98B85L
,
0x738AAD5CL
,
0x774BB0EBL
,
0x4F040D56L
,
0x4BC510E1L
,
0x46863638L
,
0x42472B8FL
,
0x5C007B8AL
,
0x58C1663DL
,
0x558240E4L
,
0x51435D53L
,
0x251D3B9EL
,
0x21DC2629L
,
0x2C9F00F0L
,
0x285E1D47L
,
0x36194D42L
,
0x32D850F5L
,
0x3F9B762CL
,
0x3B5A6B9BL
,
0x0315D626L
,
0x07D4CB91L
,
0x0A97ED48L
,
0x0E56F0FFL
,
0x1011A0FAL
,
0x14D0BD4DL
,
0x19939B94L
,
0x1D528623L
,
0xF12F560EL
,
0xF5EE4BB9L
,
0xF8AD6D60L
,
0xFC6C70D7L
,
0xE22B20D2L
,
0xE6EA3D65L
,
0xEBA91BBCL
,
0xEF68060BL
,
0xD727BBB6L
,
0xD3E6A601L
,
0xDEA580D8L
,
0xDA649D6FL
,
0xC423CD6AL
,
0xC0E2D0DDL
,
0xCDA1F604L
,
0xC960EBB3L
,
0xBD3E8D7EL
,
0xB9FF90C9L
,
0xB4BCB610L
,
0xB07DABA7L
,
0xAE3AFBA2L
,
0xAAFBE615L
,
0xA7B8C0CCL
,
0xA379DD7BL
,
0x9B3660C6L
,
0x9FF77D71L
,
0x92B45BA8L
,
0x9675461FL
,
0x8832161AL
,
0x8CF30BADL
,
0x81B02D74L
,
0x857130C3L
,
0x5D8A9099L
,
0x594B8D2EL
,
0x5408ABF7L
,
0x50C9B640L
,
0x4E8EE645L
,
0x4A4FFBF2L
,
0x470CDD2BL
,
0x43CDC09CL
,
0x7B827D21L
,
0x7F436096L
,
0x7200464FL
,
0x76C15BF8L
,
0x68860BFDL
,
0x6C47164AL
,
0x61043093L
,
0x65C52D24L
,
0x119B4BE9L
,
0x155A565EL
,
0x18197087L
,
0x1CD86D30L
,
0x029F3D35L
,
0x065E2082L
,
0x0B1D065BL
,
0x0FDC1BECL
,
0x3793A651L
,
0x3352BBE6L
,
0x3E119D3FL
,
0x3AD08088L
,
0x2497D08DL
,
0x2056CD3AL
,
0x2D15EBE3L
,
0x29D4F654L
,
0xC5A92679L
,
0xC1683BCEL
,
0xCC2B1D17L
,
0xC8EA00A0L
,
0xD6AD50A5L
,
0xD26C4D12L
,
0xDF2F6BCBL
,
0xDBEE767CL
,
0xE3A1CBC1L
,
0xE760D676L
,
0xEA23F0AFL
,
0xEEE2ED18L
,
0xF0A5BD1DL
,
0xF464A0AAL
,
0xF9278673L
,
0xFDE69BC4L
,
0x89B8FD09L
,
0x8D79E0BEL
,
0x803AC667L
,
0x84FBDBD0L
,
0x9ABC8BD5L
,
0x9E7D9662L
,
0x933EB0BBL
,
0x97FFAD0CL
,
0xAFB010B1L
,
0xAB710D06L
,
0xA6322BDFL
,
0xA2F33668L
,
0xBCB4666DL
,
0xB8757BDAL
,
0xB5365D03L
,
0xB1F740B4L
};
#ifdef CRCASM
unsigned
long
calc_crc
(
char
*
mem
,
int
len
,
unsigned
initial
)
{
unsigned
crc
,
dummy_len
;
__asm__
(
"xorl %%eax,%%eax
\n\t
"
"1:
\n\t
"
"movl %%edx,%%eax
\n\t
"
"shrl $16,%%eax
\n\t
"
"lodsb
\n\t
"
"xorb %%ah,%%al
\n\t
"
"andl $255,%%eax
\n\t
"
"shll $8,%%edx
\n\t
"
"xorl (%%edi,%%eax,4),%%edx
\n\t
"
"loop 1b"
:
"=d"
(
crc
),
"=c"
(
dummy_len
)
:
"S"
(
mem
),
"D"
(
&
crc32tab
[
0
]),
"1"
(
len
),
"0"
(
initial
)
:
"eax"
);
return
crc
;
}
#else
unsigned
long
calc_crc
(
char
*
mem
,
int
len
,
unsigned
initial
)
{
unsigned
crc
;
crc
=
initial
;
for
(;
len
;
mem
++
,
len
--
)
{
crc
=
CRC32
(
*
mem
,
crc
);
}
return
(
crc
);
}
#endif
#define crc32( crc, mem, len) calc_crc(mem, len, crc);
/* initialization routines. not used at the moment
* I will avoid these as long as possible !!
*/
int
open_atmsar
(
void
)
{
return
0
;
}
int
remove_atmsar
(
void
)
{
return
0
;
}
/* ATOMIC version of alloc_tx */
struct
sk_buff
*
atmsar_alloc_skb_wrapper
(
struct
atm_vcc
*
vcc
,
unsigned
int
size
)
{
struct
sk_buff
*
skb
;
if
(
atomic_read
(
&
vcc
->
tx_inuse
)
&&
!
atm_may_send
(
vcc
,
size
))
{
PDEBUG
(
"Sorry: tx_inuse = %d, size = %d, sndbuf = %d
\n
"
,
atomic_read
(
&
vcc
->
tx_inuse
),
size
,
vcc
->
sk
->
sndbuf
);
return
NULL
;
}
skb
=
alloc_skb
(
size
,
GFP_ATOMIC
);
if
(
!
skb
)
return
NULL
;
atomic_add
(
skb
->
truesize
+
ATM_PDU_OVHD
,
&
vcc
->
tx_inuse
);
return
skb
;
}
struct
sk_buff
*
atmsar_alloc_tx
(
struct
atmsar_vcc_data
*
vcc
,
unsigned
int
size
)
{
struct
sk_buff
*
tmp
=
NULL
;
int
bufsize
=
0
;
switch
(
vcc
->
type
)
{
case
ATMSAR_TYPE_AAL0
:
/* reserving adequate headroom */
bufsize
=
size
+
(((
size
/
48
)
+
1
)
*
((
vcc
->
flags
&
ATMSAR_USE_53BYTE_CELL
)
?
5
:
4
));
break
;
case
ATMSAR_TYPE_AAL1
:
/* reserving adequate headroom */
bufsize
=
size
+
(((
size
/
47
)
+
1
)
*
((
vcc
->
flags
&
ATMSAR_USE_53BYTE_CELL
)
?
5
:
4
));
break
;
case
ATMSAR_TYPE_AAL2
:
case
ATMSAR_TYPE_AAL34
:
/* not supported */
break
;
case
ATMSAR_TYPE_AAL5
:
/* reserving adequate tailroom */
bufsize
=
size
+
(((
size
+
8
+
47
)
/
48
)
*
48
);
break
;
}
PDEBUG
(
"Requested size %d, Allocating size %d
\n
"
,
size
,
bufsize
);
tmp
=
vcc
->
alloc_tx
(
vcc
->
vcc
,
bufsize
);
skb_put
(
tmp
,
bufsize
);
return
tmp
;
}
struct
atmsar_vcc_data
*
atmsar_open
(
struct
atmsar_vcc_data
**
list
,
struct
atm_vcc
*
vcc
,
uint
type
,
ushort
vpi
,
ushort
vci
,
unchar
pti
,
unchar
gfc
,
uint
flags
)
{
struct
atmsar_vcc_data
*
new
;
if
(
!
vcc
)
return
NULL
;
new
=
kmalloc
(
sizeof
(
struct
atmsar_vcc_data
),
GFP_KERNEL
);
if
(
!
new
)
return
NULL
;
if
(
!
vcc
)
return
NULL
;
memset
(
new
,
0
,
sizeof
(
struct
atmsar_vcc_data
));
new
->
vcc
=
vcc
;
/*
* This gives problems with the ATM layer alloc_tx().
* It is not usable from interrupt context and for
* some reason this is used in interrupt context
* with br2684.c
*
if (vcc->alloc_tx)
new->alloc_tx = vcc->alloc_tx;
else
*/
new
->
alloc_tx
=
atmsar_alloc_skb_wrapper
;
new
->
stats
=
vcc
->
stats
;
new
->
type
=
type
;
new
->
next
=
NULL
;
...
...
@@ -375,216 +198,6 @@ void atmsar_close (struct atmsar_vcc_data **list, struct atmsar_vcc_data *vcc)
kfree
(
vcc
);
}
/***********************
**
** ENCODE FUNCTIONS
**
***********************/
/* encapsulate in an AAL5 frame, which is then split into ATM cells */
unsigned
int
atmsar_encode
(
struct
atmsar_vcc_data
*
ctx
,
char
*
source
,
char
*
target
,
unsigned
int
pdu_length
)
{
unsigned
int
num_cells
=
(
pdu_length
+
ATM_AAL5_TRAILER
+
ATM_CELL_PAYLOAD
-
1
)
/
ATM_CELL_PAYLOAD
;
unsigned
int
num_pdu_cells
=
pdu_length
/
ATM_CELL_PAYLOAD
+
1
;
unsigned
int
aal5_length
=
num_cells
*
ATM_CELL_PAYLOAD
;
unsigned
int
zero_padding
=
aal5_length
-
pdu_length
-
ATM_AAL5_TRAILER
;
unsigned
int
final_length
=
num_cells
*
ATM_CELL_SIZE
;
unsigned
char
aal5_trailer
[
ATM_AAL5_TRAILER
];
unsigned
char
cell_header
[
ATM_CELL_HEADER
];
u32
crc
;
int
i
;
PDEBUG
(
"atmsar_encode entered
\n
"
);
PDEBUG
(
"pdu_length %d, num_cells %d, num_pdu_cells %d, aal5_length %d, zero_padding %d, final_length %d
\n
"
,
pdu_length
,
num_cells
,
num_pdu_cells
,
aal5_length
,
zero_padding
,
final_length
);
PDEBUG
(
"source 0x=%p, target 0x%p
\n
"
,
source
,
target
);
aal5_trailer
[
0
]
=
0
;
/* UU = 0 */
aal5_trailer
[
1
]
=
0
;
/* CPI = 0 */
aal5_trailer
[
2
]
=
pdu_length
>>
8
;
aal5_trailer
[
3
]
=
pdu_length
;
crc
=
crc32
(
~
0
,
source
,
pdu_length
);
for
(
i
=
0
;
i
<
zero_padding
;
i
++
)
crc
=
CRC32
(
0
,
crc
);
crc
=
crc32
(
crc
,
aal5_trailer
,
4
);
crc
=
~
crc
;
aal5_trailer
[
4
]
=
crc
>>
24
;
aal5_trailer
[
5
]
=
crc
>>
16
;
aal5_trailer
[
6
]
=
crc
>>
8
;
aal5_trailer
[
7
]
=
crc
;
cell_header
[
0
]
=
ctx
->
atmHeader
>>
24
;
cell_header
[
1
]
=
ctx
->
atmHeader
>>
16
;
cell_header
[
2
]
=
ctx
->
atmHeader
>>
8
;
cell_header
[
3
]
=
ctx
->
atmHeader
;
cell_header
[
4
]
=
0xec
;
for
(
i
=
1
;
i
<
num_pdu_cells
;
i
++
)
{
memcpy
(
target
,
cell_header
,
ATM_CELL_HEADER
);
target
+=
ATM_CELL_HEADER
;
memcpy
(
target
,
source
,
ATM_CELL_PAYLOAD
);
target
+=
ATM_CELL_PAYLOAD
;
source
+=
ATM_CELL_PAYLOAD
;
PDEBUG
(
"source 0x=%p, target 0x%p
\n
"
,
source
,
target
);
}
memcpy
(
target
,
cell_header
,
ATM_CELL_HEADER
);
target
+=
ATM_CELL_HEADER
;
memcpy
(
target
,
source
,
pdu_length
%
ATM_CELL_PAYLOAD
);
target
+=
pdu_length
%
ATM_CELL_PAYLOAD
;
if
(
num_pdu_cells
<
num_cells
)
{
memset
(
target
,
0
,
zero_padding
+
ATM_AAL5_TRAILER
-
ATM_CELL_PAYLOAD
);
target
+=
zero_padding
+
ATM_AAL5_TRAILER
-
ATM_CELL_PAYLOAD
;
memcpy
(
target
,
cell_header
,
ATM_CELL_HEADER
);
target
+=
ATM_CELL_HEADER
;
zero_padding
=
ATM_CELL_PAYLOAD
-
ATM_AAL5_TRAILER
;
}
memset
(
target
,
0
,
zero_padding
);
target
+=
zero_padding
;
memcpy
(
target
,
aal5_trailer
,
ATM_AAL5_TRAILER
);
/* set pti bit in last cell */
*
(
target
+
ATM_AAL5_TRAILER
+
3
-
ATM_CELL_SIZE
)
|=
0x2
;
/* update stats */
if
(
ctx
->
stats
)
atomic_inc
(
&
ctx
->
stats
->
tx
);
if
(
ctx
->
stats
&&
(
ctx
->
type
<=
ATMSAR_TYPE_AAL1
))
atomic_add
(
num_cells
,
&
(
ctx
->
stats
->
tx
));
return
final_length
;
}
struct
sk_buff
*
atmsar_encode_rawcell
(
struct
atmsar_vcc_data
*
ctx
,
struct
sk_buff
*
skb
)
{
int
number_of_cells
=
(
skb
->
len
)
/
48
;
int
total_length
=
number_of_cells
*
(
ctx
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
53
:
52
);
unsigned
char
*
source
;
unsigned
char
*
target
;
struct
sk_buff
*
out
=
NULL
;
int
i
;
PDEBUG
(
"atmsar_encode_rawcell (0x%p, 0x%p) called
\n
"
,
ctx
,
skb
);
if
(
skb_cloned
(
skb
)
||
(
skb_headroom
(
skb
)
<
(
number_of_cells
*
(
ctx
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
5
:
4
))))
{
PDEBUG
(
"atmsar_encode_rawcell allocating new skb. ctx->alloc_tx = 0x%p, ctx->vcc = 0x%p
\n
"
,
ctx
->
alloc_tx
,
ctx
->
vcc
);
/* get new skb */
out
=
ctx
->
alloc_tx
(
ctx
->
vcc
,
total_length
);
if
(
!
out
)
return
NULL
;
skb_put
(
out
,
total_length
);
source
=
skb
->
data
;
target
=
out
->
data
;
}
else
{
PDEBUG
(
"atmsar_encode_rawcell: sufficient headroom
\n
"
);
source
=
skb
->
data
;
skb_push
(
skb
,
number_of_cells
*
((
ctx
->
flags
&
ATMSAR_USE_53BYTE_CELL
)
?
5
:
4
));
target
=
skb
->
data
;
out
=
skb
;
}
PDEBUG
(
"source 0x=%p, target 0x%p
\n
"
,
source
,
target
);
if
(
ctx
->
flags
&
ATMSAR_USE_53BYTE_CELL
)
{
for
(
i
=
0
;
i
<
number_of_cells
;
i
++
)
{
ADD_HEADER
(
target
,
ctx
->
atmHeader
);
*
target
++
=
(
char
)
0xEC
;
memcpy
(
target
,
source
,
48
);
target
+=
48
;
source
+=
48
;
PDEBUG
(
"source 0x=%p, target 0x%p
\n
"
,
source
,
target
);
}
}
else
{
for
(
i
=
0
;
i
<
number_of_cells
;
i
++
)
{
ADD_HEADER
(
target
,
ctx
->
atmHeader
);
memcpy
(
target
,
source
,
48
);
target
+=
48
;
source
+=
48
;
PDEBUG
(
"source 0x=%p, target 0x%p
\n
"
,
source
,
target
);
};
}
if
(
ctx
->
flags
&
ATMSAR_SET_PTI
)
{
/* setting pti bit in last cell */
*
(
target
-
(
ctx
->
flags
&
ATMSAR_USE_53BYTE_CELL
?
50
:
49
))
|=
0x2
;
}
/* update stats */
if
(
ctx
->
stats
&&
(
ctx
->
type
<=
ATMSAR_TYPE_AAL1
))
atomic_add
(
number_of_cells
,
&
(
ctx
->
stats
->
tx
));
PDEBUG
(
"atmsar_encode_rawcell return 0x%p (length %d)
\n
"
,
out
,
out
->
len
);
return
out
;
}
struct
sk_buff
*
atmsar_encode_aal5
(
struct
atmsar_vcc_data
*
ctx
,
struct
sk_buff
*
skb
)
{
int
length
,
pdu_length
;
unsigned
char
*
trailer
;
unsigned
char
*
pad
;
uint
crc
=
0xffffffff
;
PDEBUG
(
"atmsar_encode_aal5 (0x%p, 0x%p) called
\n
"
,
ctx
,
skb
);
/* determine aal5 length */
pdu_length
=
skb
->
len
;
length
=
((
pdu_length
+
8
+
47
)
/
48
)
*
48
;
if
(
skb_tailroom
(
skb
)
<
(
length
-
pdu_length
))
{
struct
sk_buff
*
out
;
PDEBUG
(
"atmsar_encode_aal5 allocating new skb. ctx->alloc_tx = 0x%p, ctx->vcc = 0x%p
\n
"
,
ctx
->
alloc_tx
,
ctx
->
vcc
);
/* get new skb */
out
=
ctx
->
alloc_tx
(
ctx
->
vcc
,
length
);
if
(
!
out
)
return
NULL
;
PDEBUG
(
"out->data = 0x%p
\n
"
,
out
->
data
);
PDEBUG
(
"atmsar_encode_aal5 pdu length %d, allocated length %d
\n
"
,
skb
->
len
,
length
);
memcpy
(
out
->
data
,
skb
->
data
,
skb
->
len
);
skb_put
(
out
,
skb
->
len
);
skb
=
out
;
}
PDEBUG
(
"skb->data = 0x%p
\n
"
,
skb
->
data
);
/* note end of pdu and add length */
pad
=
skb_put
(
skb
,
length
-
pdu_length
);
trailer
=
skb
->
tail
-
8
;
PDEBUG
(
"trailer = 0x%p
\n
"
,
trailer
);
/* zero padding space */
memset
(
pad
,
0
,
length
-
pdu_length
-
8
);
/* add trailer */
*
trailer
++
=
(
unsigned
char
)
0
;
/* UU = 0 */
*
trailer
++
=
(
unsigned
char
)
0
;
/* CPI = 0 */
*
trailer
++
=
(
unsigned
char
)
(
pdu_length
>>
8
);
*
trailer
++
=
(
unsigned
char
)
(
pdu_length
&
0xff
);
crc
=
~
crc32
(
crc
,
skb
->
data
,
length
-
4
);
*
trailer
++
=
(
unsigned
char
)
(
crc
>>
24
);
*
trailer
++
=
(
unsigned
char
)
(
crc
>>
16
);
*
trailer
++
=
(
unsigned
char
)
(
crc
>>
8
);
*
trailer
++
=
(
unsigned
char
)
(
crc
&
0xff
);
/* update stats */
if
(
ctx
->
stats
)
atomic_inc
(
&
ctx
->
stats
->
tx
);
PDEBUG
(
"atmsar_encode_aal5 return 0x%p (length %d)
\n
"
,
skb
,
skb
->
len
);
return
skb
;
}
/***********************
**
...
...
@@ -745,7 +358,7 @@ struct sk_buff *atmsar_decode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff
skb_pull
(
skb
,
skb
->
len
-
pdu_length
);
}
crc
=
~
crc32
(
crc
,
skb
->
data
,
pdu_length
-
4
);
crc
=
~
crc32
_be
(
crc
,
skb
->
data
,
pdu_length
-
4
);
/* check crc */
if
(
pdu_crc
!=
crc
)
{
...
...
drivers/usb/misc/atmsar.h
View file @
6aa909be
...
...
@@ -58,7 +58,6 @@ struct atmsar_vcc_data {
int
type
;
/* connection specific non-atmsar data */
struct
sk_buff
*
(
*
alloc_tx
)
(
struct
atm_vcc
*
vcc
,
unsigned
int
size
);
struct
atm_vcc
*
vcc
;
struct
k_atm_aal_stats
*
stats
;
unsigned
short
mtu
;
/* max is actually 65k for AAL5... */
...
...
@@ -81,15 +80,8 @@ extern struct atmsar_vcc_data *atmsar_open (struct atmsar_vcc_data **list, struc
unchar
gfc
,
uint
flags
);
extern
void
atmsar_close
(
struct
atmsar_vcc_data
**
list
,
struct
atmsar_vcc_data
*
vcc
);
extern
struct
sk_buff
*
atmsar_encode_rawcell
(
struct
atmsar_vcc_data
*
ctx
,
struct
sk_buff
*
skb
);
extern
struct
sk_buff
*
atmsar_encode_aal5
(
struct
atmsar_vcc_data
*
ctx
,
struct
sk_buff
*
skb
);
struct
sk_buff
*
atmsar_decode_rawcell
(
struct
atmsar_vcc_data
*
list
,
struct
sk_buff
*
skb
,
struct
atmsar_vcc_data
**
ctx
);
struct
sk_buff
*
atmsar_decode_aal5
(
struct
atmsar_vcc_data
*
ctx
,
struct
sk_buff
*
skb
);
struct
sk_buff
*
atmsar_alloc_tx
(
struct
atmsar_vcc_data
*
vcc
,
unsigned
int
size
);
unsigned
int
atmsar_encode
(
struct
atmsar_vcc_data
*
ctx
,
char
*
source
,
char
*
target
,
unsigned
int
pdu_length
);
#endif
/* _ATMSAR_H_ */
drivers/usb/misc/speedtouch.c
View file @
6aa909be
...
...
@@ -61,6 +61,7 @@
#include <linux/interrupt.h>
#include <linux/atm.h>
#include <linux/atmdev.h>
#include <linux/crc32.h>
#include "atmsar.h"
/*
...
...
@@ -69,14 +70,15 @@
*/
#ifdef DEBUG
#define PDEBUG(arg...) printk(KERN_DEBUG
"SpeedTouch USB
: " arg)
#define PDEBUG(arg...) printk(KERN_DEBUG
__FILE__ "
: " arg)
#else
#define PDEBUG(arg...)
#endif
#ifdef DEBUG_PACKET
#define PACKETDEBUG(arg...) udsl_print_packet ( arg )
static
int
udsl_print_packet
(
const
unsigned
char
*
data
,
int
len
);
#define PACKETDEBUG(arg...) udsl_print_packet (arg)
#else
#define PACKETDEBUG(arg...)
#endif
...
...
@@ -88,15 +90,14 @@
#define SPEEDTOUCH_VENDORID 0x06b9
#define SPEEDTOUCH_PRODUCTID 0x4061
#define UDSL_OBUF_SIZE 32768
#define UDSL_MINOR 48
#define UDSL_NUMBER_RCV_URBS 1
#define UDSL_NUMBER_SND_URBS 1
#define UDSL_RECEIVE_BUFFER_SIZE 64*53
#define UDSL_NUMBER_SND_BUFS (2*UDSL_NUMBER_SND_URBS)
#define UDSL_RCV_BUFFER_SIZE (1*64)
/* ATM cells */
#define UDSL_SND_BUFFER_SIZE (1*64)
/* ATM cells */
/* max should be (1500 IP mtu + 2 ppp bytes + 32 * 5 cellheader overhead) for
* PPPoA and (1500 + 14 + 32*5 cellheader overhead) for PPPoE */
#define UDSL_MAX_AAL5_MRU 2048
#define UDSL_SEND_CONTEXTS 8
#define UDSL_IOCTL_START 1
#define UDSL_IOCTL_STOP 2
...
...
@@ -126,13 +127,31 @@ struct udsl_receiver {
struct
udsl_instance_data
*
instance
;
};
struct
udsl_usb_send_data_context
{
struct
udsl_send_buffer
{
struct
list_head
list
;
unsigned
char
*
base
;
unsigned
char
*
free_start
;
unsigned
int
free_cells
;
};
struct
udsl_sender
{
struct
list_head
list
;
struct
udsl_send_buffer
*
buffer
;
struct
urb
*
urb
;
struct
sk_buff
*
skb
;
struct
atm_vcc
*
vcc
;
struct
udsl_instance_data
*
instance
;
};
struct
udsl_control
{
struct
atm_skb_data
atm_data
;
unsigned
int
num_cells
;
unsigned
int
num_entire
;
unsigned
char
cell_header
[
ATM_CELL_HEADER
];
unsigned
int
pdu_padding
;
unsigned
char
aal5_trailer
[
ATM_AAL5_TRAILER
];
};
#define UDSL_SKB(x) ((struct udsl_control *)(x)->cb)
/*
* UDSL main driver data
*/
...
...
@@ -142,13 +161,10 @@ struct udsl_instance_data {
/* usb device part */
struct
usb_device
*
usb_dev
;
struct
sk_buff_head
sndqueue
;
struct
udsl_usb_send_data_context
send_ctx
[
UDSL_NUMBER_SND_URBS
];
int
firmware_loaded
;
/* atm device part */
struct
atm_dev
*
atm_dev
;
struct
atmsar_vcc_data
*
atmsar_vcc_list
;
/* receiving */
...
...
@@ -161,18 +177,30 @@ struct udsl_instance_data {
struct
list_head
completed_receivers
;
struct
tasklet_struct
receive_tasklet
;
};
static
const
char
udsl_driver_name
[]
=
"Alcatel SpeedTouch USB"
;
/* sending */
struct
udsl_sender
all_senders
[
UDSL_NUMBER_SND_URBS
];
struct
udsl_send_buffer
all_buffers
[
UDSL_NUMBER_SND_BUFS
];
#ifdef DEBUG_PACKET
static
int
udsl_print_packet
(
const
unsigned
char
*
data
,
int
len
);
#endif
struct
sk_buff_head
sndqueue
;
spinlock_t
send_lock
;
struct
list_head
spare_senders
;
struct
list_head
spare_buffers
;
struct
tasklet_struct
send_tasklet
;
struct
sk_buff
*
current_skb
;
/* being emptied */
struct
udsl_send_buffer
*
current_buffer
;
/* being filled */
struct
list_head
filled_buffers
;
};
static
const
char
udsl_driver_name
[]
=
"speedtch"
;
/*
* atm driver prototypes and stuctures
*/
static
void
udsl_atm_dev_close
(
struct
atm_dev
*
dev
);
static
int
udsl_atm_open
(
struct
atm_vcc
*
vcc
,
short
vpi
,
int
vci
);
static
void
udsl_atm_close
(
struct
atm_vcc
*
vcc
);
static
int
udsl_atm_ioctl
(
struct
atm_dev
*
dev
,
unsigned
int
cmd
,
void
*
arg
);
...
...
@@ -180,6 +208,7 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb);
static
int
udsl_atm_proc_read
(
struct
atm_dev
*
atm_dev
,
loff_t
*
pos
,
char
*
page
);
static
struct
atmdev_ops
udsl_atm_devops
=
{
.
dev_close
=
udsl_atm_dev_close
,
.
open
=
udsl_atm_open
,
.
close
=
udsl_atm_close
,
.
ioctl
=
udsl_atm_ioctl
,
...
...
@@ -187,20 +216,13 @@ static struct atmdev_ops udsl_atm_devops = {
.
proc_read
=
udsl_atm_proc_read
,
};
struct
udsl_atm_dev_data
{
struct
atmsar_vcc_data
*
atmsar_vcc
;
};
/*
* usb driver prototypes and structures
*/
static
int
udsl_usb_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
);
static
void
udsl_usb_disconnect
(
struct
usb_interface
*
intf
);
static
int
udsl_usb_send_data
(
struct
udsl_instance_data
*
instance
,
struct
atm_vcc
*
vcc
,
struct
sk_buff
*
skb
);
static
int
udsl_usb_ioctl
(
struct
usb_interface
*
intf
,
unsigned
int
code
,
void
*
user_data
);
static
int
udsl_usb_cancelsends
(
struct
udsl_instance_data
*
instance
,
struct
atm_vcc
*
vcc
);
static
struct
usb_driver
udsl_usb_driver
=
{
.
name
=
udsl_driver_name
,
...
...
@@ -211,6 +233,86 @@ static struct usb_driver udsl_usb_driver = {
};
/*************
** encode **
*************/
static
void
udsl_groom_skb
(
struct
atm_vcc
*
vcc
,
struct
sk_buff
*
skb
)
{
struct
udsl_control
*
ctrl
=
UDSL_SKB
(
skb
);
unsigned
int
i
,
zero_padding
;
unsigned
char
zero
=
0
;
u32
crc
;
ctrl
->
atm_data
.
vcc
=
vcc
;
ctrl
->
cell_header
[
0
]
=
vcc
->
vpi
>>
4
;
ctrl
->
cell_header
[
1
]
=
(
vcc
->
vpi
<<
4
)
|
(
vcc
->
vci
>>
12
);
ctrl
->
cell_header
[
2
]
=
vcc
->
vci
>>
4
;
ctrl
->
cell_header
[
3
]
=
vcc
->
vci
<<
4
;
ctrl
->
cell_header
[
4
]
=
0xec
;
ctrl
->
num_cells
=
(
skb
->
len
+
ATM_AAL5_TRAILER
+
ATM_CELL_PAYLOAD
-
1
)
/
ATM_CELL_PAYLOAD
;
ctrl
->
num_entire
=
skb
->
len
/
ATM_CELL_PAYLOAD
;
zero_padding
=
ctrl
->
num_cells
*
ATM_CELL_PAYLOAD
-
skb
->
len
-
ATM_AAL5_TRAILER
;
if
(
ctrl
->
num_entire
+
1
<
ctrl
->
num_cells
)
ctrl
->
pdu_padding
=
zero_padding
-
(
ATM_CELL_PAYLOAD
-
ATM_AAL5_TRAILER
);
else
ctrl
->
pdu_padding
=
zero_padding
;
ctrl
->
aal5_trailer
[
0
]
=
0
;
/* UU = 0 */
ctrl
->
aal5_trailer
[
1
]
=
0
;
/* CPI = 0 */
ctrl
->
aal5_trailer
[
2
]
=
skb
->
len
>>
8
;
ctrl
->
aal5_trailer
[
3
]
=
skb
->
len
;
crc
=
crc32_be
(
~
0
,
skb
->
data
,
skb
->
len
);
for
(
i
=
0
;
i
<
zero_padding
;
i
++
)
crc
=
crc32_be
(
crc
,
&
zero
,
1
);
crc
=
crc32_be
(
crc
,
ctrl
->
aal5_trailer
,
4
);
crc
=
~
crc
;
ctrl
->
aal5_trailer
[
4
]
=
crc
>>
24
;
ctrl
->
aal5_trailer
[
5
]
=
crc
>>
16
;
ctrl
->
aal5_trailer
[
6
]
=
crc
>>
8
;
ctrl
->
aal5_trailer
[
7
]
=
crc
;
}
static
char
*
udsl_write_cell
(
struct
sk_buff
*
skb
,
char
*
target
)
{
struct
udsl_control
*
ctrl
=
UDSL_SKB
(
skb
);
ctrl
->
num_cells
--
;
memcpy
(
target
,
ctrl
->
cell_header
,
ATM_CELL_HEADER
);
target
+=
ATM_CELL_HEADER
;
if
(
ctrl
->
num_entire
)
{
ctrl
->
num_entire
--
;
memcpy
(
target
,
skb
->
data
,
ATM_CELL_PAYLOAD
);
target
+=
ATM_CELL_PAYLOAD
;
__skb_pull
(
skb
,
ATM_CELL_PAYLOAD
);
return
target
;
}
memcpy
(
target
,
skb
->
data
,
skb
->
len
);
target
+=
skb
->
len
;
__skb_pull
(
skb
,
skb
->
len
);
memset
(
target
,
0
,
ctrl
->
pdu_padding
);
target
+=
ctrl
->
pdu_padding
;
if
(
ctrl
->
num_cells
)
{
ctrl
->
pdu_padding
=
ATM_CELL_PAYLOAD
-
ATM_AAL5_TRAILER
;
}
else
{
memcpy
(
target
,
ctrl
->
aal5_trailer
,
ATM_AAL5_TRAILER
);
target
+=
ATM_AAL5_TRAILER
;
/* set pti bit in last cell */
*
(
target
+
3
-
ATM_CELL_SIZE
)
|=
0x2
;
}
return
target
;
}
/**************
** receive **
**************/
...
...
@@ -221,19 +323,18 @@ static void udsl_complete_receive (struct urb *urb, struct pt_regs *regs)
struct
udsl_receiver
*
rcv
;
unsigned
long
flags
;
PDEBUG
(
"udsl_complete_receive entered
\n
"
);
if
(
!
urb
||
!
(
rcv
=
urb
->
context
)
||
!
(
instance
=
rcv
->
instance
))
{
PDEBUG
(
"udsl_complete_receive: bad urb!
\n
"
);
return
;
}
PDEBUG
(
"udsl_complete_receive entered (urb 0x%p, status %d)
\n
"
,
urb
,
urb
->
status
);
tasklet_schedule
(
&
instance
->
receive_tasklet
);
/* may not be in_interrupt() */
spin_lock_irqsave
(
&
instance
->
completed_receivers_lock
,
flags
);
list_add_tail
(
&
rcv
->
list
,
&
instance
->
completed_receivers
);
spin_unlock_irqrestore
(
&
instance
->
completed_receivers_lock
,
flags
);
PDEBUG
(
"udsl_complete_receive: scheduling tasklet
\n
"
);
tasklet_schedule
(
&
instance
->
receive_tasklet
);
}
static
void
udsl_process_receive
(
unsigned
long
data
)
...
...
@@ -246,6 +347,7 @@ static void udsl_process_receive (unsigned long data)
struct
urb
*
urb
;
struct
atmsar_vcc_data
*
atmsar_vcc
=
NULL
;
struct
sk_buff
*
new
=
NULL
,
*
tmp
=
NULL
;
int
err
;
PDEBUG
(
"udsl_process_receive entered
\n
"
);
...
...
@@ -315,12 +417,12 @@ static void udsl_process_receive (unsigned long data)
instance
->
usb_dev
,
usb_rcvbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_IN
),
(
unsigned
char
*
)
rcv
->
skb
->
data
,
UDSL_R
ECEIVE_BUFFER
_SIZE
,
UDSL_R
CV_BUFFER_SIZE
*
ATM_CELL
_SIZE
,
udsl_complete_receive
,
rcv
);
if
(
!
usb_submit_urb
(
urb
,
GFP_ATOMIC
))
if
(
!
(
err
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
)
))
break
;
PDEBUG
(
"udsl_process_receive: submission failed
\n
"
);
PDEBUG
(
"udsl_process_receive: submission failed
(%d)
\n
"
,
err
);
/* fall through */
default:
/* error or urb unlinked */
PDEBUG
(
"udsl_process_receive: adding to spare_receivers
\n
"
);
...
...
@@ -358,7 +460,7 @@ static void udsl_fire_receivers (struct udsl_instance_data *instance)
instance
->
usb_dev
,
usb_rcvbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_IN
),
(
unsigned
char
*
)
rcv
->
skb
->
data
,
UDSL_R
ECEIVE_BUFFER
_SIZE
,
UDSL_R
CV_BUFFER_SIZE
*
ATM_CELL
_SIZE
,
udsl_complete_receive
,
rcv
);
...
...
@@ -374,6 +476,210 @@ static void udsl_fire_receivers (struct udsl_instance_data *instance)
}
/***********
** send **
***********/
static
void
udsl_complete_send
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
struct
udsl_instance_data
*
instance
;
struct
udsl_sender
*
snd
;
unsigned
long
flags
;
if
(
!
urb
||
!
(
snd
=
urb
->
context
)
||
!
(
instance
=
snd
->
instance
))
{
PDEBUG
(
"udsl_complete_send: bad urb!
\n
"
);
return
;
}
PDEBUG
(
"udsl_complete_send entered (urb 0x%p, status %d)
\n
"
,
urb
,
urb
->
status
);
tasklet_schedule
(
&
instance
->
send_tasklet
);
/* may not be in_interrupt() */
spin_lock_irqsave
(
&
instance
->
send_lock
,
flags
);
list_add
(
&
snd
->
list
,
&
instance
->
spare_senders
);
list_add
(
&
snd
->
buffer
->
list
,
&
instance
->
spare_buffers
);
spin_unlock_irqrestore
(
&
instance
->
send_lock
,
flags
);
}
static
void
udsl_process_send
(
unsigned
long
data
)
{
struct
udsl_send_buffer
*
buf
;
unsigned
int
cells_to_write
;
int
err
;
unsigned
long
flags
;
unsigned
int
i
;
struct
udsl_instance_data
*
instance
=
(
struct
udsl_instance_data
*
)
data
;
struct
sk_buff
*
skb
;
struct
udsl_sender
*
snd
;
unsigned
char
*
target
;
PDEBUG
(
"udsl_process_send entered
\n
"
);
made_progress:
spin_lock_irqsave
(
&
instance
->
send_lock
,
flags
);
while
(
!
list_empty
(
&
instance
->
spare_senders
))
{
if
(
!
list_empty
(
&
instance
->
filled_buffers
))
{
buf
=
list_entry
(
instance
->
filled_buffers
.
next
,
struct
udsl_send_buffer
,
list
);
list_del
(
&
buf
->
list
);
PDEBUG
(
"sending filled buffer (0x%p)
\n
"
,
buf
);
}
else
if
((
buf
=
instance
->
current_buffer
))
{
instance
->
current_buffer
=
NULL
;
PDEBUG
(
"sending current buffer (0x%p)
\n
"
,
buf
);
}
else
/* all buffers empty */
break
;
snd
=
list_entry
(
instance
->
spare_senders
.
next
,
struct
udsl_sender
,
list
);
list_del
(
&
snd
->
list
);
spin_unlock_irqrestore
(
&
instance
->
send_lock
,
flags
);
snd
->
buffer
=
buf
;
usb_fill_bulk_urb
(
snd
->
urb
,
instance
->
usb_dev
,
usb_sndbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_OUT
),
buf
->
base
,
(
UDSL_SND_BUFFER_SIZE
-
buf
->
free_cells
)
*
ATM_CELL_SIZE
,
udsl_complete_send
,
snd
);
PDEBUG
(
"submitting urb 0x%p, contains %d cells
\n
"
,
snd
->
urb
,
UDSL_SND_BUFFER_SIZE
-
buf
->
free_cells
);
if
((
err
=
usb_submit_urb
(
snd
->
urb
,
GFP_ATOMIC
))
<
0
)
{
PDEBUG
(
"submission failed (%d)!
\n
"
,
err
);
spin_lock_irqsave
(
&
instance
->
send_lock
,
flags
);
list_add
(
&
snd
->
list
,
&
instance
->
spare_senders
);
spin_unlock_irqrestore
(
&
instance
->
send_lock
,
flags
);
list_add
(
&
buf
->
list
,
&
instance
->
filled_buffers
);
return
;
}
spin_lock_irqsave
(
&
instance
->
send_lock
,
flags
);
}
/* while */
spin_unlock_irqrestore
(
&
instance
->
send_lock
,
flags
);
if
(
!
instance
->
current_skb
&&
!
(
instance
->
current_skb
=
skb_dequeue
(
&
instance
->
sndqueue
)))
{
PDEBUG
(
"done - no more skbs
\n
"
);
return
;
}
skb
=
instance
->
current_skb
;
if
(
!
(
buf
=
instance
->
current_buffer
))
{
spin_lock_irqsave
(
&
instance
->
send_lock
,
flags
);
if
(
list_empty
(
&
instance
->
spare_buffers
))
{
instance
->
current_buffer
=
NULL
;
spin_unlock_irqrestore
(
&
instance
->
send_lock
,
flags
);
PDEBUG
(
"done - no more buffers
\n
"
);
return
;
}
buf
=
list_entry
(
instance
->
spare_buffers
.
next
,
struct
udsl_send_buffer
,
list
);
list_del
(
&
buf
->
list
);
spin_unlock_irqrestore
(
&
instance
->
send_lock
,
flags
);
buf
->
free_start
=
buf
->
base
;
buf
->
free_cells
=
UDSL_SND_BUFFER_SIZE
;
instance
->
current_buffer
=
buf
;
}
cells_to_write
=
min
(
buf
->
free_cells
,
UDSL_SKB
(
skb
)
->
num_cells
);
target
=
buf
->
free_start
;
PDEBUG
(
"writing %u cells from skb 0x%p to buffer 0x%p
\n
"
,
cells_to_write
,
skb
,
buf
);
for
(
i
=
0
;
i
<
cells_to_write
;
i
++
)
target
=
udsl_write_cell
(
skb
,
target
);
buf
->
free_start
=
target
;
if
(
!
(
buf
->
free_cells
-=
cells_to_write
))
{
list_add_tail
(
&
buf
->
list
,
&
instance
->
filled_buffers
);
instance
->
current_buffer
=
NULL
;
PDEBUG
(
"queued filled buffer
\n
"
);
}
PDEBUG
(
"buffer contains %d cells, %d left
\n
"
,
UDSL_SND_BUFFER_SIZE
-
buf
->
free_cells
,
buf
->
free_cells
);
if
(
!
UDSL_SKB
(
skb
)
->
num_cells
)
{
struct
atm_vcc
*
vcc
=
UDSL_SKB
(
skb
)
->
atm_data
.
vcc
;
PDEBUG
(
"discarding empty skb
\n
"
);
if
(
vcc
->
pop
)
vcc
->
pop
(
vcc
,
skb
);
else
kfree_skb
(
skb
);
instance
->
current_skb
=
NULL
;
if
(
vcc
->
stats
)
atomic_inc
(
&
vcc
->
stats
->
tx
);
}
goto
made_progress
;
}
static
void
udsl_cancel_send
(
struct
udsl_instance_data
*
instance
,
struct
atm_vcc
*
vcc
)
{
unsigned
long
flags
;
struct
sk_buff
*
skb
,
*
n
;
PDEBUG
(
"udsl_cancel_send entered
\n
"
);
spin_lock_irqsave
(
&
instance
->
sndqueue
.
lock
,
flags
);
for
(
skb
=
instance
->
sndqueue
.
next
,
n
=
skb
->
next
;
skb
!=
(
struct
sk_buff
*
)
&
instance
->
sndqueue
;
skb
=
n
,
n
=
skb
->
next
)
if
(
UDSL_SKB
(
skb
)
->
atm_data
.
vcc
==
vcc
)
{
PDEBUG
(
"popping skb 0x%p
\n
"
,
skb
);
__skb_unlink
(
skb
,
&
instance
->
sndqueue
);
if
(
vcc
->
pop
)
vcc
->
pop
(
vcc
,
skb
);
else
kfree_skb
(
skb
);
}
spin_unlock_irqrestore
(
&
instance
->
sndqueue
.
lock
,
flags
);
tasklet_disable
(
&
instance
->
send_tasklet
);
if
((
skb
=
instance
->
current_skb
)
&&
(
UDSL_SKB
(
skb
)
->
atm_data
.
vcc
==
vcc
))
{
PDEBUG
(
"popping current skb (0x%p)
\n
"
,
skb
);
instance
->
current_skb
=
NULL
;
if
(
vcc
->
pop
)
vcc
->
pop
(
vcc
,
skb
);
else
kfree_skb
(
skb
);
}
tasklet_enable
(
&
instance
->
send_tasklet
);
PDEBUG
(
"udsl_cancel_send done
\n
"
);
}
static
int
udsl_atm_send
(
struct
atm_vcc
*
vcc
,
struct
sk_buff
*
skb
)
{
struct
udsl_instance_data
*
instance
=
vcc
->
dev
->
dev_data
;
PDEBUG
(
"udsl_atm_send called (skb 0x%p, len %u)
\n
"
,
skb
,
skb
->
len
);
if
(
!
instance
)
{
PDEBUG
(
"NULL instance!
\n
"
);
return
-
EINVAL
;
}
if
(
!
instance
->
firmware_loaded
)
return
-
EAGAIN
;
if
(
vcc
->
qos
.
aal
!=
ATM_AAL5
)
{
PDEBUG
(
"unsupported ATM type %d!
\n
"
,
vcc
->
qos
.
aal
);
return
-
EINVAL
;
}
if
(
skb
->
len
>
ATM_MAX_AAL5_PDU
)
{
PDEBUG
(
"packet too long (%d vs %d)!
\n
"
,
skb
->
len
,
ATM_MAX_AAL5_PDU
);
return
-
EINVAL
;
}
PACKETDEBUG
(
skb
->
data
,
skb
->
len
);
udsl_groom_skb
(
vcc
,
skb
);
skb_queue_tail
(
&
instance
->
sndqueue
,
skb
);
tasklet_schedule
(
&
instance
->
send_tasklet
);
return
0
;
}
/************
** ATM **
************/
...
...
@@ -384,24 +690,21 @@ static void udsl_fire_receivers (struct udsl_instance_data *instance)
*
****************************************************************************/
static
void
udsl_atm_
stopdevice
(
struct
udsl_instance_data
*
instance
)
static
void
udsl_atm_
dev_close
(
struct
atm_dev
*
dev
)
{
struct
atm_vcc
*
walk
;
struct
atm_dev
*
atm_dev
;
struct
udsl_instance_data
*
instance
=
dev
->
dev_data
;
if
(
!
instance
->
atm_dev
)
if
(
!
instance
)
{
PDEBUG
(
"udsl_atm_dev_close: NULL instance!
\n
"
);
return
;
}
atm_dev
=
instance
->
atm_dev
;
atm_dev
->
signal
=
ATM_PHY_SIG_LOST
;
walk
=
atm_dev
->
vccs
;
shutdown_atm_dev
(
atm_dev
);
for
(;
walk
;
walk
=
walk
->
next
)
wake_up
(
&
walk
->
sleep
);
PDEBUG
(
"udsl_atm_dev_close: queue has %u elements
\n
"
,
instance
->
sndqueue
.
qlen
);
instance
->
atm_dev
=
NULL
;
PDEBUG
(
"udsl_atm_dev_close: killing tasklet
\n
"
);
tasklet_kill
(
&
instance
->
send_tasklet
);
PDEBUG
(
"udsl_atm_dev_close: freeing instance
\n
"
);
kfree
(
instance
);
}
...
...
@@ -410,17 +713,6 @@ static void udsl_atm_stopdevice (struct udsl_instance_data *instance)
* ATM helper functions
*
****************************************************************************/
static
struct
sk_buff
*
udsl_atm_alloc_tx
(
struct
atm_vcc
*
vcc
,
unsigned
int
size
)
{
struct
atmsar_vcc_data
*
atmsar_vcc
=
((
struct
udsl_atm_dev_data
*
)
vcc
->
dev_data
)
->
atmsar_vcc
;
if
(
atmsar_vcc
)
return
atmsar_alloc_tx
(
atmsar_vcc
,
size
);
printk
(
KERN_INFO
"SpeedTouch USB: udsl_atm_alloc_tx could not find correct alloc_tx function !
\n
"
);
return
NULL
;
}
static
int
udsl_atm_proc_read
(
struct
atm_dev
*
atm_dev
,
loff_t
*
pos
,
char
*
page
)
{
...
...
@@ -438,14 +730,6 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page)
atm_dev
->
esi
[
0
],
atm_dev
->
esi
[
1
],
atm_dev
->
esi
[
2
],
atm_dev
->
esi
[
3
],
atm_dev
->
esi
[
4
],
atm_dev
->
esi
[
5
]);
if
(
!
left
--
)
return
sprintf
(
page
,
"AAL0: tx %d ( %d err ), rx %d ( %d err, %d drop )
\n
"
,
atomic_read
(
&
atm_dev
->
stats
.
aal0
.
tx
),
atomic_read
(
&
atm_dev
->
stats
.
aal0
.
tx_err
),
atomic_read
(
&
atm_dev
->
stats
.
aal0
.
rx
),
atomic_read
(
&
atm_dev
->
stats
.
aal0
.
rx_err
),
atomic_read
(
&
atm_dev
->
stats
.
aal0
.
rx_drop
));
if
(
!
left
--
)
return
sprintf
(
page
,
"AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )
\n
"
,
atomic_read
(
&
atm_dev
->
stats
.
aal5
.
tx
),
...
...
@@ -458,60 +742,6 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page)
}
/***************************************************************************
*
* ATM DATA functions
*
****************************************************************************/
static
int
udsl_atm_send
(
struct
atm_vcc
*
vcc
,
struct
sk_buff
*
skb
)
{
struct
udsl_atm_dev_data
*
dev_data
=
vcc
->
dev_data
;
struct
udsl_instance_data
*
instance
=
vcc
->
dev
->
dev_data
;
struct
sk_buff
*
new
=
NULL
;
int
err
;
PDEBUG
(
"udsl_atm_send called
\n
"
);
if
(
!
dev_data
||
!
instance
)
{
PDEBUG
(
"NULL data!
\n
"
);
return
-
EINVAL
;
}
if
(
!
instance
->
firmware_loaded
)
return
-
EAGAIN
;
switch
(
vcc
->
qos
.
aal
)
{
case
ATM_AAL5
:
new
=
atmsar_encode_aal5
(
dev_data
->
atmsar_vcc
,
skb
);
if
(
!
new
)
goto
nomem
;
if
(
new
!=
skb
)
{
vcc
->
pop
(
vcc
,
skb
);
skb
=
new
;
}
new
=
atmsar_encode_rawcell
(
dev_data
->
atmsar_vcc
,
skb
);
if
(
!
new
)
goto
nomem
;
if
(
new
!=
skb
)
{
vcc
->
pop
(
vcc
,
skb
);
skb
=
new
;
}
err
=
udsl_usb_send_data
(
instance
,
vcc
,
skb
);
PDEBUG
(
"udsl_atm_send successfull (%d)
\n
"
,
err
);
return
err
;
break
;
default:
return
-
EINVAL
;
}
PDEBUG
(
"udsl_atm_send unsuccessfull
\n
"
);
return
0
;
nomem:
vcc
->
pop
(
vcc
,
skb
);
return
-
ENOMEM
;
}
/***************************************************************************
*
* SAR driver entries
...
...
@@ -520,7 +750,6 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb)
static
int
udsl_atm_open
(
struct
atm_vcc
*
vcc
,
short
vpi
,
int
vci
)
{
struct
udsl_atm_dev_data
*
dev_data
;
struct
udsl_instance_data
*
instance
=
vcc
->
dev
->
dev_data
;
PDEBUG
(
"udsl_atm_open called
\n
"
);
...
...
@@ -535,15 +764,12 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
return
-
EINVAL
;
MOD_INC_USE_COUNT
;
dev_data
=
kmalloc
(
sizeof
(
struct
udsl_atm_dev_data
),
GFP_KERNEL
);
if
(
!
dev_data
)
return
-
ENOMEM
;
dev_data
->
atmsar_vcc
=
vcc
->
dev_data
=
atmsar_open
(
&
(
instance
->
atmsar_vcc_list
),
vcc
,
ATMSAR_TYPE_AAL5
,
vpi
,
vci
,
0
,
0
,
ATMSAR_USE_53BYTE_CELL
|
ATMSAR_SET_PTI
);
if
(
!
dev_data
->
atmsar_vcc
)
{
kfree
(
dev_data
)
;
if
(
!
vcc
->
dev_data
)
{
MOD_DEC_USE_COUNT
;
return
-
ENOMEM
;
/* this is the only reason atmsar_open can fail... */
}
...
...
@@ -552,10 +778,8 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
set_bit
(
ATM_VF_ADDR
,
&
vcc
->
flags
);
set_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
);
set_bit
(
ATM_VF_READY
,
&
vcc
->
flags
);
vcc
->
dev_data
=
dev_data
;
vcc
->
alloc_tx
=
udsl_atm_alloc_tx
;
dev_data
->
atmsar_vcc
->
mtu
=
UDSL_MAX_AAL5_MRU
;
((
struct
atmsar_vcc_data
*
)
vcc
->
dev_data
)
->
mtu
=
UDSL_MAX_AAL5_MRU
;
if
(
instance
->
firmware_loaded
)
udsl_fire_receivers
(
instance
);
...
...
@@ -566,22 +790,20 @@ static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci)
static
void
udsl_atm_close
(
struct
atm_vcc
*
vcc
)
{
struct
udsl_atm_dev_data
*
dev_data
=
vcc
->
dev_data
;
struct
udsl_instance_data
*
instance
=
vcc
->
dev
->
dev_data
;
PDEBUG
(
"udsl_atm_close called
\n
"
);
if
(
!
dev_data
||
!
instance
)
{
PDEBUG
(
"NULL
data
!
\n
"
);
if
(
!
instance
)
{
PDEBUG
(
"NULL
instance
!
\n
"
);
return
;
}
/* freeing resources */
/* cancel all sends on this vcc */
udsl_
usb_cancelsends
(
instance
,
vcc
);
udsl_
cancel_send
(
instance
,
vcc
);
atmsar_close
(
&
(
instance
->
atmsar_vcc_list
),
dev_data
->
atmsar_vcc
);
kfree
(
dev_data
);
atmsar_close
(
&
(
instance
->
atmsar_vcc_list
),
vcc
->
dev_data
);
vcc
->
dev_data
=
NULL
;
clear_bit
(
ATM_VF_PARTIAL
,
&
vcc
->
flags
);
...
...
@@ -611,131 +833,6 @@ static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg)
** USB **
************/
/***************************************************************************
*
* usb data functions
*
****************************************************************************/
struct
udsl_cb
{
struct
atm_vcc
*
vcc
;
};
static
void
udsl_usb_send_data_complete
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
struct
udsl_usb_send_data_context
*
ctx
=
urb
->
context
;
struct
udsl_instance_data
*
instance
=
ctx
->
instance
;
int
err
;
PDEBUG
(
"udsl_usb_send_data_completion (vcc = %p, skb = %p, status %d)
\n
"
,
ctx
->
vcc
,
ctx
->
skb
,
urb
->
status
);
ctx
->
vcc
->
pop
(
ctx
->
vcc
,
ctx
->
skb
);
if
(
!
(
ctx
->
skb
=
skb_dequeue
(
&
(
instance
->
sndqueue
))))
return
;
/* submit next skb */
ctx
->
vcc
=
((
struct
udsl_cb
*
)
(
ctx
->
skb
->
cb
))
->
vcc
;
usb_fill_bulk_urb
(
urb
,
instance
->
usb_dev
,
usb_sndbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_OUT
),
(
unsigned
char
*
)
ctx
->
skb
->
data
,
ctx
->
skb
->
len
,
udsl_usb_send_data_complete
,
ctx
);
err
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
PDEBUG
(
"udsl_usb_send_data_completion (send packet %p with length %d), retval = %d
\n
"
,
ctx
->
skb
,
ctx
->
skb
->
len
,
err
);
}
static
int
udsl_usb_cancelsends
(
struct
udsl_instance_data
*
instance
,
struct
atm_vcc
*
vcc
)
{
int
i
;
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
{
if
(
!
instance
->
send_ctx
[
i
].
skb
)
continue
;
if
(
instance
->
send_ctx
[
i
].
vcc
==
vcc
)
{
usb_unlink_urb
(
instance
->
send_ctx
[
i
].
urb
);
usb_free_urb
(
instance
->
send_ctx
[
i
].
urb
);
instance
->
send_ctx
[
i
].
vcc
->
pop
(
instance
->
send_ctx
[
i
].
vcc
,
instance
->
send_ctx
[
i
].
skb
);
instance
->
send_ctx
[
i
].
skb
=
NULL
;
}
}
return
0
;
}
/**** send ******/
static
int
udsl_usb_send_data
(
struct
udsl_instance_data
*
instance
,
struct
atm_vcc
*
vcc
,
struct
sk_buff
*
skb
)
{
int
err
,
i
;
struct
urb
*
urb
;
unsigned
long
flags
;
PDEBUG
(
"udsl_usb_send_data entered, sending packet %p with length %d
\n
"
,
skb
,
skb
->
len
);
PACKETDEBUG
(
skb
->
data
,
skb
->
len
);
spin_lock_irqsave
(
&
instance
->
sndqueue
.
lock
,
flags
);
((
struct
udsl_cb
*
)
skb
->
cb
)
->
vcc
=
vcc
;
/* we are already queueing */
if
(
!
skb_queue_empty
(
&
instance
->
sndqueue
))
{
__skb_queue_tail
(
&
instance
->
sndqueue
,
skb
);
spin_unlock_irqrestore
(
&
instance
->
sndqueue
.
lock
,
flags
);
PDEBUG
(
"udsl_usb_send_data: already queing, skb (0x%p) queued
\n
"
,
skb
);
return
0
;
}
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
if
(
instance
->
send_ctx
[
i
].
skb
==
NULL
)
break
;
/* we must start queueing */
if
(
i
==
UDSL_NUMBER_SND_URBS
)
{
__skb_queue_tail
(
&
instance
->
sndqueue
,
skb
);
spin_unlock_irqrestore
(
&
instance
->
sndqueue
.
lock
,
flags
);
PDEBUG
(
"udsl_usb_send_data: skb (0x%p) queued
\n
"
,
skb
);
return
0
;
}
/* init context */
urb
=
instance
->
send_ctx
[
i
].
urb
;
instance
->
send_ctx
[
i
].
skb
=
skb
;
instance
->
send_ctx
[
i
].
vcc
=
vcc
;
instance
->
send_ctx
[
i
].
instance
=
instance
;
spin_unlock_irqrestore
(
&
instance
->
sndqueue
.
lock
,
flags
);
/* submit packet */
usb_fill_bulk_urb
(
urb
,
instance
->
usb_dev
,
usb_sndbulkpipe
(
instance
->
usb_dev
,
UDSL_ENDPOINT_DATA_OUT
),
(
unsigned
char
*
)
skb
->
data
,
skb
->
len
,
udsl_usb_send_data_complete
,
&
(
instance
->
send_ctx
[
i
])
);
err
=
usb_submit_urb
(
urb
,
GFP_KERNEL
);
if
(
err
!=
0
)
skb_unlink
(
skb
);
PDEBUG
(
"udsl_usb_send_data done (retval = %d)
\n
"
,
err
);
return
err
;
}
/***************************************************************************
*
* usb driver entries
*
****************************************************************************/
static
int
udsl_usb_ioctl
(
struct
usb_interface
*
intf
,
unsigned
int
code
,
void
*
user_data
)
{
struct
udsl_instance_data
*
instance
=
usb_get_intfdata
(
intf
);
...
...
@@ -752,7 +849,7 @@ static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *
instance
->
atm_dev
->
signal
=
ATM_PHY_SIG_FOUND
;
down
(
&
instance
->
serialize
);
/* vs self */
if
(
!
instance
->
firmware_loaded
)
{
usb_set_interface
(
instance
->
usb_dev
,
1
,
2
);
usb_set_interface
(
instance
->
usb_dev
,
1
,
1
);
instance
->
firmware_loaded
=
1
;
}
up
(
&
instance
->
serialize
);
...
...
@@ -773,7 +870,7 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
struct
udsl_instance_data
*
instance
;
unsigned
char
mac_str
[
13
];
unsigned
char
mac
[
6
];
int
i
,
err
;
int
i
;
PDEBUG
(
"Trying device with Vendor=0x%x, Product=0x%x, ifnum %d
\n
"
,
dev
->
descriptor
.
idVendor
,
dev
->
descriptor
.
idProduct
,
ifnum
);
...
...
@@ -788,8 +885,7 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
/* instance init */
if
(
!
(
instance
=
kmalloc
(
sizeof
(
struct
udsl_instance_data
),
GFP_KERNEL
)))
{
PDEBUG
(
"No memory for Instance data!
\n
"
);
err
=
-
ENOMEM
;
goto
fail_instance
;
return
-
ENOMEM
;
}
memset
(
instance
,
0
,
sizeof
(
struct
udsl_instance_data
));
...
...
@@ -808,46 +904,63 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
skb_queue_head_init
(
&
instance
->
sndqueue
);
/* receive urb init */
spin_lock_init
(
&
instance
->
send_lock
);
INIT_LIST_HEAD
(
&
instance
->
spare_senders
);
INIT_LIST_HEAD
(
&
instance
->
spare_buffers
);
tasklet_init
(
&
instance
->
send_tasklet
,
udsl_process_send
,
(
unsigned
long
)
instance
);
INIT_LIST_HEAD
(
&
instance
->
filled_buffers
);
/* receive init */
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
{
struct
udsl_receiver
*
rcv
=
&
(
instance
->
all_receivers
[
i
]);
if
(
!
(
rcv
->
skb
=
dev_alloc_skb
(
UDSL_R
ECEIVE_BUFFER
_SIZE
)))
{
if
(
!
(
rcv
->
skb
=
dev_alloc_skb
(
UDSL_R
CV_BUFFER_SIZE
*
ATM_CELL
_SIZE
)))
{
PDEBUG
(
"No memory for skb %d!
\n
"
,
i
);
err
=
-
ENOMEM
;
goto
fail_urbs
;
goto
fail
;
}
if
(
!
(
rcv
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
{
PDEBUG
(
"No memory for receive urb %d!
\n
"
,
i
);
err
=
-
ENOMEM
;
goto
fail_urbs
;
goto
fail
;
}
rcv
->
instance
=
instance
;
list_add
(
&
rcv
->
list
,
&
instance
->
spare_receivers
);
PDEBUG
(
"skb->truesize = %d (asked for %d)
\n
"
,
rcv
->
skb
->
truesize
,
UDSL_R
ECEIVE_BUFFER
_SIZE
);
PDEBUG
(
"skb->truesize = %d (asked for %d)
\n
"
,
rcv
->
skb
->
truesize
,
UDSL_R
CV_BUFFER_SIZE
*
ATM_CELL
_SIZE
);
}
/* send init */
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
{
struct
udsl_
usb_send_data_context
*
snd
=
&
(
instance
->
send_ctx
[
i
]);
struct
udsl_
sender
*
snd
=
&
(
instance
->
all_senders
[
i
]);
if
(
!
(
snd
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
)))
{
PDEBUG
(
"No memory for send urb %d!
\n
"
,
i
);
err
=
-
ENOMEM
;
goto
fail_urbs
;
goto
fail
;
}
snd
->
instance
=
instance
;
list_add
(
&
snd
->
list
,
&
instance
->
spare_senders
);
}
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_BUFS
;
i
++
)
{
struct
udsl_send_buffer
*
buf
=
&
(
instance
->
all_buffers
[
i
]);
if
(
!
(
buf
->
base
=
kmalloc
(
UDSL_SND_BUFFER_SIZE
*
ATM_CELL_SIZE
,
GFP_KERNEL
)))
{
PDEBUG
(
"No memory for send buffer %d!
\n
"
,
i
);
goto
fail
;
}
list_add
(
&
buf
->
list
,
&
instance
->
spare_buffers
);
}
/* atm init */
if
(
!
(
instance
->
atm_dev
=
atm_dev_register
(
udsl_driver_name
,
&
udsl_atm_devops
,
-
1
,
0
)))
{
PDEBUG
(
"failed to register ATM device!
\n
"
);
err
=
-
ENOMEM
;
goto
fail_atm
;
goto
fail
;
}
instance
->
atm_dev
->
ci_range
.
vpi_bits
=
ATM_CI_MAX
;
...
...
@@ -874,27 +987,25 @@ static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_i
return
0
;
fail_atm:
fail_urbs:
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
{
struct
udsl_usb_send_data_context
*
snd
=
&
(
instance
->
send_ctx
[
i
]);
fail:
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_BUFS
;
i
++
)
kfree
(
instance
->
all_buffers
[
i
].
base
);
if
(
snd
->
urb
)
usb_free_urb
(
snd
->
urb
);
}
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
usb_free_urb
(
instance
->
all_senders
[
i
].
urb
);
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
{
struct
udsl_receiver
*
rcv
=
&
(
instance
->
all_receivers
[
i
]);
usb_free_urb
(
rcv
->
urb
);
if
(
rcv
->
skb
)
kfree_skb
(
rcv
->
skb
);
if
(
rcv
->
urb
)
usb_free_urb
(
rcv
->
urb
);
}
kfree
(
instance
);
fail_instance:
return
err
;
return
-
ENOMEM
;
}
static
void
udsl_usb_disconnect
(
struct
usb_interface
*
intf
)
...
...
@@ -903,7 +1014,7 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
struct
list_head
*
pos
;
unsigned
long
flags
;
unsigned
int
count
=
0
;
int
i
;
int
result
,
i
;
PDEBUG
(
"disconnecting
\n
"
);
...
...
@@ -916,8 +1027,9 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
tasklet_disable
(
&
instance
->
receive_tasklet
);
/* receive finalize */
down
(
&
instance
->
serialize
);
/* vs udsl_fire_receivers */
/* no need to take the spinlock
- receive_tasklet is not running
*/
/* no need to take the spinlock */
list_for_each
(
pos
,
&
instance
->
spare_receivers
)
if
(
++
count
>
UDSL_NUMBER_RCV_URBS
)
panic
(
__FILE__
": memory corruption detected at line %d!
\n
"
,
__LINE__
);
...
...
@@ -929,7 +1041,8 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
count
=
UDSL_NUMBER_RCV_URBS
-
count
;
for
(
i
=
0
;
i
<
UDSL_NUMBER_RCV_URBS
;
i
++
)
usb_unlink_urb
(
instance
->
all_receivers
[
i
].
urb
);
if
((
result
=
usb_unlink_urb
(
instance
->
all_receivers
[
i
].
urb
))
<
0
)
PDEBUG
(
"udsl_usb_disconnect: usb_unlink_urb on receive urb %d returned %d
\n
"
,
i
,
result
);
/* wait for completion handlers to finish */
do
{
...
...
@@ -946,12 +1059,11 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
if
(
completed
==
count
)
break
;
/* not all urbs completed */
yield
();
}
while
(
1
);
PDEBUG
(
"udsl_usb_disconnect: flushing
%u completed receivers
\n
"
,
count
);
/* no need to take the spinlock
- no completion handlers running
*/
PDEBUG
(
"udsl_usb_disconnect: flushing
\n
"
);
/* no need to take the spinlock */
INIT_LIST_HEAD
(
&
instance
->
completed_receivers
);
tasklet_enable
(
&
instance
->
receive_tasklet
);
...
...
@@ -965,25 +1077,48 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
kfree_skb
(
rcv
->
skb
);
}
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
{
struct
udsl_usb_send_data_context
*
ctx
=
&
(
instance
->
send_ctx
[
i
]
);
/* send finalize */
tasklet_disable
(
&
instance
->
send_tasklet
);
usb_unlink_urb
(
ctx
->
urb
);
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
if
((
result
=
usb_unlink_urb
(
instance
->
all_senders
[
i
].
urb
))
<
0
)
PDEBUG
(
"udsl_usb_disconnect: usb_unlink_urb on send urb %d returned %d
\n
"
,
i
,
result
);
if
(
ctx
->
skb
)
ctx
->
vcc
->
pop
(
ctx
->
vcc
,
ctx
->
skb
);
ctx
->
skb
=
NULL
;
/* wait for completion handlers to finish */
do
{
count
=
0
;
spin_lock_irqsave
(
&
instance
->
send_lock
,
flags
);
list_for_each
(
pos
,
&
instance
->
spare_senders
)
if
(
++
count
>
UDSL_NUMBER_SND_URBS
)
panic
(
__FILE__
": memory corruption detected at line %d!
\n
"
,
__LINE__
);
spin_unlock_irqrestore
(
&
instance
->
send_lock
,
flags
);
usb_free_urb
(
ctx
->
urb
);
PDEBUG
(
"udsl_usb_disconnect: found %u spare senders
\n
"
,
count
);
}
if
(
count
==
UDSL_NUMBER_SND_URBS
)
break
;
yield
();
}
while
(
1
);
/* removing atm device */
if
(
instance
->
atm_dev
)
udsl_atm_stopdevice
(
instance
);
PDEBUG
(
"udsl_usb_disconnect: flushing
\n
"
);
/* no need to take the spinlock */
INIT_LIST_HEAD
(
&
instance
->
spare_senders
);
INIT_LIST_HEAD
(
&
instance
->
spare_buffers
);
instance
->
current_buffer
=
NULL
;
kfree
(
instance
);
tasklet_enable
(
&
instance
->
send_tasklet
);
PDEBUG
(
"udsl_usb_disconnect: freeing senders
\n
"
);
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_URBS
;
i
++
)
usb_free_urb
(
instance
->
all_senders
[
i
].
urb
);
PDEBUG
(
"udsl_usb_disconnect: freeing buffers
\n
"
);
for
(
i
=
0
;
i
<
UDSL_NUMBER_SND_BUFS
;
i
++
)
kfree
(
instance
->
all_buffers
[
i
].
base
);
/* atm finalize */
shutdown_atm_dev
(
instance
->
atm_dev
);
}
...
...
@@ -995,8 +1130,15 @@ static void udsl_usb_disconnect (struct usb_interface *intf)
static
int
__init
udsl_usb_init
(
void
)
{
struct
sk_buff
*
skb
;
/* dummy for sizeof */
PDEBUG
(
"udsl_usb_init: driver version "
DRIVER_VERSION
"
\n
"
);
if
(
sizeof
(
struct
udsl_control
)
>
sizeof
(
skb
->
cb
))
{
printk
(
KERN_ERR
__FILE__
": unusable with this kernel!
\n
"
);
return
-
EIO
;
}
return
usb_register
(
&
udsl_usb_driver
);
}
...
...
drivers/usb/net/kaweth.c
View file @
6aa909be
...
...
@@ -130,6 +130,7 @@ static struct usb_device_id usb_klsi_table[] = {
{
USB_DEVICE
(
0x03e8
,
0x0008
)
},
/* AOX Endpoints USB Ethernet */
{
USB_DEVICE
(
0x04bb
,
0x0901
)
},
/* I-O DATA USB-ET/T */
{
USB_DEVICE
(
0x0506
,
0x03e8
)
},
/* 3Com 3C19250 */
{
USB_DEVICE
(
0x0506
,
0x11f8
)
},
/* 3Com 3C460 */
{
USB_DEVICE
(
0x0557
,
0x2002
)
},
/* ATEN USB Ethernet */
{
USB_DEVICE
(
0x0557
,
0x4000
)
},
/* D-Link DSB-650C */
{
USB_DEVICE
(
0x0565
,
0x0002
)
},
/* Peracom Enet */
...
...
@@ -712,7 +713,7 @@ static void kaweth_usb_transmit_complete(struct urb *urb, struct pt_regs *regs)
static
int
kaweth_start_xmit
(
struct
sk_buff
*
skb
,
struct
net_device
*
net
)
{
struct
kaweth_device
*
kaweth
=
net
->
priv
;
char
*
private_header
;
u16
*
private_header
;
int
res
;
...
...
@@ -744,7 +745,7 @@ static int kaweth_start_xmit(struct sk_buff *skb, struct net_device *net)
}
private_header
=
__skb_push
(
skb
,
2
);
*
private_header
=
cpu_to_le16
(
skb
->
len
);
*
private_header
=
cpu_to_le16
(
skb
->
len
-
2
);
kaweth
->
tx_skb
=
skb
;
usb_fill_bulk_urb
(
kaweth
->
tx_urb
,
...
...
drivers/usb/net/pegasus.h
View file @
6aa909be
...
...
@@ -133,6 +133,7 @@ struct usb_eth_dev {
#define VENDOR_LANEED 0x056e
#define VENDOR_LINKSYS 0x066b
#define VENDOR_MELCO 0x0411
#define VENDOR_MOBILITY 0x1342
#define VENDOR_NETGEAR 0x0846
#define VENDOR_SMARTBRIDGES 0x08d1
#define VENDOR_SMC 0x0707
...
...
@@ -167,7 +168,7 @@ PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x200c,
PEGASUS_DEV
(
"Accton USB 10/100 Ethernet Adapter"
,
VENDOR_ACCTON
,
0x1046
,
DEFAULT_GPIO_RESET
)
PEGASUS_DEV
(
"SpeedStream USB 10/100 Ethernet"
,
VENDOR_ACCTON
,
0x5046
,
DEFAULT_GPIO_RESET
)
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
PEGASUS_DEV
(
"ADMtek ADM8511
\"
Pegasus II
\"
USB Ethernet"
,
VENDOR_ADMTEK
,
0x8511
,
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
...
...
@@ -215,6 +216,8 @@ PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK, 0xabc1,
DEFAULT_GPIO_RESET
)
PEGASUS_DEV
(
"GOLDPFEIL USB Adapter"
,
VENDOR_ELCON
,
0x0002
,
DEFAULT_GPIO_RESET
|
PEGASUS_II
|
HAS_HOME_PNA
)
PEGASUS_DEV
(
"EasiDock Ethernet"
,
VENDOR_MOBILITY
,
0x0304
,
DEFAULT_GPIO_RESET
)
PEGASUS_DEV
(
"Elsa Micolink USB2Ethernet"
,
VENDOR_ELSA
,
0x3000
,
DEFAULT_GPIO_RESET
)
PEGASUS_DEV
(
"Hawking UF100 10/100 Ethernet"
,
VENDOR_HAWKING
,
0x400c
,
...
...
drivers/usb/serial/Kconfig
View file @
6aa909be
...
...
@@ -297,10 +297,14 @@ config USB_SERIAL_KEYSPAN_USA19W
config USB_SERIAL_KEYSPAN_USA19QW
bool "USB Keyspan USA-19QW Firmware"
depends on USB_SERIAL_KEYSPAN
help
Say Y here to include firmware for the USA-19QW converter.
config USB_SERIAL_KEYSPAN_USA19QI
bool "USB Keyspan USA-19QI Firmware"
depends on USB_SERIAL_KEYSPAN
help
Say Y here to include firmware for the USA-19QI converter.
config USB_SERIAL_KEYSPAN_USA49W
bool "USB Keyspan USA-49W Firmware"
...
...
drivers/usb/serial/console.c
View file @
6aa909be
...
...
@@ -141,7 +141,6 @@ static int __init usb_console_setup(struct console *co, char *options)
}
port
=
&
serial
->
port
[
0
];
down
(
&
port
->
sem
);
port
->
tty
=
NULL
;
info
->
port
=
port
;
...
...
@@ -158,8 +157,6 @@ static int __init usb_console_setup(struct console *co, char *options)
port
->
open_count
=
0
;
}
up
(
&
port
->
sem
);
if
(
retval
)
{
err
(
"could not open USB console port"
);
return
retval
;
...
...
@@ -208,8 +205,6 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
if
(
count
==
0
)
return
;
down
(
&
port
->
sem
);
dbg
(
"%s - port %d, %d byte(s)"
,
__FUNCTION__
,
port
->
number
,
count
);
if
(
!
port
->
open_count
)
{
...
...
@@ -224,7 +219,6 @@ static void usb_console_write(struct console *co, const char *buf, unsigned coun
retval
=
usb_serial_generic_write
(
port
,
0
,
buf
,
count
);
exit:
up
(
&
port
->
sem
);
dbg
(
"%s - return value (if we had one): %d"
,
__FUNCTION__
,
retval
);
}
...
...
drivers/usb/serial/usb-serial.c
View file @
6aa909be
...
...
@@ -391,7 +391,11 @@ static LIST_HEAD(usb_serial_driver_list);
struct
usb_serial
*
usb_serial_get_by_minor
(
unsigned
int
minor
)
{
return
serial_table
[
minor
];
struct
usb_serial
*
serial
=
serial_table
[
minor
];
if
(
serial
)
kobject_get
(
&
serial
->
kobj
);
return
serial
;
}
static
struct
usb_serial
*
get_free_serial
(
struct
usb_serial
*
serial
,
int
num_ports
,
unsigned
int
*
minor
)
...
...
@@ -468,7 +472,6 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
port
=
&
serial
->
port
[
portNumber
];
tty
->
driver_data
=
port
;
down
(
&
port
->
sem
);
port
->
tty
=
tty
;
/* lock this module before we call it,
...
...
@@ -492,8 +495,6 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
}
}
bailout:
up
(
&
port
->
sem
);
return
retval
;
}
...
...
@@ -516,6 +517,7 @@ static void __serial_close(struct usb_serial_port *port, struct file *filp)
}
module_put
(
port
->
serial
->
type
->
owner
);
kobject_put
(
&
port
->
serial
->
kobj
);
}
static
void
serial_close
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
...
...
@@ -526,16 +528,12 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
if
(
!
serial
)
return
;
down
(
&
port
->
sem
);
dbg
(
"%s - port %d"
,
__FUNCTION__
,
port
->
number
);
/* if disconnect beat us to the punch here, there's nothing to do */
if
(
tty
->
driver_data
)
{
__serial_close
(
port
,
filp
);
}
up
(
&
port
->
sem
);
}
static
int
serial_write
(
struct
tty_struct
*
tty
,
int
from_user
,
const
unsigned
char
*
buf
,
int
count
)
...
...
@@ -547,8 +545,6 @@ static int serial_write (struct tty_struct * tty, int from_user, const unsigned
if
(
!
serial
)
return
-
ENODEV
;
down
(
&
port
->
sem
);
dbg
(
"%s - port %d, %d byte(s)"
,
__FUNCTION__
,
port
->
number
,
count
);
if
(
!
port
->
open_count
)
{
...
...
@@ -563,7 +559,6 @@ static int serial_write (struct tty_struct * tty, int from_user, const unsigned
retval
=
usb_serial_generic_write
(
port
,
from_user
,
buf
,
count
);
exit:
up
(
&
port
->
sem
);
return
retval
;
}
...
...
@@ -576,8 +571,6 @@ static int serial_write_room (struct tty_struct *tty)
if
(
!
serial
)
return
-
ENODEV
;
down
(
&
port
->
sem
);
dbg
(
"%s - port %d"
,
__FUNCTION__
,
port
->
number
);
if
(
!
port
->
open_count
)
{
...
...
@@ -592,7 +585,6 @@ static int serial_write_room (struct tty_struct *tty)
retval
=
usb_serial_generic_write_room
(
port
);
exit:
up
(
&
port
->
sem
);
return
retval
;
}
...
...
@@ -605,8 +597,6 @@ static int serial_chars_in_buffer (struct tty_struct *tty)
if
(
!
serial
)
return
-
ENODEV
;
down
(
&
port
->
sem
);
dbg
(
"%s = port %d"
,
__FUNCTION__
,
port
->
number
);
if
(
!
port
->
open_count
)
{
...
...
@@ -621,7 +611,6 @@ static int serial_chars_in_buffer (struct tty_struct *tty)
retval
=
usb_serial_generic_chars_in_buffer
(
port
);
exit:
up
(
&
port
->
sem
);
return
retval
;
}
...
...
@@ -633,8 +622,6 @@ static void serial_throttle (struct tty_struct * tty)
if
(
!
serial
)
return
;
down
(
&
port
->
sem
);
dbg
(
"%s - port %d"
,
__FUNCTION__
,
port
->
number
);
if
(
!
port
->
open_count
)
{
...
...
@@ -647,7 +634,6 @@ static void serial_throttle (struct tty_struct * tty)
serial
->
type
->
throttle
(
port
);
exit:
up
(
&
port
->
sem
);
}
static
void
serial_unthrottle
(
struct
tty_struct
*
tty
)
...
...
@@ -658,8 +644,6 @@ static void serial_unthrottle (struct tty_struct * tty)
if
(
!
serial
)
return
;
down
(
&
port
->
sem
);
dbg
(
"%s - port %d"
,
__FUNCTION__
,
port
->
number
);
if
(
!
port
->
open_count
)
{
...
...
@@ -672,7 +656,6 @@ static void serial_unthrottle (struct tty_struct * tty)
serial
->
type
->
unthrottle
(
port
);
exit:
up
(
&
port
->
sem
);
}
static
int
serial_ioctl
(
struct
tty_struct
*
tty
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
...
...
@@ -684,8 +667,6 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
if
(
!
serial
)
return
-
ENODEV
;
down
(
&
port
->
sem
);
dbg
(
"%s - port %d, cmd 0x%.4x"
,
__FUNCTION__
,
port
->
number
,
cmd
);
if
(
!
port
->
open_count
)
{
...
...
@@ -700,7 +681,6 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned in
retval
=
-
ENOIOCTLCMD
;
exit:
up
(
&
port
->
sem
);
return
retval
;
}
...
...
@@ -712,8 +692,6 @@ static void serial_set_termios (struct tty_struct *tty, struct termios * old)
if
(
!
serial
)
return
;
down
(
&
port
->
sem
);
dbg
(
"%s - port %d"
,
__FUNCTION__
,
port
->
number
);
if
(
!
port
->
open_count
)
{
...
...
@@ -726,7 +704,6 @@ static void serial_set_termios (struct tty_struct *tty, struct termios * old)
serial
->
type
->
set_termios
(
port
,
old
);
exit:
up
(
&
port
->
sem
);
}
static
void
serial_break
(
struct
tty_struct
*
tty
,
int
break_state
)
...
...
@@ -737,8 +714,6 @@ static void serial_break (struct tty_struct *tty, int break_state)
if
(
!
serial
)
return
;
down
(
&
port
->
sem
);
dbg
(
"%s - port %d"
,
__FUNCTION__
,
port
->
number
);
if
(
!
port
->
open_count
)
{
...
...
@@ -751,7 +726,6 @@ static void serial_break (struct tty_struct *tty, int break_state)
serial
->
type
->
break_ctl
(
port
,
break_state
);
exit:
up
(
&
port
->
sem
);
}
static
void
serial_shutdown
(
struct
usb_serial
*
serial
)
...
...
@@ -797,6 +771,7 @@ static int serial_read_proc (char *page, char **start, off_t off, int count, int
begin
+=
length
;
length
=
0
;
}
kobject_put
(
&
serial
->
kobj
);
}
*
eof
=
1
;
done:
...
...
@@ -833,6 +808,75 @@ void usb_serial_port_softint(void *private)
wake_up_interruptible
(
&
tty
->
write_wait
);
}
static
void
destroy_serial
(
struct
kobject
*
kobj
)
{
struct
usb_serial
*
serial
;
struct
usb_serial_port
*
port
;
int
i
;
dbg
(
"%s"
,
__FUNCTION__
);
serial
=
to_usb_serial
(
kobj
);
/* fail all future close/read/write/ioctl/etc calls */
for
(
i
=
0
;
i
<
serial
->
num_ports
;
++
i
)
{
port
=
&
serial
->
port
[
i
];
if
(
port
->
tty
!=
NULL
)
{
port
->
tty
->
driver_data
=
NULL
;
while
(
port
->
open_count
>
0
)
{
__serial_close
(
port
,
NULL
);
}
}
}
serial_shutdown
(
serial
);
for
(
i
=
0
;
i
<
serial
->
num_ports
;
++
i
)
device_unregister
(
&
serial
->
port
[
i
].
dev
);
for
(
i
=
0
;
i
<
serial
->
num_ports
;
++
i
)
serial
->
port
[
i
].
open_count
=
0
;
for
(
i
=
0
;
i
<
serial
->
num_bulk_in
;
++
i
)
{
port
=
&
serial
->
port
[
i
];
if
(
port
->
read_urb
)
{
usb_unlink_urb
(
port
->
read_urb
);
usb_free_urb
(
port
->
read_urb
);
}
if
(
port
->
bulk_in_buffer
)
kfree
(
port
->
bulk_in_buffer
);
}
for
(
i
=
0
;
i
<
serial
->
num_bulk_out
;
++
i
)
{
port
=
&
serial
->
port
[
i
];
if
(
port
->
write_urb
)
{
usb_unlink_urb
(
port
->
write_urb
);
usb_free_urb
(
port
->
write_urb
);
}
if
(
port
->
bulk_out_buffer
)
kfree
(
port
->
bulk_out_buffer
);
}
for
(
i
=
0
;
i
<
serial
->
num_interrupt_in
;
++
i
)
{
port
=
&
serial
->
port
[
i
];
if
(
port
->
interrupt_in_urb
)
{
usb_unlink_urb
(
port
->
interrupt_in_urb
);
usb_free_urb
(
port
->
interrupt_in_urb
);
}
if
(
port
->
interrupt_in_buffer
)
kfree
(
port
->
interrupt_in_buffer
);
}
/* return the minor range that this device had */
return_serial
(
serial
);
usb_put_dev
(
serial
->
dev
);
/* free up any memory that we allocated */
kfree
(
serial
);
}
static
struct
kobj_type
usb_serial_kobj_type
=
{
.
release
=
destroy_serial
,
};
static
struct
usb_serial
*
create_serial
(
struct
usb_device
*
dev
,
struct
usb_interface
*
interface
,
struct
usb_serial_device_type
*
type
)
...
...
@@ -845,12 +889,16 @@ static struct usb_serial * create_serial (struct usb_device *dev,
return
NULL
;
}
memset
(
serial
,
0
,
sizeof
(
*
serial
));
serial
->
dev
=
dev
;
serial
->
dev
=
usb_get_dev
(
dev
)
;
serial
->
type
=
type
;
serial
->
interface
=
interface
;
serial
->
vendor
=
dev
->
descriptor
.
idVendor
;
serial
->
product
=
dev
->
descriptor
.
idProduct
;
/* initialize the kobject portion of the usb_device */
kobject_init
(
&
serial
->
kobj
);
serial
->
kobj
.
ktype
=
&
usb_serial_kobj_type
;
return
serial
;
}
...
...
@@ -1113,7 +1161,6 @@ int usb_serial_probe(struct usb_interface *interface,
port
->
serial
=
serial
;
port
->
magic
=
USB_SERIAL_PORT_MAGIC
;
INIT_WORK
(
&
port
->
work
,
usb_serial_port_softint
,
port
);
init_MUTEX
(
&
port
->
sem
);
}
/* if this device type has an attach function, call it */
...
...
@@ -1189,67 +1236,14 @@ void usb_serial_disconnect(struct usb_interface *interface)
{
struct
usb_serial
*
serial
=
usb_get_intfdata
(
interface
);
struct
device
*
dev
=
&
interface
->
dev
;
struct
usb_serial_port
*
port
;
int
i
;
dbg
(
"%s"
,
__FUNCTION__
);
usb_set_intfdata
(
interface
,
NULL
);
if
(
serial
)
{
/* fail all future close/read/write/ioctl/etc calls */
for
(
i
=
0
;
i
<
serial
->
num_ports
;
++
i
)
{
port
=
&
serial
->
port
[
i
];
down
(
&
port
->
sem
);
if
(
port
->
tty
!=
NULL
)
{
port
->
tty
->
driver_data
=
NULL
;
while
(
port
->
open_count
>
0
)
{
__serial_close
(
port
,
NULL
);
}
}
up
(
&
port
->
sem
);
}
serial
->
dev
=
NULL
;
serial_shutdown
(
serial
);
for
(
i
=
0
;
i
<
serial
->
num_ports
;
++
i
)
device_unregister
(
&
serial
->
port
[
i
].
dev
);
for
(
i
=
0
;
i
<
serial
->
num_ports
;
++
i
)
serial
->
port
[
i
].
open_count
=
0
;
for
(
i
=
0
;
i
<
serial
->
num_bulk_in
;
++
i
)
{
port
=
&
serial
->
port
[
i
];
if
(
port
->
read_urb
)
{
usb_unlink_urb
(
port
->
read_urb
);
usb_free_urb
(
port
->
read_urb
);
}
if
(
port
->
bulk_in_buffer
)
kfree
(
port
->
bulk_in_buffer
);
}
for
(
i
=
0
;
i
<
serial
->
num_bulk_out
;
++
i
)
{
port
=
&
serial
->
port
[
i
];
if
(
port
->
write_urb
)
{
usb_unlink_urb
(
port
->
write_urb
);
usb_free_urb
(
port
->
write_urb
);
}
if
(
port
->
bulk_out_buffer
)
kfree
(
port
->
bulk_out_buffer
);
}
for
(
i
=
0
;
i
<
serial
->
num_interrupt_in
;
++
i
)
{
port
=
&
serial
->
port
[
i
];
if
(
port
->
interrupt_in_urb
)
{
usb_unlink_urb
(
port
->
interrupt_in_urb
);
usb_free_urb
(
port
->
interrupt_in_urb
);
}
if
(
port
->
interrupt_in_buffer
)
kfree
(
port
->
interrupt_in_buffer
);
}
/* return the minor range that this device had */
return_serial
(
serial
);
/* free up any memory that we allocated */
kfree
(
serial
);
/* let the last holder of this object
* cause it to be cleaned up */
kobject_put
(
&
serial
->
kobj
);
}
dev_info
(
dev
,
"device disconnected
\n
"
);
}
...
...
drivers/usb/serial/usb-serial.h
View file @
6aa909be
...
...
@@ -89,7 +89,6 @@
* @write_wait: a wait_queue_head_t used by the port.
* @work: work queue entry for the line discipline waking up.
* @open_count: number of times this port has been opened.
* @sem: struct semaphore used to lock this structure.
*
* This structure is used by the usb-serial core and drivers for the specific
* ports of a device.
...
...
@@ -116,7 +115,6 @@ struct usb_serial_port {
wait_queue_head_t
write_wait
;
struct
work_struct
work
;
int
open_count
;
struct
semaphore
sem
;
struct
device
dev
;
};
#define to_usb_serial_port(d) container_of(d, struct usb_serial_port, dev)
...
...
@@ -164,8 +162,10 @@ struct usb_serial {
__u16
vendor
;
__u16
product
;
struct
usb_serial_port
port
[
MAX_NUM_PORTS
];
struct
kobject
kobj
;
void
*
private
;
};
#define to_usb_serial(d) container_of(d, struct usb_serial, kobj)
#define NUM_DONT_CARE (-1)
...
...
drivers/usb/storage/transport.c
View file @
6aa909be
...
...
@@ -314,7 +314,7 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,
return
USB_STOR_XFER_ERROR
;
/* the transfer was cancelled, presumably by an abort */
case
-
E
NODEV
:
case
-
E
CONNRESET
:
US_DEBUGP
(
"-- transfer cancelled
\n
"
);
return
USB_STOR_XFER_ERROR
;
...
...
include/linux/usb.h
View file @
6aa909be
...
...
@@ -17,6 +17,7 @@
#include <linux/device.h>
/* for struct device */
#include <linux/fs.h>
/* for struct file_operations */
#include <linux/completion.h>
/* for struct completion */
#include <linux/sched.h>
/* for current && schedule_timeout */
static
__inline__
void
wait_ms
(
unsigned
int
ms
)
...
...
@@ -239,6 +240,7 @@ struct usb_device {
int
have_langid
;
/* whether string_langid is valid yet */
int
string_langid
;
/* language ID for strings */
int
present
;
/* if device is present or not */
void
*
hcpriv
;
/* Host Controller private data */
...
...
lib/Makefile
View file @
6aa909be
...
...
@@ -25,7 +25,7 @@ obj-$(CONFIG_ZLIB_INFLATE) += zlib_inflate/
obj-$(CONFIG_ZLIB_DEFLATE)
+=
zlib_deflate/
include
$(TOPDIR)/drivers/net/Makefile.lib
include
$(TOPDIR)/drivers/usb/
class/
Makefile.lib
include
$(TOPDIR)/drivers/usb/Makefile.lib
include
$(TOPDIR)/fs/Makefile.lib
include
$(TOPDIR)/net/bluetooth/bnep/Makefile.lib
...
...
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