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
fcc95bca
Commit
fcc95bca
authored
Jun 06, 2004
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
Merge kroah.com:/home/greg/linux/BK/bleed-2.6
into kroah.com:/home/greg/linux/BK/usb-2.6
parents
501a9693
4913d930
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
641 additions
and
548 deletions
+641
-548
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.c
+135
-188
drivers/usb/class/cdc-acm.h
drivers/usb/class/cdc-acm.h
+115
-0
drivers/usb/class/usblp.c
drivers/usb/class/usblp.c
+1
-0
drivers/usb/core/hcd.h
drivers/usb/core/hcd.h
+0
-7
drivers/usb/core/hub.c
drivers/usb/core/hub.c
+312
-77
drivers/usb/core/hub.h
drivers/usb/core/hub.h
+0
-1
drivers/usb/core/message.c
drivers/usb/core/message.c
+1
-4
drivers/usb/core/usb.c
drivers/usb/core/usb.c
+0
-229
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/dummy_hcd.c
+11
-4
drivers/usb/gadget/ether.c
drivers/usb/gadget/ether.c
+10
-11
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.c
+28
-17
drivers/usb/net/pegasus.h
drivers/usb/net/pegasus.h
+3
-0
drivers/usb/serial/bus.c
drivers/usb/serial/bus.c
+2
-2
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.c
+1
-0
drivers/usb/serial/visor.c
drivers/usb/serial/visor.c
+12
-7
drivers/usb/serial/visor.h
drivers/usb/serial/visor.h
+3
-0
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/unusual_devs.h
+7
-1
No files found.
drivers/usb/class/cdc-acm.c
View file @
fcc95bca
...
@@ -27,6 +27,7 @@
...
@@ -27,6 +27,7 @@
* v0.22 - probe only the control interface. if usbcore doesn't choose the
* v0.22 - probe only the control interface. if usbcore doesn't choose the
* config we want, sysadmin changes bConfigurationValue in sysfs.
* config we want, sysadmin changes bConfigurationValue in sysfs.
* v0.23 - use softirq for rx processing, as needed by tty layer
* v0.23 - use softirq for rx processing, as needed by tty layer
* v0.24 - change probe method to evaluate CDC union descriptor
*/
*/
/*
/*
...
@@ -60,6 +61,8 @@
...
@@ -60,6 +61,8 @@
#include <linux/usb.h>
#include <linux/usb.h>
#include <asm/byteorder.h>
#include <asm/byteorder.h>
#include "cdc-acm.h"
/*
/*
* Version Information
* Version Information
*/
*/
...
@@ -67,102 +70,12 @@
...
@@ -67,102 +70,12 @@
#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
#define DRIVER_AUTHOR "Armin Fuerst, Pavel Machek, Johannes Erdfelt, Vojtech Pavlik"
#define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
#define DRIVER_DESC "USB Abstract Control Model driver for USB modems and ISDN adapters"
/*
* CMSPAR, some architectures can't have space and mark parity.
*/
#ifndef CMSPAR
#define CMSPAR 0
#endif
/*
* Major and minor numbers.
*/
#define ACM_TTY_MAJOR 166
#define ACM_TTY_MINORS 32
/*
* Requests.
*/
#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
#define ACM_REQ_COMMAND 0x00
#define ACM_REQ_RESPONSE 0x01
#define ACM_REQ_SET_FEATURE 0x02
#define ACM_REQ_GET_FEATURE 0x03
#define ACM_REQ_CLEAR_FEATURE 0x04
#define ACM_REQ_SET_LINE 0x20
#define ACM_REQ_GET_LINE 0x21
#define ACM_REQ_SET_CONTROL 0x22
#define ACM_REQ_SEND_BREAK 0x23
/*
* IRQs.
*/
#define ACM_IRQ_NETWORK 0x00
#define ACM_IRQ_LINE_STATE 0x20
/*
* Output control lines.
*/
#define ACM_CTRL_DTR 0x01
#define ACM_CTRL_RTS 0x02
/*
* Input control lines and line errors.
*/
#define ACM_CTRL_DCD 0x01
#define ACM_CTRL_DSR 0x02
#define ACM_CTRL_BRK 0x04
#define ACM_CTRL_RI 0x08
#define ACM_CTRL_FRAMING 0x10
#define ACM_CTRL_PARITY 0x20
#define ACM_CTRL_OVERRUN 0x40
/*
* Line speed and caracter encoding.
*/
struct
acm_line
{
__u32
speed
;
__u8
stopbits
;
__u8
parity
;
__u8
databits
;
}
__attribute__
((
packed
));
/*
* Internal driver structures.
*/
struct
acm
{
struct
usb_device
*
dev
;
/* the corresponding usb device */
struct
usb_interface
*
control
;
/* control interface */
struct
usb_interface
*
data
;
/* data interface */
struct
tty_struct
*
tty
;
/* the corresponding tty */
struct
urb
*
ctrlurb
,
*
readurb
,
*
writeurb
;
/* urbs */
struct
acm_line
line
;
/* line coding (bits, stop, parity) */
struct
work_struct
work
;
/* work queue entry for line discipline waking up */
struct
tasklet_struct
bh
;
/* rx processing */
unsigned
int
ctrlin
;
/* input control lines (DCD, DSR, RI, break, overruns) */
unsigned
int
ctrlout
;
/* output control lines (DTR, RTS) */
unsigned
int
writesize
;
/* max packet size for the output bulk endpoint */
unsigned
int
used
;
/* someone has this acm's device open */
unsigned
int
minor
;
/* acm minor number */
unsigned
char
throttle
;
/* throttled by tty layer */
unsigned
char
clocal
;
/* termios CLOCAL */
};
static
struct
usb_driver
acm_driver
;
static
struct
usb_driver
acm_driver
;
static
struct
tty_driver
*
acm_tty_driver
;
static
struct
tty_driver
*
acm_tty_driver
;
static
struct
acm
*
acm_table
[
ACM_TTY_MINORS
];
static
struct
acm
*
acm_table
[
ACM_TTY_MINORS
];
static
DECLARE_MUTEX
(
open_sem
);
#define ACM_READY(acm) (acm && acm->dev && acm->used)
#define ACM_READY(acm) (acm && acm->dev && acm->used)
/*
/*
...
@@ -310,12 +223,14 @@ static void acm_write_bulk(struct urb *urb, struct pt_regs *regs)
...
@@ -310,12 +223,14 @@ static void acm_write_bulk(struct urb *urb, struct pt_regs *regs)
struct
acm
*
acm
=
(
struct
acm
*
)
urb
->
context
;
struct
acm
*
acm
=
(
struct
acm
*
)
urb
->
context
;
if
(
!
ACM_READY
(
acm
))
if
(
!
ACM_READY
(
acm
))
return
;
goto
out
;
if
(
urb
->
status
)
if
(
urb
->
status
)
dbg
(
"nonzero write bulk status received: %d"
,
urb
->
status
);
dbg
(
"nonzero write bulk status received: %d"
,
urb
->
status
);
schedule_work
(
&
acm
->
work
);
schedule_work
(
&
acm
->
work
);
out:
acm
->
ready_for_write
=
1
;
}
}
static
void
acm_softint
(
void
*
private
)
static
void
acm_softint
(
void
*
private
)
...
@@ -346,22 +261,23 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
...
@@ -346,22 +261,23 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
tty
->
driver_data
=
acm
;
tty
->
driver_data
=
acm
;
acm
->
tty
=
tty
;
acm
->
tty
=
tty
;
lock_kernel
(
);
down
(
&
open_sem
);
if
(
acm
->
used
++
)
{
if
(
acm
->
used
)
{
unlock_kernel
();
goto
done
;
return
0
;
}
}
unlock_kernel
();
acm
->
ctrlurb
->
dev
=
acm
->
dev
;
acm
->
ctrlurb
->
dev
=
acm
->
dev
;
if
(
usb_submit_urb
(
acm
->
ctrlurb
,
GFP_KERNEL
))
if
(
usb_submit_urb
(
acm
->
ctrlurb
,
GFP_KERNEL
))
{
dbg
(
"usb_submit_urb(ctrl irq) failed"
);
dbg
(
"usb_submit_urb(ctrl irq) failed"
);
goto
bail_out
;
}
acm
->
readurb
->
dev
=
acm
->
dev
;
acm
->
readurb
->
dev
=
acm
->
dev
;
if
(
usb_submit_urb
(
acm
->
readurb
,
GFP_KERNEL
))
if
(
usb_submit_urb
(
acm
->
readurb
,
GFP_KERNEL
))
{
dbg
(
"usb_submit_urb(read bulk) failed"
);
dbg
(
"usb_submit_urb(read bulk) failed"
);
goto
bail_out_and_unlink
;
}
acm_set_control
(
acm
,
acm
->
ctrlout
=
ACM_CTRL_DTR
|
ACM_CTRL_RTS
);
acm_set_control
(
acm
,
acm
->
ctrlout
=
ACM_CTRL_DTR
|
ACM_CTRL_RTS
);
...
@@ -369,7 +285,16 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
...
@@ -369,7 +285,16 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp)
otherwise it is scheduled, and with high data rates data can get lost. */
otherwise it is scheduled, and with high data rates data can get lost. */
tty
->
low_latency
=
1
;
tty
->
low_latency
=
1
;
done:
acm
->
used
++
;
up
(
&
open_sem
);
return
0
;
return
0
;
bail_out_and_unlink:
usb_unlink_urb
(
acm
->
ctrlurb
);
bail_out:
up
(
&
open_sem
);
return
-
EIO
;
}
}
static
void
acm_tty_close
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
static
void
acm_tty_close
(
struct
tty_struct
*
tty
,
struct
file
*
filp
)
...
@@ -379,6 +304,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
...
@@ -379,6 +304,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
if
(
!
acm
||
!
acm
->
used
)
if
(
!
acm
||
!
acm
->
used
)
return
;
return
;
down
(
&
open_sem
);
if
(
!--
acm
->
used
)
{
if
(
!--
acm
->
used
)
{
if
(
acm
->
dev
)
{
if
(
acm
->
dev
)
{
acm_set_control
(
acm
,
acm
->
ctrlout
=
0
);
acm_set_control
(
acm
,
acm
->
ctrlout
=
0
);
...
@@ -394,6 +320,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
...
@@ -394,6 +320,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
kfree
(
acm
);
kfree
(
acm
);
}
}
}
}
up
(
&
open_sem
);
}
}
static
int
acm_tty_write
(
struct
tty_struct
*
tty
,
int
from_user
,
const
unsigned
char
*
buf
,
int
count
)
static
int
acm_tty_write
(
struct
tty_struct
*
tty
,
int
from_user
,
const
unsigned
char
*
buf
,
int
count
)
...
@@ -403,7 +330,7 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c
...
@@ -403,7 +330,7 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c
if
(
!
ACM_READY
(
acm
))
if
(
!
ACM_READY
(
acm
))
return
-
EINVAL
;
return
-
EINVAL
;
if
(
acm
->
writeurb
->
status
==
-
EINPROGRESS
)
if
(
!
acm
->
ready_for_write
)
return
0
;
return
0
;
if
(
!
count
)
if
(
!
count
)
return
0
;
return
0
;
...
@@ -419,10 +346,11 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c
...
@@ -419,10 +346,11 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c
acm
->
writeurb
->
transfer_buffer_length
=
count
;
acm
->
writeurb
->
transfer_buffer_length
=
count
;
acm
->
writeurb
->
dev
=
acm
->
dev
;
acm
->
writeurb
->
dev
=
acm
->
dev
;
/* GFP_KERNEL probably works if from_user */
acm
->
ready_for_write
=
0
;
stat
=
usb_submit_urb
(
acm
->
writeurb
,
GFP_
ATOMIC
);
stat
=
usb_submit_urb
(
acm
->
writeurb
,
GFP_
NOIO
);
if
(
stat
<
0
)
{
if
(
stat
<
0
)
{
dbg
(
"usb_submit_urb(write bulk) failed"
);
dbg
(
"usb_submit_urb(write bulk) failed"
);
acm
->
ready_for_write
=
1
;
return
stat
;
return
stat
;
}
}
...
@@ -434,7 +362,7 @@ static int acm_tty_write_room(struct tty_struct *tty)
...
@@ -434,7 +362,7 @@ static int acm_tty_write_room(struct tty_struct *tty)
struct
acm
*
acm
=
tty
->
driver_data
;
struct
acm
*
acm
=
tty
->
driver_data
;
if
(
!
ACM_READY
(
acm
))
if
(
!
ACM_READY
(
acm
))
return
-
EINVAL
;
return
-
EINVAL
;
return
acm
->
writeurb
->
status
==
-
EINPROGRESS
?
0
:
acm
->
writesize
;
return
!
acm
->
ready_for_write
?
0
:
acm
->
writesize
;
}
}
static
int
acm_tty_chars_in_buffer
(
struct
tty_struct
*
tty
)
static
int
acm_tty_chars_in_buffer
(
struct
tty_struct
*
tty
)
...
@@ -442,7 +370,7 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty)
...
@@ -442,7 +370,7 @@ static int acm_tty_chars_in_buffer(struct tty_struct *tty)
struct
acm
*
acm
=
tty
->
driver_data
;
struct
acm
*
acm
=
tty
->
driver_data
;
if
(
!
ACM_READY
(
acm
))
if
(
!
ACM_READY
(
acm
))
return
-
EINVAL
;
return
-
EINVAL
;
return
acm
->
writeurb
->
status
==
-
EINPROGRESS
?
acm
->
writeurb
->
transfer_buffer_length
:
0
;
return
!
acm
->
ready_for_write
?
acm
->
writeurb
->
transfer_buffer_length
:
0
;
}
}
static
void
acm_tty_throttle
(
struct
tty_struct
*
tty
)
static
void
acm_tty_throttle
(
struct
tty_struct
*
tty
)
...
@@ -567,77 +495,102 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_
...
@@ -567,77 +495,102 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_
* USB probe and disconnect routines.
* USB probe and disconnect routines.
*/
*/
#define CHECK_XFERTYPE(descr, xfer_type) (((descr)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == xfer_type)
static
int
acm_probe
(
struct
usb_interface
*
intf
,
static
int
acm_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
const
struct
usb_device_id
*
id
)
{
{
struct
usb_device
*
dev
;
struct
union_desc
*
union_header
=
NULL
;
char
*
buffer
=
intf
->
altsetting
->
extra
;
int
buflen
=
intf
->
altsetting
->
extralen
;
struct
usb_interface
*
control_interface
;
struct
usb_interface
*
data_interface
;
struct
usb_endpoint_descriptor
*
epctrl
;
struct
usb_endpoint_descriptor
*
epread
;
struct
usb_endpoint_descriptor
*
epwrite
;
struct
usb_device
*
usb_dev
=
interface_to_usbdev
(
intf
);
struct
acm
*
acm
;
struct
acm
*
acm
;
struct
usb_host_config
*
cfacm
;
int
minor
;
struct
usb_interface
*
data
=
NULL
;
int
ctrlsize
,
readsize
;
struct
usb_host_interface
*
ifcom
,
*
ifdata
=
NULL
;
char
*
buf
;
struct
usb_endpoint_descriptor
*
epctrl
=
NULL
;
struct
usb_endpoint_descriptor
*
epread
=
NULL
;
if
(
!
buffer
)
{
struct
usb_endpoint_descriptor
*
epwrite
=
NULL
;
err
(
"Wierd descriptor references"
);
int
readsize
,
ctrlsize
,
minor
,
j
;
return
-
EINVAL
;
unsigned
char
*
buf
;
}
dev
=
interface_to_usbdev
(
intf
);
while
(
buflen
>
0
)
{
if
(
buffer
[
1
]
!=
USB_DT_CS_INTERFACE
)
{
cfacm
=
dev
->
actconfig
;
err
(
"skipping garbage"
);
goto
next_desc
;
/* We know we're probe()d with the control interface. */
ifcom
=
intf
->
cur_altsetting
;
/* ACM doesn't guarantee the data interface is
* adjacent to the control interface, or that if one
* is there it's not for call management ... so find
* it
*/
for
(
j
=
0
;
j
<
cfacm
->
desc
.
bNumInterfaces
;
j
++
)
{
ifdata
=
cfacm
->
interface
[
j
]
->
cur_altsetting
;
data
=
cfacm
->
interface
[
j
];
if
(
ifdata
->
desc
.
bInterfaceClass
==
USB_CLASS_CDC_DATA
&&
ifdata
->
desc
.
bNumEndpoints
==
2
)
{
epctrl
=
&
ifcom
->
endpoint
[
0
].
desc
;
epread
=
&
ifdata
->
endpoint
[
0
].
desc
;
epwrite
=
&
ifdata
->
endpoint
[
1
].
desc
;
if
((
epctrl
->
bEndpointAddress
&
USB_DIR_IN
)
!=
USB_DIR_IN
||
!
CHECK_XFERTYPE
(
epctrl
,
USB_ENDPOINT_XFER_INT
)
||
!
CHECK_XFERTYPE
(
epread
,
USB_ENDPOINT_XFER_BULK
)
||
!
CHECK_XFERTYPE
(
epwrite
,
USB_ENDPOINT_XFER_BULK
)
||
((
epread
->
bEndpointAddress
&
USB_DIR_IN
)
^
(
epwrite
->
bEndpointAddress
&
USB_DIR_IN
))
!=
USB_DIR_IN
)
{
/* not suitable */
goto
next_interface
;
}
if
((
epread
->
bEndpointAddress
&
USB_DIR_IN
)
!=
USB_DIR_IN
)
{
/* descriptors are swapped */
epread
=
&
ifdata
->
endpoint
[
1
].
desc
;
epwrite
=
&
ifdata
->
endpoint
[
0
].
desc
;
}
dev_dbg
(
&
intf
->
dev
,
"found data interface at %d
\n
"
,
j
);
break
;
}
else
{
next_interface:
ifdata
=
NULL
;
data
=
NULL
;
}
}
switch
(
buffer
[
2
])
{
case
CDC_UNION_TYPE
:
/* we've found it */
if
(
union_header
)
{
err
(
"More than one union descriptor, skipping ..."
);
goto
next_desc
;
}
union_header
=
(
struct
union_desc
*
)
buffer
;
break
;
default:
err
(
"Ignoring extra header"
);
break
;
}
next_desc:
buflen
-=
buffer
[
0
];
buffer
+=
buffer
[
0
];
}
if
(
!
union_header
)
{
dev_dbg
(
&
intf
->
dev
,
"No union descriptor, giving up
\n
"
);
return
-
ENODEV
;
}
}
/* there's been a problem */
control_interface
=
usb_ifnum_to_if
(
usb_dev
,
union_header
->
bMasterInterface0
);
if
(
!
ifdata
)
{
data_interface
=
usb_ifnum_to_if
(
usb_dev
,
union_header
->
bSlaveInterface0
);
dev_dbg
(
&
intf
->
dev
,
"data interface not found
\n
"
);
if
(
!
control_interface
||
!
data_interface
)
{
dev_dbg
(
&
intf
->
dev
,
"no interfaces
\n
"
);
return
-
ENODEV
;
return
-
ENODEV
;
}
if
(
usb_interface_claimed
(
data_interface
))
{
/* valid in this context */
dev_dbg
(
&
intf
->
dev
,
"The data interface isn't available
\n
"
);
return
-
EBUSY
;
}
/*workaround for switched interfaces */
if
(
data_interface
->
cur_altsetting
->
desc
.
bInterfaceClass
!=
CDC_DATA_INTERFACE_TYPE
)
{
if
(
control_interface
->
cur_altsetting
->
desc
.
bInterfaceClass
==
CDC_DATA_INTERFACE_TYPE
)
{
struct
usb_interface
*
t
;
dev_dbg
(
&
intf
->
dev
,
"Your device has switched interfaces.
\n
"
);
t
=
control_interface
;
control_interface
=
data_interface
;
data_interface
=
t
;
}
else
{
return
-
EINVAL
;
}
}
}
if
(
data_interface
->
cur_altsetting
->
desc
.
bNumEndpoints
<
2
)
return
-
EINVAL
;
epctrl
=
&
control_interface
->
cur_altsetting
->
endpoint
[
0
].
desc
;
epread
=
&
data_interface
->
cur_altsetting
->
endpoint
[
0
].
desc
;
epwrite
=
&
data_interface
->
cur_altsetting
->
endpoint
[
1
].
desc
;
/* workaround for switched endpoints */
if
((
epread
->
bEndpointAddress
&
USB_DIR_IN
)
!=
USB_DIR_IN
)
{
/* descriptors are swapped */
struct
usb_endpoint_descriptor
*
t
;
dev_dbg
(
&
intf
->
dev
,
"The data interface has switched endpoints
\n
"
);
t
=
epread
;
epread
=
epwrite
;
epwrite
=
t
;
}
dbg
(
"interfaces are valid"
);
for
(
minor
=
0
;
minor
<
ACM_TTY_MINORS
&&
acm_table
[
minor
];
minor
++
);
for
(
minor
=
0
;
minor
<
ACM_TTY_MINORS
&&
acm_table
[
minor
];
minor
++
);
if
(
acm_table
[
minor
])
{
if
(
acm_table
[
minor
])
{
err
(
"no more free acm devices"
);
err
(
"no more free acm devices"
);
return
-
ENODEV
;
return
-
ENODEV
;
...
@@ -647,20 +600,21 @@ static int acm_probe (struct usb_interface *intf,
...
@@ -647,20 +600,21 @@ static int acm_probe (struct usb_interface *intf,
dev_dbg
(
&
intf
->
dev
,
"out of memory (acm kmalloc)
\n
"
);
dev_dbg
(
&
intf
->
dev
,
"out of memory (acm kmalloc)
\n
"
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
memset
(
acm
,
0
,
sizeof
(
struct
acm
));
memset
(
acm
,
0
,
sizeof
(
struct
acm
));
ctrlsize
=
epctrl
->
wMaxPacketSize
;
ctrlsize
=
epctrl
->
wMaxPacketSize
;
readsize
=
epread
->
wMaxPacketSize
;
readsize
=
epread
->
wMaxPacketSize
;
acm
->
writesize
=
epwrite
->
wMaxPacketSize
;
acm
->
writesize
=
epwrite
->
wMaxPacketSize
;
acm
->
control
=
intf
;
acm
->
control
=
control_interface
;
acm
->
data
=
data
;
acm
->
data
=
data
_interface
;
acm
->
minor
=
minor
;
acm
->
minor
=
minor
;
acm
->
dev
=
dev
;
acm
->
dev
=
usb_
dev
;
acm
->
bh
.
func
=
acm_rx_tasklet
;
acm
->
bh
.
func
=
acm_rx_tasklet
;
acm
->
bh
.
data
=
(
unsigned
long
)
acm
;
acm
->
bh
.
data
=
(
unsigned
long
)
acm
;
INIT_WORK
(
&
acm
->
work
,
acm_softint
,
acm
);
INIT_WORK
(
&
acm
->
work
,
acm_softint
,
acm
);
acm
->
ready_for_write
=
1
;
if
(
!
(
buf
=
kmalloc
(
ctrlsize
+
readsize
+
acm
->
writesize
,
GFP_KERNEL
)))
{
if
(
!
(
buf
=
kmalloc
(
ctrlsize
+
readsize
+
acm
->
writesize
,
GFP_KERNEL
)))
{
dev_dbg
(
&
intf
->
dev
,
"out of memory (buf kmalloc)
\n
"
);
dev_dbg
(
&
intf
->
dev
,
"out of memory (buf kmalloc)
\n
"
);
...
@@ -693,29 +647,17 @@ static int acm_probe (struct usb_interface *intf,
...
@@ -693,29 +647,17 @@ static int acm_probe (struct usb_interface *intf,
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
usb_fill_int_urb
(
acm
->
ctrlurb
,
dev
,
usb_rcvintpipe
(
dev
,
epctrl
->
bEndpointAddress
),
usb_fill_int_urb
(
acm
->
ctrlurb
,
usb_dev
,
usb_rcvintpipe
(
usb_
dev
,
epctrl
->
bEndpointAddress
),
buf
,
ctrlsize
,
acm_ctrl_irq
,
acm
,
epctrl
->
bInterval
);
buf
,
ctrlsize
,
acm_ctrl_irq
,
acm
,
epctrl
->
bInterval
);
usb_fill_bulk_urb
(
acm
->
readurb
,
dev
,
usb_rcvbulkpipe
(
dev
,
epread
->
bEndpointAddress
),
usb_fill_bulk_urb
(
acm
->
readurb
,
usb_dev
,
usb_rcvbulkpipe
(
usb_
dev
,
epread
->
bEndpointAddress
),
buf
+=
ctrlsize
,
readsize
,
acm_read_bulk
,
acm
);
buf
+=
ctrlsize
,
readsize
,
acm_read_bulk
,
acm
);
acm
->
readurb
->
transfer_flags
|=
URB_NO_FSBR
;
acm
->
readurb
->
transfer_flags
|=
URB_NO_FSBR
;
usb_fill_bulk_urb
(
acm
->
writeurb
,
dev
,
usb_sndbulkpipe
(
dev
,
epwrite
->
bEndpointAddress
),
usb_fill_bulk_urb
(
acm
->
writeurb
,
usb_dev
,
usb_sndbulkpipe
(
usb_
dev
,
epwrite
->
bEndpointAddress
),
buf
+=
readsize
,
acm
->
writesize
,
acm_write_bulk
,
acm
);
buf
+=
readsize
,
acm
->
writesize
,
acm_write_bulk
,
acm
);
acm
->
writeurb
->
transfer_flags
|=
URB_NO_FSBR
;
acm
->
writeurb
->
transfer_flags
|=
URB_NO_FSBR
;
if
(
(
j
=
usb_driver_claim_interface
(
&
acm_driver
,
data
,
acm
))
!=
0
)
{
err
(
"claim failed"
);
usb_free_urb
(
acm
->
ctrlurb
);
usb_free_urb
(
acm
->
readurb
);
usb_free_urb
(
acm
->
writeurb
);
kfree
(
acm
);
kfree
(
buf
);
return
j
;
}
tty_register_device
(
acm_tty_driver
,
minor
,
&
intf
->
dev
);
dev_info
(
&
intf
->
dev
,
"ttyACM%d: USB ACM device
\n
"
,
minor
);
dev_info
(
&
intf
->
dev
,
"ttyACM%d: USB ACM device
\n
"
,
minor
);
acm_set_control
(
acm
,
acm
->
ctrlout
);
acm_set_control
(
acm
,
acm
->
ctrlout
);
...
@@ -724,11 +666,14 @@ static int acm_probe (struct usb_interface *intf,
...
@@ -724,11 +666,14 @@ static int acm_probe (struct usb_interface *intf,
acm
->
line
.
databits
=
8
;
acm
->
line
.
databits
=
8
;
acm_set_line
(
acm
,
&
acm
->
line
);
acm_set_line
(
acm
,
&
acm
->
line
);
usb_driver_claim_interface
(
&
acm_driver
,
data_interface
,
acm
);
tty_register_device
(
acm_tty_driver
,
minor
,
&
intf
->
dev
);
acm_table
[
minor
]
=
acm
;
acm_table
[
minor
]
=
acm
;
usb_set_intfdata
(
intf
,
acm
);
usb_set_intfdata
(
intf
,
acm
);
return
0
;
return
0
;
}
}
#undef CHECK_XFERTYPE
static
void
acm_disconnect
(
struct
usb_interface
*
intf
)
static
void
acm_disconnect
(
struct
usb_interface
*
intf
)
{
{
...
@@ -746,6 +691,8 @@ static void acm_disconnect(struct usb_interface *intf)
...
@@ -746,6 +691,8 @@ static void acm_disconnect(struct usb_interface *intf)
usb_unlink_urb
(
acm
->
readurb
);
usb_unlink_urb
(
acm
->
readurb
);
usb_unlink_urb
(
acm
->
writeurb
);
usb_unlink_urb
(
acm
->
writeurb
);
flush_scheduled_work
();
/* wait for acm_softint */
kfree
(
acm
->
ctrlurb
->
transfer_buffer
);
kfree
(
acm
->
ctrlurb
->
transfer_buffer
);
usb_driver_release_interface
(
&
acm_driver
,
acm
->
data
);
usb_driver_release_interface
(
&
acm_driver
,
acm
->
data
);
...
...
drivers/usb/class/cdc-acm.h
0 → 100644
View file @
fcc95bca
/*
*
* Includes for cdc-acm.c
*
* Mainly take from usbnet's cdc-ether part
*
*/
/*
* CMSPAR, some architectures can't have space and mark parity.
*/
#ifndef CMSPAR
#define CMSPAR 0
#endif
/*
* Major and minor numbers.
*/
#define ACM_TTY_MAJOR 166
#define ACM_TTY_MINORS 32
/*
* Requests.
*/
#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
#define ACM_REQ_COMMAND 0x00
#define ACM_REQ_RESPONSE 0x01
#define ACM_REQ_SET_FEATURE 0x02
#define ACM_REQ_GET_FEATURE 0x03
#define ACM_REQ_CLEAR_FEATURE 0x04
#define ACM_REQ_SET_LINE 0x20
#define ACM_REQ_GET_LINE 0x21
#define ACM_REQ_SET_CONTROL 0x22
#define ACM_REQ_SEND_BREAK 0x23
/*
* IRQs.
*/
#define ACM_IRQ_NETWORK 0x00
#define ACM_IRQ_LINE_STATE 0x20
/*
* Output control lines.
*/
#define ACM_CTRL_DTR 0x01
#define ACM_CTRL_RTS 0x02
/*
* Input control lines and line errors.
*/
#define ACM_CTRL_DCD 0x01
#define ACM_CTRL_DSR 0x02
#define ACM_CTRL_BRK 0x04
#define ACM_CTRL_RI 0x08
#define ACM_CTRL_FRAMING 0x10
#define ACM_CTRL_PARITY 0x20
#define ACM_CTRL_OVERRUN 0x40
/*
* Line speed and caracter encoding.
*/
struct
acm_line
{
__u32
speed
;
__u8
stopbits
;
__u8
parity
;
__u8
databits
;
}
__attribute__
((
packed
));
/*
* Internal driver structures.
*/
struct
acm
{
struct
usb_device
*
dev
;
/* the corresponding usb device */
struct
usb_interface
*
control
;
/* control interface */
struct
usb_interface
*
data
;
/* data interface */
struct
tty_struct
*
tty
;
/* the corresponding tty */
struct
urb
*
ctrlurb
,
*
readurb
,
*
writeurb
;
/* urbs */
struct
acm_line
line
;
/* line coding (bits, stop, parity) */
struct
work_struct
work
;
/* work queue entry for line discipline waking up */
struct
tasklet_struct
bh
;
/* rx processing */
unsigned
int
ctrlin
;
/* input control lines (DCD, DSR, RI, break, overruns) */
unsigned
int
ctrlout
;
/* output control lines (DTR, RTS) */
unsigned
int
writesize
;
/* max packet size for the output bulk endpoint */
unsigned
int
used
;
/* someone has this acm's device open */
unsigned
int
minor
;
/* acm minor number */
unsigned
char
throttle
;
/* throttled by tty layer */
unsigned
char
clocal
;
/* termios CLOCAL */
unsigned
char
ready_for_write
;
/* write urb can be used */
};
/* "Union Functional Descriptor" from CDC spec 5.2.3.X */
struct
union_desc
{
u8
bLength
;
u8
bDescriptorType
;
u8
bDescriptorSubType
;
u8
bMasterInterface0
;
u8
bSlaveInterface0
;
/* ... and there could be other slave interfaces */
}
__attribute__
((
packed
));
#define CDC_UNION_TYPE 0x06
#define CDC_DATA_INTERFACE_TYPE 0x0a
drivers/usb/class/usblp.c
View file @
fcc95bca
...
@@ -761,6 +761,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
...
@@ -761,6 +761,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t count,
usblp
->
minor
,
usblp
->
readurb
->
status
);
usblp
->
minor
,
usblp
->
readurb
->
status
);
usblp
->
readurb
->
dev
=
usblp
->
dev
;
usblp
->
readurb
->
dev
=
usblp
->
dev
;
usblp
->
readcount
=
0
;
usblp
->
readcount
=
0
;
usblp
->
rcomplete
=
0
;
if
(
usb_submit_urb
(
usblp
->
readurb
,
GFP_KERNEL
)
<
0
)
if
(
usb_submit_urb
(
usblp
->
readurb
,
GFP_KERNEL
)
<
0
)
dbg
(
"error submitting urb"
);
dbg
(
"error submitting urb"
);
count
=
-
EIO
;
count
=
-
EIO
;
...
...
drivers/usb/core/hcd.h
View file @
fcc95bca
...
@@ -244,17 +244,10 @@ extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
...
@@ -244,17 +244,10 @@ extern struct usb_device *usb_alloc_dev(struct usb_device *parent,
struct
usb_bus
*
,
unsigned
port
);
struct
usb_bus
*
,
unsigned
port
);
extern
int
usb_new_device
(
struct
usb_device
*
dev
);
extern
int
usb_new_device
(
struct
usb_device
*
dev
);
extern
void
usb_disconnect
(
struct
usb_device
**
);
extern
void
usb_disconnect
(
struct
usb_device
**
);
extern
void
usb_choose_address
(
struct
usb_device
*
dev
);
extern
void
usb_release_address
(
struct
usb_device
*
dev
);
/* exported to hub driver ONLY to support usb_reset_device () */
extern
int
usb_get_configuration
(
struct
usb_device
*
dev
);
extern
int
usb_get_configuration
(
struct
usb_device
*
dev
);
extern
void
usb_destroy_configuration
(
struct
usb_device
*
dev
);
extern
void
usb_destroy_configuration
(
struct
usb_device
*
dev
);
/* use these only before the device's address has been set */
#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30))
#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | USB_DIR_IN)
/*-------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
/*
/*
...
...
drivers/usb/core/hub.c
View file @
fcc95bca
...
@@ -9,6 +9,11 @@
...
@@ -9,6 +9,11 @@
*/
*/
#include <linux/config.h>
#include <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/module.h>
...
@@ -19,11 +24,6 @@
...
@@ -19,11 +24,6 @@
#include <linux/slab.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/smp_lock.h>
#include <linux/ioctl.h>
#include <linux/ioctl.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/usb.h>
#include <linux/usb.h>
#include <linux/usbdevice_fs.h>
#include <linux/usbdevice_fs.h>
#include <linux/suspend.h>
#include <linux/suspend.h>
...
@@ -40,7 +40,6 @@
...
@@ -40,7 +40,6 @@
static
spinlock_t
hub_event_lock
=
SPIN_LOCK_UNLOCKED
;
static
spinlock_t
hub_event_lock
=
SPIN_LOCK_UNLOCKED
;
static
LIST_HEAD
(
hub_event_list
);
/* List of hubs needing servicing */
static
LIST_HEAD
(
hub_event_list
);
/* List of hubs needing servicing */
static
LIST_HEAD
(
hub_list
);
/* List of all hubs (for cleanup) */
static
DECLARE_WAIT_QUEUE_HEAD
(
khubd_wait
);
static
DECLARE_WAIT_QUEUE_HEAD
(
khubd_wait
);
static
pid_t
khubd_pid
=
0
;
/* PID of khubd */
static
pid_t
khubd_pid
=
0
;
/* PID of khubd */
...
@@ -268,7 +267,7 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs)
...
@@ -268,7 +267,7 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs)
if
((
status
=
usb_submit_urb
(
hub
->
urb
,
GFP_ATOMIC
))
!=
0
if
((
status
=
usb_submit_urb
(
hub
->
urb
,
GFP_ATOMIC
))
!=
0
/* ENODEV means we raced disconnect() */
/* ENODEV means we raced disconnect() */
&&
status
!=
-
ENODEV
)
&&
status
!=
-
ENODEV
)
dev_err
(
&
hub
->
intf
->
dev
,
"resubmit --> %d
\n
"
,
urb
->
status
);
dev_err
(
&
hub
->
intf
->
dev
,
"resubmit --> %d
\n
"
,
status
);
if
(
status
==
0
)
if
(
status
==
0
)
hub
->
urb_active
=
1
;
hub
->
urb_active
=
1
;
done:
done:
...
@@ -646,7 +645,6 @@ static void hub_disconnect(struct usb_interface *intf)
...
@@ -646,7 +645,6 @@ static void hub_disconnect(struct usb_interface *intf)
/* Delete it and then reset it */
/* Delete it and then reset it */
list_del_init
(
&
hub
->
event_list
);
list_del_init
(
&
hub
->
event_list
);
list_del_init
(
&
hub
->
hub_list
);
spin_unlock_irqrestore
(
&
hub_event_lock
,
flags
);
spin_unlock_irqrestore
(
&
hub_event_lock
,
flags
);
...
@@ -695,7 +693,6 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
...
@@ -695,7 +693,6 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct
usb_device
*
hdev
;
struct
usb_device
*
hdev
;
struct
usb_hub
*
hub
;
struct
usb_hub
*
hub
;
struct
device
*
hub_dev
;
struct
device
*
hub_dev
;
unsigned
long
flags
;
desc
=
intf
->
cur_altsetting
;
desc
=
intf
->
cur_altsetting
;
hdev
=
interface_to_usbdev
(
intf
);
hdev
=
interface_to_usbdev
(
intf
);
...
@@ -711,23 +708,19 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
...
@@ -711,23 +708,19 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
}
}
/* Multiple endpoints? What kind of mutant ninja-hub is this? */
/* Multiple endpoints? What kind of mutant ninja-hub is this? */
if
(
desc
->
desc
.
bNumEndpoints
!=
1
)
{
if
(
desc
->
desc
.
bNumEndpoints
!=
1
)
goto
descriptor_error
;
goto
descriptor_error
;
}
endpoint
=
&
desc
->
endpoint
[
0
].
desc
;
endpoint
=
&
desc
->
endpoint
[
0
].
desc
;
/* Output endpoint? Curiouser and curiouser.. */
/* Output endpoint? Curiouser and curiouser.. */
if
(
!
(
endpoint
->
bEndpointAddress
&
USB_DIR_IN
))
{
if
(
!
(
endpoint
->
bEndpointAddress
&
USB_DIR_IN
))
goto
descriptor_error
;
goto
descriptor_error
;
}
/* If it's not an interrupt endpoint, we'd better punt! */
/* If it's not an interrupt endpoint, we'd better punt! */
if
((
endpoint
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
if
((
endpoint
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
!=
USB_ENDPOINT_XFER_INT
)
{
!=
USB_ENDPOINT_XFER_INT
)
goto
descriptor_error
;
goto
descriptor_error
;
return
-
EIO
;
}
/* We found a hub */
/* We found a hub */
dev_info
(
hub_dev
,
"USB hub found
\n
"
);
dev_info
(
hub_dev
,
"USB hub found
\n
"
);
...
@@ -745,12 +738,6 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
...
@@ -745,12 +738,6 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
init_MUTEX
(
&
hub
->
khubd_sem
);
init_MUTEX
(
&
hub
->
khubd_sem
);
INIT_WORK
(
&
hub
->
leds
,
led_work
,
hub
);
INIT_WORK
(
&
hub
->
leds
,
led_work
,
hub
);
/* Record the new hub's existence */
spin_lock_irqsave
(
&
hub_event_lock
,
flags
);
INIT_LIST_HEAD
(
&
hub
->
hub_list
);
list_add
(
&
hub
->
hub_list
,
&
hub_list
);
spin_unlock_irqrestore
(
&
hub_event_lock
,
flags
);
usb_set_intfdata
(
intf
,
hub
);
usb_set_intfdata
(
intf
,
hub
);
if
(
hdev
->
speed
==
USB_SPEED_HIGH
)
if
(
hdev
->
speed
==
USB_SPEED_HIGH
)
...
@@ -845,6 +832,234 @@ static void hub_start_disconnect(struct usb_device *hdev)
...
@@ -845,6 +832,234 @@ static void hub_start_disconnect(struct usb_device *hdev)
dev_err
(
&
hdev
->
dev
,
"cannot disconnect hub!
\n
"
);
dev_err
(
&
hdev
->
dev
,
"cannot disconnect hub!
\n
"
);
}
}
static
void
choose_address
(
struct
usb_device
*
udev
)
{
int
devnum
;
struct
usb_bus
*
bus
=
udev
->
bus
;
/* If khubd ever becomes multithreaded, this will need a lock */
/* Try to allocate the next devnum beginning at bus->devnum_next. */
devnum
=
find_next_zero_bit
(
bus
->
devmap
.
devicemap
,
128
,
bus
->
devnum_next
);
if
(
devnum
>=
128
)
devnum
=
find_next_zero_bit
(
bus
->
devmap
.
devicemap
,
128
,
1
);
bus
->
devnum_next
=
(
devnum
>=
127
?
1
:
devnum
+
1
);
if
(
devnum
<
128
)
{
set_bit
(
devnum
,
bus
->
devmap
.
devicemap
);
udev
->
devnum
=
devnum
;
}
}
static
void
release_address
(
struct
usb_device
*
udev
)
{
if
(
udev
->
devnum
>
0
)
{
clear_bit
(
udev
->
devnum
,
udev
->
bus
->
devmap
.
devicemap
);
udev
->
devnum
=
-
1
;
}
}
/**
* usb_disconnect - disconnect a device (usbcore-internal)
* @pdev: pointer to device being disconnected
* Context: !in_interrupt ()
*
* Something got disconnected. Get rid of it, and all of its children.
*
* Only hub drivers (including virtual root hub drivers for host
* controllers) should ever call this.
*
* This call is synchronous, and may not be used in an interrupt context.
*/
void
usb_disconnect
(
struct
usb_device
**
pdev
)
{
struct
usb_device
*
udev
=
*
pdev
;
struct
usb_bus
*
bus
;
struct
usb_operations
*
ops
;
int
i
;
if
(
!
udev
)
{
pr_debug
(
"%s nodev
\n
"
,
__FUNCTION__
);
return
;
}
bus
=
udev
->
bus
;
if
(
!
bus
)
{
pr_debug
(
"%s nobus
\n
"
,
__FUNCTION__
);
return
;
}
ops
=
bus
->
op
;
*
pdev
=
NULL
;
/* mark the device as inactive, so any further urb submissions for
* this device will fail.
*/
udev
->
state
=
USB_STATE_NOTATTACHED
;
down
(
&
udev
->
serialize
);
dev_info
(
&
udev
->
dev
,
"USB disconnect, address %d
\n
"
,
udev
->
devnum
);
/* Free up all the children before we remove this device */
for
(
i
=
0
;
i
<
USB_MAXCHILDREN
;
i
++
)
{
struct
usb_device
**
child
=
udev
->
children
+
i
;
if
(
*
child
)
usb_disconnect
(
child
);
}
/* deallocate hcd/hardware state ... nuking all pending urbs and
* cleaning up all state associated with the current configuration
*/
usb_disable_device
(
udev
,
0
);
/* Free the device number and remove the /proc/bus/usb entry */
dev_dbg
(
&
udev
->
dev
,
"unregistering device
\n
"
);
release_address
(
udev
);
usbfs_remove_device
(
udev
);
up
(
&
udev
->
serialize
);
device_unregister
(
&
udev
->
dev
);
}
static
int
choose_configuration
(
struct
usb_device
*
udev
)
{
int
c
,
i
;
/* NOTE: this should interact with hub power budgeting */
c
=
udev
->
config
[
0
].
desc
.
bConfigurationValue
;
if
(
udev
->
descriptor
.
bNumConfigurations
!=
1
)
{
for
(
i
=
0
;
i
<
udev
->
descriptor
.
bNumConfigurations
;
i
++
)
{
struct
usb_interface_descriptor
*
desc
;
/* heuristic: Linux is more likely to have class
* drivers, so avoid vendor-specific interfaces.
*/
desc
=
&
udev
->
config
[
i
].
intf_cache
[
0
]
->
altsetting
->
desc
;
if
(
desc
->
bInterfaceClass
==
USB_CLASS_VENDOR_SPEC
)
continue
;
/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */
if
(
desc
->
bInterfaceClass
==
USB_CLASS_COMM
&&
desc
->
bInterfaceSubClass
==
2
&&
desc
->
bInterfaceProtocol
==
0xff
)
continue
;
c
=
udev
->
config
[
i
].
desc
.
bConfigurationValue
;
break
;
}
dev_info
(
&
udev
->
dev
,
"configuration #%d chosen from %d choices
\n
"
,
c
,
udev
->
descriptor
.
bNumConfigurations
);
}
return
c
;
}
#ifdef DEBUG
static
void
show_string
(
struct
usb_device
*
udev
,
char
*
id
,
int
index
)
{
char
*
buf
;
if
(
!
index
)
return
;
if
(
!
(
buf
=
kmalloc
(
256
,
GFP_KERNEL
)))
return
;
if
(
usb_string
(
udev
,
index
,
buf
,
256
)
>
0
)
dev_printk
(
KERN_INFO
,
&
udev
->
dev
,
"%s: %s
\n
"
,
id
,
buf
);
kfree
(
buf
);
}
#else
static
inline
void
show_string
(
struct
usb_device
*
udev
,
char
*
id
,
int
index
)
{}
#endif
/*
* usb_new_device - perform initial device setup (usbcore-internal)
* @dev: newly addressed device (in ADDRESS state)
*
* This is called with devices which have been enumerated, but not yet
* configured. The device descriptor is available, but not descriptors
* for any device configuration. The caller owns dev->serialize, and
* the device is not visible through sysfs or other filesystem code.
*
* Returns 0 for success (device is configured and listed, with its
* interfaces, in sysfs); else a negative errno value. On error, one
* reference count to the device has been dropped.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Only the hub driver should ever call this; root hub registration
* uses it only indirectly.
*/
int
usb_new_device
(
struct
usb_device
*
udev
)
{
int
err
;
int
c
;
err
=
usb_get_configuration
(
udev
);
if
(
err
<
0
)
{
dev_err
(
&
udev
->
dev
,
"can't read configurations, error %d
\n
"
,
err
);
goto
fail
;
}
/* Tell the world! */
dev_dbg
(
&
udev
->
dev
,
"new device strings: Mfr=%d, Product=%d, "
"SerialNumber=%d
\n
"
,
udev
->
descriptor
.
iManufacturer
,
udev
->
descriptor
.
iProduct
,
udev
->
descriptor
.
iSerialNumber
);
if
(
udev
->
descriptor
.
iProduct
)
show_string
(
udev
,
"Product"
,
udev
->
descriptor
.
iProduct
);
if
(
udev
->
descriptor
.
iManufacturer
)
show_string
(
udev
,
"Manufacturer"
,
udev
->
descriptor
.
iManufacturer
);
if
(
udev
->
descriptor
.
iSerialNumber
)
show_string
(
udev
,
"SerialNumber"
,
udev
->
descriptor
.
iSerialNumber
);
/* put device-specific files into sysfs */
err
=
device_add
(
&
udev
->
dev
);
if
(
err
)
{
dev_err
(
&
udev
->
dev
,
"can't device_add, error %d
\n
"
,
err
);
goto
fail
;
}
usb_create_sysfs_dev_files
(
udev
);
/* choose and set the configuration. that registers the interfaces
* with the driver core, and lets usb device drivers bind to them.
*/
c
=
choose_configuration
(
udev
);
if
(
c
<
0
)
dev_warn
(
&
udev
->
dev
,
"can't choose an initial configuration
\n
"
);
else
{
err
=
usb_set_configuration
(
udev
,
c
);
if
(
err
)
{
dev_err
(
&
udev
->
dev
,
"can't set config #%d, error %d
\n
"
,
c
,
err
);
device_del
(
&
udev
->
dev
);
goto
fail
;
}
}
/* USB device state == configured ... usable */
/* add a /proc/bus/usb entry */
usbfs_add_device
(
udev
);
return
0
;
fail:
udev
->
state
=
USB_STATE_NOTATTACHED
;
release_address
(
udev
);
usb_put_dev
(
udev
);
return
err
;
}
static
int
hub_port_status
(
struct
usb_device
*
hdev
,
int
port
,
static
int
hub_port_status
(
struct
usb_device
*
hdev
,
int
port
,
u16
*
status
,
u16
*
change
)
u16
*
status
,
u16
*
change
)
{
{
...
@@ -975,57 +1190,62 @@ static int hub_port_disable(struct usb_device *hdev, int port)
...
@@ -975,57 +1190,62 @@ static int hub_port_disable(struct usb_device *hdev, int port)
/* USB 2.0 spec, 7.1.7.3 / fig 7-29:
/* USB 2.0 spec, 7.1.7.3 / fig 7-29:
*
*
* Between connect detection and reset signaling there must be a delay
* Between connect detection and reset signaling there must be a delay
* of 100ms at least for debounce and power-settling. The corresponding
* of 100ms at least for debounce and power-settling.
The corresponding
* timer shall restart whenever the downstream port detects a disconnect.
* timer shall restart whenever the downstream port detects a disconnect.
*
*
* Apparently there are some bluetooth and irda-dongles and a number
* Apparently there are some bluetooth and irda-dongles and a number
of
*
of low-speed devices which require longer delays of about 200-400ms
.
*
low-speed devices for which this debounce period may last over a second
.
* Not covered by the spec - but easy to deal with.
* Not covered by the spec - but easy to deal with.
*
*
* This implementation uses 400ms minimum debounce timeout and checks
* This implementation uses a 1500ms total debounce timeout; if the
* every 25ms for transient disconnects to restart the delay.
* connection isn't stable by then it returns -ETIMEDOUT. It checks
* every 25ms for transient disconnects. When the port status has been
* unchanged for 100ms it returns the port status.
*/
*/
#define HUB_DEBOUNCE_TIMEOUT
4
00
#define HUB_DEBOUNCE_TIMEOUT
15
00
#define HUB_DEBOUNCE_STEP 25
#define HUB_DEBOUNCE_STEP
25
#define HUB_DEBOUNCE_STABLE
4
#define HUB_DEBOUNCE_STABLE
100
static
int
hub_port_debounce
(
struct
usb_device
*
hdev
,
int
port
)
static
int
hub_port_debounce
(
struct
usb_device
*
hdev
,
int
port
)
{
{
int
ret
;
int
ret
;
int
delay_time
,
stable_count
;
int
total_time
,
stable_time
=
0
;
u16
portchange
,
portstatus
;
u16
portchange
,
portstatus
;
unsigned
connection
;
unsigned
connection
=
0xffff
;
connection
=
0
;
stable_count
=
0
;
for
(
delay_time
=
0
;
delay_time
<
HUB_DEBOUNCE_TIMEOUT
;
delay_time
+=
HUB_DEBOUNCE_STEP
)
{
msleep
(
HUB_DEBOUNCE_STEP
);
for
(
total_time
=
0
;
;
total_time
+=
HUB_DEBOUNCE_STEP
)
{
ret
=
hub_port_status
(
hdev
,
port
,
&
portstatus
,
&
portchange
);
ret
=
hub_port_status
(
hdev
,
port
,
&
portstatus
,
&
portchange
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
if
(
(
portstatus
&
USB_PORT_STAT_CONNECTION
)
==
connection
)
{
if
(
!
(
portchange
&
USB_PORT_STAT_C_CONNECTION
)
&&
if
(
connection
)
{
(
portstatus
&
USB_PORT_STAT_CONNECTION
)
==
connection
)
{
if
(
++
stable_count
==
HUB_DEBOUNCE_STABLE
)
stable_time
+=
HUB_DEBOUNCE_STEP
;
break
;
if
(
stable_time
>=
HUB_DEBOUNCE_STABLE
)
}
break
;
}
else
{
}
else
{
stable_count
=
0
;
stable_time
=
0
;
connection
=
portstatus
&
USB_PORT_STAT_CONNECTION
;
}
}
connection
=
portstatus
&
USB_PORT_STAT_CONNECTION
;
if
((
portchange
&
USB_PORT_STAT_C_CONNECTION
))
{
if
(
portchange
&
USB_PORT_STAT_C_CONNECTION
)
{
clear_port_feature
(
hdev
,
port
+
1
,
USB_PORT_FEAT_C_CONNECTION
);
clear_port_feature
(
hdev
,
port
+
1
,
USB_PORT_FEAT_C_CONNECTION
);
}
}
if
(
total_time
>=
HUB_DEBOUNCE_TIMEOUT
)
break
;
msleep
(
HUB_DEBOUNCE_STEP
);
}
}
dev_dbg
(
hubdev
(
hdev
),
dev_dbg
(
hubdev
(
hdev
),
"debounce: port %d:
delay %dms stable %d
status 0x%x
\n
"
,
"debounce: port %d:
total %dms stable %dms
status 0x%x
\n
"
,
port
+
1
,
delay_time
,
stable_count
,
portstatus
);
port
+
1
,
total_time
,
stable_time
,
portstatus
);
return
(
portstatus
&
USB_PORT_STAT_CONNECTION
)
?
0
:
-
ENOTCONN
;
if
(
stable_time
<
HUB_DEBOUNCE_STABLE
)
return
-
ETIMEDOUT
;
return
portstatus
;
}
}
static
int
hub_set_address
(
struct
usb_device
*
udev
)
static
int
hub_set_address
(
struct
usb_device
*
udev
)
...
@@ -1037,7 +1257,7 @@ static int hub_set_address(struct usb_device *udev)
...
@@ -1037,7 +1257,7 @@ static int hub_set_address(struct usb_device *udev)
if
(
udev
->
state
!=
USB_STATE_DEFAULT
&&
if
(
udev
->
state
!=
USB_STATE_DEFAULT
&&
udev
->
state
!=
USB_STATE_ADDRESS
)
udev
->
state
!=
USB_STATE_ADDRESS
)
return
-
EINVAL
;
return
-
EINVAL
;
retval
=
usb_control_msg
(
udev
,
usb_snddefctrl
(
udev
)
,
retval
=
usb_control_msg
(
udev
,
(
PIPE_CONTROL
<<
30
)
/* Address 0 */
,
USB_REQ_SET_ADDRESS
,
0
,
udev
->
devnum
,
0
,
USB_REQ_SET_ADDRESS
,
0
,
udev
->
devnum
,
0
,
NULL
,
0
,
HZ
*
USB_CTRL_SET_TIMEOUT
);
NULL
,
0
,
HZ
*
USB_CTRL_SET_TIMEOUT
);
if
(
retval
==
0
)
if
(
retval
==
0
)
...
@@ -1111,7 +1331,7 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port)
...
@@ -1111,7 +1331,7 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port)
/* set the address */
/* set the address */
if
(
udev
->
devnum
<=
0
)
{
if
(
udev
->
devnum
<=
0
)
{
usb_
choose_address
(
udev
);
choose_address
(
udev
);
if
(
udev
->
devnum
<=
0
)
if
(
udev
->
devnum
<=
0
)
goto
fail
;
goto
fail
;
...
@@ -1166,7 +1386,7 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port)
...
@@ -1166,7 +1386,7 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port)
udev
->
devnum
,
retval
);
udev
->
devnum
,
retval
);
fail:
fail:
hub_port_disable
(
hdev
,
port
);
hub_port_disable
(
hdev
,
port
);
usb_
release_address
(
udev
);
release_address
(
udev
);
usb_put_dev
(
udev
);
usb_put_dev
(
udev
);
up
(
&
usb_address0_sem
);
up
(
&
usb_address0_sem
);
return
retval
;
return
retval
;
...
@@ -1271,7 +1491,14 @@ hub_power_remaining (struct usb_hub *hub, struct usb_device *hdev)
...
@@ -1271,7 +1491,14 @@ hub_power_remaining (struct usb_hub *hub, struct usb_device *hdev)
}
}
return
remaining
;
return
remaining
;
}
}
/* Handle physical or logical connection change events.
* This routine is called when:
* a port connection-change occurs;
* a port enable-change occurs (often caused by EMI);
* usb_reset_device() encounters changed descriptors (as from
* a firmware download)
*/
static
void
hub_port_connect_change
(
struct
usb_hub
*
hub
,
int
port
,
static
void
hub_port_connect_change
(
struct
usb_hub
*
hub
,
int
port
,
u16
portstatus
,
u16
portchange
)
u16
portstatus
,
u16
portchange
)
{
{
...
@@ -1282,9 +1509,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
...
@@ -1282,9 +1509,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
dev_dbg
(
hub_dev
,
dev_dbg
(
hub_dev
,
"port %d, status %04x, change %04x, %s
\n
"
,
"port %d, status %04x, change %04x, %s
\n
"
,
port
+
1
,
portstatus
,
portchange
,
portspeed
(
portstatus
));
port
+
1
,
portstatus
,
portchange
,
portspeed
(
portstatus
));
/* Clear the connection change status */
clear_port_feature
(
hdev
,
port
+
1
,
USB_PORT_FEAT_C_CONNECTION
);
if
(
hub
->
has_indicators
)
{
if
(
hub
->
has_indicators
)
{
set_port_led
(
hdev
,
port
+
1
,
HUB_LED_AUTO
);
set_port_led
(
hdev
,
port
+
1
,
HUB_LED_AUTO
);
...
@@ -1295,6 +1519,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
...
@@ -1295,6 +1519,17 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
if
(
hdev
->
children
[
port
])
if
(
hdev
->
children
[
port
])
usb_disconnect
(
&
hdev
->
children
[
port
]);
usb_disconnect
(
&
hdev
->
children
[
port
]);
if
(
portchange
&
USB_PORT_STAT_C_CONNECTION
)
{
status
=
hub_port_debounce
(
hdev
,
port
);
if
(
status
<
0
)
{
dev_err
(
hub_dev
,
"connect-debounce failed, port %d disabled
\n
"
,
port
+
1
);
goto
done
;
}
portstatus
=
status
;
}
/* Return now if nothing is connected */
/* Return now if nothing is connected */
if
(
!
(
portstatus
&
USB_PORT_STAT_CONNECTION
))
{
if
(
!
(
portstatus
&
USB_PORT_STAT_CONNECTION
))
{
...
@@ -1308,13 +1543,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
...
@@ -1308,13 +1543,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
goto
done
;
goto
done
;
return
;
return
;
}
}
if
(
hub_port_debounce
(
hdev
,
port
))
{
dev_err
(
hub_dev
,
"connect-debounce failed, port %d disabled
\n
"
,
port
+
1
);
goto
done
;
}
for
(
i
=
0
;
i
<
SET_CONFIG_TRIES
;
i
++
)
{
for
(
i
=
0
;
i
<
SET_CONFIG_TRIES
;
i
++
)
{
struct
usb_device
*
udev
;
struct
usb_device
*
udev
;
...
@@ -1416,6 +1644,7 @@ static void hub_events(void)
...
@@ -1416,6 +1644,7 @@ static void hub_events(void)
u16
portstatus
;
u16
portstatus
;
u16
portchange
;
u16
portchange
;
int
i
,
ret
;
int
i
,
ret
;
int
connect_change
;
/*
/*
* We restart the list every time to avoid a deadlock with
* We restart the list every time to avoid a deadlock with
...
@@ -1461,16 +1690,22 @@ static void hub_events(void)
...
@@ -1461,16 +1690,22 @@ static void hub_events(void)
for
(
i
=
0
;
i
<
hub
->
descriptor
->
bNbrPorts
;
i
++
)
{
for
(
i
=
0
;
i
<
hub
->
descriptor
->
bNbrPorts
;
i
++
)
{
ret
=
hub_port_status
(
hdev
,
i
,
&
portstatus
,
&
portchange
);
ret
=
hub_port_status
(
hdev
,
i
,
&
portstatus
,
&
portchange
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
continue
;
continue
;
}
connect_change
=
0
;
if
(
portchange
&
USB_PORT_STAT_C_CONNECTION
)
{
if
(
portchange
&
USB_PORT_STAT_C_CONNECTION
)
{
hub_port_connect_change
(
hub
,
i
,
portstatus
,
portchange
);
clear_port_feature
(
hdev
,
}
else
if
(
portchange
&
USB_PORT_STAT_C_ENABLE
)
{
i
+
1
,
USB_PORT_FEAT_C_CONNECTION
);
dev_dbg
(
hub_dev
,
connect_change
=
1
;
"port %d enable change, status %08x
\n
"
,
}
i
+
1
,
portstatus
);
if
(
portchange
&
USB_PORT_STAT_C_ENABLE
)
{
if
(
!
connect_change
)
dev_dbg
(
hub_dev
,
"port %d enable change, "
"status %08x
\n
"
,
i
+
1
,
portstatus
);
clear_port_feature
(
hdev
,
clear_port_feature
(
hdev
,
i
+
1
,
USB_PORT_FEAT_C_ENABLE
);
i
+
1
,
USB_PORT_FEAT_C_ENABLE
);
...
@@ -1481,15 +1716,14 @@ static void hub_events(void)
...
@@ -1481,15 +1716,14 @@ static void hub_events(void)
* Works at least with mouse driver.
* Works at least with mouse driver.
*/
*/
if
(
!
(
portstatus
&
USB_PORT_STAT_ENABLE
)
if
(
!
(
portstatus
&
USB_PORT_STAT_ENABLE
)
&&
(
portstatus
&
USB_PORT_STAT_CONNECTION
)
&&
!
connect_change
&&
(
hdev
->
children
[
i
])
)
{
&&
hdev
->
children
[
i
]
)
{
dev_err
(
hub_dev
,
dev_err
(
hub_dev
,
"port %i "
"port %i "
"disabled by hub (EMI?), "
"disabled by hub (EMI?), "
"re-enabling..."
,
"re-enabling..."
,
i
+
1
);
i
+
1
);
hub_port_connect_change
(
hub
,
connect_change
=
1
;
i
,
portstatus
,
portchange
);
}
}
}
}
...
@@ -1517,6 +1751,10 @@ static void hub_events(void)
...
@@ -1517,6 +1751,10 @@ static void hub_events(void)
clear_port_feature
(
hdev
,
clear_port_feature
(
hdev
,
i
+
1
,
USB_PORT_FEAT_C_RESET
);
i
+
1
,
USB_PORT_FEAT_C_RESET
);
}
}
if
(
connect_change
)
hub_port_connect_change
(
hub
,
i
,
portstatus
,
portchange
);
}
/* end for i */
}
/* end for i */
/* deal with hub status changes */
/* deal with hub status changes */
...
@@ -1581,9 +1819,6 @@ static struct usb_driver hub_driver = {
...
@@ -1581,9 +1819,6 @@ static struct usb_driver hub_driver = {
.
id_table
=
hub_id_table
,
.
id_table
=
hub_id_table
,
};
};
/*
* This should be a separate module.
*/
int
usb_hub_init
(
void
)
int
usb_hub_init
(
void
)
{
{
pid_t
pid
;
pid_t
pid
;
...
...
drivers/usb/core/hub.h
View file @
fcc95bca
...
@@ -202,7 +202,6 @@ struct usb_hub {
...
@@ -202,7 +202,6 @@ struct usb_hub {
int
error
;
/* last reported error */
int
error
;
/* last reported error */
int
nerrors
;
/* track consecutive errors */
int
nerrors
;
/* track consecutive errors */
struct
list_head
hub_list
;
/* all hubs */
struct
list_head
event_list
;
/* hubs w/data or errs ready */
struct
list_head
event_list
;
/* hubs w/data or errs ready */
struct
usb_hub_descriptor
*
descriptor
;
/* class descriptor */
struct
usb_hub_descriptor
*
descriptor
;
/* class descriptor */
...
...
drivers/usb/core/message.c
View file @
fcc95bca
...
@@ -566,7 +566,7 @@ void usb_sg_cancel (struct usb_sg_request *io)
...
@@ -566,7 +566,7 @@ void usb_sg_cancel (struct usb_sg_request *io)
*/
*/
int
usb_get_descriptor
(
struct
usb_device
*
dev
,
unsigned
char
type
,
unsigned
char
index
,
void
*
buf
,
int
size
)
int
usb_get_descriptor
(
struct
usb_device
*
dev
,
unsigned
char
type
,
unsigned
char
index
,
void
*
buf
,
int
size
)
{
{
int
i
=
5
;
int
i
=
3
;
int
result
;
int
result
;
memset
(
buf
,
0
,
size
);
// Make sure we parse really received data
memset
(
buf
,
0
,
size
);
// Make sure we parse really received data
...
@@ -579,9 +579,6 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
...
@@ -579,9 +579,6 @@ int usb_get_descriptor(struct usb_device *dev, unsigned char type, unsigned char
HZ
*
USB_CTRL_GET_TIMEOUT
))
>
0
HZ
*
USB_CTRL_GET_TIMEOUT
))
>
0
||
result
!=
-
EPIPE
)
||
result
!=
-
EPIPE
)
break
;
break
;
dev_dbg
(
&
dev
->
dev
,
"RETRY descriptor, result %d
\n
"
,
result
);
result
=
-
ENOMSG
;
}
}
return
result
;
return
result
;
}
}
...
...
drivers/usb/core/usb.c
View file @
fcc95bca
...
@@ -944,235 +944,6 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
...
@@ -944,235 +944,6 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
return
-
1
;
return
-
1
;
}
}
/**
* usb_disconnect - disconnect a device (usbcore-internal)
* @pdev: pointer to device being disconnected
* Context: !in_interrupt ()
*
* Something got disconnected. Get rid of it, and all of its children.
*
* Only hub drivers (including virtual root hub drivers for host
* controllers) should ever call this.
*
* This call is synchronous, and may not be used in an interrupt context.
*/
void
usb_disconnect
(
struct
usb_device
**
pdev
)
{
struct
usb_device
*
dev
=
*
pdev
;
struct
usb_bus
*
bus
;
struct
usb_operations
*
ops
;
int
i
;
might_sleep
();
if
(
!
dev
)
{
pr_debug
(
"%s nodev
\n
"
,
__FUNCTION__
);
return
;
}
bus
=
dev
->
bus
;
if
(
!
bus
)
{
pr_debug
(
"%s nobus
\n
"
,
__FUNCTION__
);
return
;
}
ops
=
bus
->
op
;
*
pdev
=
NULL
;
/* mark the device as inactive, so any further urb submissions for
* this device will fail.
*/
dev
->
state
=
USB_STATE_NOTATTACHED
;
down
(
&
dev
->
serialize
);
dev_info
(
&
dev
->
dev
,
"USB disconnect, address %d
\n
"
,
dev
->
devnum
);
/* Free up all the children before we remove this device */
for
(
i
=
0
;
i
<
USB_MAXCHILDREN
;
i
++
)
{
struct
usb_device
**
child
=
dev
->
children
+
i
;
if
(
*
child
)
usb_disconnect
(
child
);
}
/* deallocate hcd/hardware state ... nuking all pending urbs and
* cleaning up all state associated with the current configuration
*/
usb_disable_device
(
dev
,
0
);
/* Free the device number and remove the /proc/bus/usb entry */
dev_dbg
(
&
dev
->
dev
,
"unregistering device
\n
"
);
usb_release_address
(
dev
);
usbfs_remove_device
(
dev
);
up
(
&
dev
->
serialize
);
device_unregister
(
&
dev
->
dev
);
}
/**
* usb_choose_address - pick device address (usbcore-internal)
* @dev: newly detected device (in DEFAULT state)
*
* Picks a device address. It's up to the hub (or root hub) driver
* to handle and manage enumeration, starting from the DEFAULT state.
* Only hub drivers (but not virtual root hub drivers for host
* controllers) should ever call this.
*/
void
usb_choose_address
(
struct
usb_device
*
dev
)
{
int
devnum
;
// FIXME needs locking for SMP!!
/* why? this is called only from the hub thread,
* which hopefully doesn't run on multiple CPU's simultaneously 8-)
*/
/* Try to allocate the next devnum beginning at bus->devnum_next. */
devnum
=
find_next_zero_bit
(
dev
->
bus
->
devmap
.
devicemap
,
128
,
dev
->
bus
->
devnum_next
);
if
(
devnum
>=
128
)
devnum
=
find_next_zero_bit
(
dev
->
bus
->
devmap
.
devicemap
,
128
,
1
);
dev
->
bus
->
devnum_next
=
(
devnum
>=
127
?
1
:
devnum
+
1
);
if
(
devnum
<
128
)
{
set_bit
(
devnum
,
dev
->
bus
->
devmap
.
devicemap
);
dev
->
devnum
=
devnum
;
}
}
/**
* usb_release_address - deallocate device address (usbcore-internal)
* @dev: newly removed device
*
* Removes and deallocates the address assigned to a device.
* Only hub drivers (but not virtual root hub drivers for host
* controllers) should ever call this.
*/
void
usb_release_address
(
struct
usb_device
*
dev
)
{
if
(
dev
->
devnum
>
0
)
{
clear_bit
(
dev
->
devnum
,
dev
->
bus
->
devmap
.
devicemap
);
dev
->
devnum
=
-
1
;
}
}
static
inline
void
usb_show_string
(
struct
usb_device
*
dev
,
char
*
id
,
int
index
)
{
char
*
buf
;
if
(
!
index
)
return
;
if
(
!
(
buf
=
kmalloc
(
256
,
GFP_KERNEL
)))
return
;
if
(
usb_string
(
dev
,
index
,
buf
,
256
)
>
0
)
dev_printk
(
KERN_INFO
,
&
dev
->
dev
,
"%s: %s
\n
"
,
id
,
buf
);
kfree
(
buf
);
}
static
int
usb_choose_configuration
(
struct
usb_device
*
dev
)
{
int
c
,
i
;
c
=
dev
->
config
[
0
].
desc
.
bConfigurationValue
;
if
(
dev
->
descriptor
.
bNumConfigurations
!=
1
)
{
for
(
i
=
0
;
i
<
dev
->
descriptor
.
bNumConfigurations
;
i
++
)
{
struct
usb_interface_descriptor
*
desc
;
/* heuristic: Linux is more likely to have class
* drivers, so avoid vendor-specific interfaces.
*/
desc
=
&
dev
->
config
[
i
].
intf_cache
[
0
]
->
altsetting
->
desc
;
if
(
desc
->
bInterfaceClass
==
USB_CLASS_VENDOR_SPEC
)
continue
;
/* COMM/2/all is CDC ACM, except 0xff is MSFT RNDIS */
if
(
desc
->
bInterfaceClass
==
USB_CLASS_COMM
&&
desc
->
bInterfaceSubClass
==
2
&&
desc
->
bInterfaceProtocol
==
0xff
)
continue
;
c
=
dev
->
config
[
i
].
desc
.
bConfigurationValue
;
break
;
}
dev_info
(
&
dev
->
dev
,
"configuration #%d chosen from %d choices
\n
"
,
c
,
dev
->
descriptor
.
bNumConfigurations
);
}
return
c
;
}
/*
* usb_new_device - perform initial device setup (usbcore-internal)
* @dev: newly addressed device (in ADDRESS state)
*
* This is called with devices which have been enumerated, but not yet
* configured. The device descriptor is available, but not descriptors
* for any device configuration. The caller owns dev->serialize, and
* the device is not visible through sysfs or other filesystem code.
*
* Returns 0 for success (device is configured and listed, with its
* interfaces, in sysfs); else a negative errno value. On error, one
* reference count to the device has been dropped.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Only the hub driver should ever call this; root hub registration
* uses it only indirectly.
*/
int
usb_new_device
(
struct
usb_device
*
dev
)
{
int
err
;
int
c
;
err
=
usb_get_configuration
(
dev
);
if
(
err
<
0
)
{
dev_err
(
&
dev
->
dev
,
"can't read configurations, error %d
\n
"
,
err
);
goto
fail
;
}
/* Tell the world! */
dev_dbg
(
&
dev
->
dev
,
"new device strings: Mfr=%d, Product=%d, SerialNumber=%d
\n
"
,
dev
->
descriptor
.
iManufacturer
,
dev
->
descriptor
.
iProduct
,
dev
->
descriptor
.
iSerialNumber
);
#ifdef DEBUG
if
(
dev
->
descriptor
.
iProduct
)
usb_show_string
(
dev
,
"Product"
,
dev
->
descriptor
.
iProduct
);
if
(
dev
->
descriptor
.
iManufacturer
)
usb_show_string
(
dev
,
"Manufacturer"
,
dev
->
descriptor
.
iManufacturer
);
if
(
dev
->
descriptor
.
iSerialNumber
)
usb_show_string
(
dev
,
"SerialNumber"
,
dev
->
descriptor
.
iSerialNumber
);
#endif
/* put device-specific files into sysfs */
err
=
device_add
(
&
dev
->
dev
);
if
(
err
)
{
dev_err
(
&
dev
->
dev
,
"can't device_add, error %d
\n
"
,
err
);
goto
fail
;
}
usb_create_sysfs_dev_files
(
dev
);
/* choose and set the configuration. that registers the interfaces
* with the driver core, and lets usb device drivers bind to them.
* NOTE: should interact with hub power budgeting.
*/
c
=
usb_choose_configuration
(
dev
);
err
=
usb_set_configuration
(
dev
,
c
);
if
(
err
)
{
dev_err
(
&
dev
->
dev
,
"can't set config #%d, error %d
\n
"
,
c
,
err
);
device_del
(
&
dev
->
dev
);
goto
fail
;
}
/* USB device state == configured ... usable */
/* add a /proc/bus/usb entry */
usbfs_add_device
(
dev
);
return
0
;
fail:
dev
->
state
=
USB_STATE_NOTATTACHED
;
usb_release_address
(
dev
);
usb_put_dev
(
dev
);
return
err
;
}
/**
/**
* usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP
* usb_buffer_alloc - allocate dma-consistent buffer for URB_NO_xxx_DMA_MAP
* @dev: device the buffer will be used with
* @dev: device the buffer will be used with
...
...
drivers/usb/gadget/dummy_hcd.c
View file @
fcc95bca
...
@@ -825,8 +825,7 @@ static int dummy_urb_enqueue (
...
@@ -825,8 +825,7 @@ static int dummy_urb_enqueue (
dum
=
container_of
(
hcd
,
struct
dummy
,
hcd
);
dum
=
container_of
(
hcd
,
struct
dummy
,
hcd
);
spin_lock_irqsave
(
&
dum
->
lock
,
flags
);
spin_lock_irqsave
(
&
dum
->
lock
,
flags
);
if
(
!
dum
->
hdev
)
dum
->
hdev
=
urb
->
dev
->
hcpriv
;
dum
->
hdev
=
urb
->
dev
->
hcpriv
;
urb
->
hcpriv
=
dum
;
urb
->
hcpriv
=
dum
;
if
(
usb_pipetype
(
urb
->
pipe
)
==
PIPE_CONTROL
)
if
(
usb_pipetype
(
urb
->
pipe
)
==
PIPE_CONTROL
)
urb
->
error_count
=
1
;
/* mark as a new urb */
urb
->
error_count
=
1
;
/* mark as a new urb */
...
@@ -994,10 +993,17 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
...
@@ -994,10 +993,17 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep)
return
limit
;
return
limit
;
}
}
#define is_active(dum) ((dum->port_status & \
(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE | \
USB_PORT_STAT_SUSPEND)) \
== (USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE))
static
struct
dummy_ep
*
find_endpoint
(
struct
dummy
*
dum
,
u8
address
)
static
struct
dummy_ep
*
find_endpoint
(
struct
dummy
*
dum
,
u8
address
)
{
{
int
i
;
int
i
;
if
(
!
is_active
(
dum
))
return
NULL
;
if
((
address
&
~
USB_DIR_IN
)
==
0
)
if
((
address
&
~
USB_DIR_IN
)
==
0
)
return
&
dum
->
ep
[
0
];
return
&
dum
->
ep
[
0
];
for
(
i
=
1
;
i
<
DUMMY_ENDPOINTS
;
i
++
)
{
for
(
i
=
1
;
i
<
DUMMY_ENDPOINTS
;
i
++
)
{
...
@@ -1011,6 +1017,8 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
...
@@ -1011,6 +1017,8 @@ static struct dummy_ep *find_endpoint (struct dummy *dum, u8 address)
return
NULL
;
return
NULL
;
}
}
#undef is_active
#define Dev_Request (USB_TYPE_STANDARD | USB_RECIP_DEVICE)
#define Dev_Request (USB_TYPE_STANDARD | USB_RECIP_DEVICE)
#define Dev_InRequest (Dev_Request | USB_DIR_IN)
#define Dev_InRequest (Dev_Request | USB_DIR_IN)
#define Intf_Request (USB_TYPE_STANDARD | USB_RECIP_INTERFACE)
#define Intf_Request (USB_TYPE_STANDARD | USB_RECIP_INTERFACE)
...
@@ -1404,9 +1412,8 @@ static int dummy_hub_control (
...
@@ -1404,9 +1412,8 @@ static int dummy_hub_control (
break
;
break
;
case
USB_PORT_FEAT_POWER
:
case
USB_PORT_FEAT_POWER
:
dum
->
port_status
=
0
;
dum
->
port_status
=
0
;
dum
->
address
=
0
;
dum
->
hdev
=
0
;
dum
->
resuming
=
0
;
dum
->
resuming
=
0
;
stop_activity
(
dum
,
dum
->
driver
);
break
;
break
;
default:
default:
dum
->
port_status
&=
~
(
1
<<
wValue
);
dum
->
port_status
&=
~
(
1
<<
wValue
);
...
...
drivers/usb/gadget/ether.c
View file @
fcc95bca
...
@@ -2302,17 +2302,6 @@ eth_bind (struct usb_gadget *gadget)
...
@@ -2302,17 +2302,6 @@ eth_bind (struct usb_gadget *gadget)
UTS_SYSNAME
" "
UTS_RELEASE
"/%s"
,
UTS_SYSNAME
" "
UTS_RELEASE
"/%s"
,
gadget
->
name
);
gadget
->
name
);
/* CDC subset ... recognized by Linux since 2.4.10, but Windows
* drivers aren't widely available.
*/
if
(
!
cdc
)
{
device_desc
.
bDeviceClass
=
USB_CLASS_VENDOR_SPEC
;
device_desc
.
idVendor
=
__constant_cpu_to_le16
(
SIMPLE_VENDOR_NUM
);
device_desc
.
idProduct
=
__constant_cpu_to_le16
(
SIMPLE_PRODUCT_NUM
);
}
/* If there's an RNDIS configuration, that's what Windows wants to
/* If there's an RNDIS configuration, that's what Windows wants to
* be using ... so use these product IDs here and in the "linux.inf"
* be using ... so use these product IDs here and in the "linux.inf"
* needed to install MSFT drivers. Current Linux kernels will use
* needed to install MSFT drivers. Current Linux kernels will use
...
@@ -2326,6 +2315,16 @@ eth_bind (struct usb_gadget *gadget)
...
@@ -2326,6 +2315,16 @@ eth_bind (struct usb_gadget *gadget)
__constant_cpu_to_le16
(
RNDIS_PRODUCT_NUM
);
__constant_cpu_to_le16
(
RNDIS_PRODUCT_NUM
);
snprintf
(
product_desc
,
sizeof
product_desc
,
snprintf
(
product_desc
,
sizeof
product_desc
,
"RNDIS/%s"
,
driver_desc
);
"RNDIS/%s"
,
driver_desc
);
/* CDC subset ... recognized by Linux since 2.4.10, but Windows
* drivers aren't widely available.
*/
}
else
if
(
!
cdc
)
{
device_desc
.
bDeviceClass
=
USB_CLASS_VENDOR_SPEC
;
device_desc
.
idVendor
=
__constant_cpu_to_le16
(
SIMPLE_VENDOR_NUM
);
device_desc
.
idProduct
=
__constant_cpu_to_le16
(
SIMPLE_PRODUCT_NUM
);
}
}
/* support optional vendor/distro customization */
/* support optional vendor/distro customization */
...
...
drivers/usb/host/uhci-hcd.c
View file @
fcc95bca
...
@@ -103,8 +103,8 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
...
@@ -103,8 +103,8 @@ static void uhci_free_pending_tds(struct uhci_hcd *uhci);
static
void
hc_state_transitions
(
struct
uhci_hcd
*
uhci
);
static
void
hc_state_transitions
(
struct
uhci_hcd
*
uhci
);
/* If a transfer is still active after this much time, turn off FSBR */
/* If a transfer is still active after this much time, turn off FSBR */
#define IDLE_TIMEOUT
(HZ / 20)
/* 50 ms */
#define IDLE_TIMEOUT
msecs_to_jiffies(50)
#define FSBR_DELAY
(HZ / 20)
/* 50 ms */
#define FSBR_DELAY
msecs_to_jiffies(50)
/* When we timeout an idle transfer for FSBR, we'll switch it over to */
/* When we timeout an idle transfer for FSBR, we'll switch it over to */
/* depth first traversal. We'll do it in groups of this number of TD's */
/* depth first traversal. We'll do it in groups of this number of TD's */
...
@@ -1611,6 +1611,7 @@ static void stall_callback(unsigned long ptr)
...
@@ -1611,6 +1611,7 @@ static void stall_callback(unsigned long ptr)
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
struct
list_head
list
,
*
tmp
,
*
head
;
struct
list_head
list
,
*
tmp
,
*
head
;
unsigned
long
flags
;
unsigned
long
flags
;
int
called_uhci_finish_completion
=
0
;
INIT_LIST_HEAD
(
&
list
);
INIT_LIST_HEAD
(
&
list
);
...
@@ -1619,6 +1620,7 @@ static void stall_callback(unsigned long ptr)
...
@@ -1619,6 +1620,7 @@ static void stall_callback(unsigned long ptr)
uhci_get_current_frame_number
(
uhci
)
!=
uhci
->
urb_remove_age
)
{
uhci_get_current_frame_number
(
uhci
)
!=
uhci
->
urb_remove_age
)
{
uhci_remove_pending_urbps
(
uhci
);
uhci_remove_pending_urbps
(
uhci
);
uhci_finish_completion
(
hcd
,
NULL
);
uhci_finish_completion
(
hcd
,
NULL
);
called_uhci_finish_completion
=
1
;
}
}
head
=
&
uhci
->
urb_list
;
head
=
&
uhci
->
urb_list
;
...
@@ -1646,6 +1648,10 @@ static void stall_callback(unsigned long ptr)
...
@@ -1646,6 +1648,10 @@ static void stall_callback(unsigned long ptr)
}
}
spin_unlock_irqrestore
(
&
uhci
->
schedule_lock
,
flags
);
spin_unlock_irqrestore
(
&
uhci
->
schedule_lock
,
flags
);
/* Wake up anyone waiting for an URB to complete */
if
(
called_uhci_finish_completion
)
wake_up_all
(
&
uhci
->
waitqh
);
head
=
&
list
;
head
=
&
list
;
tmp
=
head
->
next
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
while
(
tmp
!=
head
)
{
...
@@ -1676,7 +1682,7 @@ static int init_stall_timer(struct usb_hcd *hcd)
...
@@ -1676,7 +1682,7 @@ static int init_stall_timer(struct usb_hcd *hcd)
init_timer
(
&
uhci
->
stall_timer
);
init_timer
(
&
uhci
->
stall_timer
);
uhci
->
stall_timer
.
function
=
stall_callback
;
uhci
->
stall_timer
.
function
=
stall_callback
;
uhci
->
stall_timer
.
data
=
(
unsigned
long
)
hcd
;
uhci
->
stall_timer
.
data
=
(
unsigned
long
)
hcd
;
uhci
->
stall_timer
.
expires
=
jiffies
+
(
HZ
/
1
0
);
uhci
->
stall_timer
.
expires
=
jiffies
+
msecs_to_jiffies
(
10
0
);
add_timer
(
&
uhci
->
stall_timer
);
add_timer
(
&
uhci
->
stall_timer
);
return
0
;
return
0
;
...
@@ -1831,16 +1837,20 @@ static void reset_hc(struct uhci_hcd *uhci)
...
@@ -1831,16 +1837,20 @@ static void reset_hc(struct uhci_hcd *uhci)
{
{
unsigned
int
io_addr
=
uhci
->
io_addr
;
unsigned
int
io_addr
=
uhci
->
io_addr
;
/* Turn off PIRQ, SMI, and all interrupts. This also turns off
* the BIOS's USB Legacy Support.
*/
pci_write_config_word
(
to_pci_dev
(
uhci_dev
(
uhci
)),
USBLEGSUP
,
0
);
outw
(
0
,
uhci
->
io_addr
+
USBINTR
);
/* Global reset for 50ms */
/* Global reset for 50ms */
uhci
->
state
=
UHCI_RESET
;
uhci
->
state
=
UHCI_RESET
;
outw
(
USBCMD_GRESET
,
io_addr
+
USBCMD
);
outw
(
USBCMD_GRESET
,
io_addr
+
USBCMD
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
msleep
(
50
);
schedule_timeout
((
HZ
*
50
+
999
)
/
1000
);
outw
(
0
,
io_addr
+
USBCMD
);
outw
(
0
,
io_addr
+
USBCMD
);
/* Another 10ms delay */
/* Another 10ms delay */
set_current_state
(
TASK_UNINTERRUPTIBLE
);
msleep
(
10
);
schedule_timeout
((
HZ
*
10
+
999
)
/
1000
);
uhci
->
resume_detect
=
0
;
uhci
->
resume_detect
=
0
;
}
}
...
@@ -1865,7 +1875,7 @@ static void wakeup_hc(struct uhci_hcd *uhci)
...
@@ -1865,7 +1875,7 @@ static void wakeup_hc(struct uhci_hcd *uhci)
/* Global resume for >= 20ms */
/* Global resume for >= 20ms */
outw
(
USBCMD_FGR
|
USBCMD_EGSM
,
io_addr
+
USBCMD
);
outw
(
USBCMD_FGR
|
USBCMD_EGSM
,
io_addr
+
USBCMD
);
uhci
->
state
=
UHCI_RESUMING_1
;
uhci
->
state
=
UHCI_RESUMING_1
;
uhci
->
state_end
=
jiffies
+
(
20
*
HZ
+
999
)
/
1000
;
uhci
->
state_end
=
jiffies
+
msecs_to_jiffies
(
20
)
;
break
;
break
;
case
UHCI_RESUMING_1
:
/* End global resume */
case
UHCI_RESUMING_1
:
/* End global resume */
...
@@ -1990,7 +2000,9 @@ static void start_hc(struct uhci_hcd *uhci)
...
@@ -1990,7 +2000,9 @@ static void start_hc(struct uhci_hcd *uhci)
}
}
}
}
/* Turn on all interrupts */
/* Turn on PIRQ and all interrupts */
pci_write_config_word
(
to_pci_dev
(
uhci_dev
(
uhci
)),
USBLEGSUP
,
USBLEGSUP_DEFAULT
);
outw
(
USBINTR_TIMEOUT
|
USBINTR_RESUME
|
USBINTR_IOC
|
USBINTR_SP
,
outw
(
USBINTR_TIMEOUT
|
USBINTR_RESUME
|
USBINTR_IOC
|
USBINTR_SP
,
io_addr
+
USBINTR
);
io_addr
+
USBINTR
);
...
@@ -2054,15 +2066,10 @@ static int uhci_reset(struct usb_hcd *hcd)
...
@@ -2054,15 +2066,10 @@ static int uhci_reset(struct usb_hcd *hcd)
uhci
->
io_addr
=
(
unsigned
long
)
hcd
->
regs
;
uhci
->
io_addr
=
(
unsigned
long
)
hcd
->
regs
;
/* Turn off all interrupts */
/* Kick BIOS off this hardware and reset, so we won't get
outw
(
0
,
uhci
->
io_addr
+
USBINTR
);
/* Maybe kick BIOS off this hardware. Then reset, so we won't get
* interrupts from any previous setup.
* interrupts from any previous setup.
*/
*/
reset_hc
(
uhci
);
reset_hc
(
uhci
);
pci_write_config_word
(
to_pci_dev
(
uhci_dev
(
uhci
)),
USBLEGSUP
,
USBLEGSUP_DEFAULT
);
return
0
;
return
0
;
}
}
...
@@ -2369,14 +2376,18 @@ static int uhci_resume(struct usb_hcd *hcd)
...
@@ -2369,14 +2376,18 @@ static int uhci_resume(struct usb_hcd *hcd)
/*
/*
* Some systems don't maintain the UHCI register values
* Some systems don't maintain the UHCI register values
* during a PM suspend/resume cycle, so reinitialize
* during a PM suspend/resume cycle, so reinitialize
* the Frame Number,
the Framelist Base Address, and the
* the Frame Number,
Framelist Base Address, Interrupt
*
Interrupt Enable
registers.
*
Enable, and Legacy Support
registers.
*/
*/
pci_write_config_word
(
to_pci_dev
(
uhci_dev
(
uhci
)),
USBLEGSUP
,
0
);
outw
(
uhci
->
saved_framenumber
,
uhci
->
io_addr
+
USBFRNUM
);
outw
(
uhci
->
saved_framenumber
,
uhci
->
io_addr
+
USBFRNUM
);
outl
(
uhci
->
fl
->
dma_handle
,
uhci
->
io_addr
+
USBFLBASEADD
);
outl
(
uhci
->
fl
->
dma_handle
,
uhci
->
io_addr
+
USBFLBASEADD
);
outw
(
USBINTR_TIMEOUT
|
USBINTR_RESUME
|
USBINTR_IOC
|
outw
(
USBINTR_TIMEOUT
|
USBINTR_RESUME
|
USBINTR_IOC
|
USBINTR_SP
,
uhci
->
io_addr
+
USBINTR
);
USBINTR_SP
,
uhci
->
io_addr
+
USBINTR
);
uhci
->
resume_detect
=
1
;
uhci
->
resume_detect
=
1
;
pci_write_config_word
(
to_pci_dev
(
uhci_dev
(
uhci
)),
USBLEGSUP
,
USBLEGSUP_DEFAULT
);
}
else
{
}
else
{
reset_hc
(
uhci
);
reset_hc
(
uhci
);
start_hc
(
uhci
);
start_hc
(
uhci
);
...
...
drivers/usb/net/pegasus.h
View file @
fcc95bca
...
@@ -121,6 +121,7 @@ struct usb_eth_dev {
...
@@ -121,6 +121,7 @@ struct usb_eth_dev {
#define VENDOR_ADMTEK 0x07a6
#define VENDOR_ADMTEK 0x07a6
#define VENDOR_AEILAB 0x3334
#define VENDOR_AEILAB 0x3334
#define VENDOR_ALLIEDTEL 0x07c9
#define VENDOR_ALLIEDTEL 0x07c9
#define VENDOR_ATEN 0x0557
#define VENDOR_BELKIN 0x050d
#define VENDOR_BELKIN 0x050d
#define VENDOR_BILLIONTON 0x08dd
#define VENDOR_BILLIONTON 0x08dd
#define VENDOR_COMPAQ 0x049f
#define VENDOR_COMPAQ 0x049f
...
@@ -150,6 +151,8 @@ struct usb_eth_dev {
...
@@ -150,6 +151,8 @@ struct usb_eth_dev {
PEGASUS_DEV
(
"3Com USB Ethernet 3C460B"
,
VENDOR_3COM
,
0x4601
,
PEGASUS_DEV
(
"3Com USB Ethernet 3C460B"
,
VENDOR_3COM
,
0x4601
,
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
PEGASUS_DEV
(
"ATEN USB Ethernet UC-110T"
,
VENDOR_ATEN
,
0x2007
,
DEFAULT_GPIO_RESET
|
PEGASUS_II
)
PEGASUS_DEV
(
"USB HPNA/Ethernet"
,
VENDOR_ABOCOM
,
0x110c
,
PEGASUS_DEV
(
"USB HPNA/Ethernet"
,
VENDOR_ABOCOM
,
0x110c
,
DEFAULT_GPIO_RESET
|
PEGASUS_II
|
HAS_HOME_PNA
)
DEFAULT_GPIO_RESET
|
PEGASUS_II
|
HAS_HOME_PNA
)
PEGASUS_DEV
(
"USB HPNA/Ethernet"
,
VENDOR_ABOCOM
,
0x4104
,
PEGASUS_DEV
(
"USB HPNA/Ethernet"
,
VENDOR_ABOCOM
,
0x4104
,
...
...
drivers/usb/serial/bus.c
View file @
fcc95bca
...
@@ -78,8 +78,8 @@ static int usb_serial_device_probe (struct device *dev)
...
@@ -78,8 +78,8 @@ static int usb_serial_device_probe (struct device *dev)
minor
=
port
->
number
;
minor
=
port
->
number
;
tty_register_device
(
usb_serial_tty_driver
,
minor
,
dev
);
tty_register_device
(
usb_serial_tty_driver
,
minor
,
dev
);
dev_info
(
&
port
->
serial
->
dev
->
dev
,
dev_info
(
&
port
->
serial
->
dev
->
dev
,
"%s converter now attached to ttyUSB%d
(or usb/tts/%d for devfs)
\n
"
,
"%s converter now attached to ttyUSB%d
\n
"
,
driver
->
name
,
minor
,
minor
);
driver
->
name
,
minor
);
exit:
exit:
return
retval
;
return
retval
;
...
...
drivers/usb/serial/ftdi_sio.c
View file @
fcc95bca
...
@@ -1504,6 +1504,7 @@ static int ftdi_write (struct usb_serial_port *port, int from_user,
...
@@ -1504,6 +1504,7 @@ static int ftdi_write (struct usb_serial_port *port, int from_user,
if
(
status
)
{
if
(
status
)
{
err
(
"%s - failed submitting write urb, error %d"
,
__FUNCTION__
,
status
);
err
(
"%s - failed submitting write urb, error %d"
,
__FUNCTION__
,
status
);
count
=
status
;
count
=
status
;
kfree
(
buffer
);
}
}
/* we are done with this urb, so let the host driver
/* we are done with this urb, so let the host driver
...
...
drivers/usb/serial/visor.c
View file @
fcc95bca
...
@@ -247,6 +247,8 @@ static struct usb_device_id id_table [] = {
...
@@ -247,6 +247,8 @@ static struct usb_device_id id_table [] = {
.
driver_info
=
(
kernel_ulong_t
)
&
palm_os_4_probe
},
.
driver_info
=
(
kernel_ulong_t
)
&
palm_os_4_probe
},
{
USB_DEVICE
(
ACEECA_VENDOR_ID
,
ACEECA_MEZ1000_ID
),
{
USB_DEVICE
(
ACEECA_VENDOR_ID
,
ACEECA_MEZ1000_ID
),
.
driver_info
=
(
kernel_ulong_t
)
&
palm_os_4_probe
},
.
driver_info
=
(
kernel_ulong_t
)
&
palm_os_4_probe
},
{
USB_DEVICE
(
KYOCERA_VENDOR_ID
,
KYOCERA_7135_ID
),
.
driver_info
=
(
kernel_ulong_t
)
&
palm_os_4_probe
},
{
},
/* optional parameter entry */
{
},
/* optional parameter entry */
{
}
/* Terminating entry */
{
}
/* Terminating entry */
};
};
...
@@ -290,6 +292,7 @@ static struct usb_device_id id_table_combined [] = {
...
@@ -290,6 +292,7 @@ static struct usb_device_id id_table_combined [] = {
{
USB_DEVICE
(
SAMSUNG_VENDOR_ID
,
SAMSUNG_SPH_I500_ID
)
},
{
USB_DEVICE
(
SAMSUNG_VENDOR_ID
,
SAMSUNG_SPH_I500_ID
)
},
{
USB_DEVICE
(
GARMIN_VENDOR_ID
,
GARMIN_IQUE_3600_ID
)
},
{
USB_DEVICE
(
GARMIN_VENDOR_ID
,
GARMIN_IQUE_3600_ID
)
},
{
USB_DEVICE
(
ACEECA_VENDOR_ID
,
ACEECA_MEZ1000_ID
)
},
{
USB_DEVICE
(
ACEECA_VENDOR_ID
,
ACEECA_MEZ1000_ID
)
},
{
USB_DEVICE
(
KYOCERA_VENDOR_ID
,
KYOCERA_7135_ID
)
},
{
},
/* optional parameter entry */
{
},
/* optional parameter entry */
{
}
/* Terminating entry */
{
}
/* Terminating entry */
};
};
...
@@ -515,6 +518,7 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
...
@@ -515,6 +518,7 @@ static int visor_write (struct usb_serial_port *port, int from_user, const unsig
dev_err
(
&
port
->
dev
,
"%s - usb_submit_urb(write bulk) failed with status = %d
\n
"
,
dev_err
(
&
port
->
dev
,
"%s - usb_submit_urb(write bulk) failed with status = %d
\n
"
,
__FUNCTION__
,
status
);
__FUNCTION__
,
status
);
count
=
status
;
count
=
status
;
kfree
(
buffer
);
}
else
{
}
else
{
bytes_out
+=
count
;
bytes_out
+=
count
;
}
}
...
@@ -795,7 +799,7 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
...
@@ -795,7 +799,7 @@ static int palm_os_4_probe (struct usb_serial *serial, const struct usb_device_i
dev_err
(
dev
,
"%s - error %d getting connection info
\n
"
,
dev_err
(
dev
,
"%s - error %d getting connection info
\n
"
,
__FUNCTION__
,
retval
);
__FUNCTION__
,
retval
);
else
else
usb_serial_debug_data
(
__FILE__
,
__FUNCTION__
,
0x14
,
transfer_buffer
);
usb_serial_debug_data
(
__FILE__
,
__FUNCTION__
,
retval
,
transfer_buffer
);
kfree
(
transfer_buffer
);
kfree
(
transfer_buffer
);
return
0
;
return
0
;
...
@@ -881,18 +885,19 @@ static int treo_attach (struct usb_serial *serial)
...
@@ -881,18 +885,19 @@ static int treo_attach (struct usb_serial *serial)
/* Only do this endpoint hack for the Handspring devices with
/* Only do this endpoint hack for the Handspring devices with
* interrupt in endpoints, which for now are the Treo devices. */
* interrupt in endpoints, which for now are the Treo devices. */
if
((
serial
->
dev
->
descriptor
.
idVendor
!=
HANDSPRING_VENDOR_ID
)
||
if
(
!
((
serial
->
dev
->
descriptor
.
idVendor
==
HANDSPRING_VENDOR_ID
)
||
(
serial
->
dev
->
descriptor
.
idVendor
==
KYOCERA_VENDOR_ID
))
||
(
serial
->
num_interrupt_in
==
0
))
(
serial
->
num_interrupt_in
==
0
))
return
0
;
return
0
;
dbg
(
"%s"
,
__FUNCTION__
);
dbg
(
"%s"
,
__FUNCTION__
);
/*
/*
* It appears that Treos
want to use the 1st interrupt endpoint to
* It appears that Treos
and Kyoceras want to use the
*
communicate with the 2nd bulk out endpoint, so let's swap the 1st
*
1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
*
and 2nd bulk in and interrupt endpoints. Note that swapping the
*
so let's swap the 1st and 2nd bulk in and interrupt endpoints.
*
bulk out endpoints would break lots of apps that want to communicate
*
Note that swapping the bulk out endpoints would break lots of
* on the second port.
*
apps that want to communicate
on the second port.
*/
*/
#define COPY_PORT(dest, src) \
#define COPY_PORT(dest, src) \
dest->read_urb = src->read_urb; \
dest->read_urb = src->read_urb; \
...
...
drivers/usb/serial/visor.h
View file @
fcc95bca
...
@@ -55,6 +55,9 @@
...
@@ -55,6 +55,9 @@
#define ACEECA_VENDOR_ID 0x4766
#define ACEECA_VENDOR_ID 0x4766
#define ACEECA_MEZ1000_ID 0x0001
#define ACEECA_MEZ1000_ID 0x0001
#define KYOCERA_VENDOR_ID 0x0C88
#define KYOCERA_7135_ID 0x0021
/****************************************************************************
/****************************************************************************
* Handspring Visor Vendor specific request codes (bRequest values)
* Handspring Visor Vendor specific request codes (bRequest values)
* A big thank you to Handspring for providing the following information.
* A big thank you to Handspring for providing the following information.
...
...
drivers/usb/storage/unusual_devs.h
View file @
fcc95bca
...
@@ -359,13 +359,19 @@ UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999,
...
@@ -359,13 +359,19 @@ UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999,
UNUSUAL_DEV
(
0x0595
,
0x4343
,
0x0000
,
0x2210
,
UNUSUAL_DEV
(
0x0595
,
0x4343
,
0x0000
,
0x2210
,
"Fujifilm"
,
"Fujifilm"
,
"Digital Camera EX-20 DSC"
,
"Digital Camera EX-20 DSC"
,
US_SC_8070
,
US_PR_
CBI
,
NULL
,
0
),
US_SC_8070
,
US_PR_
DEVICE
,
NULL
,
0
),
UNUSUAL_DEV
(
0x059f
,
0xa601
,
0x0200
,
0x0200
,
UNUSUAL_DEV
(
0x059f
,
0xa601
,
0x0200
,
0x0200
,
"LaCie"
,
"LaCie"
,
"USB Hard Disk"
,
"USB Hard Disk"
,
US_SC_RBC
,
US_PR_CB
,
NULL
,
0
),
US_SC_RBC
,
US_PR_CB
,
NULL
,
0
),
/* Submitted by Jol Bourquard <numlock@freesurf.ch> */
UNUSUAL_DEV
(
0x05ab
,
0x0060
,
0x1104
,
0x1110
,
"In-System"
,
"PyroGate External CD-ROM Enclosure (FCD-523)"
,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
0
),
#ifdef CONFIG_USB_STORAGE_ISD200
#ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV
(
0x05ab
,
0x0031
,
0x0100
,
0x0110
,
UNUSUAL_DEV
(
0x05ab
,
0x0031
,
0x0100
,
0x0110
,
"In-System"
,
"In-System"
,
...
...
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