Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
7f6cf788
Commit
7f6cf788
authored
Feb 18, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://linuxusb.bkbits.net/linus-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
c0630ba1
7730f361
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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
/*
* 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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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 @
7f6cf788
...
...
@@ -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