Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
f749ccc0
Commit
f749ccc0
authored
Feb 05, 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
9e81ab3b
662c60e7
Changes
37
Show whitespace changes
Inline
Side-by-side
Showing
37 changed files
with
1106 additions
and
2158 deletions
+1106
-2158
MAINTAINERS
MAINTAINERS
+2
-2
drivers/media/dvb/ttusb-dec/ttusb_dec.c
drivers/media/dvb/ttusb-dec/ttusb_dec.c
+21
-4
drivers/usb/Makefile
drivers/usb/Makefile
+0
-1
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-acm.c
+6
-1
drivers/usb/core/Makefile
drivers/usb/core/Makefile
+1
-1
drivers/usb/core/hcd.c
drivers/usb/core/hcd.c
+12
-7
drivers/usb/core/hcd.h
drivers/usb/core/hcd.h
+1
-1
drivers/usb/core/hub.c
drivers/usb/core/hub.c
+1
-1
drivers/usb/core/usb-debug.c
drivers/usb/core/usb-debug.c
+0
-201
drivers/usb/core/usb.c
drivers/usb/core/usb.c
+13
-0
drivers/usb/gadget/ether.c
drivers/usb/gadget/ether.c
+29
-7
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/file_storage.c
+16
-5
drivers/usb/gadget/net2280.c
drivers/usb/gadget/net2280.c
+6
-2
drivers/usb/gadget/pxa2xx_udc.c
drivers/usb/gadget/pxa2xx_udc.c
+97
-45
drivers/usb/gadget/pxa2xx_udc.h
drivers/usb/gadget/pxa2xx_udc.h
+12
-6
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hcd.c
+8
-1
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-hcd.c
+5
-3
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-omap.c
+6
-6
drivers/usb/host/ohci-sa1111.c
drivers/usb/host/ohci-sa1111.c
+0
-2
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.c
+4
-3
drivers/usb/image/Kconfig
drivers/usb/image/Kconfig
+0
-13
drivers/usb/image/Makefile
drivers/usb/image/Makefile
+0
-1
drivers/usb/image/scanner.c
drivers/usb/image/scanner.c
+0
-1216
drivers/usb/image/scanner.h
drivers/usb/image/scanner.h
+0
-387
drivers/usb/input/hid-core.c
drivers/usb/input/hid-core.c
+4
-2
drivers/usb/misc/usbtest.c
drivers/usb/misc/usbtest.c
+664
-115
drivers/usb/misc/uss720.c
drivers/usb/misc/uss720.c
+4
-4
drivers/usb/net/Kconfig
drivers/usb/net/Kconfig
+3
-2
drivers/usb/net/usbnet.c
drivers/usb/net/usbnet.c
+172
-101
drivers/usb/serial/belkin_sa.c
drivers/usb/serial/belkin_sa.c
+3
-1
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/kobil_sct.c
+0
-4
drivers/usb/serial/visor.c
drivers/usb/serial/visor.c
+3
-0
drivers/usb/serial/visor.h
drivers/usb/serial/visor.h
+3
-0
drivers/usb/storage/datafab.h
drivers/usb/storage/datafab.h
+1
-1
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/unusual_devs.h
+8
-1
drivers/usb/storage/usb.c
drivers/usb/storage/usb.c
+1
-1
include/linux/usb.h
include/linux/usb.h
+0
-10
No files found.
MAINTAINERS
View file @
f749ccc0
...
...
@@ -2239,8 +2239,8 @@ W: http://www.linux-usb.org
S: Supported
USB UHCI DRIVER
P:
Johannes Erdfelt
M:
johannes@erdfelt.com
P:
Alan Stern
M:
stern@rowland.harvard.edu
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
S: Maintained
...
...
drivers/media/dvb/ttusb-dec/ttusb_dec.c
View file @
f749ccc0
...
...
@@ -204,12 +204,23 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
int
*
result_length
,
u8
cmd_result
[])
{
int
result
,
actual_len
,
i
;
u8
b
[
COMMAND_PACKET_SIZE
+
4
];
u8
c
[
COMMAND_PACKET_SIZE
+
4
];
u8
*
b
;
u8
*
c
;
b
=
kmalloc
(
COMMAND_PACKET_SIZE
+
4
,
GFP_KERNEL
);
if
(
!
b
)
return
-
ENOMEM
;
c
=
kmalloc
(
COMMAND_PACKET_SIZE
+
4
,
GFP_KERNEL
);
if
(
!
c
)
{
kfree
(
b
);
return
-
ENOMEM
;
}
dprintk
(
"%s
\n
"
,
__FUNCTION__
);
if
((
result
=
down_interruptible
(
&
dec
->
usb_sem
)))
{
kfree
(
b
);
kfree
(
c
);
printk
(
"%s: Failed to down usb semaphore.
\n
"
,
__FUNCTION__
);
return
result
;
}
...
...
@@ -230,22 +241,26 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
}
result
=
usb_bulk_msg
(
dec
->
udev
,
dec
->
command_pipe
,
b
,
sizeof
(
b
)
,
&
actual_len
,
HZ
);
COMMAND_PACKET_SIZE
+
4
,
&
actual_len
,
HZ
);
if
(
result
)
{
printk
(
"%s: command bulk message failed: error %d
\n
"
,
__FUNCTION__
,
result
);
up
(
&
dec
->
usb_sem
);
kfree
(
b
);
kfree
(
c
);
return
result
;
}
result
=
usb_bulk_msg
(
dec
->
udev
,
dec
->
result_pipe
,
c
,
sizeof
(
c
)
,
&
actual_len
,
HZ
);
COMMAND_PACKET_SIZE
+
4
,
&
actual_len
,
HZ
);
if
(
result
)
{
printk
(
"%s: result bulk message failed: error %d
\n
"
,
__FUNCTION__
,
result
);
up
(
&
dec
->
usb_sem
);
kfree
(
b
);
kfree
(
c
);
return
result
;
}
else
{
if
(
debug
)
{
...
...
@@ -262,6 +277,8 @@ static int ttusb_dec_send_command(struct ttusb_dec *dec, const u8 command,
up
(
&
dec
->
usb_sem
);
kfree
(
b
);
kfree
(
c
);
return
0
;
}
}
...
...
drivers/usb/Makefile
View file @
f749ccc0
...
...
@@ -46,7 +46,6 @@ obj-$(CONFIG_USB_DC2XX) += image/
obj-$(CONFIG_USB_HPUSBSCSI)
+=
image/
obj-$(CONFIG_USB_MDC800)
+=
image/
obj-$(CONFIG_USB_MICROTEK)
+=
image/
obj-$(CONFIG_USB_SCANNER)
+=
image/
obj-$(CONFIG_USB_SERIAL)
+=
serial/
...
...
drivers/usb/class/cdc-acm.c
View file @
f749ccc0
...
...
@@ -399,6 +399,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
static
int
acm_tty_write
(
struct
tty_struct
*
tty
,
int
from_user
,
const
unsigned
char
*
buf
,
int
count
)
{
struct
acm
*
acm
=
tty
->
driver_data
;
int
stat
;
if
(
!
ACM_READY
(
acm
))
return
-
EINVAL
;
...
...
@@ -418,8 +419,12 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c
acm
->
writeurb
->
transfer_buffer_length
=
count
;
acm
->
writeurb
->
dev
=
acm
->
dev
;
if
(
usb_submit_urb
(
acm
->
writeurb
,
GFP_KERNEL
))
/* GFP_KERNEL probably works if from_user */
stat
=
usb_submit_urb
(
acm
->
writeurb
,
GFP_ATOMIC
);
if
(
stat
<
0
)
{
dbg
(
"usb_submit_urb(write bulk) failed"
);
return
stat
;
}
return
count
;
}
...
...
drivers/usb/core/Makefile
View file @
f749ccc0
...
...
@@ -2,7 +2,7 @@
# Makefile for USB Core files and filesystem
#
usbcore-objs
:=
usb.o
usb-debug.o
hub.o hcd.o urb.o message.o
\
usbcore-objs
:=
usb.o hub.o hcd.o urb.o message.o
\
config.o file.o buffer.o driverfs.o
ifeq
($(CONFIG_PCI),y)
...
...
drivers/usb/core/hcd.c
View file @
f749ccc0
...
...
@@ -34,7 +34,10 @@
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/uts.h>
/* for UTS_SYSNAME */
#include <linux/pci.h>
/* for hcd->pdev and dma addressing */
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/scatterlist.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <asm/byteorder.h>
...
...
@@ -1474,16 +1477,16 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs
if
(
hcd
->
controller
->
dma_mask
)
{
if
(
usb_pipecontrol
(
urb
->
pipe
)
&&
!
(
urb
->
transfer_flags
&
URB_NO_SETUP_DMA_MAP
))
pci_unmap_single
(
hcd
->
pdev
,
urb
->
setup_dma
,
dma_unmap_single
(
hcd
->
controller
,
urb
->
setup_dma
,
sizeof
(
struct
usb_ctrlrequest
),
PCI_DMA_TO
DEVICE
);
DMA_TO_
DEVICE
);
if
(
urb
->
transfer_buffer_length
!=
0
&&
!
(
urb
->
transfer_flags
&
URB_NO_TRANSFER_DMA_MAP
))
pci_unmap_single
(
hcd
->
pdev
,
urb
->
transfer_dma
,
dma_unmap_single
(
hcd
->
controller
,
urb
->
transfer_dma
,
urb
->
transfer_buffer_length
,
usb_pipein
(
urb
->
pipe
)
?
PCI_DMA_FROM
DEVICE
:
PCI_DMA_TO
DEVICE
);
?
DMA_FROM_
DEVICE
:
DMA_TO_
DEVICE
);
}
/* pass ownership to the completion handler */
...
...
@@ -1513,7 +1516,9 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r)
return
IRQ_NONE
;
hcd
->
saw_irq
=
1
;
hcd
->
driver
->
irq
(
hcd
,
r
);
if
(
hcd
->
driver
->
irq
(
hcd
,
r
)
==
IRQ_NONE
)
return
IRQ_NONE
;
if
(
hcd
->
state
!=
start
&&
hcd
->
state
==
USB_STATE_HALT
)
usb_hc_died
(
hcd
);
return
IRQ_HANDLED
;
...
...
drivers/usb/core/hcd.h
View file @
f749ccc0
...
...
@@ -163,7 +163,7 @@ struct hc_driver {
const
char
*
description
;
/* "ehci-hcd" etc */
/* irq handler */
void
(
*
irq
)
(
struct
usb_hcd
*
hcd
,
struct
pt_regs
*
regs
);
irqreturn_t
(
*
irq
)
(
struct
usb_hcd
*
hcd
,
struct
pt_regs
*
regs
);
int
flags
;
#define HCD_MEMORY 0x0001
/* HC regs use memory (else I/O) */
...
...
drivers/usb/core/hub.c
View file @
f749ccc0
...
...
@@ -179,7 +179,7 @@ static inline int
hub_clear_tt_buffer
(
struct
usb_device
*
hub
,
u16
devinfo
,
u16
tt
)
{
return
usb_control_msg
(
hub
,
usb_rcvctrlpipe
(
hub
,
0
),
HUB_CLEAR_TT_BUFFER
,
USB_
DIR_IN
|
USB_RECIP_OTHER
,
HUB_CLEAR_TT_BUFFER
,
USB_
RT_PORT
,
devinfo
,
tt
,
0
,
0
,
HZ
);
}
...
...
drivers/usb/core/usb-debug.c
deleted
100644 → 0
View file @
9e81ab3b
/*
* debug.c - USB debug helper routines.
*
* I just want these out of the way where they aren't in your
* face, but so that you can still use them..
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/slab.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/usb.h>
static
void
usb_show_endpoint
(
struct
usb_host_endpoint
*
endpoint
)
{
usb_show_endpoint_descriptor
(
&
endpoint
->
desc
);
}
static
void
usb_show_interface
(
struct
usb_host_interface
*
altsetting
)
{
int
i
;
usb_show_interface_descriptor
(
&
altsetting
->
desc
);
for
(
i
=
0
;
i
<
altsetting
->
desc
.
bNumEndpoints
;
i
++
)
usb_show_endpoint
(
altsetting
->
endpoint
+
i
);
}
static
void
usb_show_config
(
struct
usb_host_config
*
config
)
{
int
i
,
j
;
struct
usb_interface
*
ifp
;
usb_show_config_descriptor
(
&
config
->
desc
);
for
(
i
=
0
;
i
<
config
->
desc
.
bNumInterfaces
;
i
++
)
{
ifp
=
config
->
interface
[
i
];
if
(
!
ifp
)
break
;
printk
(
"
\n
Interface: %d
\n
"
,
i
);
for
(
j
=
0
;
j
<
ifp
->
num_altsetting
;
j
++
)
usb_show_interface
(
ifp
->
altsetting
+
j
);
}
}
void
usb_show_device
(
struct
usb_device
*
dev
)
{
int
i
;
usb_show_device_descriptor
(
&
dev
->
descriptor
);
for
(
i
=
0
;
i
<
dev
->
descriptor
.
bNumConfigurations
;
i
++
)
usb_show_config
(
dev
->
config
+
i
);
}
/*
* Parse and show the different USB descriptors.
*/
void
usb_show_device_descriptor
(
struct
usb_device_descriptor
*
desc
)
{
if
(
!
desc
)
{
printk
(
"Invalid USB device descriptor (NULL POINTER)
\n
"
);
return
;
}
printk
(
" Length = %2d%s
\n
"
,
desc
->
bLength
,
desc
->
bLength
==
USB_DT_DEVICE_SIZE
?
""
:
" (!!!)"
);
printk
(
" DescriptorType = %02x
\n
"
,
desc
->
bDescriptorType
);
printk
(
" USB version = %x.%02x
\n
"
,
desc
->
bcdUSB
>>
8
,
desc
->
bcdUSB
&
0xff
);
printk
(
" Vendor:Product = %04x:%04x
\n
"
,
desc
->
idVendor
,
desc
->
idProduct
);
printk
(
" MaxPacketSize0 = %d
\n
"
,
desc
->
bMaxPacketSize0
);
printk
(
" NumConfigurations = %d
\n
"
,
desc
->
bNumConfigurations
);
printk
(
" Device version = %x.%02x
\n
"
,
desc
->
bcdDevice
>>
8
,
desc
->
bcdDevice
&
0xff
);
printk
(
" Device Class:SubClass:Protocol = %02x:%02x:%02x
\n
"
,
desc
->
bDeviceClass
,
desc
->
bDeviceSubClass
,
desc
->
bDeviceProtocol
);
switch
(
desc
->
bDeviceClass
)
{
case
0
:
printk
(
" Per-interface classes
\n
"
);
break
;
case
USB_CLASS_AUDIO
:
printk
(
" Audio device class
\n
"
);
break
;
case
USB_CLASS_COMM
:
printk
(
" Communications class
\n
"
);
break
;
case
USB_CLASS_HID
:
printk
(
" Human Interface Devices class
\n
"
);
break
;
case
USB_CLASS_PRINTER
:
printk
(
" Printer device class
\n
"
);
break
;
case
USB_CLASS_MASS_STORAGE
:
printk
(
" Mass Storage device class
\n
"
);
break
;
case
USB_CLASS_HUB
:
printk
(
" Hub device class
\n
"
);
break
;
case
USB_CLASS_VENDOR_SPEC
:
printk
(
" Vendor class
\n
"
);
break
;
default:
printk
(
" Unknown class
\n
"
);
}
}
void
usb_show_config_descriptor
(
struct
usb_config_descriptor
*
desc
)
{
printk
(
"Configuration:
\n
"
);
printk
(
" bLength = %4d%s
\n
"
,
desc
->
bLength
,
desc
->
bLength
==
USB_DT_CONFIG_SIZE
?
""
:
" (!!!)"
);
printk
(
" bDescriptorType = %02x
\n
"
,
desc
->
bDescriptorType
);
printk
(
" wTotalLength = %04x
\n
"
,
desc
->
wTotalLength
);
printk
(
" bNumInterfaces = %02x
\n
"
,
desc
->
bNumInterfaces
);
printk
(
" bConfigurationValue = %02x
\n
"
,
desc
->
bConfigurationValue
);
printk
(
" iConfiguration = %02x
\n
"
,
desc
->
iConfiguration
);
printk
(
" bmAttributes = %02x
\n
"
,
desc
->
bmAttributes
);
printk
(
" bMaxPower = %4dmA
\n
"
,
desc
->
bMaxPower
*
2
);
}
void
usb_show_interface_descriptor
(
struct
usb_interface_descriptor
*
desc
)
{
printk
(
" Alternate Setting: %2d
\n
"
,
desc
->
bAlternateSetting
);
printk
(
" bLength = %4d%s
\n
"
,
desc
->
bLength
,
desc
->
bLength
==
USB_DT_INTERFACE_SIZE
?
""
:
" (!!!)"
);
printk
(
" bDescriptorType = %02x
\n
"
,
desc
->
bDescriptorType
);
printk
(
" bInterfaceNumber = %02x
\n
"
,
desc
->
bInterfaceNumber
);
printk
(
" bAlternateSetting = %02x
\n
"
,
desc
->
bAlternateSetting
);
printk
(
" bNumEndpoints = %02x
\n
"
,
desc
->
bNumEndpoints
);
printk
(
" bInterface Class:SubClass:Protocol = %02x:%02x:%02x
\n
"
,
desc
->
bInterfaceClass
,
desc
->
bInterfaceSubClass
,
desc
->
bInterfaceProtocol
);
printk
(
" iInterface = %02x
\n
"
,
desc
->
iInterface
);
}
void
usb_show_endpoint_descriptor
(
struct
usb_endpoint_descriptor
*
desc
)
{
char
*
LengthCommentString
=
(
desc
->
bLength
==
USB_DT_ENDPOINT_AUDIO_SIZE
)
?
" (Audio)"
:
(
desc
->
bLength
==
USB_DT_ENDPOINT_SIZE
)
?
""
:
" (!!!)"
;
char
*
EndpointType
[
4
]
=
{
"Control"
,
"Isochronous"
,
"Bulk"
,
"Interrupt"
};
printk
(
" Endpoint:
\n
"
);
printk
(
" bLength = %4d%s
\n
"
,
desc
->
bLength
,
LengthCommentString
);
printk
(
" bDescriptorType = %02x
\n
"
,
desc
->
bDescriptorType
);
printk
(
" bEndpointAddress = %02x (%s)
\n
"
,
desc
->
bEndpointAddress
,
(
desc
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_CONTROL
?
"i/o"
:
(
desc
->
bEndpointAddress
&
USB_ENDPOINT_DIR_MASK
)
?
"in"
:
"out"
);
printk
(
" bmAttributes = %02x (%s)
\n
"
,
desc
->
bmAttributes
,
EndpointType
[
USB_ENDPOINT_XFERTYPE_MASK
&
desc
->
bmAttributes
]);
printk
(
" wMaxPacketSize = %04x
\n
"
,
desc
->
wMaxPacketSize
);
printk
(
" bInterval = %02x
\n
"
,
desc
->
bInterval
);
/* Audio extensions to the endpoint descriptor */
if
(
desc
->
bLength
==
USB_DT_ENDPOINT_AUDIO_SIZE
)
{
printk
(
" bRefresh = %02x
\n
"
,
desc
->
bRefresh
);
printk
(
" bSynchAddress = %02x
\n
"
,
desc
->
bSynchAddress
);
}
}
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
);
}
void
usb_dump_urb
(
struct
urb
*
urb
)
{
printk
(
"urb :%p
\n
"
,
urb
);
printk
(
"dev :%p
\n
"
,
urb
->
dev
);
printk
(
"pipe :%08X
\n
"
,
urb
->
pipe
);
printk
(
"status :%d
\n
"
,
urb
->
status
);
printk
(
"transfer_flags :%08X
\n
"
,
urb
->
transfer_flags
);
printk
(
"transfer_buffer :%p
\n
"
,
urb
->
transfer_buffer
);
printk
(
"transfer_buffer_length:%d
\n
"
,
urb
->
transfer_buffer_length
);
printk
(
"actual_length :%d
\n
"
,
urb
->
actual_length
);
printk
(
"setup_packet :%p
\n
"
,
urb
->
setup_packet
);
printk
(
"start_frame :%d
\n
"
,
urb
->
start_frame
);
printk
(
"number_of_packets :%d
\n
"
,
urb
->
number_of_packets
);
printk
(
"interval :%d
\n
"
,
urb
->
interval
);
printk
(
"error_count :%d
\n
"
,
urb
->
error_count
);
printk
(
"context :%p
\n
"
,
urb
->
context
);
printk
(
"complete :%p
\n
"
,
urb
->
complete
);
}
drivers/usb/core/usb.c
View file @
f749ccc0
...
...
@@ -984,6 +984,19 @@ int usb_set_address(struct usb_device *dev)
return
retval
;
}
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
);
}
/*
* By the time we get here, we chose a new device address
* and is in the default state. We need to identify the thing and
...
...
drivers/usb/gadget/ether.c
View file @
f749ccc0
...
...
@@ -19,7 +19,7 @@
*/
#define DEBUG 1
//
#define DEBUG 1
// #define VERBOSE
#include <linux/config.h>
...
...
@@ -885,8 +885,11 @@ set_ether_config (struct eth_dev *dev, int gfp_flags)
#ifndef DEV_CONFIG_CDC
if
(
result
==
0
)
{
netif_carrier_on
(
dev
->
net
);
if
(
netif_running
(
dev
->
net
))
if
(
netif_running
(
dev
->
net
))
{
spin_unlock
(
&
dev
->
lock
);
eth_start
(
dev
,
GFP_ATOMIC
);
spin_lock
(
&
dev
->
lock
);
}
}
else
{
(
void
)
usb_ep_disable
(
dev
->
in_ep
);
dev
->
in_ep
=
0
;
...
...
@@ -1246,8 +1249,11 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
#ifdef EP_STATUS_NUM
issue_start_status
(
dev
);
#endif
if
(
netif_running
(
dev
->
net
))
if
(
netif_running
(
dev
->
net
))
{
spin_unlock
(
&
dev
->
lock
);
eth_start
(
dev
,
GFP_ATOMIC
);
spin_lock
(
&
dev
->
lock
);
}
}
else
{
netif_stop_queue
(
dev
->
net
);
netif_carrier_off
(
dev
->
net
);
...
...
@@ -1414,16 +1420,14 @@ static int
rx_submit
(
struct
eth_dev
*
dev
,
struct
usb_request
*
req
,
int
gfp_flags
)
{
struct
sk_buff
*
skb
;
int
retval
=
0
;
int
retval
=
-
ENOMEM
;
size_t
size
;
size
=
(
sizeof
(
struct
ethhdr
)
+
dev
->
net
->
mtu
+
RX_EXTRA
);
if
((
skb
=
alloc_skb
(
size
,
gfp_flags
))
==
0
)
{
DEBUG
(
dev
,
"no rx skb
\n
"
);
defer_kevent
(
dev
,
WORK_RX_MEMORY
);
list_add
(
&
req
->
list
,
&
dev
->
rx_reqs
);
return
-
ENOMEM
;
goto
enomem
;
}
req
->
buf
=
skb
->
data
;
...
...
@@ -1433,11 +1437,14 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, int gfp_flags)
retval
=
usb_ep_queue
(
dev
->
out_ep
,
req
,
gfp_flags
);
if
(
retval
==
-
ENOMEM
)
enomem:
defer_kevent
(
dev
,
WORK_RX_MEMORY
);
if
(
retval
)
{
DEBUG
(
dev
,
"rx submit --> %d
\n
"
,
retval
);
dev_kfree_skb_any
(
skb
);
spin_lock
(
&
dev
->
lock
);
list_add
(
&
req
->
list
,
&
dev
->
rx_reqs
);
spin_unlock
(
&
dev
->
lock
);
}
return
retval
;
}
...
...
@@ -1502,6 +1509,7 @@ static void rx_complete (struct usb_ep *ep, struct usb_request *req)
dev_kfree_skb_any
(
skb
);
if
(
!
netif_running
(
dev
->
net
))
{
clean:
/* nobody reading rx_reqs, so no dev->lock */
list_add
(
&
req
->
list
,
&
dev
->
rx_reqs
);
req
=
0
;
}
...
...
@@ -1568,19 +1576,26 @@ static int alloc_requests (struct eth_dev *dev, unsigned n, int gfp_flags)
static
void
rx_fill
(
struct
eth_dev
*
dev
,
int
gfp_flags
)
{
struct
usb_request
*
req
;
unsigned
long
flags
;
clear_bit
(
WORK_RX_MEMORY
,
&
dev
->
todo
);
/* fill unused rxq slots with some skb */
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
while
(
!
list_empty
(
&
dev
->
rx_reqs
))
{
req
=
container_of
(
dev
->
rx_reqs
.
next
,
struct
usb_request
,
list
);
list_del_init
(
&
req
->
list
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
if
(
rx_submit
(
dev
,
req
,
gfp_flags
)
<
0
)
{
defer_kevent
(
dev
,
WORK_RX_MEMORY
);
return
;
}
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
}
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
}
static
void
eth_work
(
void
*
_dev
)
...
...
@@ -1616,7 +1631,9 @@ static void tx_complete (struct usb_ep *ep, struct usb_request *req)
}
dev
->
stats
.
tx_packets
++
;
spin_lock
(
&
dev
->
lock
);
list_add
(
&
req
->
list
,
&
dev
->
tx_reqs
);
spin_unlock
(
&
dev
->
lock
);
dev_kfree_skb_any
(
skb
);
atomic_dec
(
&
dev
->
tx_qlen
);
...
...
@@ -1630,11 +1647,14 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
int
length
=
skb
->
len
;
int
retval
;
struct
usb_request
*
req
=
0
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
req
=
container_of
(
dev
->
tx_reqs
.
next
,
struct
usb_request
,
list
);
list_del
(
&
req
->
list
);
if
(
list_empty
(
&
dev
->
tx_reqs
))
netif_stop_queue
(
net
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
/* no buffer copies needed, unless the network stack did it
* or the hardware can't use skb buffers.
...
...
@@ -1675,9 +1695,11 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
if
(
retval
)
{
dev
->
stats
.
tx_dropped
++
;
dev_kfree_skb_any
(
skb
);
spin_lock_irqsave
(
&
dev
->
lock
,
flags
);
if
(
list_empty
(
&
dev
->
tx_reqs
))
netif_start_queue
(
net
);
list_add
(
&
req
->
list
,
&
dev
->
tx_reqs
);
spin_unlock_irqrestore
(
&
dev
->
lock
,
flags
);
}
return
0
;
}
...
...
drivers/usb/gadget/file_storage.c
View file @
f749ccc0
/*
* file_storage.c -- File-backed USB Storage Gadget, for USB development
*
* Copyright (C) 2003 Alan Stern
* Copyright (C) 2003
, 2004
Alan Stern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
...
...
@@ -244,7 +244,7 @@
#define DRIVER_DESC "File-backed Storage Gadget"
#define DRIVER_NAME "g_file_storage"
#define DRIVER_VERSION "
14
January 2004"
#define DRIVER_VERSION "
26
January 2004"
static
const
char
longname
[]
=
DRIVER_DESC
;
static
const
char
shortname
[]
=
DRIVER_NAME
;
...
...
@@ -435,7 +435,7 @@ static const char EP_INTR_IN_NAME [] = "ep3-bulk";
#define LDBG(lun,fmt,args...) \
yprintk(lun , KERN_DEBUG , fmt , ## args)
#define MDBG(fmt,args...) \
printk(KERN_DEBUG DRIVER_NAME ": " fmt, ## args)
printk(KERN_DEBUG DRIVER_NAME ": " fmt
, ## args)
#else
#define DBG(fsg,fmt,args...) \
do { } while (0)
...
...
@@ -473,7 +473,7 @@ static const char EP_INTR_IN_NAME [] = "ep3-bulk";
yprintk(lun , KERN_INFO , fmt , ## args)
#define MINFO(fmt,args...) \
printk(KERN_INFO DRIVER_NAME ": " fmt, ## args)
printk(KERN_INFO DRIVER_NAME ": " fmt
, ## args)
/*-------------------------------------------------------------------------*/
...
...
@@ -848,6 +848,7 @@ struct fsg_dev {
unsigned
int
nluns
;
struct
lun
*
luns
;
struct
lun
*
curlun
;
struct
completion
lun_released
;
};
typedef
void
(
*
fsg_routine_t
)(
struct
fsg_dev
*
);
...
...
@@ -3771,6 +3772,13 @@ static DEVICE_ATTR(file, 0444, show_file, NULL);
/*-------------------------------------------------------------------------*/
static
void
lun_release
(
struct
device
*
dev
)
{
struct
fsg_dev
*
fsg
=
(
struct
fsg_dev
*
)
dev_get_drvdata
(
dev
);
complete
(
&
fsg
->
lun_released
);
}
static
void
fsg_unbind
(
struct
usb_gadget
*
gadget
)
{
struct
fsg_dev
*
fsg
=
get_gadget_data
(
gadget
);
...
...
@@ -3782,12 +3790,14 @@ static void fsg_unbind(struct usb_gadget *gadget)
clear_bit
(
REGISTERED
,
&
fsg
->
atomic_bitflags
);
/* Unregister the sysfs attribute files and the LUNs */
init_completion
(
&
fsg
->
lun_released
);
for
(
i
=
0
;
i
<
fsg
->
nluns
;
++
i
)
{
curlun
=
&
fsg
->
luns
[
i
];
if
(
curlun
->
registered
)
{
device_remove_file
(
&
curlun
->
dev
,
&
dev_attr_ro
);
device_remove_file
(
&
curlun
->
dev
,
&
dev_attr_file
);
device_unregister_wait
(
&
curlun
->
dev
);
device_unregister
(
&
curlun
->
dev
);
wait_for_completion
(
&
fsg
->
lun_released
);
curlun
->
registered
=
0
;
}
}
...
...
@@ -4140,6 +4150,7 @@ static int __init fsg_init(void)
INFO
(
fsg
,
"failed to register LUN%d: %d
\n
"
,
i
,
rc
);
else
{
curlun
->
registered
=
1
;
curlun
->
dev
.
release
=
lun_release
;
device_create_file
(
&
curlun
->
dev
,
&
dev_attr_ro
);
device_create_file
(
&
curlun
->
dev
,
&
dev_attr_file
);
}
...
...
drivers/usb/gadget/net2280.c
View file @
f749ccc0
...
...
@@ -534,7 +534,10 @@ write_fifo (struct net2280_ep *ep, struct usb_request *req)
}
/* write just one packet at a time */
count
=
min
(
ep
->
ep
.
maxpacket
,
total
);
count
=
ep
->
ep
.
maxpacket
;
if
(
count
>
total
)
/* min() cannot be used on a bitfield */
count
=
total
;
VDEBUG
(
ep
->
dev
,
"write %s fifo (IN) %d bytes%s req %p
\n
"
,
ep
->
ep
.
name
,
count
,
(
count
!=
ep
->
ep
.
maxpacket
)
?
" (short)"
:
""
,
...
...
@@ -2197,7 +2200,8 @@ static void handle_ep_small (struct net2280_ep *ep)
unsigned
len
;
len
=
req
->
req
.
length
-
req
->
req
.
actual
;
len
=
min
(
ep
->
ep
.
maxpacket
,
len
);
if
(
len
>
ep
->
ep
.
maxpacket
)
len
=
ep
->
ep
.
maxpacket
;
req
->
req
.
actual
+=
len
;
/* if we wrote it all, we're usually done */
...
...
drivers/usb/gadget/pxa2xx_udc.c
View file @
f749ccc0
/*
* linux/drivers/usb/gadget/pxa2xx_udc.c
* Intel PXA2xx on-chip full speed USB device controllers
* Intel PXA2xx
and IXP4xx
on-chip full speed USB device controllers
*
* Copyright (C) 2002 Intrinsyc, Inc. (Frank Becker)
* Copyright (C) 2003 Robert Schwebel, Pengutronix
...
...
@@ -59,12 +59,11 @@
#include <asm/arch/udc.h>
#include "pxa2xx_udc.h"
/*
* This driver handles the USB Device Controller (UDC) in Intel's PXA 2xx
* series processors. The UDC for the IXP 4xx series is very similar.
* There are fifteen endpoints, in addition to ep0.
*
* Such controller drivers work with a gadget driver. The gadget driver
* returns descriptors, implements configuration and data protocols used
...
...
@@ -78,7 +77,7 @@
* pxa250 a0/a1 b0/b1/b2 sure act like they're still there.
*/
#define DRIVER_VERSION "
7-Nov
-2003"
#define DRIVER_VERSION "
14-Dec
-2003"
#define DRIVER_DESC "PXA 2xx USB Device Controller driver"
...
...
@@ -95,6 +94,19 @@ static const char ep0name [] = "ep0";
#define UDC_PROC_FILE
#endif
#ifdef CONFIG_ARCH_IXP425
#undef USE_DMA
/* cpu-specific register addresses are compiled in to this code */
#ifdef CONFIG_ARCH_PXA
#error "Can't configure both IXP and PXA"
#endif
#endif
#include "pxa2xx_udc.h"
#ifdef CONFIG_EMBEDDED
/* few strings, and little code to use them */
#undef DEBUG
...
...
@@ -215,7 +227,8 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
if
(
!
_ep
||
!
desc
||
ep
->
desc
||
_ep
->
name
==
ep0name
||
desc
->
bDescriptorType
!=
USB_DT_ENDPOINT
||
ep
->
bEndpointAddress
!=
desc
->
bEndpointAddress
||
ep
->
ep
.
maxpacket
<
desc
->
wMaxPacketSize
)
{
||
ep
->
fifo_size
<
le16_to_cpu
(
desc
->
wMaxPacketSize
))
{
DMSG
(
"%s, bad ep or descriptor
\n
"
,
__FUNCTION__
);
return
-
EINVAL
;
}
...
...
@@ -230,7 +243,8 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
/* hardware _could_ do smaller, but driver doesn't */
if
((
desc
->
bmAttributes
==
USB_ENDPOINT_XFER_BULK
&&
desc
->
wMaxPacketSize
!=
BULK_FIFO_SIZE
)
&&
le16_to_cpu
(
desc
->
wMaxPacketSize
)
!=
BULK_FIFO_SIZE
)
||
!
desc
->
wMaxPacketSize
)
{
DMSG
(
"%s, bad %s maxpacket
\n
"
,
__FUNCTION__
,
_ep
->
name
);
return
-
ERANGE
;
...
...
@@ -246,6 +260,7 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
ep
->
dma
=
-
1
;
ep
->
stopped
=
0
;
ep
->
pio_irqs
=
ep
->
dma_irqs
=
0
;
ep
->
ep
.
maxpacket
=
le16_to_cpu
(
desc
->
wMaxPacketSize
);
/* flush fifo (mostly for OUT buffers) */
pxa2xx_ep_fifo_flush
(
_ep
);
...
...
@@ -258,14 +273,14 @@ static int pxa2xx_ep_enable (struct usb_ep *_ep,
*/
switch
(
ep
->
bmAttributes
)
{
case
USB_ENDPOINT_XFER_ISOC
:
if
(
desc
->
wMaxPacketSize
%
32
)
if
(
le16_to_cpu
(
desc
->
wMaxPacketSize
)
%
32
)
break
;
// fall through
case
USB_ENDPOINT_XFER_BULK
:
if
(
!
use_dma
||
!
ep
->
reg_drcmr
)
break
;
ep
->
dma
=
pxa_request_dma
((
char
*
)
_ep
->
name
,
(
desc
->
wMaxPacketSize
>
64
)
(
le16_to_cpu
(
desc
->
wMaxPacketSize
)
>
64
)
?
DMA_PRIO_MEDIUM
/* some iso */
:
DMA_PRIO_LOW
,
dma_nodesc_handler
,
ep
);
...
...
@@ -437,7 +452,7 @@ write_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
{
unsigned
max
;
max
=
ep
->
desc
->
wMaxPacketSize
;
max
=
le16_to_cpu
(
ep
->
desc
->
wMaxPacketSize
)
;
do
{
unsigned
count
;
int
is_last
,
is_short
;
...
...
@@ -454,13 +469,7 @@ write_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
else
is_last
=
1
;
/* interrupt/iso maxpacket may not fill the fifo */
is_short
=
unlikely
(
max
<
ep
->
ep
.
maxpacket
);
/* FIXME ep.maxpacket should be the current size,
* modified (for periodic endpoints) when the
* ep is enabled. do that, re-init as needed,
* and change maxpacket refs accordingly.
*/
is_short
=
unlikely
(
max
<
ep
->
fifo_size
);
}
DBG
(
DBG_VERY_NOISY
,
"wrote %s %d bytes%s%s %d left %p
\n
"
,
...
...
@@ -598,7 +607,7 @@ read_fifo (struct pxa2xx_ep *ep, struct pxa2xx_request *req)
req
->
req
.
actual
+=
min
(
count
,
bufferspace
);
}
else
/* zlp */
count
=
0
;
is_short
=
(
count
<
ep
->
desc
->
wMaxPacketSize
);
is_short
=
(
count
<
ep
->
ep
.
maxpacket
);
DBG
(
DBG_VERY_NOISY
,
"read %s %02x, %d bytes%s req %p %d/%d
\n
"
,
ep
->
ep
.
name
,
udccs
,
count
,
is_short
?
"/S"
:
""
,
...
...
@@ -897,13 +906,14 @@ pxa2xx_ep_queue(struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
* we can report per-packet status. that also helps with dma.
*/
if
(
unlikely
(
ep
->
bmAttributes
==
USB_ENDPOINT_XFER_ISOC
&&
req
->
req
.
length
>
ep
->
desc
->
wMaxPacketSize
))
&&
req
->
req
.
length
>
le16_to_cpu
(
ep
->
desc
->
wMaxPacketSize
)))
return
-
EMSGSIZE
;
#ifdef USE_DMA
// FIXME caller may already have done the dma mapping
if
(
ep
->
dma
>=
0
)
{
_req
->
dma
=
dma_map_single
(
&
dev
->
dev
.
dev
,
_req
->
dma
=
dma_map_single
(
dev
->
dev
,
_req
->
buf
,
_req
->
length
,
((
ep
->
bEndpointAddress
&
USB_DIR_IN
)
!=
0
)
?
DMA_TO_DEVICE
...
...
@@ -1017,11 +1027,21 @@ static int pxa2xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
unsigned
long
flags
;
ep
=
container_of
(
_ep
,
struct
pxa2xx_ep
,
ep
);
req
=
container_of
(
_req
,
struct
pxa2xx_request
,
req
);
if
(
!
_ep
||
!
_req
||
ep
->
ep
.
name
==
ep0name
)
if
(
!
_ep
||
ep
->
ep
.
name
==
ep0name
)
return
-
EINVAL
;
local_irq_save
(
flags
);
/* make sure it's actually queued on this endpoint */
list_for_each_entry
(
req
,
&
ep
->
queue
,
queue
)
{
if
(
&
req
->
req
==
_req
)
break
;
}
if
(
&
req
->
req
!=
_req
)
{
local_irq_restore
(
flags
);
return
-
EINVAL
;
}
#ifdef USE_DMA
if
(
ep
->
dma
>=
0
&&
ep
->
queue
.
next
==
&
req
->
queue
&&
!
ep
->
stopped
)
{
cancel_dma
(
ep
);
...
...
@@ -1034,13 +1054,10 @@ static int pxa2xx_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
}
}
else
#endif
if
(
!
list_empty
(
&
req
->
queue
))
done
(
ep
,
req
,
-
ECONNRESET
);
else
req
=
0
;
local_irq_restore
(
flags
);
return
req
?
0
:
-
EOPNOTSUPP
;
local_irq_restore
(
flags
);
return
0
;
}
/*-------------------------------------------------------------------------*/
...
...
@@ -1386,8 +1403,10 @@ static void udc_disable(struct pxa2xx_udc *dev)
udc_clear_mask_UDCCR
(
UDCCR_UDE
);
#ifdef CONFIG_ARCH_PXA
/* Disable clock for USB device */
CKEN
&=
~
CKEN11_USB
;
#endif
ep0_idle
(
dev
);
dev
->
gadget
.
speed
=
USB_SPEED_UNKNOWN
;
...
...
@@ -1430,8 +1449,10 @@ static void udc_enable (struct pxa2xx_udc *dev)
{
udc_clear_mask_UDCCR
(
UDCCR_UDE
);
#ifdef CONFIG_ARCH_PXA
/* Enable clock for USB device */
CKEN
|=
CKEN11_USB
;
#endif
/* try to clear these bits before we enable the udc */
udc_ack_int_UDCCR
(
UDCCR_SUSIR
|
/*UDCCR_RSTIR|*/
UDCCR_RESIR
);
...
...
@@ -1590,9 +1611,10 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
local_irq_disable
();
udc_disable
(
dev
);
stop_activity
(
dev
,
driver
);
local_irq_enable
();
driver
->
unbind
(
&
dev
->
gadget
);
dev
->
driver
=
0
;
local_irq_enable
();
device_del
(
&
dev
->
gadget
.
dev
);
device_remove_file
(
dev
->
dev
,
&
dev_attr_function
);
...
...
@@ -1776,7 +1798,6 @@ static void handle_ep0 (struct pxa2xx_udc *dev)
* else use AREN (later) not SA|OPR
* USIR0_IR0 acts edge sensitive
*/
dev
->
req_pending
=
0
;
}
break
;
/* ... and here, even more ... */
...
...
@@ -1853,6 +1874,7 @@ static void handle_ep0 (struct pxa2xx_udc *dev)
/* pxa210/250 erratum 131 for B0/B1 says RNE lies.
* still observed on a pxa255 a0.
*/
DBG
(
DBG_VERBOSE
,
"e131
\n
"
);
nuke
(
ep
,
-
EPROTO
);
/* read SETUP data, but don't trust it too much */
...
...
@@ -2043,7 +2065,7 @@ pxa2xx_udc_irq(int irq, void *_dev, struct pt_regs *r)
stop_activity
(
dev
,
dev
->
driver
);
}
else
{
dev_info
(
&
dev
->
gadget
.
dev
,
"USB reset
\n
"
);
INFO
(
"USB reset
\n
"
);
dev
->
gadget
.
speed
=
USB_SPEED_FULL
;
LED_CONNECTED_ON
;
memset
(
&
dev
->
stats
,
0
,
sizeof
dev
->
stats
);
...
...
@@ -2133,11 +2155,12 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
BULK_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
BULK_FIFO_SIZE
,
.
bEndpointAddress
=
USB_DIR_IN
|
1
,
.
bmAttributes
=
USB_ENDPOINT_XFER_BULK
,
.
reg_udccs
=
&
UDCCS1
,
.
reg_uddr
=
&
UDDR1
,
.
reg_drcmr
=
&
DRCMR25
,
drcmr
(
25
)
},
.
ep
[
2
]
=
{
.
ep
=
{
...
...
@@ -2146,12 +2169,13 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
BULK_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
BULK_FIFO_SIZE
,
.
bEndpointAddress
=
2
,
.
bmAttributes
=
USB_ENDPOINT_XFER_BULK
,
.
reg_udccs
=
&
UDCCS2
,
.
reg_ubcr
=
&
UBCR2
,
.
reg_uddr
=
&
UDDR2
,
.
reg_drcmr
=
&
DRCMR26
,
drcmr
(
26
)
},
#ifndef CONFIG_USB_PXA2XX_SMALL
.
ep
[
3
]
=
{
...
...
@@ -2161,11 +2185,12 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
ISO_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
ISO_FIFO_SIZE
,
.
bEndpointAddress
=
USB_DIR_IN
|
3
,
.
bmAttributes
=
USB_ENDPOINT_XFER_ISOC
,
.
reg_udccs
=
&
UDCCS3
,
.
reg_uddr
=
&
UDDR3
,
.
reg_drcmr
=
&
DRCMR27
,
drcmr
(
27
)
},
.
ep
[
4
]
=
{
.
ep
=
{
...
...
@@ -2174,12 +2199,13 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
ISO_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
ISO_FIFO_SIZE
,
.
bEndpointAddress
=
4
,
.
bmAttributes
=
USB_ENDPOINT_XFER_ISOC
,
.
reg_udccs
=
&
UDCCS4
,
.
reg_ubcr
=
&
UBCR4
,
.
reg_uddr
=
&
UDDR4
,
.
reg_drcmr
=
&
DRCMR28
,
drcmr
(
28
)
},
.
ep
[
5
]
=
{
.
ep
=
{
...
...
@@ -2188,6 +2214,7 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
INT_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
INT_FIFO_SIZE
,
.
bEndpointAddress
=
USB_DIR_IN
|
5
,
.
bmAttributes
=
USB_ENDPOINT_XFER_INT
,
.
reg_udccs
=
&
UDCCS5
,
...
...
@@ -2202,11 +2229,12 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
BULK_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
BULK_FIFO_SIZE
,
.
bEndpointAddress
=
USB_DIR_IN
|
6
,
.
bmAttributes
=
USB_ENDPOINT_XFER_BULK
,
.
reg_udccs
=
&
UDCCS6
,
.
reg_uddr
=
&
UDDR6
,
.
reg_drcmr
=
&
DRCMR30
,
drcmr
(
30
)
},
.
ep
[
7
]
=
{
.
ep
=
{
...
...
@@ -2215,12 +2243,13 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
BULK_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
BULK_FIFO_SIZE
,
.
bEndpointAddress
=
7
,
.
bmAttributes
=
USB_ENDPOINT_XFER_BULK
,
.
reg_udccs
=
&
UDCCS7
,
.
reg_ubcr
=
&
UBCR7
,
.
reg_uddr
=
&
UDDR7
,
.
reg_drcmr
=
&
DRCMR31
,
drcmr
(
31
)
},
.
ep
[
8
]
=
{
.
ep
=
{
...
...
@@ -2229,11 +2258,12 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
ISO_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
ISO_FIFO_SIZE
,
.
bEndpointAddress
=
USB_DIR_IN
|
8
,
.
bmAttributes
=
USB_ENDPOINT_XFER_ISOC
,
.
reg_udccs
=
&
UDCCS8
,
.
reg_uddr
=
&
UDDR8
,
.
reg_drcmr
=
&
DRCMR32
,
drcmr
(
32
)
},
.
ep
[
9
]
=
{
.
ep
=
{
...
...
@@ -2242,12 +2272,13 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
ISO_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
ISO_FIFO_SIZE
,
.
bEndpointAddress
=
9
,
.
bmAttributes
=
USB_ENDPOINT_XFER_ISOC
,
.
reg_udccs
=
&
UDCCS9
,
.
reg_ubcr
=
&
UBCR9
,
.
reg_uddr
=
&
UDDR9
,
.
reg_drcmr
=
&
DRCMR33
,
drcmr
(
33
)
},
.
ep
[
10
]
=
{
.
ep
=
{
...
...
@@ -2256,6 +2287,7 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
INT_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
INT_FIFO_SIZE
,
.
bEndpointAddress
=
USB_DIR_IN
|
10
,
.
bmAttributes
=
USB_ENDPOINT_XFER_INT
,
.
reg_udccs
=
&
UDCCS10
,
...
...
@@ -2270,11 +2302,12 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
BULK_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
BULK_FIFO_SIZE
,
.
bEndpointAddress
=
USB_DIR_IN
|
11
,
.
bmAttributes
=
USB_ENDPOINT_XFER_BULK
,
.
reg_udccs
=
&
UDCCS11
,
.
reg_uddr
=
&
UDDR11
,
.
reg_drcmr
=
&
DRCMR35
,
drcmr
(
35
)
},
.
ep
[
12
]
=
{
.
ep
=
{
...
...
@@ -2283,12 +2316,13 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
BULK_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
BULK_FIFO_SIZE
,
.
bEndpointAddress
=
12
,
.
bmAttributes
=
USB_ENDPOINT_XFER_BULK
,
.
reg_udccs
=
&
UDCCS12
,
.
reg_ubcr
=
&
UBCR12
,
.
reg_uddr
=
&
UDDR12
,
.
reg_drcmr
=
&
DRCMR36
,
drcmr
(
36
)
},
.
ep
[
13
]
=
{
.
ep
=
{
...
...
@@ -2297,11 +2331,12 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
ISO_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
ISO_FIFO_SIZE
,
.
bEndpointAddress
=
USB_DIR_IN
|
13
,
.
bmAttributes
=
USB_ENDPOINT_XFER_ISOC
,
.
reg_udccs
=
&
UDCCS13
,
.
reg_uddr
=
&
UDDR13
,
.
reg_drcmr
=
&
DRCMR37
,
drcmr
(
37
)
},
.
ep
[
14
]
=
{
.
ep
=
{
...
...
@@ -2310,12 +2345,13 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
ISO_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
ISO_FIFO_SIZE
,
.
bEndpointAddress
=
14
,
.
bmAttributes
=
USB_ENDPOINT_XFER_ISOC
,
.
reg_udccs
=
&
UDCCS14
,
.
reg_ubcr
=
&
UBCR14
,
.
reg_uddr
=
&
UDDR14
,
.
reg_drcmr
=
&
DRCMR38
,
drcmr
(
38
)
},
.
ep
[
15
]
=
{
.
ep
=
{
...
...
@@ -2324,6 +2360,7 @@ static struct pxa2xx_udc memory = {
.
maxpacket
=
INT_FIFO_SIZE
,
},
.
dev
=
&
memory
,
.
fifo_size
=
INT_FIFO_SIZE
,
.
bEndpointAddress
=
USB_DIR_IN
|
15
,
.
bmAttributes
=
USB_ENDPOINT_XFER_INT
,
.
reg_udccs
=
&
UDCCS15
,
...
...
@@ -2333,8 +2370,15 @@ static struct pxa2xx_udc memory = {
};
#define CP15R0_VENDOR_MASK 0xffffe000
#if defined(CONFIG_ARCH_PXA)
#define CP15R0_XSCALE_VALUE 0x69052000
/* intel/arm/xscale */
#elif defined(CONFIG_ARCH_IXP425)
#define CP15R0_XSCALE_VALUE 0x69054000
/* intel/arm/ixp425 */
#endif
#define CP15R0_PROD_MASK 0x000003f0
#define PXA25x 0x00000100
/* and PXA26x */
#define PXA210 0x00000120
...
...
@@ -2355,6 +2399,7 @@ static struct pxa2xx_udc memory = {
#define PXA210_B2 0x00000124
#define PXA210_B1 0x00000123
#define PXA210_B0 0x00000122
#define IXP425_A0 0x000001c1
/*
* probe - binds to the platform device
...
...
@@ -2374,6 +2419,7 @@ static int __init pxa2xx_udc_probe(struct device *_dev)
/* trigger chiprev-specific logic */
switch
(
chiprev
&
CP15R0_PRODREV_MASK
)
{
#if defined(CONFIG_ARCH_PXA)
case
PXA255_A0
:
dev
->
has_cfr
=
1
;
break
;
...
...
@@ -2388,6 +2434,11 @@ static int __init pxa2xx_udc_probe(struct device *_dev)
/* fall through */
case
PXA250_C0
:
case
PXA210_C0
:
break
;
#elif defined(CONFIG_ARCH_IXP425)
case
IXP425_A0
:
out_dma
=
0
;
break
;
#endif
default:
out_dma
=
0
;
printk
(
KERN_ERR
"%s: unrecognized processor: %08x
\n
"
,
...
...
@@ -2443,6 +2494,7 @@ static int __init pxa2xx_udc_probe(struct device *_dev)
}
dev
->
got_irq
=
1
;
#ifdef CONFIG_ARCH_LUBBOCK
if
(
machine_is_lubbock
())
{
disable_irq
(
LUBBOCK_USB_DISC_IRQ
);
retval
=
request_irq
(
LUBBOCK_USB_DISC_IRQ
,
...
...
@@ -2457,7 +2509,7 @@ static int __init pxa2xx_udc_probe(struct device *_dev)
}
dev
->
got_disc
=
1
;
}
#endif
create_proc_files
();
return
0
;
...
...
drivers/usb/gadget/pxa2xx_udc.h
View file @
f749ccc0
...
...
@@ -52,8 +52,9 @@ struct pxa2xx_ep {
struct
list_head
queue
;
unsigned
long
pio_irqs
;
unsigned
long
dma_irqs
;
int
dma
;
short
dma
;
unsigned
short
fifo_size
;
u8
bEndpointAddress
;
u8
bmAttributes
;
...
...
@@ -68,7 +69,12 @@ struct pxa2xx_ep {
volatile
u32
*
reg_udccs
;
volatile
u32
*
reg_ubcr
;
volatile
u32
*
reg_uddr
;
#ifdef USE_DMA
volatile
u32
*
reg_drcmr
;
#define drcmr(n) .reg_drcmr = & DRCMR ## n ,
#else
#define drcmr(n)
#endif
};
struct
pxa2xx_request
{
...
...
@@ -181,14 +187,14 @@ static inline void make_usb_disappear(void)
{
if
(
!
the_controller
->
mach
->
udc_command
)
return
;
the_controller
->
mach
->
udc_command
(
PXA2XX_UDC_CMD_CONNECT
);
the_controller
->
mach
->
udc_command
(
PXA2XX_UDC_CMD_
DIS
CONNECT
);
}
static
inline
void
let_usb_appear
(
void
)
{
if
(
!
the_controller
->
mach
->
udc_command
)
return
;
the_controller
->
mach
->
udc_command
(
PXA2XX_UDC_CMD_
DIS
CONNECT
);
the_controller
->
mach
->
udc_command
(
PXA2XX_UDC_CMD_CONNECT
);
}
/*-------------------------------------------------------------------------*/
...
...
@@ -305,7 +311,7 @@ dump_state(struct pxa2xx_udc *dev)
#define DBG(lvl, stuff...) do{if ((lvl) <= UDC_DEBUG) DMSG(stuff);}while(0)
#define WARN(stuff...) printk(KERN_WARNING "udc: " stuff)
#define INFO(stuff...) printk(KERN_INFO "udc: " stuff)
#endif
/* __LINUX_USB_GADGET_PXA2XX_H */
drivers/usb/host/ehci-hcd.c
View file @
f749ccc0
...
...
@@ -680,7 +680,7 @@ static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
/*-------------------------------------------------------------------------*/
static
void
ehci_irq
(
struct
usb_hcd
*
hcd
,
struct
pt_regs
*
regs
)
static
irqreturn_t
ehci_irq
(
struct
usb_hcd
*
hcd
,
struct
pt_regs
*
regs
)
{
struct
ehci_hcd
*
ehci
=
hcd_to_ehci
(
hcd
);
u32
status
;
...
...
@@ -690,6 +690,12 @@ static void ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
status
=
readl
(
&
ehci
->
regs
->
status
);
/* shared irq */
if
(
status
==
0
)
{
spin_unlock
(
&
ehci
->
lock
);
return
IRQ_NONE
;
}
/* e.g. cardbus physical eject */
if
(
status
==
~
(
u32
)
0
)
{
ehci_dbg
(
ehci
,
"device removed
\n
"
);
...
...
@@ -743,6 +749,7 @@ static void ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
ehci_work
(
ehci
,
regs
);
done:
spin_unlock
(
&
ehci
->
lock
);
return
IRQ_HANDLED
;
}
/*-------------------------------------------------------------------------*/
...
...
drivers/usb/host/ohci-hcd.c
View file @
f749ccc0
...
...
@@ -545,7 +545,7 @@ static int hc_start (struct ohci_hcd *ohci)
/* an interrupt happens */
static
void
ohci_irq
(
struct
usb_hcd
*
hcd
,
struct
pt_regs
*
ptregs
)
static
irqreturn_t
ohci_irq
(
struct
usb_hcd
*
hcd
,
struct
pt_regs
*
ptregs
)
{
struct
ohci_hcd
*
ohci
=
hcd_to_ohci
(
hcd
);
struct
ohci_regs
*
regs
=
ohci
->
regs
;
...
...
@@ -560,11 +560,11 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
}
else
if
((
ints
=
readl
(
&
regs
->
intrstatus
))
==
~
(
u32
)
0
)
{
disable
(
ohci
);
ohci_dbg
(
ohci
,
"device removed!
\n
"
);
return
;
return
IRQ_HANDLED
;
/* interrupt for some other device? */
}
else
if
((
ints
&=
readl
(
&
regs
->
intrenable
))
==
0
)
{
return
;
return
IRQ_NONE
;
}
if
(
ints
&
OHCI_INTR_UE
)
{
...
...
@@ -604,6 +604,8 @@ static void ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
// flush those pci writes
(
void
)
readl
(
&
ohci
->
regs
->
control
);
}
return
IRQ_HANDLED
;
}
/*-------------------------------------------------------------------------*/
...
...
drivers/usb/host/ohci-omap.c
View file @
f749ccc0
...
...
@@ -134,7 +134,7 @@ static int omap_ohci_clock_power(int on)
writel
(
readl
(
ULPD_SOFT_REQ_REG
)
|
SOFT_USB_REQ
,
ULPD_SOFT_REQ_REG
);
outl
(
in
l
(
ULPD_STATUS_REQ_REG
)
|
USB_HOST_DPLL_REQ
,
writel
(
read
l
(
ULPD_STATUS_REQ_REG
)
|
USB_HOST_DPLL_REQ
,
ULPD_STATUS_REQ_REG
);
}
...
...
@@ -248,7 +248,7 @@ static int omap_1610_usb_init(int mode)
val
|=
(
1
<<
2
);
/* Disable pulldown on integrated transceiver DM */
val
|=
(
1
<<
1
);
/* Disable pulldown on integraded transceiver DP */
out
l
(
val
,
USB_TRANSCEIVER_CTRL
);
write
l
(
val
,
USB_TRANSCEIVER_CTRL
);
/* Set the USB0_TRX_MODE */
val
=
0
;
...
...
@@ -256,7 +256,7 @@ static int omap_1610_usb_init(int mode)
val
&=
~
DEV_IDLE_EN
;
val
&=
~
(
7
<<
16
);
/* Clear USB0_TRX_MODE */
val
|=
(
3
<<
16
);
/* 0 or 3, 6-wire DAT/SE0, TRM p 15-159 */
out
l
(
val
,
OTG_SYSCON_1
);
write
l
(
val
,
OTG_SYSCON_1
);
/*
* Control via OTG, see TRM p 15-163
...
...
@@ -275,10 +275,10 @@ static int omap_1610_usb_init(int mode)
val
|=
(
4
<<
16
);
/* Must be 4 */
val
|=
USBX_SYNCHRO
;
/* Must be set */
val
|=
SRP_VBUS
;
out
l
(
val
,
OTG_SYSCON_2
);
write
l
(
val
,
OTG_SYSCON_2
);
/* Enable OTG idle */
//
outl(in
l(OTG_SYSCON_1) | OTG_IDLE_EN, OTG_SYSCON_1);
//
writel(read
l(OTG_SYSCON_1) | OTG_IDLE_EN, OTG_SYSCON_1);
return
0
;
}
...
...
@@ -631,7 +631,7 @@ static struct omap_dev ohci_hcd_omap_device = {
.
end
=
OMAP_OHCI_BASE
+
OMAP_OHCI_SIZE
,
},
.
irq
=
{
INT_
OHCI
,
INT_
USB_HHC_1
,
},
};
...
...
drivers/usb/host/ohci-sa1111.c
View file @
f749ccc0
...
...
@@ -254,8 +254,6 @@ void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev)
hcd_buffer_destroy
(
hcd
);
usb_deregister_bus
(
&
hcd
->
self
);
if
(
atomic_read
(
&
hcd
->
self
.
refcnt
)
!=
1
)
err
(
"%s: %s, count != 1"
,
__FUNCTION__
,
hcd
->
self
.
bus_name
);
base
=
hcd
->
regs
;
hcd
->
driver
->
hcd_free
(
hcd
);
...
...
drivers/usb/host/uhci-hcd.c
View file @
f749ccc0
/*
* Universal Host Controller Interface driver for USB.
*
* Maintainer:
Johannes Erdfelt <johannes@erdfelt.com
>
* Maintainer:
Alan Stern <stern@rowland.harvard.edu
>
*
* (C) Copyright 1999 Linus Torvalds
* (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
...
...
@@ -1909,7 +1909,7 @@ static void uhci_remove_pending_qhs(struct uhci_hcd *uhci)
spin_unlock_irqrestore
(
&
uhci
->
urb_remove_list_lock
,
flags
);
}
static
void
uhci_irq
(
struct
usb_hcd
*
hcd
,
struct
pt_regs
*
regs
)
static
irqreturn_t
uhci_irq
(
struct
usb_hcd
*
hcd
,
struct
pt_regs
*
regs
)
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
unsigned
int
io_addr
=
uhci
->
io_addr
;
...
...
@@ -1922,7 +1922,7 @@ static void uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
*/
status
=
inw
(
io_addr
+
USBSTS
);
if
(
!
status
)
/* shared interrupt, not mine */
return
;
return
IRQ_NONE
;
outw
(
status
,
io_addr
+
USBSTS
);
/* Clear it */
if
(
status
&
~
(
USBSTS_USBINT
|
USBSTS_ERROR
|
USBSTS_RD
))
{
...
...
@@ -1963,6 +1963,7 @@ static void uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
spin_unlock
(
&
uhci
->
urb_list_lock
);
uhci_finish_completion
(
hcd
,
regs
);
return
IRQ_HANDLED
;
}
static
void
reset_hc
(
struct
uhci_hcd
*
uhci
)
...
...
drivers/usb/image/Kconfig
View file @
f749ccc0
...
...
@@ -17,19 +17,6 @@ config USB_MDC800
To compile this driver as a module, choose M here: the
module will be called mdc800.
config USB_SCANNER
tristate "USB Scanner support (OBSOLETE)"
depends on USB
help
Say Y here if you want to connect a USB scanner to your computer's
USB port. Please read <file:Documentation/usb/scanner.txt> for more
information.
This driver has been obsoleted by support via libusb.
To compile this driver as a module, choose M here: the
module will be called scanner.
config USB_MICROTEK
tristate "Microtek X6USB scanner support"
depends on USB && SCSI
...
...
drivers/usb/image/Makefile
View file @
f749ccc0
...
...
@@ -5,4 +5,3 @@
obj-$(CONFIG_USB_MDC800)
+=
mdc800.o
obj-$(CONFIG_USB_HPUSBSCSI)
+=
hpusbscsi.o
obj-$(CONFIG_USB_MICROTEK)
+=
microtek.o
obj-$(CONFIG_USB_SCANNER)
+=
scanner.o
drivers/usb/image/scanner.c
deleted
100644 → 0
View file @
9e81ab3b
/* -*- linux-c -*- */
/*
* Driver for USB Scanners (linux-2.6)
*
* Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
* Copyright (C) 2002, 2003 Henning Meier-Geinitz
*
* Portions may be copyright Brad Keryan and Michael Gee.
*
* Previously maintained by Brian Beattie
*
* Current maintainer: Henning Meier-Geinitz <henning@meier-geinitz.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Originally based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
*
* History
*
* 0.1 8/31/1999
*
* Developed/tested using linux-2.3.15 with minor ohci.c changes to
* support short packets during bulk xfer mode. Some testing was
* done with ohci-hcd but the performance was low. Very limited
* testing was performed with uhci but I was unable to get it to
* work. Initial relase to the linux-usb development effort.
*
*
* 0.2 10/16/1999
*
* - Device can't be opened unless a scanner is plugged into the USB.
* - Finally settled on a reasonable value for the I/O buffer's.
* - Cleaned up write_scanner()
* - Disabled read/write stats
* - A little more code cleanup
*
*
* 0.3 10/18/1999
*
* - Device registration changed to reflect new device
* allocation/registration for linux-2.3.22+.
* - Adopted David Brownell's <david-b@pacbell.net> technique for
* assigning bulk endpoints.
* - Removed unnecessary #include's
* - Scanner model now reported via syslog INFO after being detected
* *and* configured.
* - Added user specified vendor:product USB ID's which can be passed
* as module parameters.
*
*
* 0.3.1
*
* - Applied patches for linux-2.3.25.
* - Error number reporting changed to reflect negative return codes.
*
*
* 0.3.2
*
* - Applied patches for linux-2.3.26 to scanner_init().
* - Debug read/write stats now report values as signed decimal.
*
*
* 0.3.3
*
* - Updated the bulk_msg() calls to usb usb_bulk_msg().
* - Added a small delay in the write_scanner() method to aid in
* avoiding NULL data reads on HP scanners. We'll see how this works.
* - Return values from usb_bulk_msg() now ignore positive values for
* use with the ohci driver.
* - Added conditional debugging instead of commenting/uncommenting
* all over the place.
* - kfree()'d the pointer after using usb_string() as documented in
* linux-usb-api.txt.
* - Added usb_set_configuration(). It got lost in version 0.3 -- ack!
* - Added the HP 5200C USB Vendor/Product ID's.
*
*
* 0.3.4 1/23/2000
*
* - Added Greg K-H's <greg@kroah.com> patch for better handling of
* Product/Vendor detection.
* - The driver now autoconfigures its endpoints including interrupt
* endpoints if one is detected. The concept was originally based
* upon David Brownell's method.
* - Added some Seiko/Epson ID's. Thanks to Karl Heinz
* Kremer <khk@khk.net>.
* - Added some preliminary ioctl() calls for the PV8630 which is used
* by the HP4200. The ioctl()'s still have to be registered. Thanks
* to Adrian Perez Jorge <adrianpj@easynews.com>.
* - Moved/migrated stuff to scanner.h
* - Removed the usb_set_configuration() since this is handled by
* the usb_new_device() routine in usb.c.
* - Added the HP 3300C. Thanks to Bruce Tenison.
* - Changed user specified vendor/product id so that root hub doesn't
* get falsely attached to. Thanks to Greg K-H.
* - Added some Mustek ID's. Thanks to Gernot Hoyler
* <Dr.Hoyler@t-online.de>.
* - Modified the usb_string() reporting. See kfree() comment above.
* - Added Umax Astra 2000U. Thanks to Doug Alcorn <doug@lathi.net>.
* - Updated the printk()'s to use the info/warn/dbg macros.
* - Updated usb_bulk_msg() argument types to fix gcc warnings.
*
*
* 0.4 2/4/2000
*
* - Removed usb_string() from probe_scanner since the core now does a
* good job of reporting what was connnected.
* - Finally, simultaneous multiple device attachment!
* - Fixed some potential memory freeing issues should memory allocation
* fail in probe_scanner();
* - Some fixes to disconnect_scanner().
* - Added interrupt endpoint support.
* - Added Agfa SnapScan Touch. Thanks to Jan Van den Bergh
* <jan.vandenbergh@cs.kuleuven.ac.be>.
* - Added Umax 1220U ID's. Thanks to Maciek Klimkowski
* <mac@nexus.carleton.ca>.
* - Fixed bug in write_scanner(). The buffer was not being properly
* updated for writes larger than OBUF_SIZE. Thanks to Henrik
* Johansson <henrikjo@post.utfors.se> for identifying it.
* - Added Microtek X6 ID's. Thanks to Oliver Neukum
* <Oliver.Neukum@lrz.uni-muenchen.de>.
*
*
* 0.4.1 2/15/2000
*
* - Fixed 'count' bug in read_scanner(). Thanks to Henrik
* Johansson <henrikjo@post.utfors.se> for identifying it. Amazing
* it has worked this long.
* - Fixed '>=' bug in both read/write_scanner methods.
* - Cleaned up both read/write_scanner() methods so that they are
* a little more readable.
* - Added a lot of Microtek ID's. Thanks to Adrian Perez Jorge.
* - Adopted the __initcall().
* - Added #include <linux/init.h> to scanner.h for __initcall().
* - Added one liner in irq_scanner() to keep gcc from complaining
* about an unused variable (data) if debugging was disabled
* in scanner.c.
* - Increased the timeout parameter in read_scanner() to 120 Secs.
*
*
* 0.4.2 3/23/2000
*
* - Added Umax 1236U ID. Thanks to Philipp Baer <ph_baer@npw.net>.
* - Added Primax, ReadyScan, Visioneer, Colorado, and Genius ID's.
* Thanks to Adrian Perez Jorge <adrianpj@easynews.com>.
* - Fixed error number reported for non-existant devices. Thanks to
* Spyridon Papadimitriou <Spyridon_Papadimitriou@gs91.sp.cs.cmu.edu>.
* - Added Acer Prisascan 620U ID's. Thanks to Joao <joey@knoware.nl>.
* - Replaced __initcall() with module_init()/module_exit(). Updates
* from patch-2.3.48.
* - Replaced file_operations structure with new syntax. Updates
* from patch-2.3.49.
* - Changed #include "usb.h" to #include <linux/usb.h>
* - Added #define SCN_IOCTL to exclude development areas
* since 2.4.x is about to be released. This mainly affects the
* ioctl() stuff. See scanner.h for more details.
* - Changed the return value for signal_pending() from -ERESTARTSYS to
* -EINTR.
*
*
* 0.4.3 4/30/2000
*
* - Added Umax Astra 2200 ID. Thanks to Flynn Marquardt
* <flynn@isr.uni-stuttgart.de>.
* - Added iVina 1200U ID. Thanks to Dyson Lin <dyson@avision.com.tw>.
* - Added access time update for the device file courtesy of Paul
* Mackerras <paulus@samba.org>. This allows a user space daemon
* to turn the lamp off for a Umax 1220U scanner after a prescribed
* time.
* - Fixed HP S20 ID's. Thanks to Ruud Linders <rlinders@xs4all.nl>.
* - Added Acer ScanPrisa 620U ID. Thanks to Oliver
* Schwartz <Oliver.Schwartz@gmx.de> via sane-devel mail list.
* - Fixed bug in read_scanner for copy_to_user() function. The returned
* value should be 'partial' not 'this_read'.
* - Fixed bug in read_scanner. 'count' should be decremented
* by 'this_read' and not by 'partial'. This resulted in twice as many
* calls to read_scanner() for small amounts of data and possibly
* unexpected returns of '0'. Thanks to Karl Heinz
* Kremer <khk@khk.net> and Alain Knaff <Alain.Knaff@ltnb.lu>
* for discovering this.
* - Integrated Randy Dunlap's <randy.dunlap@intel.com> patch for a
* scanner lookup/ident table. Thanks Randy.
* - Documentation updates.
* - Added wait queues to read_scanner().
*
*
* 0.4.3.1
*
* - Fixed HP S20 ID's...again..sigh. Thanks to Ruud
* Linders <rlinders@xs4all.nl>.
*
* 0.4.4
* - Added addtional Mustek ID's (BearPaw 1200, 600 CU, 1200 USB,
* and 1200 UB. Thanks to Henning Meier-Geinitz <henningmg@gmx.de>.
* - Added the Vuego Scan Brisa 340U ID's. Apparently this scanner is
* marketed by Acer Peripherals as a cheap 300 dpi model. Thanks to
* David Gundersen <gundersd@paradise.net.nz>.
* - Added the Epson Expression1600 ID's. Thanks to Karl Heinz
* Kremer <khk@khk.net>.
*
* 0.4.5 2/28/2001
* - Added Mustek ID's (BearPaw 2400, 1200 CU Plus, BearPaw 1200F).
* Thanks to Henning Meier-Geinitz <henningmg@gmx.de>.
* - Added read_timeout module parameter to override RD_NAK_TIMEOUT
* when read()'ing from devices.
* - Stalled pipes are now checked and cleared with
* usb_clear_halt() for the read_scanner() function. This should
* address the "funky result: -32" error messages.
* - Removed Microtek scanner ID's. Microtek scanners are now
* supported via the drivers/usb/microtek.c driver.
* - Added scanner specific read timeout's.
* - Return status errors are NEGATIVE!!! This should address the
* "funky result: -110" error messages.
* - Replaced USB_ST_TIMEOUT with ETIMEDOUT.
* - rd_nak was still defined in MODULE_PARM. It's been updated with
* read_timeout. Thanks to Mark W. Webb <markwebb@adelphia.net> for
* reporting this bug.
* - Added Epson Perfection 1640SU and 1640SU Photo. Thanks to
* Jean-Luc <f5ibh@db0bm.ampr.org> and Manuel
* Pelayo <Manuel.Pelayo@sesips.org>. Reported to work fine by Manuel.
*
* 0.4.6 9/27/2001
* - Added IOCTL's to report back scanner USB ID's. Thanks to
* Karl Heinz <khk@lynx.phpwebhosting.com>
* - Added Umax Astra 2100U ID's. Thanks to Ron
* Wellsted <ron@wellsted.org.uk>.
* and Manuel Pelayo <Manuel.Pelayo@sesips.org>.
* - Added HP 3400 ID's. Thanks to Harald Hannelius <harald@iki.fi>
* and Bertrik Sikken <bertrik@zonnet.nl>. Reported to work at
* htpp://home.zonnet.nl/bertrik/hp3300c/hp3300c.htm.
* - Added Minolta Dimage Scan Dual II ID's. Thanks to Jose Paulo
* Moitinho de Almeida <moitinho@civil.ist.utl.pt>
* - Confirmed addition for SnapScan E20. Thanks to Steffen Hübner
* <hueb_s@gmx.de>.
* - Added Lifetec LT9385 ID's. Thanks to Van Bruwaene Kris
* <krvbr@yahoo.co.uk>
* - Added Agfa SnapScan e26 ID's. Reported to work with SANE
* 1.0.5. Thanks to Falk Sauer <falk@mgnkatze.franken.de>.
* - Added HP 4300 ID's. Thanks to Stefan Schlosser
* <castla@grmmbl.org>.
* - Added Relisis Episode ID's. Thanks to Manfred
* Morgner <odb-devel@gmx.net>.
* - Added many Acer ID's. Thanks to Oliver
* Schwartz <Oliver.Schwartz@gmx.de>.
* - Added Snapscan e40 ID's. Thanks to Oliver
* Schwartz <Oliver.Schwartz@gmx.de>.
* - Thanks to Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>
* for helping with races.
* - Added Epson Perfection 1650 ID's. Thanks to Karl Heinz
* Kremer <khk@khk.net>.
* - Added Epson Perfection 2450 ID's (aka GT-9700 for the Japanese
* market). Thanks to Karl Heinz Kremer <khk@khk.net>.
* - Added Mustek 600 USB ID's. Thanks to Marcus
* Alanen <maalanen@ra.abo.fi>.
* - Added Acer ScanPrisa 1240UT ID's. Thanks to Morgan
* Collins <sirmorcant@morcant.org>.
* - Incorporated devfs patches!! Thanks to Tom Rini
* <trini@kernel.crashing.org>, Pavel Roskin <proski@gnu.org>,
* Greg KH <greg@kroah.com>, Yves Duret <yduret@mandrakesoft.com>,
* Flavio Stanchina <flavio.stanchina@tin.it>.
* - Removed Minolta ScanImage II. This scanner uses USB SCSI. Thanks
* to Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de> for pointing
* this out.
* - Added additional SMP locking. Thanks to David Brownell and
* Oliver Neukum for their help.
* - Added version reporting - reports for both module load and modinfo
* - Started path to hopefully straighten/clean out ioctl()'s.
* - Users are now notified to consult the Documentation/usb/scanner.txt
* for common error messages rather than the maintainer.
*
* 0.4.7 11/28/2001
* - Fixed typo in Documentation/usb/scanner.txt. Thanks to
* Karel <karel.vervaeke@pandora.be> for pointing it out.
* - Added ID's for a Memorex 6136u. Thanks to Álvaro Gaspar de
* Valenzuela" <agaspard@utsi.edu>.
* - Added ID's for Agfa e25. Thanks to Heinrich
* Rust <Heinrich.Rust@gmx.de>. Also reported to work with
* Linux and SANE (?).
* - Added Canon FB620U, D646U, and 1220U ID's. Thanks to Paul
* Rensing <Paul_Rensing@StanfordAlumni.org>. For more info
* on Linux support for these models, contact
* salvestrini@users.sourceforge.net.
* - Added Plustek OpticPro UT12, OpticPro U24, KYE/Genius
* ColorPage-HR6 V2 ID's in addition to many "Unknown" models
* under those vendors. Thanks to
* Jaeger, Gerhard" <g.jaeger@earthling.net>. These scanner are
* apparently based upon the LM983x IC's.
* - Applied Frank's patch that addressed some locking and module
* referencing counts. Thanks to both
* Frank Zago <fzago@greshamstorage.com> and
* Oliver Neukum <520047054719-0001@t-online.de> for reviewing/testing.
*
* 0.4.8 5/30/2002
* - Added Mustek BearPaw 2400 TA. Thanks to Sergey
* Vlasov <vsu@mivlgu.murom.ru>.
* - Added Mustek 1200UB Plus and Mustek BearPaw 1200 CU ID's. These use
* the Grandtech GT-6801 chip. Thanks to Henning
* Meier-Geinitz <henning@meier-geinitz.de>.
* - Increased Epson timeout to 60 secs as requested from
* Karl Heinz Kremer <khk@khk.net>.
* - Changed maintainership from David E. Nelson to Brian
* Beattie <beattie@beattie-home.net>.
*
* 0.4.9 12/19/2002
* - Added vendor/product ids for Nikon, Mustek, Plustek, Genius, Epson,
* Canon, Umax, Hewlett-Packard, Benq, Agfa, Minolta scanners.
* Thanks to Dieter Faulbaum <faulbaum@mail.bessy.de>, Stian Jordet
* <liste@jordet.nu>, "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>,
* "Jaeger, Gerhard" <gerhard@gjaeger.de>, Ira Childress
* <ichildress@mn.rr.com>, Till Kamppeter <till.kamppeter@gmx.net>,
* Ed Hamrick <EdHamrick@aol.com>, Oliver Schwartz
* <Oliver.Schwartz@gmx.de> and everyone else who sent ids.
* - Some Benq, Genius and Plustek ids are identified now.
* - Accept scanners with only one bulk (in) endpoint (thanks to Sergey
* Vlasov <vsu@mivlgu.murom.ru>).
* - Accept devices with more than one interface. Only use interfaces that
* look like belonging to scanners.
* - Fix compilation error when debugging is enabled.
* - Add locking to ioctl_scanner(). Thanks to Oliver Neukum
* <oliver@neukum.name>.
*
* 0.4.10 01/07/2003
* - Added vendor/product ids for Artec, Canon, Compaq, Epson, HP, Microtek
* and Visioneer scanners. Thanks to William Lam <wklam@triad.rr.com>,
* Till Kamppeter <till.kamppeter@gmx.net> and others for all the ids.
* - Cleaned up list of vendor/product ids.
* - Print information about user-supplied ids only once at startup instead
* of every time any USB device is plugged in.
* - Removed PV8630 ioctls. Use the standard ioctls instead.
* - Made endpoint detection more generic. Basically, only one bulk-in
* endpoint is required, everything else is optional.
* - New maintainer: Henning Meier-Geinitz.
* - Print ids and device number when a device was detected.
* - Don't print errors when the device is busy.
*
* 0.4.11 2003-02-25
* - Added vendor/product ids for Artec, Avision, Brother, Canon, Compaq,
* Fujitsu, Hewlett-Packard, Lexmark, LG Electronics, Medion, Microtek,
* Primax, Prolink, Plustek, SYSCAN, Trust and UMAX scanners.
* - Fixed generation of devfs names if dynamic minors are disabled.
* - Used kobject reference counting to free the scn struct when the device
* is closed and disconnected. Avoids crashes when writing to a
* disconnected device. (Thanks to Greg KH).
*
* 0.4.12 2003-04-11
* - Fixed endpoint detection. The endpoints were numbered from 1 to n but
* that assumption is not correct in all cases.
*
* 0.4.13 2003-05-30
* - Added vendor/product ids for Genius, Hewlett-Packard, Microtek,
* Mustek, Pacific Image Electronics, Plustek, and Visioneer scanners.
* Fixed names of some other scanners.
*
* 0.4.14 2003-07-15
* - Fixed race between open and probe (Oliver Neukum).
* - Added vendor/product ids for Avision, Canon, HP, Microtek and Relisys scanners.
* - Clean up irq urb when not enough memory is available.
*
* 0.4.15 2003-09-22
* - Use static declarations for usb_scanner_init/usb_scanner_exit
* (Daniele Bellucci).
* - Report back return codes of usb_register and usb_usbmit_urb instead of -1 or
* -ENONMEM (Daniele Bellucci).
* - Balancing usb_register_dev/usb_deregister_dev in probe_scanner when a fail
* condition occours (Daniele Bellucci).
* - Added vendor/product ids for Canon, HP, Microtek, Mustek, Siemens, UMAX, and
* Visioneer scanners.
* - Added test for USB_CLASS_CDC_DATA which is used by some fingerprint scanners.
*
* 0.4.16 2003-11-04
* - Added vendor/product ids for Epson, Genius, Microtek, Plustek, Reflecta, and
* Visioneer scanners. Removed ids for HP PSC devices as these are supported by
* the hpoj userspace driver.
*
* TODO
* - Performance
* - Select/poll methods
* - More testing
* - More general usage ioctl's
*
*
* Thanks to:
*
* - All the folks on the linux-usb list who put up with me. :) This
* has been a great learning experience for me.
* - To Linus Torvalds for this great OS.
* - The GNU folks.
* - The folks that forwarded Vendor:Product ID's to me.
* - Johannes Erdfelt for the loaning of a USB analyzer for tracking an
* issue with HP-4100 and uhci.
* - Adolfo Montero for his assistance.
* - All the folks who chimed in with reports and suggestions.
* - All the developers that are working on USB SANE backends or other
* applications to use USB scanners.
* - Thanks to Greg KH <greg@kroah.com> for setting up Brian Beattie
* and Henning Meier-Geinitz to be the new USB Scanner maintainer.
*
* Performance:
*
* System: Pentium 120, 80 MB RAM, OHCI, Linux 2.3.23, HP 4100C USB Scanner
* 300 dpi scan of the entire bed
* 24 Bit Color ~ 70 secs - 3.6 Mbit/sec
* 8 Bit Gray ~ 17 secs - 4.2 Mbit/sec */
/*
* For documentation, see Documentation/usb/scanner.txt.
* Website: http://www.meier-geinitz.de/kernel/
* Please contact the maintainer if your scanner is not detected by this
* driver automatically.
*/
#include <asm/byteorder.h>
/*
* Scanner definitions, macros, module info,
* debug/ioctl/data_dump enable, and other constants.
*/
#include "scanner.h"
static
void
irq_scanner
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
/*
* For the meantime, this is just a placeholder until I figure out what
* all I want to do with it -- or somebody else for that matter.
*/
struct
scn_usb_data
*
scn
;
unsigned
char
*
data
;
int
status
;
scn
=
urb
->
context
;
data
=
&
scn
->
button
;
data
+=
0
;
/* Keep gcc from complaining about unused var */
switch
(
urb
->
status
)
{
case
0
:
/* success */
break
;
case
-
ECONNRESET
:
case
-
ENOENT
:
case
-
ESHUTDOWN
:
/* this urb is terminated, clean up */
dbg
(
"%s - urb shutting down with status: %d"
,
__FUNCTION__
,
urb
->
status
);
return
;
default:
dbg
(
"%s - nonzero urb status received: %d"
,
__FUNCTION__
,
urb
->
status
);
return
;
}
dbg
(
"irq_scanner(%d): data:%x"
,
scn
->
scn_minor
,
*
data
);
status
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
if
(
status
)
err
(
"%s - usb_submit_urb failed with result %d"
,
__FUNCTION__
,
status
);
}
static
int
open_scanner
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
scn_usb_data
*
scn
;
struct
usb_device
*
dev
;
struct
usb_interface
*
intf
;
int
scn_minor
;
int
err
=
0
;
down
(
&
scn_mutex
);
scn_minor
=
USB_SCN_MINOR
(
inode
);
dbg
(
"open_scanner: scn_minor:%d"
,
scn_minor
);
intf
=
usb_find_interface
(
&
scanner_driver
,
scn_minor
);
if
(
!
intf
)
{
up
(
&
scn_mutex
);
err
(
"open_scanner(%d): Unable to access minor data"
,
scn_minor
);
return
-
ENODEV
;
}
scn
=
usb_get_intfdata
(
intf
);
kobject_get
(
&
scn
->
kobj
);
dev
=
scn
->
scn_dev
;
down
(
&
(
scn
->
sem
));
/* Now protect the scn_usb_data structure */
up
(
&
scn_mutex
);
/* Now handled by the above */
if
(
!
dev
)
{
err
(
"open_scanner(%d): Scanner device not present"
,
scn_minor
);
err
=
-
ENODEV
;
goto
out_error
;
}
if
(
!
scn
->
present
)
{
err
(
"open_scanner(%d): Scanner is not present"
,
scn_minor
);
err
=
-
ENODEV
;
goto
out_error
;
}
if
(
scn
->
isopen
)
{
dbg
(
"open_scanner(%d): Scanner device is already open"
,
scn_minor
);
err
=
-
EBUSY
;
goto
out_error
;
}
init_waitqueue_head
(
&
scn
->
rd_wait_q
);
scn
->
isopen
=
1
;
file
->
private_data
=
scn
;
/* Used by the read and write methods */
out_error:
up
(
&
(
scn
->
sem
));
/* Wake up any possible contending processes */
return
err
;
}
static
int
close_scanner
(
struct
inode
*
inode
,
struct
file
*
file
)
{
struct
scn_usb_data
*
scn
=
file
->
private_data
;
int
scn_minor
;
scn_minor
=
USB_SCN_MINOR
(
inode
);
dbg
(
"close_scanner: scn_minor:%d"
,
scn_minor
);
down
(
&
scn_mutex
);
down
(
&
(
scn
->
sem
));
scn
->
isopen
=
0
;
file
->
private_data
=
NULL
;
up
(
&
scn_mutex
);
up
(
&
(
scn
->
sem
));
kobject_put
(
&
scn
->
kobj
);
return
0
;
}
static
ssize_t
write_scanner
(
struct
file
*
file
,
const
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
struct
scn_usb_data
*
scn
;
struct
usb_device
*
dev
;
ssize_t
bytes_written
=
0
;
/* Overall count of bytes written */
ssize_t
ret
=
0
;
int
scn_minor
;
int
this_write
;
/* Number of bytes to write */
int
partial
;
/* Number of bytes successfully written */
int
result
=
0
;
char
*
obuf
;
scn
=
file
->
private_data
;
down
(
&
(
scn
->
sem
));
if
(
!
scn
->
bulk_out_ep
)
{
/* This scanner does not have a bulk-out endpoint */
up
(
&
(
scn
->
sem
));
return
-
EINVAL
;
}
scn_minor
=
scn
->
scn_minor
;
obuf
=
scn
->
obuf
;
dev
=
scn
->
scn_dev
;
file
->
f_dentry
->
d_inode
->
i_atime
=
CURRENT_TIME
;
while
(
count
>
0
)
{
if
(
signal_pending
(
current
))
{
ret
=
-
ERESTARTSYS
;
break
;
}
this_write
=
(
count
>=
OBUF_SIZE
)
?
OBUF_SIZE
:
count
;
if
(
copy_from_user
(
scn
->
obuf
,
buffer
,
this_write
))
{
ret
=
-
EFAULT
;
break
;
}
result
=
usb_bulk_msg
(
dev
,
usb_sndbulkpipe
(
dev
,
scn
->
bulk_out_ep
),
obuf
,
this_write
,
&
partial
,
60
*
HZ
);
dbg
(
"write stats(%d): result:%d this_write:%d partial:%d"
,
scn_minor
,
result
,
this_write
,
partial
);
if
(
result
==
-
ETIMEDOUT
)
{
/* NAK -- shouldn't happen */
warn
(
"write_scanner: NAK received."
);
ret
=
result
;
break
;
}
else
if
(
result
<
0
)
{
/* We should not get any I/O errors */
warn
(
"write_scanner(%d): funky result: %d. Consult Documentataion/usb/scanner.txt."
,
scn_minor
,
result
);
ret
=
-
EIO
;
break
;
}
#ifdef WR_DATA_DUMP
if
(
partial
)
{
unsigned
char
cnt
,
cnt_max
;
cnt_max
=
(
partial
>
24
)
?
24
:
partial
;
printk
(
KERN_DEBUG
"dump(%d): "
,
scn_minor
);
for
(
cnt
=
0
;
cnt
<
cnt_max
;
cnt
++
)
{
printk
(
"%X "
,
obuf
[
cnt
]);
}
printk
(
"
\n
"
);
}
#endif
if
(
partial
!=
this_write
)
{
/* Unable to write all contents of obuf */
ret
=
-
EIO
;
break
;
}
if
(
partial
)
{
/* Data written */
buffer
+=
partial
;
count
-=
partial
;
bytes_written
+=
partial
;
}
else
{
/* No data written */
ret
=
0
;
break
;
}
}
up
(
&
(
scn
->
sem
));
mdelay
(
5
);
/* This seems to help with SANE queries */
return
ret
?
ret
:
bytes_written
;
}
static
ssize_t
read_scanner
(
struct
file
*
file
,
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
{
struct
scn_usb_data
*
scn
;
struct
usb_device
*
dev
;
ssize_t
bytes_read
;
/* Overall count of bytes_read */
ssize_t
ret
;
int
scn_minor
;
int
partial
;
/* Number of bytes successfully read */
int
this_read
;
/* Max number of bytes to read */
int
result
;
int
rd_expire
=
RD_EXPIRE
;
char
*
ibuf
;
scn
=
file
->
private_data
;
down
(
&
(
scn
->
sem
));
scn_minor
=
scn
->
scn_minor
;
ibuf
=
scn
->
ibuf
;
dev
=
scn
->
scn_dev
;
bytes_read
=
0
;
ret
=
0
;
file
->
f_dentry
->
d_inode
->
i_atime
=
CURRENT_TIME
;
/* Update the
atime of
the device
node */
while
(
count
>
0
)
{
if
(
signal_pending
(
current
))
{
ret
=
-
ERESTARTSYS
;
break
;
}
this_read
=
(
count
>=
IBUF_SIZE
)
?
IBUF_SIZE
:
count
;
result
=
usb_bulk_msg
(
dev
,
usb_rcvbulkpipe
(
dev
,
scn
->
bulk_in_ep
),
ibuf
,
this_read
,
&
partial
,
scn
->
rd_nak_timeout
);
dbg
(
"read stats(%d): result:%d this_read:%d partial:%d count:%d"
,
scn_minor
,
result
,
this_read
,
partial
,
count
);
/*
* Scanners are sometimes inheriently slow since they are mechanical
* in nature. USB bulk reads tend to timeout while the scanner is
* positioning, resetting, warming up the lamp, etc if the timeout is
* set too low. A very long timeout parameter for bulk reads was used
* to overcome this limitation, but this sometimes resulted in folks
* having to wait for the timeout to expire after pressing Ctrl-C from
* an application. The user was sometimes left with the impression
* that something had hung or crashed when in fact the USB read was
* just waiting on data. So, the below code retains the same long
* timeout period, but splits it up into smaller parts so that
* Ctrl-C's are acted upon in a reasonable amount of time.
*/
if
(
result
==
-
ETIMEDOUT
)
{
/* NAK */
if
(
!
partial
)
{
/* No data */
if
(
--
rd_expire
<=
0
)
{
/* Give it up */
warn
(
"read_scanner(%d): excessive NAK's received"
,
scn_minor
);
ret
=
result
;
break
;
}
else
{
/* Keep trying to read data */
interruptible_sleep_on_timeout
(
&
scn
->
rd_wait_q
,
scn
->
rd_nak_timeout
);
continue
;
}
}
else
{
/* Timeout w/ some data */
goto
data_recvd
;
}
}
if
(
result
==
-
EPIPE
)
{
/* No hope */
if
(
usb_clear_halt
(
dev
,
scn
->
bulk_in_ep
))
{
err
(
"read_scanner(%d): Failure to clear endpoint halt condition (%Zd)."
,
scn_minor
,
ret
);
}
ret
=
result
;
break
;
}
else
if
((
result
<
0
)
&&
(
result
!=
-
EREMOTEIO
))
{
warn
(
"read_scanner(%d): funky result:%d. Consult Documentation/usb/scanner.txt."
,
scn_minor
,
(
int
)
result
);
ret
=
-
EIO
;
break
;
}
data_recvd:
#ifdef RD_DATA_DUMP
if
(
partial
)
{
unsigned
char
cnt
,
cnt_max
;
cnt_max
=
(
partial
>
24
)
?
24
:
partial
;
printk
(
KERN_DEBUG
"dump(%d): "
,
scn_minor
);
for
(
cnt
=
0
;
cnt
<
cnt_max
;
cnt
++
)
{
printk
(
"%X "
,
ibuf
[
cnt
]);
}
printk
(
"
\n
"
);
}
#endif
if
(
partial
)
{
/* Data returned */
if
(
copy_to_user
(
buffer
,
ibuf
,
partial
))
{
ret
=
-
EFAULT
;
break
;
}
count
-=
this_read
;
/* Compensate for short reads */
bytes_read
+=
partial
;
/* Keep tally of what actually was read */
buffer
+=
partial
;
}
else
{
ret
=
0
;
break
;
}
}
up
(
&
(
scn
->
sem
));
return
ret
?
ret
:
bytes_read
;
}
static
int
ioctl_scanner
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
struct
usb_device
*
dev
;
struct
scn_usb_data
*
scn
=
file
->
private_data
;
int
retval
=
-
ENOTTY
;
int
scn_minor
;
scn_minor
=
USB_SCN_MINOR
(
inode
);
down
(
&
(
scn
->
sem
));
dev
=
scn
->
scn_dev
;
switch
(
cmd
)
{
case
SCANNER_IOCTL_VENDOR
:
retval
=
(
put_user
(
dev
->
descriptor
.
idVendor
,
(
unsigned
int
*
)
arg
));
break
;
case
SCANNER_IOCTL_PRODUCT
:
retval
=
(
put_user
(
dev
->
descriptor
.
idProduct
,
(
unsigned
int
*
)
arg
));
break
;
case
SCANNER_IOCTL_CTRLMSG
:
{
struct
ctrlmsg_ioctl
{
struct
usb_ctrlrequest
req
;
void
*
data
;
}
cmsg
;
int
pipe
,
nb
,
ret
;
unsigned
char
buf
[
64
];
retval
=
0
;
if
(
copy_from_user
(
&
cmsg
,
(
void
*
)
arg
,
sizeof
(
cmsg
)))
{
retval
=
-
EFAULT
;
break
;
}
nb
=
cmsg
.
req
.
wLength
;
if
(
nb
>
sizeof
(
buf
))
{
retval
=
-
EINVAL
;
break
;
}
if
((
cmsg
.
req
.
bRequestType
&
0x80
)
==
0
)
{
pipe
=
usb_sndctrlpipe
(
dev
,
0
);
if
(
nb
>
0
&&
copy_from_user
(
buf
,
cmsg
.
data
,
nb
))
{
retval
=
-
EFAULT
;
break
;
}
}
else
{
pipe
=
usb_rcvctrlpipe
(
dev
,
0
);
}
ret
=
usb_control_msg
(
dev
,
pipe
,
cmsg
.
req
.
bRequest
,
cmsg
.
req
.
bRequestType
,
cmsg
.
req
.
wValue
,
cmsg
.
req
.
wIndex
,
buf
,
nb
,
HZ
);
if
(
ret
<
0
)
{
err
(
"ioctl_scanner(%d): control_msg returned %d
\n
"
,
scn_minor
,
ret
);
retval
=
-
EIO
;
break
;
}
if
(
nb
>
0
&&
(
cmsg
.
req
.
bRequestType
&
0x80
)
&&
copy_to_user
(
cmsg
.
data
,
buf
,
nb
))
retval
=
-
EFAULT
;
break
;
}
default:
break
;
}
up
(
&
(
scn
->
sem
));
return
retval
;
}
static
void
destroy_scanner
(
struct
kobject
*
kobj
)
{
struct
scn_usb_data
*
scn
;
dbg
(
"%s"
,
__FUNCTION__
);
scn
=
to_scanner
(
kobj
);
down
(
&
scn_mutex
);
down
(
&
(
scn
->
sem
));
usb_driver_release_interface
(
&
scanner_driver
,
scn
->
scn_dev
->
actconfig
->
interface
[
scn
->
ifnum
]);
kfree
(
scn
->
ibuf
);
kfree
(
scn
->
obuf
);
usb_free_urb
(
scn
->
scn_irq
);
usb_put_dev
(
scn
->
scn_dev
);
up
(
&
(
scn
->
sem
));
kfree
(
scn
);
up
(
&
scn_mutex
);
}
static
struct
kobj_type
scanner_kobj_type
=
{
.
release
=
destroy_scanner
,
};
static
struct
file_operations
usb_scanner_fops
=
{
.
owner
=
THIS_MODULE
,
.
read
=
read_scanner
,
.
write
=
write_scanner
,
.
ioctl
=
ioctl_scanner
,
.
open
=
open_scanner
,
.
release
=
close_scanner
,
};
static
struct
usb_class_driver
scanner_class
=
{
.
name
=
"usb/scanner%d"
,
.
fops
=
&
usb_scanner_fops
,
.
mode
=
S_IFCHR
|
S_IRUSR
|
S_IWUSR
|
S_IRGRP
|
S_IWGRP
|
S_IROTH
|
S_IWOTH
,
.
minor_base
=
SCN_BASE_MNR
,
};
static
int
probe_scanner
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
struct
usb_device
*
dev
=
interface_to_usbdev
(
intf
);
struct
scn_usb_data
*
scn
;
struct
usb_host_interface
*
interface
;
struct
usb_endpoint_descriptor
*
endpoint
;
int
ep_cnt
;
int
ix
;
int
retval
;
char
valid_device
=
0
;
char
have_bulk_in
,
have_bulk_out
,
have_intr
;
char
name
[
14
];
dbg
(
"probe_scanner: USB dev address:%p"
,
dev
);
/*
* 1. Check Vendor/Product
* 2. Determine/Assign Bulk Endpoints
* 3. Determine/Assign Intr Endpoint
*/
/*
* There doesn't seem to be an imaging class defined in the USB
* Spec. (yet). If there is, HP isn't following it and it doesn't
* look like anybody else is either. Therefore, we have to test the
* Vendor and Product ID's to see what we have. Also, other scanners
* may be able to use this driver by specifying both vendor and
* product ID's as options to the scanner module in conf.modules.
*
* NOTE: Just because a product is supported here does not mean that
* applications exist that support the product. It's in the hopes
* that this will allow developers a means to produce applications
* that will support USB products.
*
* Until we detect a device which is pleasing, we silently punt.
*/
for
(
ix
=
0
;
ix
<
sizeof
(
scanner_device_ids
)
/
sizeof
(
struct
usb_device_id
);
ix
++
)
{
if
((
dev
->
descriptor
.
idVendor
==
scanner_device_ids
[
ix
].
idVendor
)
&&
(
dev
->
descriptor
.
idProduct
==
scanner_device_ids
[
ix
].
idProduct
))
{
valid_device
=
1
;
break
;
}
}
if
(
dev
->
descriptor
.
idVendor
==
vendor
&&
/* User specified */
dev
->
descriptor
.
idProduct
==
product
)
{
/* User specified */
valid_device
=
1
;
}
if
(
!
valid_device
)
return
-
ENODEV
;
/* We didn't find anything pleasing */
/*
* After this point we can be a little noisy about what we are trying to
* configure.
*/
if
(
dev
->
descriptor
.
bNumConfigurations
!=
1
)
{
info
(
"probe_scanner: Only one device configuration is supported."
);
return
-
ENODEV
;
}
interface
=
intf
->
altsetting
;
if
(
interface
[
0
].
desc
.
bInterfaceClass
!=
USB_CLASS_VENDOR_SPEC
&&
interface
[
0
].
desc
.
bInterfaceClass
!=
USB_CLASS_PER_INTERFACE
&&
interface
[
0
].
desc
.
bInterfaceClass
!=
USB_CLASS_CDC_DATA
&&
interface
[
0
].
desc
.
bInterfaceClass
!=
SCN_CLASS_SCANJET
)
{
dbg
(
"probe_scanner: This interface doesn't look like a scanner (class=0x%x)."
,
interface
[
0
].
desc
.
bInterfaceClass
);
return
-
ENODEV
;
}
/*
* Start checking for bulk and interrupt endpoints. We are only using the first
* one of each type of endpoint. If we have an interrupt endpoint go ahead and
* setup the handler. FIXME: This is a future enhancement...
*/
dbg
(
"probe_scanner: Number of Endpoints:%d"
,
(
int
)
interface
->
desc
.
bNumEndpoints
);
ep_cnt
=
have_bulk_in
=
have_bulk_out
=
have_intr
=
0
;
while
(
ep_cnt
<
interface
->
desc
.
bNumEndpoints
)
{
endpoint
=
&
interface
->
endpoint
[
ep_cnt
].
desc
;
if
(
IS_EP_BULK_IN
(
endpoint
))
{
ep_cnt
++
;
if
(
have_bulk_in
)
{
info
(
"probe_scanner: ignoring additional bulk_in_ep:%d"
,
ep_cnt
);
continue
;
}
have_bulk_in
=
endpoint
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
dbg
(
"probe_scanner: bulk_in_ep:%d"
,
have_bulk_in
);
continue
;
}
if
(
IS_EP_BULK_OUT
(
endpoint
))
{
ep_cnt
++
;
if
(
have_bulk_out
)
{
info
(
"probe_scanner: ignoring additional bulk_out_ep:%d"
,
ep_cnt
);
continue
;
}
have_bulk_out
=
endpoint
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
dbg
(
"probe_scanner: bulk_out_ep:%d"
,
have_bulk_out
);
continue
;
}
if
(
IS_EP_INTR
(
endpoint
))
{
ep_cnt
++
;
if
(
have_intr
)
{
info
(
"probe_scanner: ignoring additional intr_ep:%d"
,
ep_cnt
);
continue
;
}
have_intr
=
endpoint
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
dbg
(
"probe_scanner: intr_ep:%d"
,
have_intr
);
continue
;
}
info
(
"probe_scanner: Undetected endpoint -- consult Documentation/usb/scanner.txt."
);
return
-
EIO
;
/* Shouldn't ever get here unless we have something weird */
}
/*
* Perform a quick check to make sure that everything worked as it
* should have.
*/
if
(
!
have_bulk_in
)
{
err
(
"probe_scanner: One bulk-in endpoint required."
);
return
-
EIO
;
}
/*
* Determine a minor number and initialize the structure associated
* with it. The problem with this is that we are counting on the fact
* that the user will sequentially add device nodes for the scanner
* devices. */
down
(
&
scn_mutex
);
retval
=
usb_register_dev
(
intf
,
&
scanner_class
);
if
(
retval
)
{
err
(
"Not able to get a minor for this device."
);
up
(
&
scn_mutex
);
return
-
ENOMEM
;
}
dbg
(
"probe_scanner: Allocated minor:%d"
,
intf
->
minor
);
if
(
!
(
scn
=
kmalloc
(
sizeof
(
struct
scn_usb_data
),
GFP_KERNEL
)))
{
err
(
"probe_scanner: Out of memory."
);
up
(
&
scn_mutex
);
return
-
ENOMEM
;
}
memset
(
scn
,
0
,
sizeof
(
struct
scn_usb_data
));
kobject_init
(
&
scn
->
kobj
);
scn
->
kobj
.
ktype
=
&
scanner_kobj_type
;
scn
->
scn_irq
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
scn
->
scn_irq
)
{
usb_deregister_dev
(
intf
,
&
scanner_class
);
kfree
(
scn
);
up
(
&
scn_mutex
);
return
-
ENOMEM
;
}
init_MUTEX
(
&
(
scn
->
sem
));
/* Initializes to unlocked */
dbg
(
"probe_scanner(%d): Address of scn:%p"
,
intf
->
minor
,
scn
);
/* Ok, if we detected an interrupt EP, setup a handler for it */
if
(
have_intr
)
{
dbg
(
"probe_scanner(%d): Configuring IRQ handler for intr EP:%d"
,
intf
->
minor
,
have_intr
);
usb_fill_int_urb
(
scn
->
scn_irq
,
dev
,
usb_rcvintpipe
(
dev
,
have_intr
),
&
scn
->
button
,
1
,
irq_scanner
,
scn
,
// endpoint[(int)have_intr].bInterval);
250
);
retval
=
usb_submit_urb
(
scn
->
scn_irq
,
GFP_KERNEL
);
if
(
retval
)
{
err
(
"probe_scanner(%d): Unable to allocate INT URB."
,
intf
->
minor
);
usb_deregister_dev
(
intf
,
&
scanner_class
);
kfree
(
scn
);
up
(
&
scn_mutex
);
return
retval
;
}
}
/* Ok, now initialize all the relevant values */
if
(
!
(
scn
->
obuf
=
(
char
*
)
kmalloc
(
OBUF_SIZE
,
GFP_KERNEL
)))
{
err
(
"probe_scanner(%d): Not enough memory for the output buffer."
,
intf
->
minor
);
if
(
have_intr
)
usb_unlink_urb
(
scn
->
scn_irq
);
usb_free_urb
(
scn
->
scn_irq
);
usb_deregister_dev
(
intf
,
&
scanner_class
);
kfree
(
scn
);
up
(
&
scn_mutex
);
return
-
ENOMEM
;
}
dbg
(
"probe_scanner(%d): obuf address:%p"
,
intf
->
minor
,
scn
->
obuf
);
if
(
!
(
scn
->
ibuf
=
(
char
*
)
kmalloc
(
IBUF_SIZE
,
GFP_KERNEL
)))
{
err
(
"probe_scanner(%d): Not enough memory for the input buffer."
,
intf
->
minor
);
if
(
have_intr
)
usb_unlink_urb
(
scn
->
scn_irq
);
usb_free_urb
(
scn
->
scn_irq
);
usb_deregister_dev
(
intf
,
&
scanner_class
);
kfree
(
scn
->
obuf
);
kfree
(
scn
);
up
(
&
scn_mutex
);
return
-
ENOMEM
;
}
dbg
(
"probe_scanner(%d): ibuf address:%p"
,
intf
->
minor
,
scn
->
ibuf
);
switch
(
dev
->
descriptor
.
idVendor
)
{
/* Scanner specific read timeout parameters */
case
0x04b8
:
/* Seiko/Epson */
scn
->
rd_nak_timeout
=
HZ
*
60
;
break
;
case
0x055f
:
/* Mustek */
case
0x0400
:
/* Another Mustek */
scn
->
rd_nak_timeout
=
HZ
*
1
;
default:
scn
->
rd_nak_timeout
=
RD_NAK_TIMEOUT
;
}
if
(
read_timeout
>
0
)
{
/* User specified read timeout overrides everything */
info
(
"probe_scanner: User specified USB read timeout - %d"
,
read_timeout
);
scn
->
rd_nak_timeout
=
read_timeout
;
}
usb_get_dev
(
dev
);
scn
->
bulk_in_ep
=
have_bulk_in
;
scn
->
bulk_out_ep
=
have_bulk_out
;
scn
->
intr_ep
=
have_intr
;
scn
->
present
=
1
;
scn
->
scn_dev
=
dev
;
scn
->
scn_minor
=
intf
->
minor
;
scn
->
isopen
=
0
;
snprintf
(
name
,
sizeof
(
name
),
scanner_class
.
name
,
intf
->
minor
-
scanner_class
.
minor_base
);
info
(
"USB scanner device (0x%04x/0x%04x) now attached to %s"
,
dev
->
descriptor
.
idVendor
,
dev
->
descriptor
.
idProduct
,
name
);
usb_set_intfdata
(
intf
,
scn
);
up
(
&
scn_mutex
);
return
0
;
}
static
void
disconnect_scanner
(
struct
usb_interface
*
intf
)
{
struct
scn_usb_data
*
scn
=
usb_get_intfdata
(
intf
);
/* disable open() */
dbg
(
"%s: De-allocating minor:%d"
,
__FUNCTION__
,
scn
->
scn_minor
);
usb_deregister_dev
(
intf
,
&
scanner_class
);
usb_set_intfdata
(
intf
,
NULL
);
if
(
scn
->
intr_ep
)
{
dbg
(
"%s(%d): Unlinking IRQ URB"
,
__FUNCTION__
,
scn
->
scn_minor
);
usb_unlink_urb
(
scn
->
scn_irq
);
}
if
(
scn
)
kobject_put
(
&
scn
->
kobj
);
}
/* we want to look at all devices, as the vendor/product id can change
* depending on the command line argument */
static
struct
usb_device_id
ids
[]
=
{
{.
driver_info
=
42
},
{}
};
static
struct
usb_driver
scanner_driver
=
{
.
owner
=
THIS_MODULE
,
.
name
=
"usbscanner"
,
.
probe
=
probe_scanner
,
.
disconnect
=
disconnect_scanner
,
.
id_table
=
ids
,
};
static
void
__exit
usb_scanner_exit
(
void
)
{
usb_deregister
(
&
scanner_driver
);
}
static
int
__init
usb_scanner_init
(
void
)
{
int
retval
;
retval
=
usb_register
(
&
scanner_driver
);
if
(
retval
)
goto
out
;
info
(
DRIVER_VERSION
":"
DRIVER_DESC
);
if
(
vendor
!=
-
1
&&
product
!=
-
1
)
info
(
"probe_scanner: User specified USB scanner -- Vendor:Product - %x:%x"
,
vendor
,
product
);
out:
return
retval
;
}
module_init
(
usb_scanner_init
);
module_exit
(
usb_scanner_exit
);
drivers/usb/image/scanner.h
deleted
100644 → 0
View file @
9e81ab3b
/*
* Driver for USB Scanners (linux-2.6)
*
* Copyright (C) 1999, 2000, 2001, 2002 David E. Nelson
* Previously maintained by Brian Beattie
*
* Current maintainer: Henning Meier-Geinitz <henning@meier-geinitz.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* For documentation, see Documentation/usb/scanner.txt.
* Website: http://www.meier-geinitz.de/kernel/
* Please contact the maintainer if your scanner is not detected by this
* driver automatically.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/ioctl.h>
#include <linux/sched.h>
#include <linux/smp_lock.h>
// #define DEBUG
#define DRIVER_VERSION "0.4.16"
#define DRIVER_DESC "USB Scanner Driver"
#include <linux/usb.h>
static
__s32
vendor
=-
1
,
product
=-
1
,
read_timeout
=
0
;
MODULE_AUTHOR
(
"Henning Meier-Geinitz, henning@meier-geinitz.de"
);
MODULE_DESCRIPTION
(
DRIVER_DESC
" "
DRIVER_VERSION
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
vendor
,
"i"
);
MODULE_PARM_DESC
(
vendor
,
"User specified USB idVendor"
);
MODULE_PARM
(
product
,
"i"
);
MODULE_PARM_DESC
(
product
,
"User specified USB idProduct"
);
MODULE_PARM
(
read_timeout
,
"i"
);
MODULE_PARM_DESC
(
read_timeout
,
"User specified read timeout in seconds"
);
/* WARNING: These DATA_DUMP's can produce a lot of data. Caveat Emptor. */
// #define RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */
// #define WR_DATA_DUMP /* DEBUG does not have to be defined. */
static
struct
usb_device_id
scanner_device_ids
[]
=
{
/* Acer (now Benq) */
{
USB_DEVICE
(
0x04a5
,
0x1a20
)
},
/* Prisa 310U */
{
USB_DEVICE
(
0x04a5
,
0x1a2a
)
},
/* Another 620U */
{
USB_DEVICE
(
0x04a5
,
0x2022
)
},
/* 340U */
{
USB_DEVICE
(
0x04a5
,
0x2040
)
},
/* 620U (!) */
{
USB_DEVICE
(
0x04a5
,
0x2060
)
},
/* 620U & 640U (!)*/
{
USB_DEVICE
(
0x04a5
,
0x207e
)
},
/* 640BU */
{
USB_DEVICE
(
0x04a5
,
0x20b0
)
},
/* Benq 4300 */
{
USB_DEVICE
(
0x04a5
,
0x20be
)
},
/* Unknown - Oliver Schwartz */
{
USB_DEVICE
(
0x04a5
,
0x20c0
)
},
/* 1240UT, 1240U */
{
USB_DEVICE
(
0x04a5
,
0x20de
)
},
/* S2W 3300U */
{
USB_DEVICE
(
0x04a5
,
0x20fc
)
},
/* Benq 5000 */
{
USB_DEVICE
(
0x04a5
,
0x20fe
)
},
/* Benq 5300 */
/* Agfa */
{
USB_DEVICE
(
0x06bd
,
0x0001
)
},
/* SnapScan 1212U */
{
USB_DEVICE
(
0x06bd
,
0x0002
)
},
/* SnapScan 1236U */
{
USB_DEVICE
(
0x06bd
,
0x0100
)
},
/* SnapScan Touch */
{
USB_DEVICE
(
0x06bd
,
0x2061
)
},
/* Another SnapScan 1212U (?)*/
{
USB_DEVICE
(
0x06bd
,
0x208d
)
},
/* Snapscan e40 */
{
USB_DEVICE
(
0x06bd
,
0x208f
)
},
/* SnapScan e50*/
{
USB_DEVICE
(
0x06bd
,
0x2091
)
},
/* SnapScan e20 */
{
USB_DEVICE
(
0x06bd
,
0x2093
)
},
/* SnapScan e10*/
{
USB_DEVICE
(
0x06bd
,
0x2095
)
},
/* SnapScan e25 */
{
USB_DEVICE
(
0x06bd
,
0x2097
)
},
/* SnapScan e26 */
{
USB_DEVICE
(
0x06bd
,
0x20fd
)
},
/* SnapScan e52*/
{
USB_DEVICE
(
0x06bd
,
0x20ff
)
},
/* SnapScan e42*/
/* Artec */
{
USB_DEVICE
(
0x05d8
,
0x4001
)
},
/* Ultima 2000 */
{
USB_DEVICE
(
0x05d8
,
0x4002
)
},
/* Ultima 2000 (GT6801 based) */
{
USB_DEVICE
(
0x05d8
,
0x4003
)
},
/* E+ 48U */
{
USB_DEVICE
(
0x05d8
,
0x4004
)
},
/* E+ Pro */
/* Avision */
{
USB_DEVICE
(
0x0638
,
0x0268
)
},
/* iVina 1200U */
{
USB_DEVICE
(
0x0638
,
0x0a10
)
},
/* iVina FB1600 (=Umax Astra 4500) */
{
USB_DEVICE
(
0x0638
,
0x0a20
)
},
/* iVina FB1800 (=Umax Astra 4700) */
/* Benq: see Acer */
/* Brother */
{
USB_DEVICE
(
0x04f9
,
0x010f
)
},
/* MFC 5100C */
{
USB_DEVICE
(
0x04f9
,
0x0111
)
},
/* MFC 6800 */
/* Canon */
{
USB_DEVICE
(
0x04a9
,
0x2201
)
},
/* CanoScan FB320U */
{
USB_DEVICE
(
0x04a9
,
0x2202
)
},
/* CanoScan FB620U */
{
USB_DEVICE
(
0x04a9
,
0x2204
)
},
/* CanoScan FB630U/FB636U */
{
USB_DEVICE
(
0x04a9
,
0x2205
)
},
/* CanoScan FB1210U */
{
USB_DEVICE
(
0x04a9
,
0x2206
)
},
/* CanoScan N650U/N656U */
{
USB_DEVICE
(
0x04a9
,
0x2207
)
},
/* CanoScan N1220U */
{
USB_DEVICE
(
0x04a9
,
0x2208
)
},
/* CanoScan D660U */
{
USB_DEVICE
(
0x04a9
,
0x220a
)
},
/* CanoScan D2400UF */
{
USB_DEVICE
(
0x04a9
,
0x220b
)
},
/* CanoScan D646U */
{
USB_DEVICE
(
0x04a9
,
0x220c
)
},
/* CanoScan D1250U2 */
{
USB_DEVICE
(
0x04a9
,
0x220d
)
},
/* CanoScan N670U/N676U/LIDE 20 */
{
USB_DEVICE
(
0x04a9
,
0x220e
)
},
/* CanoScan N1240U/LIDE 30 */
{
USB_DEVICE
(
0x04a9
,
0x220f
)
},
/* CanoScan 8000F */
{
USB_DEVICE
(
0x04a9
,
0x2210
)
},
/* CanoScan 9900F */
{
USB_DEVICE
(
0x04a9
,
0x2212
)
},
/* CanoScan 5000F */
{
USB_DEVICE
(
0x04a9
,
0x2213
)
},
/* LIDE 50 */
{
USB_DEVICE
(
0x04a9
,
0x2215
)
},
/* CanoScan 3000 */
{
USB_DEVICE
(
0x04a9
,
0x3042
)
},
/* FS4000US */
/* Colorado -- See Primax/Colorado below */
/* Compaq */
{
USB_DEVICE
(
0x049f
,
0x001a
)
},
/* S4 100 */
{
USB_DEVICE
(
0x049f
,
0x0021
)
},
/* S200 */
/* Epson -- See Seiko/Epson below */
/* Fujitsu */
{
USB_DEVICE
(
0x04c5
,
0x1041
)
},
/* fi-4220c USB/SCSI info:mza@mu-tec.de */
{
USB_DEVICE
(
0x04c5
,
0x1042
)
},
/* fi-4120c USB/SCSI info:mza@mu-tec.de */
{
USB_DEVICE
(
0x04c5
,
0x1029
)
},
/* fi-4010c USB AVision info:mza@mu-tec.de */
/* Genius */
{
USB_DEVICE
(
0x0458
,
0x2001
)
},
/* ColorPage Vivid Pro */
{
USB_DEVICE
(
0x0458
,
0x2007
)
},
/* ColorPage HR6 V2 */
{
USB_DEVICE
(
0x0458
,
0x2008
)
},
/* ColorPage HR6 V2 */
{
USB_DEVICE
(
0x0458
,
0x2009
)
},
/* ColorPage HR6A */
{
USB_DEVICE
(
0x0458
,
0x2011
)
},
/* ColorPage Vivid3x */
{
USB_DEVICE
(
0x0458
,
0x2013
)
},
/* ColorPage HR7 */
{
USB_DEVICE
(
0x0458
,
0x2015
)
},
/* ColorPage HR7LE */
{
USB_DEVICE
(
0x0458
,
0x2016
)
},
/* ColorPage HR6X */
{
USB_DEVICE
(
0x0458
,
0x2018
)
},
/* ColorPage HR7X */
{
USB_DEVICE
(
0x0458
,
0x201b
)
},
/* Colorpage Vivid 4x */
/* Hewlett Packard */
/* IMPORTANT: Hewlett-Packard multi-function peripherals (OfficeJet,
Printer/Scanner/Copier (PSC), LaserJet, or PhotoSmart printer)
should not be added to this table because they are accessed by a
userspace driver (hpoj) */
{
USB_DEVICE
(
0x03f0
,
0x0101
)
},
/* ScanJet 4100C */
{
USB_DEVICE
(
0x03f0
,
0x0102
)
},
/* PhotoSmart S20 */
{
USB_DEVICE
(
0x03f0
,
0x0105
)
},
/* ScanJet 4200C */
{
USB_DEVICE
(
0x03f0
,
0x0201
)
},
/* ScanJet 6200C */
{
USB_DEVICE
(
0x03f0
,
0x0205
)
},
/* ScanJet 3300C */
{
USB_DEVICE
(
0x03f0
,
0x0305
)
},
/* ScanJet 4300C */
{
USB_DEVICE
(
0x03f0
,
0x0401
)
},
/* ScanJet 5200C */
{
USB_DEVICE
(
0x03f0
,
0x0405
)
},
/* ScanJet 3400C */
{
USB_DEVICE
(
0x03f0
,
0x0505
)
},
/* ScanJet 2100C */
{
USB_DEVICE
(
0x03f0
,
0x0601
)
},
/* ScanJet 6300C */
{
USB_DEVICE
(
0x03f0
,
0x0605
)
},
/* ScanJet 2200C */
// { USB_DEVICE(0x03f0, 0x0701) }, /* ScanJet 5300C - NOT SUPPORTED - use hpusbscsi driver */
{
USB_DEVICE
(
0x03f0
,
0x0705
)
},
/* ScanJet 4400C */
// { USB_DEVICE(0x03f0, 0x0801) }, /* ScanJet 7400C - NOT SUPPORTED - use hpusbscsi driver */
{
USB_DEVICE
(
0x03f0
,
0x0805
)
},
/* ScanJet 4470c */
{
USB_DEVICE
(
0x03f0
,
0x0901
)
},
/* ScanJet 2300C */
{
USB_DEVICE
(
0x03f0
,
0x0a01
)
},
/* ScanJet 2400c */
{
USB_DEVICE
(
0x03F0
,
0x1005
)
},
/* ScanJet 5400C */
{
USB_DEVICE
(
0x03F0
,
0x1105
)
},
/* ScanJet 5470C */
{
USB_DEVICE
(
0x03f0
,
0x1205
)
},
/* ScanJet 5550C */
{
USB_DEVICE
(
0x03f0
,
0x1305
)
},
/* Scanjet 4570c */
// { USB_DEVICE(0x03f0, 0x1411) }, /* PSC 750 - NOT SUPPORTED - use hpoj userspace driver */
{
USB_DEVICE
(
0x03f0
,
0x2005
)
},
/* ScanJet 3570c */
{
USB_DEVICE
(
0x03f0
,
0x2205
)
},
/* ScanJet 3500c */
// { USB_DEVICE(0x03f0, 0x2f11) }, /* PSC 1210 - NOT SUPPORTED - use hpoj userspace driver */
/* Lexmark */
{
USB_DEVICE
(
0x043d
,
0x002d
)
},
/* X70/X73 */
{
USB_DEVICE
(
0x043d
,
0x003d
)
},
/* X83 */
/* LG Electronics */
{
USB_DEVICE
(
0x0461
,
0x0364
)
},
/* Scanworks 600U (repackaged Primax?) */
/* Medion */
{
USB_DEVICE
(
0x0461
,
0x0377
)
},
/* MD 5345 - repackaged Primax? */
/* Memorex */
{
USB_DEVICE
(
0x0461
,
0x0346
)
},
/* 6136u - repackaged Primax ? */
/* Microtek */
{
USB_DEVICE
(
0x05da
,
0x20a7
)
},
/* ScanMaker 5600 */
{
USB_DEVICE
(
0x05da
,
0x20c9
)
},
/* ScanMaker 6700 */
{
USB_DEVICE
(
0x05da
,
0x30ce
)
},
/* ScanMaker 3800 */
{
USB_DEVICE
(
0x05da
,
0x30cf
)
},
/* ScanMaker 4800 */
{
USB_DEVICE
(
0x05da
,
0x30d4
)
},
/* ScanMaker 3830 + 3840 */
{
USB_DEVICE
(
0x05da
,
0x30d8
)
},
/* ScanMaker 5900 */
{
USB_DEVICE
(
0x04a7
,
0x0224
)
},
/* Scanport 3000 (actually Visioneer?)*/
/* The following SCSI-over-USB Microtek devices are supported by the
microtek driver: Enable SCSI and USB Microtek in kernel config */
// { USB_DEVICE(0x05da, 0x0099) }, /* ScanMaker X6 - X6U */
// { USB_DEVICE(0x05da, 0x0094) }, /* Phantom 336CX - C3 */
// { USB_DEVICE(0x05da, 0x00a0) }, /* Phantom 336CX - C3 #2 */
// { USB_DEVICE(0x05da, 0x009a) }, /* Phantom C6 */
// { USB_DEVICE(0x05da, 0x00a3) }, /* ScanMaker V6USL */
// { USB_DEVICE(0x05da, 0x80a3) }, /* ScanMaker V6USL #2 */
// { USB_DEVICE(0x05da, 0x80ac) }, /* ScanMaker V6UL - SpicyU */
/* Minolta */
{
USB_DEVICE
(
0x0686
,
0x400d
)
},
/* Scan Dual III */
/* The following SCSI-over-USB Minolta devices are supported by the
hpusbscsi driver: Enable SCSI and USB hpusbscsi in kernel config */
// { USB_DEVICE(0x0638, 0x026a) }, /* Minolta Dimage Scan Dual II */
// { USB_DEVICE(0x0686, 0x4004) }, /* Scan Elite II (need interrupt ep) */
/* Mustek */
{
USB_DEVICE
(
0x0400
,
0x1000
)
},
/* BearPaw 1200 (National Semiconductor LM9831) */
{
USB_DEVICE
(
0x0400
,
0x1001
)
},
/* BearPaw 2400 (National Semiconductor LM9832) */
{
USB_DEVICE
(
0x055f
,
0x0001
)
},
/* ScanExpress 1200 CU */
{
USB_DEVICE
(
0x055f
,
0x0002
)
},
/* ScanExpress 600 CU */
{
USB_DEVICE
(
0x055f
,
0x0003
)
},
/* ScanExpress 1200 USB */
{
USB_DEVICE
(
0x055f
,
0x0006
)
},
/* ScanExpress 1200 UB */
{
USB_DEVICE
(
0x055f
,
0x0007
)
},
/* ScanExpress 1200 USB Plus */
{
USB_DEVICE
(
0x055f
,
0x0008
)
},
/* ScanExpress 1200 CU Plus */
{
USB_DEVICE
(
0x055f
,
0x0010
)
},
/* BearPaw 1200F */
{
USB_DEVICE
(
0x055f
,
0x0210
)
},
/* ScanExpress A3 USB */
{
USB_DEVICE
(
0x055f
,
0x0218
)
},
/* BearPaw 2400 TA */
{
USB_DEVICE
(
0x055f
,
0x0219
)
},
/* BearPaw 2400 TA Plus */
{
USB_DEVICE
(
0x055f
,
0x021c
)
},
/* BearPaw 1200 CU Plus */
{
USB_DEVICE
(
0x055f
,
0x021d
)
},
/* Bearpaw 2400 CU Plus */
{
USB_DEVICE
(
0x055f
,
0x021e
)
},
/* BearPaw 1200 TA/CS */
{
USB_DEVICE
(
0x055f
,
0x0400
)
},
/* BearPaw 2400 TA PRO */
{
USB_DEVICE
(
0x055f
,
0x0401
)
},
/* P 3600 A3 Pro */
{
USB_DEVICE
(
0x055f
,
0x0409
)
},
/* BearPaw 2448TA Pro */
{
USB_DEVICE
(
0x055f
,
0x0873
)
},
/* ScanExpress 600 USB */
{
USB_DEVICE
(
0x055f
,
0x1000
)
},
/* BearPaw 4800 TA PRO */
// { USB_DEVICE(0x05d8, 0x4002) }, /* BearPaw 1200 CU and ScanExpress 1200 UB Plus (see Artec) */
/* Nikon */
{
USB_DEVICE
(
0x04b0
,
0x4000
)
},
/* Coolscan LS 40 ED */
/* Pacific Image Electronics */
{
USB_DEVICE
(
0x05e3
,
0x0120
)
},
/* PrimeFilm 1800u */
/* Plustek */
{
USB_DEVICE
(
0x07b3
,
0x0001
)
},
/* 1212U */
{
USB_DEVICE
(
0x07b3
,
0x0005
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0007
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x000F
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0010
)
},
/* OpticPro U12 */
{
USB_DEVICE
(
0x07b3
,
0x0011
)
},
/* OpticPro U24 */
{
USB_DEVICE
(
0x07b3
,
0x0012
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0013
)
},
/* UT12 */
{
USB_DEVICE
(
0x07b3
,
0x0014
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0015
)
},
/* OpticPro U24 */
{
USB_DEVICE
(
0x07b3
,
0x0016
)
},
/* Unknown */
{
USB_DEVICE
(
0x07b3
,
0x0017
)
},
/* OpticPro UT12/UT16/UT24 */
{
USB_DEVICE
(
0x07b3
,
0x0400
)
},
/* OpticPro 1248U */
{
USB_DEVICE
(
0x07b3
,
0x0401
)
},
/* OpticPro 1248U (another one) */
{
USB_DEVICE
(
0x07b3
,
0x0403
)
},
/* U16B */
{
USB_DEVICE
(
0x07b3
,
0x0413
)
},
/* OpticSlim 1200 */
/* Primax/Colorado */
{
USB_DEVICE
(
0x0461
,
0x0300
)
},
/* G2-300 #1 */
{
USB_DEVICE
(
0x0461
,
0x0301
)
},
/* G2E-300 #1 */
{
USB_DEVICE
(
0x0461
,
0x0302
)
},
/* G2-300 #2 */
{
USB_DEVICE
(
0x0461
,
0x0303
)
},
/* G2E-300 #2 */
{
USB_DEVICE
(
0x0461
,
0x0340
)
},
/* Colorado USB 9600 */
{
USB_DEVICE
(
0x0461
,
0x0341
)
},
/* Colorado 600u */
{
USB_DEVICE
(
0x0461
,
0x0347
)
},
/* Primascan Colorado 2600u */
{
USB_DEVICE
(
0x0461
,
0x0360
)
},
/* Colorado USB 19200 */
{
USB_DEVICE
(
0x0461
,
0x0361
)
},
/* Colorado 1200u */
{
USB_DEVICE
(
0x0461
,
0x0380
)
},
/* G2-600 #1 */
{
USB_DEVICE
(
0x0461
,
0x0381
)
},
/* ReadyScan 636i */
{
USB_DEVICE
(
0x0461
,
0x0382
)
},
/* G2-600 #2 */
{
USB_DEVICE
(
0x0461
,
0x0383
)
},
/* G2E-600 */
/* Prolink */
{
USB_DEVICE
(
0x06dc
,
0x0014
)
},
/* Winscan Pro 2448U */
/* Reflecta */
{
USB_DEVICE
(
0x05e3
,
0x0120
)
},
/* iScan 1800 */
/* Relisis */
// { USB_DEVICE(0x0475, 0x0103) }, /* Episode - undetected endpoint */
{
USB_DEVICE
(
0x0475
,
0x0210
)
},
/* Scorpio Ultra 3 */
/* Seiko/Epson Corp. */
{
USB_DEVICE
(
0x04b8
,
0x0101
)
},
/* Perfection 636U and 636Photo */
{
USB_DEVICE
(
0x04b8
,
0x0102
)
},
/* GT-2200 */
{
USB_DEVICE
(
0x04b8
,
0x0103
)
},
/* Perfection 610 */
{
USB_DEVICE
(
0x04b8
,
0x0104
)
},
/* Perfection 1200U and 1200Photo*/
{
USB_DEVICE
(
0x04b8
,
0x0105
)
},
/* StylusScan 2000 */
{
USB_DEVICE
(
0x04b8
,
0x0106
)
},
/* Stylus Scan 2500 */
{
USB_DEVICE
(
0x04b8
,
0x0107
)
},
/* Expression 1600 */
{
USB_DEVICE
(
0x04b8
,
0x0109
)
},
/* Expression 1640XL */
{
USB_DEVICE
(
0x04b8
,
0x010a
)
},
/* Perfection 1640SU and 1640SU Photo */
{
USB_DEVICE
(
0x04b8
,
0x010b
)
},
/* Perfection 1240U */
{
USB_DEVICE
(
0x04b8
,
0x010c
)
},
/* Perfection 640U */
{
USB_DEVICE
(
0x04b8
,
0x010e
)
},
/* Expression 1680 */
{
USB_DEVICE
(
0x04b8
,
0x010f
)
},
/* Perfection 1250U */
{
USB_DEVICE
(
0x04b8
,
0x0110
)
},
/* Perfection 1650 */
{
USB_DEVICE
(
0x04b8
,
0x0112
)
},
/* Perfection 2450 - GT-9700 for the Japanese mkt */
{
USB_DEVICE
(
0x04b8
,
0x0114
)
},
/* Perfection 660 */
{
USB_DEVICE
(
0x04b8
,
0x011b
)
},
/* Perfection 2400 Photo */
{
USB_DEVICE
(
0x04b8
,
0x011c
)
},
/* Perfection 3200 */
{
USB_DEVICE
(
0x04b8
,
0x011d
)
},
/* Perfection 1260 */
{
USB_DEVICE
(
0x04b8
,
0x011e
)
},
/* Perfection 1660 Photo */
{
USB_DEVICE
(
0x04b8
,
0x011f
)
},
/* Perfection 1670 */
{
USB_DEVICE
(
0x04b8
,
0x0801
)
},
/* Stylus CX5200 */
{
USB_DEVICE
(
0x04b8
,
0x0802
)
},
/* Stylus CX3200 */
/* Siemens */
{
USB_DEVICE
(
0x0681
,
0x0005
)
},
/* ID Mouse Professional */
{
USB_DEVICE
(
0x0681
,
0x0010
)
},
/* Cherry FingerTIP ID Board - Sensor */
/* SYSCAN */
{
USB_DEVICE
(
0x0a82
,
0x4600
)
},
/* TravelScan 460/464 */
/* Trust */
{
USB_DEVICE
(
0x05cb
,
0x1483
)
},
/* CombiScan 19200 */
{
USB_DEVICE
(
0x05d8
,
0x4006
)
},
/* Easy Webscan 19200 (repackaged Artec?) */
/* Umax */
{
USB_DEVICE
(
0x05d8
,
0x4009
)
},
/* Astraslim (actually Artec?) */
{
USB_DEVICE
(
0x1606
,
0x0010
)
},
/* Astra 1220U */
{
USB_DEVICE
(
0x1606
,
0x0030
)
},
/* Astra 2000U */
{
USB_DEVICE
(
0x1606
,
0x0060
)
},
/* Astra 3400U/3450U */
{
USB_DEVICE
(
0x1606
,
0x0070
)
},
/* Astra 4400 */
{
USB_DEVICE
(
0x1606
,
0x0130
)
},
/* Astra 2100U */
{
USB_DEVICE
(
0x1606
,
0x0160
)
},
/* Astra 5400U */
{
USB_DEVICE
(
0x1606
,
0x0230
)
},
/* Astra 2200U */
/* Visioneer */
{
USB_DEVICE
(
0x04a7
,
0x0211
)
},
/* OneTouch 7600 USB */
{
USB_DEVICE
(
0x04a7
,
0x0221
)
},
/* OneTouch 5300 USB */
{
USB_DEVICE
(
0x04a7
,
0x0224
)
},
/* OneTouch 4800 USB */
{
USB_DEVICE
(
0x04a7
,
0x0226
)
},
/* OneTouch 5800 USB */
{
USB_DEVICE
(
0x04a7
,
0x0229
)
},
/* OneTouch 7100 USB */
{
USB_DEVICE
(
0x04a7
,
0x022c
)
},
/* OneTouch 9020 USB */
{
USB_DEVICE
(
0x04a7
,
0x0231
)
},
/* 6100 USB */
{
USB_DEVICE
(
0x04a7
,
0x0311
)
},
/* 6200 EPP/USB */
{
USB_DEVICE
(
0x04a7
,
0x0321
)
},
/* OneTouch 8100 EPP/USB */
{
USB_DEVICE
(
0x04a7
,
0x0331
)
},
/* OneTouch 8600 EPP/USB */
{
USB_DEVICE
(
0x0461
,
0x0345
)
},
/* 6200 (actually Primax?) */
{
USB_DEVICE
(
0x0461
,
0x0371
)
},
/* Onetouch 8920 USB (actually Primax?) */
{
}
/* Terminating entry */
};
MODULE_DEVICE_TABLE
(
usb
,
scanner_device_ids
);
#define IS_EP_BULK(ep) ((ep)->bmAttributes == USB_ENDPOINT_XFER_BULK ? 1 : 0)
#define IS_EP_BULK_IN(ep) (IS_EP_BULK(ep) && ((ep)->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
#define IS_EP_BULK_OUT(ep) (IS_EP_BULK(ep) && ((ep)->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
#define IS_EP_INTR(ep) ((ep)->bmAttributes == USB_ENDPOINT_XFER_INT ? 1 : 0)
#define USB_SCN_MINOR(X) iminor(X)
#ifdef DEBUG
#define SCN_DEBUG(X) X
#else
#define SCN_DEBUG(X)
#endif
#define IBUF_SIZE 32768
#define OBUF_SIZE 4096
/* read_scanner timeouts -- RD_NAK_TIMEOUT * RD_EXPIRE = Number of seconds */
#define RD_NAK_TIMEOUT (10*HZ)
/* Default number of X seconds to wait */
#define RD_EXPIRE 12
/* Number of attempts to wait X seconds */
/* read vendor and product IDs from the scanner */
#define SCANNER_IOCTL_VENDOR _IOR('U', 0x20, int)
#define SCANNER_IOCTL_PRODUCT _IOR('U', 0x21, int)
/* send/recv a control message to the scanner */
#define SCANNER_IOCTL_CTRLMSG _IOWR('U', 0x22, struct usb_ctrlrequest)
/* USB bInterfaceClass used by Hewlett-Packard ScanJet 3300c and Genius HR6
USB - Vivid III */
#define SCN_CLASS_SCANJET 16
#define SCN_BASE_MNR 48
/* USB Scanners start at minor 48 */
static
DECLARE_MUTEX
(
scn_mutex
);
/* Initializes to unlocked */
struct
scn_usb_data
{
struct
usb_device
*
scn_dev
;
struct
urb
*
scn_irq
;
unsigned
int
ifnum
;
/* Interface number of the USB device */
int
scn_minor
;
/* Scanner minor - used in disconnect() */
unsigned
char
button
;
/* Front panel buffer */
char
isopen
;
/* Not zero if the device is open */
char
present
;
/* Not zero if device is present */
char
*
obuf
,
*
ibuf
;
/* transfer buffers */
char
bulk_in_ep
,
bulk_out_ep
,
intr_ep
;
/* Endpoint assignments */
wait_queue_head_t
rd_wait_q
;
/* read timeouts */
struct
semaphore
sem
;
/* lock to prevent concurrent reads or writes */
unsigned
int
rd_nak_timeout
;
/* Seconds to wait before read() timeout. */
struct
kobject
kobj
;
/* Handles our reference counting */
};
#define to_scanner(d) container_of(d, struct scn_usb_data, kobj)
static
struct
usb_driver
scanner_driver
;
drivers/usb/input/hid-core.c
View file @
f749ccc0
...
...
@@ -602,14 +602,16 @@ static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item)
case
2
:
if
((
end
-
start
)
<
2
)
return
NULL
;
item
->
data
.
u16
=
le16_to_cpu
(
get_unaligned
(((
__u16
*
)
start
)
++
));
item
->
data
.
u16
=
le16_to_cpu
(
get_unaligned
((
__u16
*
)
start
));
start
=
(
__u8
*
)((
__u16
*
)
start
+
1
);
return
start
;
case
3
:
item
->
size
++
;
if
((
end
-
start
)
<
4
)
return
NULL
;
item
->
data
.
u32
=
le32_to_cpu
(
get_unaligned
(((
__u32
*
)
start
)
++
));
item
->
data
.
u32
=
le32_to_cpu
(
get_unaligned
((
__u32
*
)
start
));
start
=
(
__u8
*
)((
__u32
*
)
start
+
1
);
return
start
;
}
...
...
drivers/usb/misc/usbtest.c
View file @
f749ccc0
#include <linux/config.h>
#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)
# define DEBUG
#endif
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <asm/scatterlist.h>
#if !defined (DEBUG) && defined (CONFIG_USB_DEBUG)
# define DEBUG
#endif
#include <linux/usb.h>
...
...
@@ -20,10 +21,10 @@
struct
usbtest_param
{
// inputs
unsigned
test_num
;
/* 0..(TEST_CASES-1) */
int
iterations
;
int
length
;
int
vary
;
int
sglen
;
unsigned
iterations
;
unsigned
length
;
unsigned
vary
;
unsigned
sglen
;
// outputs
struct
timeval
duration
;
...
...
@@ -48,6 +49,8 @@ struct usbtest_info {
u8
ep_in
;
/* bulk/intr source */
u8
ep_out
;
/* bulk/intr sink */
unsigned
autoconf
:
1
;
unsigned
ctrl_out
:
1
;
unsigned
iso
:
1
;
/* try iso in/out */
int
alt
;
};
...
...
@@ -60,9 +63,11 @@ struct usbtest_info {
struct
usbtest_dev
{
struct
usb_interface
*
intf
;
struct
usbtest_info
*
info
;
char
id
[
32
];
int
in_pipe
;
int
out_pipe
;
int
in_iso_pipe
;
int
out_iso_pipe
;
struct
usb_endpoint_descriptor
*
iso_in
,
*
iso_out
;
struct
semaphore
sem
;
#define TBUF_SIZE 256
...
...
@@ -77,6 +82,31 @@ static struct usb_device *testdev_to_usbdev (struct usbtest_dev *test)
/* set up all urbs so they can be used with either bulk or interrupt */
#define INTERRUPT_RATE 1
/* msec/transfer */
#define xprintk(tdev,level,fmt,args...) \
dev_printk(level , &(tdev)->intf->dev , fmt , ## args)
#ifdef DEBUG
#define DBG(dev,fmt,args...) \
xprintk(dev , KERN_DEBUG , fmt , ## args)
#else
#define DBG(dev,fmt,args...) \
do { } while (0)
#endif
/* DEBUG */
#ifdef VERBOSE
#define VDBG DBG
#else
#define VDBG(dev,fmt,args...) \
do { } while (0)
#endif
/* VERBOSE */
#define ERROR(dev,fmt,args...) \
xprintk(dev , KERN_ERR , fmt , ## args)
#define WARN(dev,fmt,args...) \
xprintk(dev , KERN_WARNING , fmt , ## args)
#define INFO(dev,fmt,args...) \
xprintk(dev , KERN_INFO , fmt , ## args)
/*-------------------------------------------------------------------------*/
static
int
...
...
@@ -85,12 +115,14 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
int
tmp
;
struct
usb_host_interface
*
alt
;
struct
usb_host_endpoint
*
in
,
*
out
;
struct
usb_host_endpoint
*
iso_in
,
*
iso_out
;
struct
usb_device
*
udev
;
for
(
tmp
=
0
;
tmp
<
intf
->
num_altsetting
;
tmp
++
)
{
unsigned
ep
;
in
=
out
=
0
;
iso_in
=
iso_out
=
0
;
alt
=
intf
->
altsetting
+
tmp
;
/* take the first altsetting with in-bulk + out-bulk;
...
...
@@ -100,8 +132,16 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
struct
usb_host_endpoint
*
e
;
e
=
alt
->
endpoint
+
ep
;
if
(
e
->
desc
.
bmAttributes
!=
USB_ENDPOINT_XFER_BULK
)
switch
(
e
->
desc
.
bmAttributes
)
{
case
USB_ENDPOINT_XFER_BULK
:
break
;
case
USB_ENDPOINT_XFER_ISOC
:
if
(
dev
->
info
->
iso
)
goto
try_iso
;
// FALLTHROUGH
default:
continue
;
}
if
(
e
->
desc
.
bEndpointAddress
&
USB_DIR_IN
)
{
if
(
!
in
)
in
=
e
;
...
...
@@ -111,6 +151,17 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
}
if
(
in
&&
out
)
goto
found
;
continue
;
try_iso:
if
(
e
->
desc
.
bEndpointAddress
&
USB_DIR_IN
)
{
if
(
!
iso_in
)
iso_in
=
e
;
}
else
{
if
(
!
iso_out
)
iso_out
=
e
;
}
if
(
iso_in
&&
iso_out
)
goto
found
;
}
}
return
-
EINVAL
;
...
...
@@ -125,10 +176,21 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
return
tmp
;
}
if
(
in
)
{
dev
->
in_pipe
=
usb_rcvbulkpipe
(
udev
,
in
->
desc
.
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
);
dev
->
out_pipe
=
usb_sndbulkpipe
(
udev
,
out
->
desc
.
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
);
}
else
if
(
iso_in
)
{
dev
->
iso_in
=
&
iso_in
->
desc
;
dev
->
in_iso_pipe
=
usb_rcvisocpipe
(
udev
,
iso_in
->
desc
.
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
);
dev
->
iso_out
=
&
iso_out
->
desc
;
dev
->
out_iso_pipe
=
usb_sndisocpipe
(
udev
,
iso_out
->
desc
.
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
);
}
return
0
;
}
...
...
@@ -176,6 +238,63 @@ static struct urb *simple_alloc_urb (
return
urb
;
}
static
unsigned
pattern
=
0
;
module_param
(
pattern
,
uint
,
S_IRUGO
);
// MODULE_PARM_DESC (pattern, "i/o pattern (0 == zeroes)");
static
inline
void
simple_fill_buf
(
struct
urb
*
urb
)
{
unsigned
i
;
u8
*
buf
=
urb
->
transfer_buffer
;
unsigned
len
=
urb
->
transfer_buffer_length
;
switch
(
pattern
)
{
default:
// FALLTHROUGH
case
0
:
memset
(
buf
,
0
,
len
);
break
;
case
1
:
/* mod63 */
for
(
i
=
0
;
i
<
len
;
i
++
)
*
buf
++
=
(
u8
)
(
i
%
63
);
break
;
}
}
static
inline
int
simple_check_buf
(
struct
urb
*
urb
)
{
unsigned
i
;
u8
expected
;
u8
*
buf
=
urb
->
transfer_buffer
;
unsigned
len
=
urb
->
actual_length
;
for
(
i
=
0
;
i
<
len
;
i
++
,
buf
++
)
{
switch
(
pattern
)
{
/* all-zeroes has no synchronization issues */
case
0
:
expected
=
0
;
break
;
/* mod63 stays in sync with short-terminated transfers,
* or otherwise when host and gadget agree on how large
* each usb transfer request should be. resync is done
* with set_interface or set_config.
*/
case
1
:
/* mod63 */
expected
=
i
%
63
;
break
;
/* always fail unsupported patterns */
default:
expected
=
!*
buf
;
break
;
}
if
(
*
buf
==
expected
)
continue
;
dbg
(
"buf[%d] = %d (not %d)"
,
i
,
*
buf
,
expected
);
return
-
EINVAL
;
}
return
0
;
}
static
void
simple_free_urb
(
struct
urb
*
urb
)
{
usb_buffer_free
(
urb
->
dev
,
urb
->
transfer_buffer_length
,
...
...
@@ -186,7 +305,9 @@ static void simple_free_urb (struct urb *urb)
static
int
simple_io
(
struct
urb
*
urb
,
int
iterations
,
int
vary
int
vary
,
int
expected
,
const
char
*
label
)
{
struct
usb_device
*
udev
=
urb
->
dev
;
...
...
@@ -197,6 +318,8 @@ static int simple_io (
urb
->
context
=
&
completion
;
while
(
retval
==
0
&&
iterations
--
>
0
)
{
init_completion
(
&
completion
);
if
(
usb_pipeout
(
urb
->
pipe
))
simple_fill_buf
(
urb
);
if
((
retval
=
usb_submit_urb
(
urb
,
SLAB_KERNEL
))
!=
0
)
break
;
...
...
@@ -204,6 +327,8 @@ static int simple_io (
wait_for_completion
(
&
completion
);
retval
=
urb
->
status
;
urb
->
dev
=
udev
;
if
(
retval
==
0
&&
usb_pipein
(
urb
->
pipe
))
retval
=
simple_check_buf
(
urb
);
if
(
vary
)
{
int
len
=
urb
->
transfer_buffer_length
;
...
...
@@ -219,14 +344,14 @@ static int simple_io (
}
urb
->
transfer_buffer_length
=
max
;
// FIXME for unlink or fault handling tests, don't report
// failure if retval is as we expected ...
if
(
retval
)
dbg
(
"simple_io failed, iterations left %d, status %d"
,
iterations
,
retval
);
if
(
expected
!=
retval
)
dev_dbg
(
&
udev
->
dev
,
"%s failed, iterations left %d, status %d (not %d)
\n
"
,
label
,
iterations
,
retval
,
expected
);
return
retval
;
}
/*-------------------------------------------------------------------------*/
/* We use scatterlist primitives to test queued I/O.
...
...
@@ -360,54 +485,18 @@ static int get_altsetting (struct usbtest_dev *dev)
}
}
/* this is usb_set_interface(), with no 'only one altsetting' case */
static
int
set_altsetting
(
struct
usbtest_dev
*
dev
,
int
alternate
)
{
struct
usb_interface
*
iface
=
dev
->
intf
;
struct
usb_device
*
udev
;
struct
usb_host_interface
*
iface_as
;
int
i
,
ret
;
if
(
alternate
<
0
||
alternate
>=
iface
->
num_altsetting
)
return
-
EINVAL
;
udev
=
interface_to_usbdev
(
iface
);
if
((
ret
=
usb_control_msg
(
udev
,
usb_sndctrlpipe
(
udev
,
0
),
USB_REQ_SET_INTERFACE
,
USB_RECIP_INTERFACE
,
alternate
,
iface
->
altsetting
->
desc
.
bInterfaceNumber
,
NULL
,
0
,
HZ
*
USB_CTRL_SET_TIMEOUT
))
<
0
)
return
ret
;
// FIXME usbcore should be more like this:
// - remove that special casing in usbcore.
// - fix usbcore signature to take interface
/* prevent requests using previous endpoint settings */
iface_as
=
iface
->
altsetting
+
iface
->
act_altsetting
;
for
(
i
=
0
;
i
<
iface_as
->
desc
.
bNumEndpoints
;
i
++
)
{
u8
ep
=
iface_as
->
endpoint
[
i
].
desc
.
bEndpointAddress
;
int
out
=
!
(
ep
&
USB_DIR_IN
);
ep
&=
USB_ENDPOINT_NUMBER_MASK
;
(
out
?
udev
->
epmaxpacketout
:
udev
->
epmaxpacketin
)
[
ep
]
=
0
;
// FIXME want hcd hook here, "forget this endpoint"
}
iface
->
act_altsetting
=
alternate
;
/* reset toggles and maxpacket for all endpoints affected */
iface_as
=
iface
->
altsetting
+
iface
->
act_altsetting
;
for
(
i
=
0
;
i
<
iface_as
->
desc
.
bNumEndpoints
;
i
++
)
{
u8
ep
=
iface_as
->
endpoint
[
i
].
desc
.
bEndpointAddress
;
int
out
=
!
(
ep
&
USB_DIR_IN
);
ep
&=
USB_ENDPOINT_NUMBER_MASK
;
usb_settoggle
(
udev
,
ep
,
out
,
0
);
(
out
?
udev
->
epmaxpacketout
:
udev
->
epmaxpacketin
)
[
ep
]
=
iface_as
->
endpoint
[
i
].
desc
.
wMaxPacketSize
;
}
return
0
;
return
usb_set_interface
(
udev
,
iface
->
altsetting
[
0
].
desc
.
bInterfaceNumber
,
alternate
);
}
static
int
is_good_config
(
char
*
buf
,
int
len
)
...
...
@@ -421,15 +510,19 @@ static int is_good_config (char *buf, int len)
switch
(
config
->
bDescriptorType
)
{
case
USB_DT_CONFIG
:
case
USB_DT_OTHER_SPEED_CONFIG
:
if
(
config
->
bLength
!=
9
)
if
(
config
->
bLength
!=
9
)
{
dbg
(
"bogus config descriptor length"
);
return
0
;
}
/* this bit 'must be 1' but often isn't */
if
(
!
realworld
&&
!
(
config
->
bmAttributes
&
0x80
))
{
dbg
(
"high bit of config attributes not set"
);
return
0
;
}
if
(
config
->
bmAttributes
&
0x1f
)
/* reserved == 0 */
if
(
config
->
bmAttributes
&
0x1f
)
{
/* reserved == 0 */
dbg
(
"reserved config bits set"
);
return
0
;
}
break
;
default:
return
0
;
...
...
@@ -438,7 +531,10 @@ static int is_good_config (char *buf, int len)
le16_to_cpus
(
&
config
->
wTotalLength
);
if
(
config
->
wTotalLength
==
len
)
/* read it all */
return
1
;
return
config
->
wTotalLength
>=
TBUF_SIZE
;
/* max partial read */
if
(
config
->
wTotalLength
>=
TBUF_SIZE
)
/* max partial read */
return
1
;
dbg
(
"bogus config descriptor read size"
);
return
0
;
}
/* sanity test for standard requests working with usb_control_mesg() and some
...
...
@@ -471,8 +567,9 @@ static int ch9_postconfig (struct usbtest_dev *dev)
* they're ordered meaningfully in this array
*/
if
(
iface
->
altsetting
[
i
].
desc
.
bAlternateSetting
!=
i
)
{
dbg
(
"%s, invalid alt [%d].bAltSetting = %d"
,
dev
->
id
,
i
,
dev_dbg
(
&
iface
->
dev
,
"invalid alt [%d].bAltSetting = %d
\n
"
,
i
,
iface
->
altsetting
[
i
].
desc
.
bAlternateSetting
);
return
-
EDOM
;
...
...
@@ -485,16 +582,16 @@ static int ch9_postconfig (struct usbtest_dev *dev)
/* [9.4.10] set_interface */
retval
=
set_altsetting
(
dev
,
i
);
if
(
retval
)
{
d
bg
(
"%s can't set_interface = %d, %d
"
,
dev
->
id
,
i
,
retval
);
d
ev_dbg
(
&
iface
->
dev
,
"can't set_interface = %d, %d
\n
"
,
i
,
retval
);
return
retval
;
}
/* [9.4.4] get_interface always works */
retval
=
get_altsetting
(
dev
);
if
(
retval
!=
i
)
{
d
bg
(
"%s get alt should be %d, was %d
"
,
dev
->
id
,
i
,
retval
);
d
ev_dbg
(
&
iface
->
dev
,
"get alt should be %d, was %d
\n
"
,
i
,
retval
);
return
(
retval
<
0
)
?
retval
:
-
EDOM
;
}
...
...
@@ -513,7 +610,8 @@ static int ch9_postconfig (struct usbtest_dev *dev)
USB_DIR_IN
|
USB_RECIP_DEVICE
,
0
,
0
,
dev
->
buf
,
1
,
HZ
*
USB_CTRL_GET_TIMEOUT
);
if
(
retval
!=
1
||
dev
->
buf
[
0
]
!=
expected
)
{
dbg
(
"%s get config --> %d (%d)"
,
dev
->
id
,
retval
,
dev_dbg
(
&
iface
->
dev
,
"get config --> %d (%d)
\n
"
,
retval
,
expected
);
return
(
retval
<
0
)
?
retval
:
-
EDOM
;
}
...
...
@@ -523,7 +621,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
retval
=
usb_get_descriptor
(
udev
,
USB_DT_DEVICE
,
0
,
dev
->
buf
,
sizeof
udev
->
descriptor
);
if
(
retval
!=
sizeof
udev
->
descriptor
)
{
d
bg
(
"%s dev descriptor --> %d"
,
dev
->
id
,
retval
);
d
ev_dbg
(
&
iface
->
dev
,
"dev descriptor --> %d
\n
"
,
retval
);
return
(
retval
<
0
)
?
retval
:
-
EDOM
;
}
...
...
@@ -532,8 +630,9 @@ static int ch9_postconfig (struct usbtest_dev *dev)
retval
=
usb_get_descriptor
(
udev
,
USB_DT_CONFIG
,
i
,
dev
->
buf
,
TBUF_SIZE
);
if
(
!
is_good_config
(
dev
->
buf
,
retval
))
{
dbg
(
"%s config [%d] descriptor --> %d"
,
dev
->
id
,
i
,
retval
);
dev_dbg
(
&
iface
->
dev
,
"config [%d] descriptor --> %d
\n
"
,
i
,
retval
);
return
(
retval
<
0
)
?
retval
:
-
EDOM
;
}
...
...
@@ -551,13 +650,14 @@ static int ch9_postconfig (struct usbtest_dev *dev)
sizeof
(
struct
usb_qualifier_descriptor
));
if
(
retval
==
-
EPIPE
)
{
if
(
udev
->
speed
==
USB_SPEED_HIGH
)
{
dbg
(
"%s hs dev qualifier --> %d"
,
dev
->
id
,
retval
);
dev_dbg
(
&
iface
->
dev
,
"hs dev qualifier --> %d
\n
"
,
retval
);
return
(
retval
<
0
)
?
retval
:
-
EDOM
;
}
/* usb2.0 but not high-speed capable; fine */
}
else
if
(
retval
!=
sizeof
(
struct
usb_qualifier_descriptor
))
{
d
bg
(
"%s dev qualifier --> %d"
,
dev
->
id
,
retval
);
d
ev_dbg
(
&
iface
->
dev
,
"dev qualifier --> %d
\n
"
,
retval
);
return
(
retval
<
0
)
?
retval
:
-
EDOM
;
}
else
d
=
(
struct
usb_qualifier_descriptor
*
)
dev
->
buf
;
...
...
@@ -570,8 +670,9 @@ static int ch9_postconfig (struct usbtest_dev *dev)
USB_DT_OTHER_SPEED_CONFIG
,
i
,
dev
->
buf
,
TBUF_SIZE
);
if
(
!
is_good_config
(
dev
->
buf
,
retval
))
{
dbg
(
"%s other speed config --> %d"
,
dev
->
id
,
retval
);
dev_dbg
(
&
iface
->
dev
,
"other speed config --> %d
\n
"
,
retval
);
return
(
retval
<
0
)
?
retval
:
-
EDOM
;
}
}
...
...
@@ -582,7 +683,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
/* [9.4.5] get_status always works */
retval
=
usb_get_status
(
udev
,
USB_RECIP_DEVICE
,
0
,
dev
->
buf
);
if
(
retval
!=
2
)
{
d
bg
(
"%s get dev status --> %d"
,
dev
->
id
,
retval
);
d
ev_dbg
(
&
iface
->
dev
,
"get dev status --> %d
\n
"
,
retval
);
return
(
retval
<
0
)
?
retval
:
-
EDOM
;
}
...
...
@@ -592,7 +693,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
retval
=
usb_get_status
(
udev
,
USB_RECIP_INTERFACE
,
iface
->
altsetting
[
0
].
desc
.
bInterfaceNumber
,
dev
->
buf
);
if
(
retval
!=
2
)
{
d
bg
(
"%s get interface status --> %d"
,
dev
->
id
,
retval
);
d
ev_dbg
(
&
iface
->
dev
,
"get interface status --> %d
\n
"
,
retval
);
return
(
retval
<
0
)
?
retval
:
-
EDOM
;
}
// FIXME get status for each endpoint in the interface
...
...
@@ -606,7 +707,7 @@ static int ch9_postconfig (struct usbtest_dev *dev)
* (a) queues work for control, keeping N subtests queued and
* active (auto-resubmit) for M loops through the queue.
* (b) protocol stalls (control-only) will autorecover.
* it's
quite
not like bulk/intr; no halt clearing.
* it's not like bulk/intr; no halt clearing.
* (c) short control reads are reported and handled.
* (d) queues are always processed in-order
*/
...
...
@@ -654,6 +755,7 @@ static void ctrl_complete (struct urb *urb, struct pt_regs *regs)
dbg
(
"subcase %d completed out of order, last %d"
,
subcase
->
number
,
ctx
->
last
);
status
=
-
EDOM
;
ctx
->
last
=
subcase
->
number
;
goto
error
;
}
}
...
...
@@ -995,6 +1097,368 @@ static int unlink_simple (struct usbtest_dev *dev, int pipe, int len)
/*-------------------------------------------------------------------------*/
static
int
verify_not_halted
(
int
ep
,
struct
urb
*
urb
)
{
int
retval
;
u16
status
;
/* shouldn't look or act halted */
retval
=
usb_get_status
(
urb
->
dev
,
USB_RECIP_ENDPOINT
,
ep
,
&
status
);
if
(
retval
<
0
)
{
dbg
(
"ep %02x couldn't get no-halt status, %d"
,
ep
,
retval
);
return
retval
;
}
if
(
status
!=
0
)
{
dbg
(
"ep %02x bogus status: %04x != 0"
,
ep
,
status
);
return
-
EINVAL
;
}
retval
=
simple_io
(
urb
,
1
,
0
,
0
,
__FUNCTION__
);
if
(
retval
!=
0
)
return
-
EINVAL
;
return
0
;
}
static
int
verify_halted
(
int
ep
,
struct
urb
*
urb
)
{
int
retval
;
u16
status
;
/* should look and act halted */
retval
=
usb_get_status
(
urb
->
dev
,
USB_RECIP_ENDPOINT
,
ep
,
&
status
);
if
(
retval
<
0
)
{
dbg
(
"ep %02x couldn't get halt status, %d"
,
ep
,
retval
);
return
retval
;
}
if
(
status
!=
1
)
{
dbg
(
"ep %02x bogus status: %04x != 1"
,
ep
,
status
);
return
-
EINVAL
;
}
retval
=
simple_io
(
urb
,
1
,
0
,
-
EPIPE
,
__FUNCTION__
);
if
(
retval
!=
-
EPIPE
)
return
-
EINVAL
;
retval
=
simple_io
(
urb
,
1
,
0
,
-
EPIPE
,
"verify_still_halted"
);
if
(
retval
!=
-
EPIPE
)
return
-
EINVAL
;
return
0
;
}
static
int
test_halt
(
int
ep
,
struct
urb
*
urb
)
{
int
retval
;
/* shouldn't look or act halted now */
retval
=
verify_not_halted
(
ep
,
urb
);
if
(
retval
<
0
)
return
retval
;
/* set halt (protocol test only), verify it worked */
retval
=
usb_control_msg
(
urb
->
dev
,
usb_sndctrlpipe
(
urb
->
dev
,
0
),
USB_REQ_SET_FEATURE
,
USB_RECIP_ENDPOINT
,
0
,
ep
,
NULL
,
0
,
HZ
*
USB_CTRL_SET_TIMEOUT
);
if
(
retval
<
0
)
{
dbg
(
"ep %02x couldn't set halt, %d"
,
ep
,
retval
);
return
retval
;
}
retval
=
verify_halted
(
ep
,
urb
);
if
(
retval
<
0
)
return
retval
;
/* clear halt (tests API + protocol), verify it worked */
retval
=
usb_clear_halt
(
urb
->
dev
,
urb
->
pipe
);
if
(
retval
<
0
)
{
dbg
(
"ep %02x couldn't clear halt, %d"
,
ep
,
retval
);
return
retval
;
}
retval
=
verify_not_halted
(
ep
,
urb
);
if
(
retval
<
0
)
return
retval
;
/* NOTE: could also verify SET_INTERFACE clear halts ... */
return
0
;
}
static
int
halt_simple
(
struct
usbtest_dev
*
dev
)
{
int
ep
;
int
retval
=
0
;
struct
urb
*
urb
;
urb
=
simple_alloc_urb
(
testdev_to_usbdev
(
dev
),
0
,
512
);
if
(
urb
==
0
)
return
-
ENOMEM
;
if
(
dev
->
in_pipe
)
{
ep
=
usb_pipeendpoint
(
dev
->
in_pipe
)
|
USB_DIR_IN
;
urb
->
pipe
=
dev
->
in_pipe
;
retval
=
test_halt
(
ep
,
urb
);
if
(
retval
<
0
)
goto
done
;
}
if
(
dev
->
out_pipe
)
{
ep
=
usb_pipeendpoint
(
dev
->
out_pipe
);
urb
->
pipe
=
dev
->
out_pipe
;
retval
=
test_halt
(
ep
,
urb
);
}
done:
simple_free_urb
(
urb
);
return
retval
;
}
/*-------------------------------------------------------------------------*/
/* Control OUT tests use the vendor control requests from Intel's
* USB 2.0 compliance test device: write a buffer, read it back.
*
* Intel's spec only _requires_ that it work for one packet, which
* is pretty weak. Some HCDs place limits here; most devices will
* need to be able to handle more than one OUT data packet. We'll
* try whatever we're told to try.
*/
static
int
ctrl_out
(
struct
usbtest_dev
*
dev
,
unsigned
count
,
unsigned
length
,
unsigned
vary
)
{
unsigned
i
,
j
,
len
,
retval
;
u8
*
buf
;
char
*
what
=
"?"
;
struct
usb_device
*
udev
;
if
(
length
>
0xffff
||
vary
>=
length
)
return
-
EINVAL
;
buf
=
kmalloc
(
length
,
SLAB_KERNEL
);
if
(
!
buf
)
return
-
ENOMEM
;
udev
=
testdev_to_usbdev
(
dev
);
len
=
length
;
retval
=
0
;
/* NOTE: hardware might well act differently if we pushed it
* with lots back-to-back queued requests.
*/
for
(
i
=
0
;
i
<
count
;
i
++
)
{
/* write patterned data */
for
(
j
=
0
;
j
<
len
;
j
++
)
buf
[
j
]
=
i
+
j
;
retval
=
usb_control_msg
(
udev
,
usb_sndctrlpipe
(
udev
,
0
),
0x5b
,
USB_DIR_OUT
|
USB_TYPE_VENDOR
,
0
,
0
,
buf
,
len
,
HZ
*
USB_CTRL_SET_TIMEOUT
);
if
(
retval
!=
len
)
{
what
=
"write"
;
break
;
}
/* read it back -- assuming nothing intervened!! */
retval
=
usb_control_msg
(
udev
,
usb_rcvctrlpipe
(
udev
,
0
),
0x5c
,
USB_DIR_IN
|
USB_TYPE_VENDOR
,
0
,
0
,
buf
,
len
,
HZ
*
USB_CTRL_GET_TIMEOUT
);
if
(
retval
!=
len
)
{
what
=
"read"
;
break
;
}
/* fail if we can't verify */
for
(
j
=
0
;
j
<
len
;
j
++
)
{
if
(
buf
[
j
]
!=
(
u8
)
(
i
+
j
))
{
INFO
(
dev
,
"ctrl_out, byte %d is %d not %d
\n
"
,
j
,
buf
[
j
],
(
u8
)
i
+
j
);
retval
=
-
EBADMSG
;
break
;
}
}
if
(
retval
<
0
)
{
what
=
"verify"
;
break
;
}
len
+=
vary
;
if
(
len
>
length
)
len
=
0
;
}
if
(
retval
<
0
)
INFO
(
dev
,
"ctrl_out %s failed, code %d, count %d
\n
"
,
what
,
retval
,
i
);
kfree
(
buf
);
return
retval
;
}
/*-------------------------------------------------------------------------*/
/* ISO tests ... mimics common usage
* - buffer length is split into N packets (mostly maxpacket sized)
* - multi-buffers according to sglen
*/
struct
iso_context
{
unsigned
count
;
unsigned
pending
;
spinlock_t
lock
;
struct
completion
done
;
unsigned
long
errors
;
struct
usbtest_dev
*
dev
;
};
static
void
iso_callback
(
struct
urb
*
urb
,
struct
pt_regs
*
regs
)
{
struct
iso_context
*
ctx
=
urb
->
context
;
spin_lock
(
&
ctx
->
lock
);
ctx
->
count
--
;
if
(
urb
->
error_count
>
0
)
ctx
->
errors
+=
urb
->
error_count
;
if
(
urb
->
status
==
0
&&
ctx
->
count
>
(
ctx
->
pending
-
1
))
{
int
status
=
usb_submit_urb
(
urb
,
GFP_ATOMIC
);
switch
(
status
)
{
case
0
:
goto
done
;
default:
dev_dbg
(
&
ctx
->
dev
->
intf
->
dev
,
"iso resubmit err %d
\n
"
,
status
);
/* FALLTHROUGH */
case
-
ENODEV
:
/* disconnected */
break
;
}
}
simple_free_urb
(
urb
);
ctx
->
pending
--
;
if
(
ctx
->
pending
==
0
)
{
if
(
ctx
->
errors
)
dev_dbg
(
&
ctx
->
dev
->
intf
->
dev
,
"iso test, %lu errors
\n
"
,
ctx
->
errors
);
complete
(
&
ctx
->
done
);
}
else
done:
spin_unlock
(
&
ctx
->
lock
);
}
static
struct
urb
*
iso_alloc_urb
(
struct
usb_device
*
udev
,
int
pipe
,
struct
usb_endpoint_descriptor
*
desc
,
long
bytes
)
{
struct
urb
*
urb
;
unsigned
i
,
maxp
,
packets
;
if
(
bytes
<
0
||
!
desc
)
return
0
;
maxp
=
0x7ff
&
desc
->
wMaxPacketSize
;
maxp
*=
1
+
(
0x3
&
(
desc
->
wMaxPacketSize
>>
11
));
packets
=
(
bytes
+
maxp
-
1
)
/
maxp
;
urb
=
usb_alloc_urb
(
packets
,
SLAB_KERNEL
);
if
(
!
urb
)
return
urb
;
urb
->
dev
=
udev
;
urb
->
pipe
=
pipe
;
urb
->
number_of_packets
=
packets
;
urb
->
transfer_buffer_length
=
bytes
;
urb
->
transfer_buffer
=
usb_buffer_alloc
(
udev
,
bytes
,
SLAB_KERNEL
,
&
urb
->
transfer_dma
);
if
(
!
urb
->
transfer_buffer
)
{
usb_free_urb
(
urb
);
return
0
;
}
memset
(
urb
->
transfer_buffer
,
0
,
bytes
);
for
(
i
=
0
;
i
<
packets
;
i
++
)
{
/* here, only the last packet will be short */
urb
->
iso_frame_desc
[
i
].
length
=
min
((
unsigned
)
bytes
,
maxp
);
bytes
-=
urb
->
iso_frame_desc
[
i
].
length
;
urb
->
iso_frame_desc
[
i
].
offset
=
maxp
*
i
;
}
urb
->
complete
=
iso_callback
;
// urb->context = SET BY CALLER
urb
->
interval
=
1
<<
(
desc
->
bInterval
-
1
);
urb
->
transfer_flags
=
URB_ISO_ASAP
|
URB_NO_TRANSFER_DMA_MAP
;
return
urb
;
}
static
int
test_iso_queue
(
struct
usbtest_dev
*
dev
,
struct
usbtest_param
*
param
,
int
pipe
,
struct
usb_endpoint_descriptor
*
desc
)
{
struct
iso_context
context
;
struct
usb_device
*
udev
;
unsigned
i
;
unsigned
long
packets
=
0
;
int
status
;
struct
urb
*
urbs
[
10
];
/* FIXME no limit */
if
(
param
->
sglen
>
10
)
return
-
EDOM
;
context
.
count
=
param
->
iterations
*
param
->
sglen
;
context
.
pending
=
param
->
sglen
;
context
.
errors
=
0
;
context
.
dev
=
dev
;
init_completion
(
&
context
.
done
);
spin_lock_init
(
&
context
.
lock
);
memset
(
urbs
,
0
,
sizeof
urbs
);
udev
=
testdev_to_usbdev
(
dev
);
dev_dbg
(
&
dev
->
intf
->
dev
,
"... iso period %d %sframes, wMaxPacket %04x
\n
"
,
1
<<
(
desc
->
bInterval
-
1
),
(
udev
->
speed
==
USB_SPEED_HIGH
)
?
"micro"
:
""
,
desc
->
wMaxPacketSize
);
for
(
i
=
0
;
i
<
param
->
sglen
;
i
++
)
{
urbs
[
i
]
=
iso_alloc_urb
(
udev
,
pipe
,
desc
,
param
->
length
);
if
(
!
urbs
[
i
])
{
status
=
-
ENOMEM
;
goto
fail
;
}
packets
+=
urbs
[
i
]
->
number_of_packets
;
urbs
[
i
]
->
context
=
&
context
;
}
packets
*=
param
->
iterations
;
dev_dbg
(
&
dev
->
intf
->
dev
,
"... total %lu msec (%lu packets)
\n
"
,
(
packets
*
(
1
<<
(
desc
->
bInterval
-
1
)))
/
((
udev
->
speed
==
USB_SPEED_HIGH
)
?
8
:
1
),
packets
);
spin_lock_irq
(
&
context
.
lock
);
for
(
i
=
0
;
i
<
param
->
sglen
;
i
++
)
{
status
=
usb_submit_urb
(
urbs
[
i
],
SLAB_ATOMIC
);
if
(
status
<
0
)
{
ERROR
(
dev
,
"submit iso[%d], error %d
\n
"
,
i
,
status
);
if
(
i
==
0
)
goto
fail
;
simple_free_urb
(
urbs
[
i
]);
context
.
pending
--
;
}
}
spin_unlock_irq
(
&
context
.
lock
);
wait_for_completion
(
&
context
.
done
);
return
0
;
fail:
for
(
i
=
0
;
i
<
param
->
sglen
;
i
++
)
{
if
(
urbs
[
i
])
simple_free_urb
(
urbs
[
i
]);
}
return
status
;
}
/*-------------------------------------------------------------------------*/
/* We only have this one interface to user space, through usbfs.
* User mode code can scan usbfs to find N different devices (maybe on
* different busses) to use when testing, and allocate one thread per
...
...
@@ -1047,8 +1511,9 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
}
res
=
set_altsetting
(
dev
,
dev
->
info
->
alt
);
if
(
res
)
{
err
(
"%s: set altsetting to %d failed, %d"
,
dev
->
id
,
dev
->
info
->
alt
,
res
);
dev_err
(
&
intf
->
dev
,
"set altsetting to %d failed, %d
\n
"
,
dev
->
info
->
alt
,
res
);
up
(
&
dev
->
sem
);
return
res
;
}
...
...
@@ -1067,7 +1532,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
switch
(
param
->
test_num
)
{
case
0
:
d
bg
(
"%s TEST 0: NOP"
,
dev
->
id
);
d
ev_dbg
(
&
intf
->
dev
,
"TEST 0: NOP
\n
"
);
retval
=
0
;
break
;
...
...
@@ -1075,7 +1540,8 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
case
1
:
if
(
dev
->
out_pipe
==
0
)
break
;
dbg
(
"%s TEST 1: write %d bytes %u times"
,
dev
->
id
,
dev_dbg
(
&
intf
->
dev
,
"TEST 1: write %d bytes %u times
\n
"
,
param
->
length
,
param
->
iterations
);
urb
=
simple_alloc_urb
(
udev
,
dev
->
out_pipe
,
param
->
length
);
if
(
!
urb
)
{
...
...
@@ -1083,13 +1549,14 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
break
;
}
// FIRMWARE: bulk sink (maybe accepts short writes)
retval
=
simple_io
(
urb
,
param
->
iterations
,
0
);
retval
=
simple_io
(
urb
,
param
->
iterations
,
0
,
0
,
"test1"
);
simple_free_urb
(
urb
);
break
;
case
2
:
if
(
dev
->
in_pipe
==
0
)
break
;
dbg
(
"%s TEST 2: read %d bytes %u times"
,
dev
->
id
,
dev_dbg
(
&
intf
->
dev
,
"TEST 2: read %d bytes %u times
\n
"
,
param
->
length
,
param
->
iterations
);
urb
=
simple_alloc_urb
(
udev
,
dev
->
in_pipe
,
param
->
length
);
if
(
!
urb
)
{
...
...
@@ -1097,13 +1564,14 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
break
;
}
// FIRMWARE: bulk source (maybe generates short writes)
retval
=
simple_io
(
urb
,
param
->
iterations
,
0
);
retval
=
simple_io
(
urb
,
param
->
iterations
,
0
,
0
,
"test2"
);
simple_free_urb
(
urb
);
break
;
case
3
:
if
(
dev
->
out_pipe
==
0
||
param
->
vary
==
0
)
break
;
dbg
(
"%s TEST 3: write/%d 0..%d bytes %u times"
,
dev
->
id
,
dev_dbg
(
&
intf
->
dev
,
"TEST 3: write/%d 0..%d bytes %u times
\n
"
,
param
->
vary
,
param
->
length
,
param
->
iterations
);
urb
=
simple_alloc_urb
(
udev
,
dev
->
out_pipe
,
param
->
length
);
if
(
!
urb
)
{
...
...
@@ -1111,13 +1579,15 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
break
;
}
// FIRMWARE: bulk sink (maybe accepts short writes)
retval
=
simple_io
(
urb
,
param
->
iterations
,
param
->
vary
);
retval
=
simple_io
(
urb
,
param
->
iterations
,
param
->
vary
,
0
,
"test3"
);
simple_free_urb
(
urb
);
break
;
case
4
:
if
(
dev
->
in_pipe
==
0
||
param
->
vary
==
0
)
break
;
dbg
(
"%s TEST 4: read/%d 0..%d bytes %u times"
,
dev
->
id
,
dev_dbg
(
&
intf
->
dev
,
"TEST 4: read/%d 0..%d bytes %u times
\n
"
,
param
->
vary
,
param
->
length
,
param
->
iterations
);
urb
=
simple_alloc_urb
(
udev
,
dev
->
in_pipe
,
param
->
length
);
if
(
!
urb
)
{
...
...
@@ -1125,7 +1595,8 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
break
;
}
// FIRMWARE: bulk source (maybe generates short writes)
retval
=
simple_io
(
urb
,
param
->
iterations
,
param
->
vary
);
retval
=
simple_io
(
urb
,
param
->
iterations
,
param
->
vary
,
0
,
"test4"
);
simple_free_urb
(
urb
);
break
;
...
...
@@ -1133,8 +1604,9 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
case
5
:
if
(
dev
->
out_pipe
==
0
||
param
->
sglen
==
0
)
break
;
dbg
(
"%s TEST 5: write %d sglists, %d entries of %d bytes"
,
dev
->
id
,
param
->
iterations
,
dev_dbg
(
&
intf
->
dev
,
"TEST 5: write %d sglists %d entries of %d bytes
\n
"
,
param
->
iterations
,
param
->
sglen
,
param
->
length
);
sg
=
alloc_sglist
(
param
->
sglen
,
param
->
length
,
0
);
if
(
!
sg
)
{
...
...
@@ -1150,8 +1622,9 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
case
6
:
if
(
dev
->
in_pipe
==
0
||
param
->
sglen
==
0
)
break
;
dbg
(
"%s TEST 6: read %d sglists, %d entries of %d bytes"
,
dev
->
id
,
param
->
iterations
,
dev_dbg
(
&
intf
->
dev
,
"TEST 6: read %d sglists %d entries of %d bytes
\n
"
,
param
->
iterations
,
param
->
sglen
,
param
->
length
);
sg
=
alloc_sglist
(
param
->
sglen
,
param
->
length
,
0
);
if
(
!
sg
)
{
...
...
@@ -1166,8 +1639,9 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
case
7
:
if
(
dev
->
out_pipe
==
0
||
param
->
sglen
==
0
||
param
->
vary
==
0
)
break
;
dbg
(
"%s TEST 7: write/%d %d sglists, %d entries 0..%d bytes"
,
dev
->
id
,
param
->
vary
,
param
->
iterations
,
dev_dbg
(
&
intf
->
dev
,
"TEST 7: write/%d %d sglists %d entries 0..%d bytes
\n
"
,
param
->
vary
,
param
->
iterations
,
param
->
sglen
,
param
->
length
);
sg
=
alloc_sglist
(
param
->
sglen
,
param
->
length
,
param
->
vary
);
if
(
!
sg
)
{
...
...
@@ -1182,8 +1656,9 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
case
8
:
if
(
dev
->
in_pipe
==
0
||
param
->
sglen
==
0
||
param
->
vary
==
0
)
break
;
dbg
(
"%s TEST 8: read/%d %d sglists, %d entries 0..%d bytes"
,
dev
->
id
,
param
->
vary
,
param
->
iterations
,
dev_dbg
(
&
intf
->
dev
,
"TEST 8: read/%d %d sglists %d entries 0..%d bytes
\n
"
,
param
->
vary
,
param
->
iterations
,
param
->
sglen
,
param
->
length
);
sg
=
alloc_sglist
(
param
->
sglen
,
param
->
length
,
param
->
vary
);
if
(
!
sg
)
{
...
...
@@ -1199,8 +1674,9 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
/* non-queued sanity tests for control (chapter 9 subset) */
case
9
:
retval
=
0
;
dbg
(
"%s TEST 9: ch9 (subset) control tests, %d times"
,
dev
->
id
,
param
->
iterations
);
dev_dbg
(
&
intf
->
dev
,
"TEST 9: ch9 (subset) control tests, %d times
\n
"
,
param
->
iterations
);
for
(
i
=
param
->
iterations
;
retval
==
0
&&
i
--
;
/* NOP */
)
retval
=
ch9_postconfig
(
dev
);
if
(
retval
)
...
...
@@ -1212,8 +1688,9 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
if
(
param
->
sglen
==
0
)
break
;
retval
=
0
;
dbg
(
"%s TEST 10: queue %d control calls, %d times"
,
dev
->
id
,
param
->
sglen
,
dev_dbg
(
&
intf
->
dev
,
"TEST 10: queue %d control calls, %d times
\n
"
,
param
->
sglen
,
param
->
iterations
);
retval
=
test_ctrl_queue
(
dev
,
param
);
break
;
...
...
@@ -1223,10 +1700,11 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
if
(
dev
->
in_pipe
==
0
||
!
param
->
length
)
break
;
retval
=
0
;
d
bg
(
"%s TEST 11: unlink %d reads of %d
"
,
dev
->
id
,
param
->
iterations
,
param
->
length
);
d
ev_dbg
(
&
intf
->
dev
,
"TEST 11: unlink %d reads of %d
\n
"
,
param
->
iterations
,
param
->
length
);
for
(
i
=
param
->
iterations
;
retval
==
0
&&
i
--
;
/* NOP */
)
retval
=
unlink_simple
(
dev
,
dev
->
in_pipe
,
param
->
length
);
retval
=
unlink_simple
(
dev
,
dev
->
in_pipe
,
param
->
length
);
if
(
retval
)
dbg
(
"unlink reads failed, iterations left %d"
,
i
);
break
;
...
...
@@ -1234,14 +1712,65 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
if
(
dev
->
out_pipe
==
0
||
!
param
->
length
)
break
;
retval
=
0
;
d
bg
(
"%s TEST 12: unlink %d writes of %d
"
,
dev
->
id
,
param
->
iterations
,
param
->
length
);
d
ev_dbg
(
&
intf
->
dev
,
"TEST 12: unlink %d writes of %d
\n
"
,
param
->
iterations
,
param
->
length
);
for
(
i
=
param
->
iterations
;
retval
==
0
&&
i
--
;
/* NOP */
)
retval
=
unlink_simple
(
dev
,
dev
->
out_pipe
,
param
->
length
);
retval
=
unlink_simple
(
dev
,
dev
->
out_pipe
,
param
->
length
);
if
(
retval
)
dbg
(
"unlink writes failed, iterations left %d"
,
i
);
break
;
/* ep halt tests */
case
13
:
if
(
dev
->
out_pipe
==
0
&&
dev
->
in_pipe
==
0
)
break
;
retval
=
0
;
dev_dbg
(
&
intf
->
dev
,
"TEST 13: set/clear %d halts
\n
"
,
param
->
iterations
);
for
(
i
=
param
->
iterations
;
retval
==
0
&&
i
--
;
/* NOP */
)
retval
=
halt_simple
(
dev
);
if
(
retval
)
DBG
(
dev
,
"halts failed, iterations left %d
\n
"
,
i
);
break
;
/* control write tests */
case
14
:
if
(
!
dev
->
info
->
ctrl_out
)
break
;
dev_dbg
(
&
intf
->
dev
,
"TEST 14: %d ep0out, 0..%d vary %d
\n
"
,
param
->
iterations
,
param
->
length
,
param
->
vary
);
retval
=
ctrl_out
(
dev
,
param
->
iterations
,
param
->
length
,
param
->
vary
);
break
;
/* iso write tests */
case
15
:
if
(
dev
->
out_iso_pipe
==
0
||
param
->
sglen
==
0
)
break
;
dev_dbg
(
&
intf
->
dev
,
"TEST 15: write %d iso, %d entries of %d bytes
\n
"
,
param
->
iterations
,
param
->
sglen
,
param
->
length
);
// FIRMWARE: iso sink
retval
=
test_iso_queue
(
dev
,
param
,
dev
->
out_iso_pipe
,
dev
->
iso_out
);
break
;
/* iso read tests */
case
16
:
if
(
dev
->
in_iso_pipe
==
0
||
param
->
sglen
==
0
)
break
;
dev_dbg
(
&
intf
->
dev
,
"TEST 16: read %d iso, %d entries of %d bytes
\n
"
,
param
->
iterations
,
param
->
sglen
,
param
->
length
);
// FIRMWARE: iso source
retval
=
test_iso_queue
(
dev
,
param
,
dev
->
in_iso_pipe
,
dev
->
iso_in
);
break
;
// FIXME unlink from queue (ring with N urbs)
// FIXME scatterlist cancel (needs helper thread)
...
...
@@ -1262,7 +1791,7 @@ usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf)
static
int
force_interrupt
=
0
;
MODULE_PARM
(
force_interrupt
,
"i"
);
MODULE_PARM_DESC
(
force_interrupt
,
"0 = test
bulk (default),
else interrupt"
);
MODULE_PARM_DESC
(
force_interrupt
,
"0 = test
default;
else interrupt"
);
#ifdef GENERIC
static
int
vendor
;
...
...
@@ -1281,6 +1810,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
struct
usbtest_dev
*
dev
;
struct
usbtest_info
*
info
;
char
*
rtest
,
*
wtest
;
char
*
irtest
,
*
iwtest
;
udev
=
interface_to_usbdev
(
intf
);
...
...
@@ -1306,10 +1836,6 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
dev
->
info
=
info
;
init_MUTEX
(
&
dev
->
sem
);
/* use the same kind of id the hid driver shows */
snprintf
(
dev
->
id
,
sizeof
dev
->
id
,
"%s-%s:%d"
,
udev
->
bus
->
bus_name
,
udev
->
devpath
,
intf
->
altsetting
[
0
].
desc
.
bInterfaceNumber
);
dev
->
intf
=
intf
;
/* cacheline-aligned scratch for i/o */
...
...
@@ -1323,6 +1849,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
* "high bandwidth" modes (up to 3 packets/uframe).
*/
rtest
=
wtest
=
""
;
irtest
=
iwtest
=
""
;
if
(
force_interrupt
||
udev
->
speed
==
USB_SPEED_LOW
)
{
if
(
info
->
ep_in
)
{
dev
->
in_pipe
=
usb_rcvintpipe
(
udev
,
info
->
ep_in
);
...
...
@@ -1341,6 +1868,7 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
dbg
(
"couldn't get endpoints, %d
\n
"
,
status
);
return
status
;
}
/* may find bulk or ISO pipes */
}
else
{
if
(
info
->
ep_in
)
dev
->
in_pipe
=
usb_rcvbulkpipe
(
udev
,
...
...
@@ -1353,18 +1881,26 @@ usbtest_probe (struct usb_interface *intf, const struct usb_device_id *id)
rtest
=
" bulk-in"
;
if
(
dev
->
out_pipe
)
wtest
=
" bulk-out"
;
if
(
dev
->
in_iso_pipe
)
irtest
=
" iso-in"
;
if
(
dev
->
out_iso_pipe
)
iwtest
=
" iso-out"
;
}
usb_set_intfdata
(
intf
,
dev
);
info
(
"%s at %s ... %s speed {control%s%s} tests"
,
info
->
name
,
dev
->
id
,
dev_info
(
&
intf
->
dev
,
"%s
\n
"
,
info
->
name
);
dev_info
(
&
intf
->
dev
,
"%s speed {control%s%s%s%s%s} tests%s
\n
"
,
({
char
*
tmp
;
switch
(
udev
->
speed
)
{
case
USB_SPEED_LOW
:
tmp
=
"low"
;
break
;
case
USB_SPEED_FULL
:
tmp
=
"full"
;
break
;
case
USB_SPEED_HIGH
:
tmp
=
"high"
;
break
;
default:
tmp
=
"unknown"
;
break
;
};
tmp
;
}),
rtest
,
wtest
);
};
tmp
;
}),
info
->
ctrl_out
?
" in/out"
:
""
,
rtest
,
wtest
,
irtest
,
iwtest
,
info
->
alt
>=
0
?
" (+alt)"
:
""
);
return
0
;
}
...
...
@@ -1375,7 +1911,7 @@ static void usbtest_disconnect (struct usb_interface *intf)
down
(
&
dev
->
sem
);
usb_set_intfdata
(
intf
,
NULL
);
info
(
"unbound %s"
,
dev
->
id
);
dev_dbg
(
&
intf
->
dev
,
"disconnect
\n
"
);
kfree
(
dev
);
}
...
...
@@ -1423,6 +1959,7 @@ static struct usbtest_info fw_info = {
static
struct
usbtest_info
gz_info
=
{
.
name
=
"Linux gadget zero"
,
.
autoconf
=
1
,
.
ctrl_out
=
1
,
.
alt
=
0
,
};
...
...
@@ -1432,6 +1969,13 @@ static struct usbtest_info um_info = {
.
alt
=
-
1
,
};
static
struct
usbtest_info
um2_info
=
{
.
name
=
"Linux user mode ISO test driver"
,
.
autoconf
=
1
,
.
iso
=
1
,
.
alt
=
-
1
,
};
#ifdef IBOT2
/* this is a nice source of high speed bulk data;
* uses an FX2, with firmware provided in the device
...
...
@@ -1502,6 +2046,11 @@ static struct usb_device_id id_table [] = {
.
driver_info
=
(
unsigned
long
)
&
um_info
,
},
/* ... and a user-mode variant that talks iso */
{
USB_DEVICE
(
0x0525
,
0xa4a3
),
.
driver_info
=
(
unsigned
long
)
&
um2_info
,
},
#ifdef KEYSPAN_19Qi
/* Keyspan 19qi uses an21xx (original EZ-USB) */
// this does not coexist with the real Keyspan 19qi driver!
...
...
drivers/usb/misc/uss720.c
View file @
f749ccc0
...
...
@@ -333,7 +333,7 @@ static size_t parport_uss720_epp_read_data(struct parport *pp, void *buf, size_t
for
(;
got
<
length
;
got
++
)
{
if
(
get_1284_register
(
pp
,
4
,
(
char
*
)
buf
))
break
;
((
char
*
)
buf
)
++
;
buf
++
;
if
(
priv
->
reg
[
0
]
&
0x01
)
{
clear_epp_timeout
(
pp
);
break
;
...
...
@@ -392,7 +392,7 @@ static size_t parport_uss720_epp_read_addr(struct parport *pp, void *buf, size_t
for
(;
got
<
length
;
got
++
)
{
if
(
get_1284_register
(
pp
,
3
,
(
char
*
)
buf
))
break
;
((
char
*
)
buf
)
++
;
buf
++
;
if
(
priv
->
reg
[
0
]
&
0x01
)
{
clear_epp_timeout
(
pp
);
break
;
...
...
@@ -412,7 +412,7 @@ static size_t parport_uss720_epp_write_addr(struct parport *pp, const void *buf,
for
(;
written
<
length
;
written
++
)
{
if
(
set_1284_register
(
pp
,
3
,
*
(
char
*
)
buf
))
break
;
((
char
*
)
buf
)
++
;
buf
++
;
if
(
get_1284_register
(
pp
,
1
,
NULL
))
break
;
if
(
priv
->
reg
[
0
]
&
0x01
)
{
...
...
@@ -469,7 +469,7 @@ static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buff
for
(;
written
<
len
;
written
++
)
{
if
(
set_1284_register
(
pp
,
5
,
*
(
char
*
)
buffer
))
break
;
((
char
*
)
buffer
)
++
;
buffer
++
;
}
change_mode
(
pp
,
ECR_PS2
);
return
written
;
...
...
drivers/usb/net/Kconfig
View file @
f749ccc0
...
...
@@ -254,13 +254,14 @@ config USB_AX8817X
10/100 Ethernet devices.
This driver should work with at least the following devices:
* Aten UC210T
* ASIX AX88172
* D-Link DUB-E100
* Hawking UF200
* Linksys USB200M
* Netgear FA120
* Intellinet
* ST Lab USB Ethernet
* Intellinet
USB 2.0 Ethernet
* ST Lab USB
2.0
Ethernet
* TrendNet TU2-ET100
This driver creates an interface named "ethX", where X depends on
...
...
drivers/usb/net/usbnet.c
View file @
f749ccc0
...
...
@@ -222,6 +222,7 @@ struct driver_info {
#define FLAG_FRAMING_NC 0x0001
/* guard against device dropouts */
#define FLAG_FRAMING_GL 0x0002
/* genelink batches packets */
#define FLAG_FRAMING_Z 0x0004
/* zaurus adds a trailer */
#define FLAG_FRAMING_RN 0x0008
/* RNDIS batches, plus huge header */
#define FLAG_NO_SETINT 0x0010
/* device can't set_interface() */
#define FLAG_ETHER 0x0020
/* maybe use "eth%d" names */
...
...
@@ -300,7 +301,6 @@ MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
/*-------------------------------------------------------------------------*/
static
struct
ethtool_ops
usbnet_ethtool_ops
;
static
void
usbnet_get_drvinfo
(
struct
net_device
*
,
struct
ethtool_drvinfo
*
);
static
u32
usbnet_get_link
(
struct
net_device
*
);
static
u32
usbnet_get_msglevel
(
struct
net_device
*
);
...
...
@@ -364,6 +364,25 @@ get_endpoints (struct usbnet *dev, struct usb_interface *intf)
return
0
;
}
static
void
skb_return
(
struct
usbnet
*
dev
,
struct
sk_buff
*
skb
)
{
int
status
;
skb
->
dev
=
dev
->
net
;
skb
->
protocol
=
eth_type_trans
(
skb
,
dev
->
net
);
dev
->
stats
.
rx_packets
++
;
dev
->
stats
.
rx_bytes
+=
skb
->
len
;
#ifdef VERBOSE
devdbg
(
dev
,
"< rx, len %d, type 0x%x"
,
skb
->
len
+
sizeof
(
struct
ethhdr
),
skb
->
protocol
);
#endif
memset
(
skb
->
cb
,
0
,
sizeof
(
struct
skb_data
));
status
=
netif_rx
(
skb
);
if
(
status
!=
NET_RX_SUCCESS
)
devdbg
(
dev
,
"netif_rx status %d"
,
status
);
}
#ifdef CONFIG_USB_AN2720
#define HAVE_HARDWARE
...
...
@@ -818,23 +837,30 @@ static const struct driver_info belkin_info = {
#if defined (CONFIG_USB_CDCETHER) || defined (CONFIG_USB_ZAURUS)
/*-------------------------------------------------------------------------
*
* Communications Device Class, Ethernet Control model
*
* Takes two interfaces. The DATA interface is inactive till an altsetting
* is selected. Configuration data includes class descriptors.
*
* Zaurus uses nonstandard framing, and doesn't uniquify its Ethernet
* addresses, but is otherwise CDC Ether.
*
* This should interop with whatever the 2.4 "CDCEther.c" driver
* (by Brad Hards) talked with.
* Communications Device Class declarations.
* Used by CDC Ethernet, and some CDC variants
*
*-------------------------------------------------------------------------*/
#ifdef CONFIG_USB_CDCETHER
#define NEED_GENERIC_CDC
#endif
#ifdef CONFIG_USB_ZAURUS
/* Ethernet variant uses funky framing, broken ethernet addressing */
#define NEED_GENERIC_CDC
#endif
#ifdef CONFIG_USB_RNDIS
/* ACM variant uses even funkier framing, complex control RPC scheme */
#define NEED_GENERIC_CDC
#endif
#ifdef NEED_GENERIC_CDC
/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */
struct
header_desc
{
u8
bLength
;
...
...
@@ -876,43 +902,21 @@ struct cdc_state {
struct
usb_interface
*
data
;
};
#include <linux/ctype.h>
static
u8
nibble
(
unsigned
char
c
)
{
if
(
likely
(
isdigit
(
c
)))
return
c
-
'0'
;
c
=
toupper
(
c
);
if
(
likely
(
isxdigit
(
c
)))
return
10
+
c
-
'A'
;
return
0
;
}
static
inline
int
get_ethernet_addr
(
struct
usbnet
*
dev
,
struct
ether_desc
*
e
)
{
int
tmp
,
i
;
unsigned
char
buf
[
13
];
tmp
=
usb_string
(
dev
->
udev
,
e
->
iMACAddress
,
buf
,
sizeof
buf
);
if
(
tmp
<
0
)
return
tmp
;
else
if
(
tmp
!=
12
)
return
-
EINVAL
;
for
(
i
=
tmp
=
0
;
i
<
6
;
i
++
,
tmp
+=
2
)
dev
->
net
->
dev_addr
[
i
]
=
(
nibble
(
buf
[
tmp
])
<<
4
)
+
nibble
(
buf
[
tmp
+
1
]);
return
0
;
}
static
struct
usb_driver
usbnet_driver
;
static
int
cdc_bind
(
struct
usbnet
*
dev
,
struct
usb_interface
*
intf
)
/*
* probes control interface, claims data interface, collects the bulk
* endpoints, activates data interface (if needed), maybe sets MTU.
* all pure cdc, except for certain firmware workarounds.
*/
static
int
generic_cdc_bind
(
struct
usbnet
*
dev
,
struct
usb_interface
*
intf
)
{
u8
*
buf
=
intf
->
altsetting
->
extra
;
int
len
=
intf
->
altsetting
->
extralen
;
struct
usb_interface_descriptor
*
d
;
struct
cdc_state
*
info
=
(
void
*
)
&
dev
->
data
;
int
status
;
int
rndis
;
if
(
sizeof
dev
->
data
<
sizeof
*
info
)
return
-
EDOM
;
...
...
@@ -931,14 +935,23 @@ static int cdc_bind (struct usbnet *dev, struct usb_interface *intf)
"CDC descriptors on config
\n
"
);
}
/* this assumes that if there's a non-RNDIS vendor variant
* of cdc-acm, it'll fail RNDIS requests cleanly.
*/
rndis
=
(
intf
->
altsetting
->
desc
.
bInterfaceProtocol
==
0xff
);
memset
(
info
,
0
,
sizeof
*
info
);
info
->
control
=
intf
;
while
(
len
>
3
)
{
if
(
buf
[
1
]
!=
USB_DT_CS_INTERFACE
)
goto
next_desc
;
/* bDescriptorSubType identifies three "must have" descriptors;
* save them for later.
/* use bDescriptorSubType to identify the CDC descriptors.
* We expect devices with CDC header and union descriptors.
* For CDC Ethernet we need the ethernet descriptor.
* For RNDIS, ignore two (pointless) CDC modem descriptors
* in favor of a complicated OID-based RPC scheme doing what
* CDC Ethernet achieves with a simple descriptor.
*/
switch
(
buf
[
2
])
{
case
0x00
:
/* Header, mostly useless */
...
...
@@ -1001,8 +1014,6 @@ static int cdc_bind (struct usbnet *dev, struct usb_interface *intf)
d
->
bInterfaceClass
);
goto
bad_desc
;
}
if
(
usb_interface_claimed
(
info
->
data
))
return
-
EBUSY
;
break
;
case
0x0F
:
/* Ethernet Networking */
if
(
info
->
ether
)
{
...
...
@@ -1015,13 +1026,20 @@ static int cdc_bind (struct usbnet *dev, struct usb_interface *intf)
info
->
u
->
bLength
);
goto
bad_desc
;
}
dev
->
net
->
mtu
=
cpu_to_le16p
(
&
info
->
ether
->
wMaxSegmentSize
)
-
ETH_HLEN
;
/* because of Zaurus, we may be ignoring the host
* side link address we were given.
*/
break
;
}
next_desc:
len
-=
buf
[
0
];
/* bLength */
buf
+=
buf
[
0
];
}
if
(
!
info
->
header
||
!
info
->
u
||
!
info
->
ether
)
{
if
(
!
info
->
header
||
!
info
->
u
||
(
!
rndis
&&
!
info
->
ether
))
{
dev_dbg
(
&
intf
->
dev
,
"missing cdc %s%s%sdescriptor
\n
"
,
info
->
header
?
""
:
"header "
,
info
->
u
?
""
:
"union "
,
...
...
@@ -1029,18 +1047,6 @@ static int cdc_bind (struct usbnet *dev, struct usb_interface *intf)
goto
bad_desc
;
}
#ifdef CONFIG_USB_ZAURUS
/* Zaurus ethernet addresses aren't unique ... */
if
((
dev
->
driver_info
->
flags
&
FLAG_FRAMING_Z
)
!=
0
)
/* ignore */
;
else
#endif
{
status
=
get_ethernet_addr
(
dev
,
info
->
ether
);
if
(
status
<
0
)
return
status
;
}
/* claim data interface and set it up ... with side effects.
* network traffic can't flow until an altsetting is enabled.
*/
...
...
@@ -1049,16 +1055,11 @@ static int cdc_bind (struct usbnet *dev, struct usb_interface *intf)
return
status
;
status
=
get_endpoints
(
dev
,
info
->
data
);
if
(
status
<
0
)
{
/* ensure immediate exit from usbnet_disconnect */
usb_set_intfdata
(
info
->
data
,
NULL
);
usb_driver_release_interface
(
&
usbnet_driver
,
info
->
data
);
return
status
;
}
/* FIXME cdc-ether has some multicast code too, though it complains
* in routine cases. info->ether describes the multicast support.
*/
dev
->
net
->
mtu
=
cpu_to_le16p
(
&
info
->
ether
->
wMaxSegmentSize
)
-
ETH_HLEN
;
return
0
;
bad_desc:
...
...
@@ -1072,24 +1073,89 @@ static void cdc_unbind (struct usbnet *dev, struct usb_interface *intf)
/* disconnect master --> disconnect slave */
if
(
intf
==
info
->
control
&&
info
->
data
)
{
/* ensure immediate exit from usbnet_disconnect */
usb_set_intfdata
(
info
->
data
,
NULL
);
usb_driver_release_interface
(
&
usbnet_driver
,
info
->
data
);
info
->
data
=
0
;
}
/* and vice versa (just in case) */
else
if
(
intf
==
info
->
data
&&
info
->
control
)
{
/* ensure immediate exit from usbnet_disconnect */
usb_set_intfdata
(
info
->
control
,
NULL
);
usb_driver_release_interface
(
&
usbnet_driver
,
info
->
control
);
info
->
control
=
0
;
}
}
#endif
/* CONFIG_USB_ZAURUS || CONFIG_USB_CDCETHER */
#endif
/* NEED_GENERIC_CDC */
#ifdef CONFIG_USB_CDCETHER
#define HAVE_HARDWARE
/*-------------------------------------------------------------------------
*
* Communications Device Class, Ethernet Control model
*
* Takes two interfaces. The DATA interface is inactive till an altsetting
* is selected. Configuration data includes class descriptors.
*
* This should interop with whatever the 2.4 "CDCEther.c" driver
* (by Brad Hards) talked with.
*
*-------------------------------------------------------------------------*/
#include <linux/ctype.h>
static
u8
nibble
(
unsigned
char
c
)
{
if
(
likely
(
isdigit
(
c
)))
return
c
-
'0'
;
c
=
toupper
(
c
);
if
(
likely
(
isxdigit
(
c
)))
return
10
+
c
-
'A'
;
return
0
;
}
static
inline
int
get_ethernet_addr
(
struct
usbnet
*
dev
,
struct
ether_desc
*
e
)
{
int
tmp
,
i
;
unsigned
char
buf
[
13
];
tmp
=
usb_string
(
dev
->
udev
,
e
->
iMACAddress
,
buf
,
sizeof
buf
);
if
(
tmp
<
0
)
return
tmp
;
else
if
(
tmp
!=
12
)
return
-
EINVAL
;
for
(
i
=
tmp
=
0
;
i
<
6
;
i
++
,
tmp
+=
2
)
dev
->
net
->
dev_addr
[
i
]
=
(
nibble
(
buf
[
tmp
])
<<
4
)
+
nibble
(
buf
[
tmp
+
1
]);
return
0
;
}
static
int
cdc_bind
(
struct
usbnet
*
dev
,
struct
usb_interface
*
intf
)
{
int
status
;
struct
cdc_state
*
info
=
(
void
*
)
&
dev
->
data
;
status
=
generic_cdc_bind
(
dev
,
intf
);
if
(
status
<
0
)
return
status
;
status
=
get_ethernet_addr
(
dev
,
info
->
ether
);
if
(
status
<
0
)
{
usb_driver_release_interface
(
&
usbnet_driver
,
info
->
data
);
return
status
;
}
/* FIXME cdc-ether has some multicast code too, though it complains
* in routine cases. info->ether describes the multicast support.
*/
return
0
;
}
static
const
struct
driver_info
cdc_info
=
{
.
description
=
"CDC Ethernet Device"
,
.
flags
=
FLAG_ETHER
,
...
...
@@ -1337,7 +1403,6 @@ static int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
struct
gl_header
*
header
;
struct
gl_packet
*
packet
;
struct
sk_buff
*
gl_skb
;
int
status
;
u32
size
;
header
=
(
struct
gl_header
*
)
skb
->
data
;
...
...
@@ -1373,17 +1438,7 @@ static int genelink_rx_fixup (struct usbnet *dev, struct sk_buff *skb)
// copy the packet data to the new skb
memcpy
(
skb_put
(
gl_skb
,
size
),
packet
->
packet_data
,
size
);
gl_skb
->
dev
=
dev
->
net
;
// determine the packet's protocol ID
gl_skb
->
protocol
=
eth_type_trans
(
gl_skb
,
dev
->
net
);
// update the status
dev
->
stats
.
rx_packets
++
;
dev
->
stats
.
rx_bytes
+=
size
;
// notify os of the received packet
status
=
netif_rx
(
gl_skb
);
skb_return
(
dev
,
skb
);
}
// advance to the next packet
...
...
@@ -2141,7 +2196,7 @@ static const struct driver_info zaurus_sl5x00_info = {
.
description
=
"Sharp Zaurus SL-5x00"
,
.
flags
=
FLAG_FRAMING_Z
,
.
check_connect
=
always_connected
,
.
bind
=
cdc_bind
,
.
bind
=
generic_
cdc_bind
,
.
unbind
=
cdc_unbind
,
.
tx_fixup
=
zaurus_tx_fixup
,
};
...
...
@@ -2255,6 +2310,11 @@ static void rx_submit (struct usbnet *dev, struct urb *urb, int flags)
if
(
dev
->
driver_info
->
flags
&
FLAG_FRAMING_Z
)
size
=
6
+
(
sizeof
(
struct
ethhdr
)
+
dev
->
net
->
mtu
);
else
#endif
#ifdef CONFIG_USB_RNDIS
if
(
dev
->
driver_info
->
flags
&
FLAG_FRAMING_RN
)
size
=
RNDIS_MAX_TRANSFER
;
else
#endif
size
=
(
sizeof
(
struct
ethhdr
)
+
dev
->
net
->
mtu
);
...
...
@@ -2319,23 +2379,9 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
goto
error
;
// else network stack removes extra byte if we forced a short packet
if
(
skb
->
len
)
{
int
status
;
skb
->
dev
=
dev
->
net
;
skb
->
protocol
=
eth_type_trans
(
skb
,
dev
->
net
);
dev
->
stats
.
rx_packets
++
;
dev
->
stats
.
rx_bytes
+=
skb
->
len
;
#ifdef VERBOSE
devdbg
(
dev
,
"< rx, len %d, type 0x%x"
,
skb
->
len
+
sizeof
(
struct
ethhdr
),
skb
->
protocol
);
#endif
memset
(
skb
->
cb
,
0
,
sizeof
(
struct
skb_data
));
status
=
netif_rx
(
skb
);
if
(
status
!=
NET_RX_SUCCESS
)
devdbg
(
dev
,
"netif_rx status %d"
,
status
);
}
else
{
if
(
skb
->
len
)
skb_return
(
dev
,
skb
);
else
{
devdbg
(
dev
,
"drop"
);
error:
dev
->
stats
.
rx_errors
++
;
...
...
@@ -2544,6 +2590,8 @@ static int usbnet_open (struct net_device *net)
framing
=
"GeneSys"
;
else
if
(
dev
->
driver_info
->
flags
&
FLAG_FRAMING_Z
)
framing
=
"Zaurus"
;
else
if
(
dev
->
driver_info
->
flags
&
FLAG_FRAMING_RN
)
framing
=
"RNDIS"
;
else
framing
=
"simple"
;
...
...
@@ -2941,6 +2989,8 @@ static void usbnet_disconnect (struct usb_interface *intf)
/*-------------------------------------------------------------------------*/
static
struct
ethtool_ops
usbnet_ethtool_ops
;
// precondition: never called in_interrupt
int
...
...
@@ -3127,6 +3177,10 @@ static const struct usb_device_id products [] = {
// Hawking UF200, TrendNet TU2-ET100
USB_DEVICE
(
0x07b8
,
0x420a
),
.
driver_info
=
(
unsigned
long
)
&
hawking_uf200_info
,
},
{
// ATEN UC210T
USB_DEVICE
(
0x0557
,
0x2009
),
.
driver_info
=
(
unsigned
long
)
&
ax8817x_info
,
},
#endif
...
...
@@ -3167,6 +3221,14 @@ static const struct usb_device_id products [] = {
},
#endif
#ifdef CONFIG_USB_RNDIS
{
/* RNDIS is MSFT's un-official variant of CDC ACM */
USB_INTERFACE_INFO
(
USB_CLASS_COMM
,
2
/* ACM */
,
0x0ff
),
.
driver_info
=
(
unsigned
long
)
&
rndis_info
,
},
#endif
#ifdef CONFIG_USB_ARMLINUX
/*
* SA-1100 using standard ARM Linux kernels, or compatible.
...
...
@@ -3238,7 +3300,16 @@ static const struct usb_device_id products [] = {
.
match_flags
=
USB_DEVICE_ID_MATCH_INT_INFO
|
USB_DEVICE_ID_MATCH_DEVICE
,
.
idVendor
=
0x04DD
,
.
idProduct
=
0x9031
,
/* C-750 */
.
idProduct
=
0x9031
,
/* C-750 C-760 */
.
bInterfaceClass
=
0x02
,
.
bInterfaceSubClass
=
0x0a
,
.
bInterfaceProtocol
=
0x00
,
.
driver_info
=
(
unsigned
long
)
&
zaurus_pxa_info
,
},
{
.
match_flags
=
USB_DEVICE_ID_MATCH_INT_INFO
|
USB_DEVICE_ID_MATCH_DEVICE
,
.
idVendor
=
0x04DD
,
.
idProduct
=
0x9032
,
/* SL-6000 */
.
bInterfaceClass
=
0x02
,
.
bInterfaceSubClass
=
0x0a
,
.
bInterfaceProtocol
=
0x00
,
...
...
drivers/usb/serial/belkin_sa.c
View file @
f749ccc0
...
...
@@ -232,8 +232,10 @@ static int belkin_sa_open (struct usb_serial_port *port, struct file *filp)
port
->
interrupt_in_urb
->
dev
=
port
->
serial
->
dev
;
retval
=
usb_submit_urb
(
port
->
interrupt_in_urb
,
GFP_KERNEL
);
if
(
retval
)
if
(
retval
)
{
usb_unlink_urb
(
port
->
read_urb
);
err
(
" usb_submit_urb(read int) failed"
);
}
exit:
return
retval
;
...
...
drivers/usb/serial/kobil_sct.c
View file @
f749ccc0
...
...
@@ -409,8 +409,6 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
// someone sets the dev to 0 if the close method has been called
port
->
interrupt_in_urb
->
dev
=
port
->
serial
->
dev
;
// usb_dump_urb(port->interrupt_in_urb);
result
=
usb_submit_urb
(
port
->
interrupt_in_urb
,
GFP_ATOMIC
);
dbg
(
"%s - port %d Send read URB returns: %i"
,
__FUNCTION__
,
port
->
number
,
result
);
}
...
...
@@ -496,8 +494,6 @@ static int kobil_write (struct usb_serial_port *port, int from_user,
port
->
interrupt_in_urb
->
dev
=
port
->
serial
->
dev
;
// start reading
//usb_dump_urb(port->interrupt_in_urb);
result
=
usb_submit_urb
(
port
->
interrupt_in_urb
,
GFP_ATOMIC
);
dbg
(
"%s - port %d Send read URB returns: %i"
,
__FUNCTION__
,
port
->
number
,
result
);
}
...
...
drivers/usb/serial/visor.c
View file @
f749ccc0
...
...
@@ -241,6 +241,8 @@ static struct usb_device_id id_table [] = {
.
driver_info
=
(
kernel_ulong_t
)
&
palm_os_4_probe
},
{
USB_DEVICE
(
GARMIN_VENDOR_ID
,
GARMIN_IQUE_3600_ID
),
.
driver_info
=
(
kernel_ulong_t
)
&
palm_os_4_probe
},
{
USB_DEVICE
(
ACEECA_VENDOR_ID
,
ACEECA_MEZ1000_ID
),
.
driver_info
=
(
kernel_ulong_t
)
&
palm_os_4_probe
},
{
},
/* optional parameter entry */
{
}
/* Terminating entry */
};
...
...
@@ -274,6 +276,7 @@ static struct usb_device_id id_table_combined [] = {
{
USB_DEVICE
(
SONY_VENDOR_ID
,
SONY_CLIE_TJ25_ID
)
},
{
USB_DEVICE
(
SAMSUNG_VENDOR_ID
,
SAMSUNG_SCH_I330_ID
)
},
{
USB_DEVICE
(
GARMIN_VENDOR_ID
,
GARMIN_IQUE_3600_ID
)
},
{
USB_DEVICE
(
ACEECA_VENDOR_ID
,
ACEECA_MEZ1000_ID
)
},
{
},
/* optional parameter entry */
{
}
/* Terminating entry */
};
...
...
drivers/usb/serial/visor.h
View file @
f749ccc0
...
...
@@ -50,6 +50,9 @@
#define GARMIN_VENDOR_ID 0x091E
#define GARMIN_IQUE_3600_ID 0x0004
#define ACEECA_VENDOR_ID 0x4766
#define ACEECA_MEZ1000_ID 0x0001
/****************************************************************************
* Handspring Visor Vendor specific request codes (bRequest values)
* A big thank you to Handspring for providing the following information.
...
...
drivers/usb/storage/datafab.h
View file @
f749ccc0
...
...
@@ -29,7 +29,7 @@ extern int datafab_transport(Scsi_Cmnd *srb, struct us_data *us);
struct
datafab_info
{
unsigned
long
sectors
;
// total sector count
unsigned
long
ssize
;
// sector size in bytes
char
lun
;
// used for dual-slot readers
signed
char
lun
;
// used for dual-slot readers
// the following aren't used yet
unsigned
char
sense_key
;
...
...
drivers/usb/storage/unusual_devs.h
View file @
f749ccc0
...
...
@@ -604,7 +604,14 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff,
* - They don't like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
*/
UNUSUAL_DEV
(
0x07cf
,
0x1001
,
0x1000
,
0x9999
,
UNUSUAL_DEV
(
0x07cf
,
0x1001
,
0x1000
,
0x9009
,
"Casio"
,
"QV DigitalCamera"
,
US_SC_8070
,
US_PR_CB
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Later Casio cameras apparently tell the truth */
UNUSUAL_DEV
(
0x07cf
,
0x1001
,
0x9010
,
0x9999
,
"Casio"
,
"QV DigitalCamera"
,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
...
...
drivers/usb/storage/usb.c
View file @
f749ccc0
...
...
@@ -834,7 +834,7 @@ void usb_stor_release_resources(struct us_data *us)
/* Finish the SCSI host removal sequence */
if
(
us
->
host
)
{
(
struct
us_data
*
)
us
->
host
->
hostdata
[
0
]
=
NULL
;
us
->
host
->
hostdata
[
0
]
=
0
;
scsi_host_put
(
us
->
host
);
}
...
...
include/linux/usb.h
View file @
f749ccc0
...
...
@@ -1016,16 +1016,6 @@ static inline unsigned int __create_pipe(struct usb_device *dev, unsigned int en
/* -------------------------------------------------------------------------- */
/*
* Debugging and troubleshooting/diagnostic helpers.
*/
void
usb_show_device_descriptor
(
struct
usb_device_descriptor
*
);
void
usb_show_config_descriptor
(
struct
usb_config_descriptor
*
);
void
usb_show_interface_descriptor
(
struct
usb_interface_descriptor
*
);
void
usb_show_endpoint_descriptor
(
struct
usb_endpoint_descriptor
*
);
void
usb_show_device
(
struct
usb_device
*
);
void
usb_show_string
(
struct
usb_device
*
dev
,
char
*
id
,
int
index
);
#ifdef DEBUG
#define dbg(format, arg...) printk(KERN_DEBUG "%s: " format "\n" , __FILE__ , ## arg)
#else
...
...
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