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
a98b28b1
Commit
a98b28b1
authored
May 29, 2003
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
Merge
bk://kernel.bkbits.net/acme/usb-2.5
into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents
832b5fae
25d1aa56
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
302 additions
and
663 deletions
+302
-663
drivers/usb/Makefile
drivers/usb/Makefile
+3
-0
drivers/usb/core/hub.c
drivers/usb/core/hub.c
+9
-5
drivers/usb/image/hpusbscsi.c
drivers/usb/image/hpusbscsi.c
+74
-149
drivers/usb/image/hpusbscsi.h
drivers/usb/image/hpusbscsi.h
+0
-22
drivers/usb/image/microtek.c
drivers/usb/image/microtek.c
+44
-247
drivers/usb/image/microtek.h
drivers/usb/image/microtek.h
+0
-3
drivers/usb/storage/scsiglue.c
drivers/usb/storage/scsiglue.c
+29
-3
drivers/usb/storage/transport.c
drivers/usb/storage/transport.c
+122
-173
drivers/usb/storage/transport.h
drivers/usb/storage/transport.h
+2
-6
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/unusual_devs.h
+6
-41
drivers/usb/storage/usb.c
drivers/usb/storage/usb.c
+5
-11
drivers/usb/storage/usb.h
drivers/usb/storage/usb.h
+8
-3
No files found.
drivers/usb/Makefile
View file @
a98b28b1
...
...
@@ -59,3 +59,6 @@ obj-$(CONFIG_USB_TEST) += misc/
obj-$(CONFIG_USB_TIGL)
+=
misc/
obj-$(CONFIG_USB_USS720)
+=
misc/
obj-$(CONFIG_USB_NET2280)
+=
gadget/
obj-$(CONFIG_USB_ZERO)
+=
gadget/
obj-$(CONFIG_USB_ETH)
+=
gadget/
drivers/usb/core/hub.c
View file @
a98b28b1
...
...
@@ -1199,12 +1199,18 @@ int usb_physical_reset_device(struct usb_device *dev)
if
(
port
<
0
)
return
-
ENOENT
;
descriptor
=
kmalloc
(
sizeof
*
descriptor
,
GFP_NOIO
);
if
(
!
descriptor
)
{
return
-
ENOMEM
;
}
down
(
&
usb_address0_sem
);
/* Send a reset to the device */
if
(
usb_hub_port_reset
(
parent
,
port
,
dev
,
HUB_SHORT_RESET_TIME
))
{
usb_hub_port_disable
(
parent
,
port
);
up
(
&
usb_address0_sem
);
kfree
(
descriptor
);
return
(
-
ENODEV
);
}
...
...
@@ -1214,6 +1220,7 @@ int usb_physical_reset_device(struct usb_device *dev)
err
(
"USB device not accepting new address (error=%d)"
,
ret
);
usb_hub_port_disable
(
parent
,
port
);
up
(
&
usb_address0_sem
);
kfree
(
descriptor
);
return
ret
;
}
...
...
@@ -1231,10 +1238,7 @@ int usb_physical_reset_device(struct usb_device *dev)
* If nothing changed, we reprogram the configuration and then
* the alternate settings.
*/
descriptor
=
kmalloc
(
sizeof
*
descriptor
,
GFP_NOIO
);
if
(
!
descriptor
)
{
return
-
ENOMEM
;
}
ret
=
usb_get_descriptor
(
dev
,
USB_DT_DEVICE
,
0
,
descriptor
,
sizeof
(
*
descriptor
));
if
(
ret
<
0
)
{
...
...
drivers/usb/image/hpusbscsi.c
View file @
a98b28b1
...
...
@@ -22,63 +22,54 @@ static char *states[]={"FREE", "BEGINNING", "WORKING", "ERROR", "WAIT", "PREMATU
#define TRACE_STATE printk(KERN_DEBUG"hpusbscsi->state = %s at line %d\n", states[hpusbscsi->state], __LINE__)
/* global variables */
struct
list_head
hpusbscsi_devices
;
//LIST_HEAD(hpusbscsi_devices);
/* USB related parts */
static
Scsi_Host_Template
hpusbscsi_scsi_host_template
=
{
.
module
=
THIS_MODULE
,
.
name
=
"hpusbscsi"
,
.
proc_name
=
"hpusbscsi"
,
.
queuecommand
=
hpusbscsi_scsi_queuecommand
,
.
eh_abort_handler
=
hpusbscsi_scsi_abort
,
.
eh_host_reset_handler
=
hpusbscsi_scsi_host_reset
,
.
sg_tablesize
=
SG_ALL
,
.
can_queue
=
1
,
.
this_id
=
-
1
,
.
cmd_per_lun
=
1
,
.
use_clustering
=
1
,
.
emulated
=
1
,
};
static
int
hpusbscsi_usb_probe
(
struct
usb_interface
*
intf
,
hpusbscsi_usb_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
struct
usb_device
*
dev
=
interface_to_usbdev
(
intf
);
struct
usb_host_interface
*
altsetting
=
intf
->
altsetting
;
struct
hpusbscsi
*
new
;
struct
usb_device
*
dev
=
interface_to_usbdev
(
intf
);
struct
usb_host_interface
*
altsetting
=
&
(
intf
->
altsetting
[
0
]);
int
error
=
-
ENOMEM
;
int
i
,
result
;
/* basic check */
if
(
altsetting
->
desc
.
bNumEndpoints
!=
3
)
{
printk
(
KERN_ERR
"Wrong number of endpoints
\n
"
);
return
-
ENODEV
;
}
/* descriptor allocation */
new
=
(
struct
hpusbscsi
*
)
kmalloc
(
sizeof
(
struct
hpusbscsi
),
GFP_KERNEL
);
if
(
new
==
NULL
)
new
=
kmalloc
(
sizeof
(
struct
hpusbscsi
),
GFP_KERNEL
);
if
(
!
new
)
return
-
ENOMEM
;
DEBUG
(
"Allocated memory
\n
"
);
memset
(
new
,
0
,
sizeof
(
struct
hpusbscsi
));
memset
(
new
,
0
,
sizeof
(
struct
hpusbscsi
));
new
->
dataurb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
new
->
dataurb
)
{
kfree
(
new
);
return
-
ENOMEM
;
}
if
(
!
new
->
dataurb
)
goto
out_kfree
;
new
->
controlurb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
new
->
controlurb
)
{
usb_free_urb
(
new
->
dataurb
);
kfree
(
new
);
return
-
ENOMEM
;
}
new
->
dev
=
dev
;
init_waitqueue_head
(
&
new
->
pending
);
init_waitqueue_head
(
&
new
->
deathrow
);
INIT_LIST_HEAD
(
&
new
->
lh
);
if
(
!
new
->
controlurb
)
goto
out_free_dataurb
;
new
->
dev
=
dev
;
init_waitqueue_head
(
&
new
->
pending
);
init_waitqueue_head
(
&
new
->
deathrow
);
/* finding endpoints */
error
=
-
ENODEV
;
for
(
i
=
0
;
i
<
altsetting
->
desc
.
bNumEndpoints
;
i
++
)
{
if
(
(
altsetting
->
endpoint
[
i
].
desc
.
if
((
altsetting
->
endpoint
[
i
].
desc
.
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_BULK
)
{
if
(
altsetting
->
endpoint
[
i
].
desc
.
...
...
@@ -97,57 +88,71 @@ hpusbscsi_usb_probe (struct usb_interface *intf,
new
->
ep_int
=
altsetting
->
endpoint
[
i
].
desc
.
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
;
new
->
interrupt_interval
=
altsetting
->
endpoint
[
i
].
desc
.
bInterval
;
new
->
interrupt_interval
=
altsetting
->
endpoint
[
i
].
desc
.
bInterval
;
}
}
/* USB initialisation magic for the simple case */
result
=
usb_set_interface
(
dev
,
altsetting
->
desc
.
bInterfaceNumber
,
0
);
result
=
usb_set_interface
(
dev
,
altsetting
->
desc
.
bInterfaceNumber
,
0
);
switch
(
result
)
{
case
0
:
/* no error */
break
;
default:
printk
(
KERN_ERR
"unknown error %d from usb_set_interface
\n
"
,
printk
(
KERN_ERR
"unknown error %d from usb_set_interface
\n
"
,
result
);
goto
err_out
;
goto
out_free_controlurb
;
}
/* making a template for the scsi layer to fake detection of a scsi device */
/* build and submit an interrupt URB for status byte handling */
usb_fill_int_urb
(
new
->
controlurb
,
new
->
dev
,
usb_rcvintpipe
(
new
->
dev
,
new
->
ep_int
),
&
new
->
scsi_state_byte
,
1
,
control_interrupt_callback
,
new
,
new
->
interrupt_interval
);
if
(
usb_submit_urb
(
new
->
controlurb
,
GFP_KERNEL
)
<
0
)
goto
out_free_controlurb
;
memcpy
(
&
(
new
->
ctempl
),
&
hpusbscsi_scsi_host_template
,
sizeof
(
hpusbscsi_scsi_host_template
));
(
struct
hpusbscsi
*
)
new
->
ctempl
.
proc_dir
=
new
;
new
->
ctempl
.
module
=
THIS_MODULE
;
/* In host->hostdata we store a pointer to desc */
new
->
host
=
scsi_register
(
&
hpusbscsi_scsi_host_template
,
sizeof
(
new
));
if
(
!
new
->
host
)
goto
out_unlink_controlurb
;
if
(
scsi_register_host
(
&
new
->
ctempl
))
goto
err_out
;
new
->
host
->
hostdata
[
0
]
=
(
unsigned
long
)
new
;
scsi_add_host
(
new
->
host
,
&
intf
->
dev
)
;
new
->
sense_command
[
0
]
=
REQUEST_SENSE
;
new
->
sense_command
[
4
]
=
HPUSBSCSI_SENSE_LENGTH
;
/* adding to list for module unload */
list_add
(
&
hpusbscsi_devices
,
&
new
->
lh
);
usb_set_intfdata
(
intf
,
new
);
return
0
;
err_out:
usb_free_urb
(
new
->
controlurb
);
usb_free_urb
(
new
->
dataurb
);
kfree
(
new
);
return
-
ENODEV
;
out_unlink_controlurb:
usb_unlink_urb
(
new
->
controlurb
);
out_free_controlurb:
usb_free_urb
(
new
->
controlurb
);
out_free_dataurb:
usb_free_urb
(
new
->
dataurb
);
out_kfree:
kfree
(
new
);
return
error
;
}
static
void
hpusbscsi_usb_disconnect
(
struct
usb_interface
*
intf
)
hpusbscsi_usb_disconnect
(
struct
usb_interface
*
intf
)
{
struct
hpusbscsi
*
desc
=
usb_get_intfdata
(
intf
);
usb_set_intfdata
(
intf
,
NULL
);
if
(
desc
)
scsi_remove_host
(
desc
->
host
);
usb_unlink_urb
(
desc
->
controlurb
);
scsi_unregister
(
desc
->
host
);
usb_free_urb
(
desc
->
controlurb
);
usb_free_urb
(
desc
->
dataurb
);
kfree
(
desc
);
}
static
struct
usb_device_id
hpusbscsi_usb_ids
[]
=
{
...
...
@@ -178,101 +183,21 @@ static struct usb_driver hpusbscsi_usb_driver = {
/* module initialisation */
int
__init
static
int
__init
hpusbscsi_init
(
void
)
{
int
result
;
INIT_LIST_HEAD
(
&
hpusbscsi_devices
);
DEBUG
(
"Driver loaded
\n
"
);
if
((
result
=
usb_register
(
&
hpusbscsi_usb_driver
))
<
0
)
{
printk
(
KERN_ERR
"hpusbscsi: driver registration failed
\n
"
);
return
-
1
;
}
else
{
return
0
;
}
return
usb_register
(
&
hpusbscsi_usb_driver
);
}
void
__exit
static
void
__exit
hpusbscsi_exit
(
void
)
{
struct
list_head
*
tmp
;
struct
list_head
*
old
;
struct
hpusbscsi
*
o
;
for
(
tmp
=
hpusbscsi_devices
.
next
;
tmp
!=
&
hpusbscsi_devices
;
/*nothing */
)
{
old
=
tmp
;
tmp
=
tmp
->
next
;
o
=
(
struct
hpusbscsi
*
)
old
;
usb_unlink_urb
(
o
->
controlurb
);
scsi_unregister_host
(
&
o
->
ctempl
);
usb_free_urb
(
o
->
controlurb
);
usb_free_urb
(
o
->
dataurb
);
kfree
(
old
);
}
usb_deregister
(
&
hpusbscsi_usb_driver
);
usb_deregister
(
&
hpusbscsi_usb_driver
);
}
module_init
(
hpusbscsi_init
);
module_exit
(
hpusbscsi_exit
);
/* interface to the scsi layer */
static
int
hpusbscsi_scsi_detect
(
struct
SHT
*
sht
)
{
/* Whole function stolen from usb-storage */
struct
hpusbscsi
*
desc
=
(
struct
hpusbscsi
*
)
sht
->
proc_dir
;
/* What a hideous hack! */
char
local_name
[
48
];
/* set up the name of our subdirectory under /proc/scsi/ */
sprintf
(
local_name
,
"hpusbscsi-%d"
,
desc
->
number
);
sht
->
proc_name
=
kmalloc
(
strlen
(
local_name
)
+
1
,
GFP_KERNEL
);
/* FIXME: where is this freed ? */
if
(
!
sht
->
proc_name
)
{
return
0
;
}
strcpy
(
sht
->
proc_name
,
local_name
);
sht
->
proc_dir
=
NULL
;
/* build and submit an interrupt URB for status byte handling */
usb_fill_int_urb
(
desc
->
controlurb
,
desc
->
dev
,
usb_rcvintpipe
(
desc
->
dev
,
desc
->
ep_int
),
&
desc
->
scsi_state_byte
,
1
,
control_interrupt_callback
,
desc
,
desc
->
interrupt_interval
);
if
(
0
>
usb_submit_urb
(
desc
->
controlurb
,
GFP_KERNEL
))
{
kfree
(
sht
->
proc_name
);
return
0
;
}
/* In host->hostdata we store a pointer to desc */
desc
->
host
=
scsi_register
(
sht
,
sizeof
(
desc
));
if
(
desc
->
host
==
NULL
)
{
kfree
(
sht
->
proc_name
);
usb_unlink_urb
(
desc
->
controlurb
);
return
0
;
}
desc
->
host
->
hostdata
[
0
]
=
(
unsigned
long
)
desc
;
return
1
;
}
static
int
hpusbscsi_scsi_queuecommand
(
Scsi_Cmnd
*
srb
,
scsi_callback
callback
)
{
struct
hpusbscsi
*
hpusbscsi
=
(
struct
hpusbscsi
*
)(
srb
->
device
->
host
->
hostdata
[
0
]);
...
...
drivers/usb/image/hpusbscsi.h
View file @
a98b28b1
...
...
@@ -13,7 +13,6 @@ typedef void (*scsi_callback)(Scsi_Cmnd *);
struct
hpusbscsi
{
struct
list_head
lh
;
struct
usb_device
*
dev
;
/* NULL indicates unplugged device */
int
ep_out
;
int
ep_in
;
...
...
@@ -36,7 +35,6 @@ struct hpusbscsi
int
state
;
int
current_data_pipe
;
Scsi_Host_Template
ctempl
;
u8
sense_command
[
SENSE_COMMAND_SIZE
];
u8
scsi_state_byte
;
};
...
...
@@ -52,7 +50,6 @@ static const unsigned char scsi_command_direction[256/8] = {
#define DIRECTION_IS_IN(x) ((scsi_command_direction[x>>3] >> (x & 7)) & 1)
static
int
hpusbscsi_scsi_detect
(
struct
SHT
*
sht
);
static
void
simple_command_callback
(
struct
urb
*
u
,
struct
pt_regs
*
regs
);
static
void
scatter_gather_callback
(
struct
urb
*
u
,
struct
pt_regs
*
regs
);
static
void
simple_payload_callback
(
struct
urb
*
u
,
struct
pt_regs
*
regs
);
...
...
@@ -64,25 +61,6 @@ static int hpusbscsi_scsi_host_reset (Scsi_Cmnd *srb);
static
int
hpusbscsi_scsi_abort
(
Scsi_Cmnd
*
srb
);
static
void
issue_request_sense
(
struct
hpusbscsi
*
hpusbscsi
);
static
Scsi_Host_Template
hpusbscsi_scsi_host_template
=
{
.
name
=
"hpusbscsi"
,
.
detect
=
hpusbscsi_scsi_detect
,
// .release = hpusbscsi_scsi_release,
.
queuecommand
=
hpusbscsi_scsi_queuecommand
,
.
eh_abort_handler
=
hpusbscsi_scsi_abort
,
.
eh_host_reset_handler
=
hpusbscsi_scsi_host_reset
,
.
sg_tablesize
=
SG_ALL
,
.
can_queue
=
1
,
.
this_id
=
-
1
,
.
cmd_per_lun
=
1
,
.
present
=
0
,
.
unchecked_isa_dma
=
FALSE
,
.
use_clustering
=
TRUE
,
.
emulated
=
TRUE
};
/* defines for internal driver state */
#define HP_STATE_FREE 0
/*ready for next request */
#define HP_STATE_BEGINNING 1
/*command being transferred */
...
...
drivers/usb/image/microtek.c
View file @
a98b28b1
...
...
@@ -327,76 +327,6 @@ static inline void mts_urb_abort(struct mts_desc* desc) {
usb_unlink_urb
(
desc
->
urb
);
}
static
struct
mts_desc
*
mts_list
;
/* list of active scanners */
struct
semaphore
mts_list_semaphore
;
/* Internal list operations */
static
void
mts_remove_nolock
(
struct
mts_desc
*
to_remove
)
{
MTS_DEBUG
(
"removing 0x%x from list
\n
"
,
(
int
)
to_remove
);
lock_kernel
();
mts_urb_abort
(
to_remove
);
MTS_DEBUG_GOT_HERE
();
if
(
to_remove
!=
mts_list
)
{
MTS_DEBUG_GOT_HERE
();
if
(
to_remove
->
prev
&&
to_remove
->
next
)
to_remove
->
prev
->
next
=
to_remove
->
next
;
}
else
{
MTS_DEBUG_GOT_HERE
();
mts_list
=
to_remove
->
next
;
if
(
mts_list
)
{
MTS_DEBUG_GOT_HERE
();
mts_list
->
prev
=
0
;
}
}
if
(
to_remove
->
next
)
{
MTS_DEBUG_GOT_HERE
();
to_remove
->
next
->
prev
=
to_remove
->
prev
;
}
MTS_DEBUG_GOT_HERE
();
scsi_unregister_host
(
&
to_remove
->
ctempl
);
unlock_kernel
();
usb_free_urb
(
to_remove
->
urb
);
kfree
(
to_remove
);
}
static
void
mts_add_nolock
(
struct
mts_desc
*
to_add
)
{
MTS_DEBUG
(
"adding 0x%x to list
\n
"
,
(
int
)
to_add
);
to_add
->
prev
=
0
;
to_add
->
next
=
mts_list
;
if
(
mts_list
)
{
mts_list
->
prev
=
to_add
;
}
mts_list
=
to_add
;
}
/* SCSI driver interface */
/* scsi related functions - dummies for now mostly */
static
int
mts_scsi_release
(
struct
Scsi_Host
*
psh
)
{
MTS_DEBUG_GOT_HERE
();
return
0
;
}
static
int
mts_scsi_abort
(
Scsi_Cmnd
*
srb
)
{
struct
mts_desc
*
desc
=
(
struct
mts_desc
*
)(
srb
->
device
->
host
->
hostdata
[
0
]);
...
...
@@ -419,54 +349,6 @@ static int mts_scsi_host_reset (Scsi_Cmnd *srb)
return
0
;
/* RANT why here 0 and not SUCCESS */
}
/* the core of the scsi part */
/* faking a detection - which can't fail :-) */
static
int
mts_scsi_detect
(
struct
SHT
*
sht
)
{
/* Whole function stolen from usb-storage */
struct
mts_desc
*
desc
=
(
struct
mts_desc
*
)
sht
->
proc_dir
;
/* What a hideous hack! */
char
local_name
[
48
];
MTS_DEBUG_GOT_HERE
();
/* set up the name of our subdirectory under /proc/scsi/ */
sprintf
(
local_name
,
"microtek-%d"
,
desc
->
host_number
);
sht
->
proc_name
=
kmalloc
(
strlen
(
local_name
)
+
1
,
GFP_KERNEL
);
/* FIXME: where is this freed ? */
if
(
!
sht
->
proc_name
)
{
MTS_ERROR
(
"unable to allocate memory for proc interface!!
\n
"
);
return
0
;
}
strcpy
(
sht
->
proc_name
,
local_name
);
sht
->
proc_dir
=
NULL
;
/* In host->hostdata we store a pointer to desc */
desc
->
host
=
scsi_register
(
sht
,
sizeof
(
desc
));
if
(
desc
->
host
==
NULL
)
{
MTS_ERROR
(
"Cannot register due to low memory"
);
kfree
(
sht
->
proc_name
);
return
0
;
}
desc
->
host
->
hostdata
[
0
]
=
(
unsigned
long
)
desc
;
/* FIXME: what if sizeof(void*) != sizeof(unsigned long)? */
return
1
;
}
/* Main entrypoint: SCSI commands are dispatched to here */
static
int
mts_scsi_queuecommand
(
Scsi_Cmnd
*
srb
,
mts_scsi_cmnd_callback
callback
);
...
...
@@ -744,52 +626,22 @@ int mts_scsi_queuecommand( Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback )
out:
return
err
;
}
/*
* this defines our 'host'
*/
/* NOTE: This is taken from usb-storage, should be right. */
static
Scsi_Host_Template
mts_scsi_host_template
=
{
.
module
=
THIS_MODULE
,
.
name
=
"microtekX6"
,
.
detect
=
mts_scsi_detect
,
.
release
=
mts_scsi_release
,
.
proc_name
=
"microtekX6"
,
.
queuecommand
=
mts_scsi_queuecommand
,
.
eh_abort_handler
=
mts_scsi_abort
,
.
eh_host_reset_handler
=
mts_scsi_host_reset
,
.
eh_host_reset_handler
=
mts_scsi_host_reset
,
.
sg_tablesize
=
SG_ALL
,
.
can_queue
=
1
,
.
this_id
=
-
1
,
.
cmd_per_lun
=
1
,
.
present
=
0
,
.
unchecked_isa_dma
=
FALSE
,
.
use_clustering
=
TRUE
,
.
emulated
=
TRUE
.
use_clustering
=
1
,
.
emulated
=
1
,
};
/* USB layer driver interface implementation */
static
void
mts_usb_disconnect
(
struct
usb_interface
*
intf
)
{
struct
mts_desc
*
to_remove
=
usb_get_intfdata
(
intf
);
MTS_DEBUG_GOT_HERE
();
usb_set_intfdata
(
intf
,
NULL
);
if
(
to_remove
)
{
/* leave the list - lock it */
down
(
&
mts_list_semaphore
);
mts_remove_nolock
(
to_remove
);
up
(
&
mts_list_semaphore
);
}
}
struct
vendor_product
{
char
*
name
;
...
...
@@ -837,7 +689,7 @@ static struct usb_device_id mts_usb_ids [] =
MODULE_DEVICE_TABLE
(
usb
,
mts_usb_ids
);
static
int
mts_usb_probe
(
struct
usb_interface
*
intf
,
static
int
mts_usb_probe
(
struct
usb_interface
*
intf
,
const
struct
usb_device_id
*
id
)
{
int
i
;
...
...
@@ -930,39 +782,23 @@ static int mts_usb_probe (struct usb_interface *intf,
}
/* allocating a new descriptor */
new_desc
=
(
struct
mts_desc
*
)
kmalloc
(
sizeof
(
struct
mts_desc
),
GFP_KERNEL
);
if
(
new_desc
==
NULL
)
{
MTS_ERROR
(
"couldn't allocate scanner desc, bailing out!
\n
"
);
return
-
ENOMEM
;
}
new_desc
=
kmalloc
(
sizeof
(
struct
mts_desc
),
GFP_KERNEL
);
if
(
!
new_desc
)
goto
out
;
memset
(
new_desc
,
0
,
sizeof
(
*
new_desc
)
);
memset
(
new_desc
,
0
,
sizeof
(
*
new_desc
)
);
new_desc
->
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
if
(
!
new_desc
->
urb
)
{
kfree
(
new_desc
);
return
-
ENOMEM
;
}
if
(
!
new_desc
->
urb
)
goto
out_kfree
;
/* initialising that descriptor */
new_desc
->
usb_dev
=
dev
;
init_MUTEX
(
&
new_desc
->
lock
);
if
(
mts_list
){
new_desc
->
host_number
=
mts_list
->
host_number
+
1
;
}
else
{
new_desc
->
host_number
=
0
;
}
/* endpoints */
new_desc
->
ep_out
=
ep_out
;
new_desc
->
ep_response
=
ep_in_set
[
0
];
new_desc
->
ep_image
=
ep_in_set
[
1
];
if
(
new_desc
->
ep_out
!=
MTS_EP_OUT
)
MTS_WARNING
(
"will this work? Command EP is not usually %d
\n
"
,
(
int
)
new_desc
->
ep_out
);
...
...
@@ -975,87 +811,48 @@ static int mts_usb_probe (struct usb_interface *intf,
MTS_WARNING
(
"will this work? Image data EP is not usually %d
\n
"
,
(
int
)
new_desc
->
ep_image
);
new_desc
->
host
=
scsi_register
(
&
mts_scsi_host_template
,
sizeof
(
new_desc
));
if
(
!
new_desc
->
host
)
goto
out_free_urb
;
/* Initialize the host template based on the default one */
memcpy
(
&
(
new_desc
->
ctempl
),
&
mts_scsi_host_template
,
sizeof
(
mts_scsi_host_template
));
/* HACK from usb-storage - this is needed for scsi detection */
(
struct
mts_desc
*
)
new_desc
->
ctempl
.
proc_dir
=
new_desc
;
/* FIXME */
new_desc
->
host
->
hostdata
[
0
]
=
(
unsigned
long
)
new_desc
;
scsi_add_host
(
new_desc
->
host
,
NULL
);
MTS_DEBUG
(
"registering SCSI module
\n
"
);
new_desc
->
ctempl
.
module
=
THIS_MODULE
;
result
=
scsi_register_host
(
&
new_desc
->
ctempl
);
/* Will get hit back in microtek_detect by this func */
if
(
result
)
{
MTS_ERROR
(
"error %d from scsi_register_host! Help!
\n
"
,
(
int
)
result
);
usb_set_intfdata
(
intf
,
new_desc
);
return
0
;
/* FIXME: need more cleanup? */
kfree
(
new_desc
);
out_free_urb:
usb_free_urb
(
new_desc
->
urb
);
out_kfree:
kfree
(
new_desc
);
out:
return
-
ENOMEM
;
}
MTS_DEBUG_GOT_HERE
();
/* FIXME: the bomb is armed, must the host be registered under lock ? */
/* join the list - lock it */
down
(
&
mts_list_semaphore
);
mts_add_nolock
(
new_desc
);
}
up
(
&
mts_list_semaphore
);
static
void
mts_usb_disconnect
(
struct
usb_interface
*
intf
)
{
struct
mts_desc
*
desc
=
usb_get_intfdata
(
intf
);
usb_set_intfdata
(
intf
,
NULL
);
MTS_DEBUG
(
"completed probe and exiting happily
\n
"
);
scsi_remove_host
(
desc
->
host
);
usb_unlink_urb
(
desc
->
urb
);
scsi_unregister
(
desc
->
host
);
usb_
set_intfdata
(
intf
,
new_desc
);
return
0
;
usb_
free_urb
(
desc
->
urb
);
kfree
(
desc
)
;
}
/* get us noticed by the rest of the kernel */
int
__init
microtek_drv_init
(
void
)
static
int
__init
microtek_drv_init
(
void
)
{
int
result
;
MTS_DEBUG_GOT_HERE
();
init_MUTEX
(
&
mts_list_semaphore
);
if
((
result
=
usb_register
(
&
mts_usb_driver
))
<
0
)
{
MTS_DEBUG
(
"usb_register returned %d
\n
"
,
result
);
return
-
1
;
}
else
{
MTS_DEBUG
(
"driver registered.
\n
"
);
}
info
(
DRIVER_VERSION
":"
DRIVER_DESC
);
return
0
;
return
usb_register
(
&
mts_usb_driver
);
}
void
__exit
microtek_drv_exit
(
void
)
static
void
__exit
microtek_drv_exit
(
void
)
{
struct
mts_desc
*
next
;
MTS_DEBUG_GOT_HERE
();
usb_deregister
(
&
mts_usb_driver
);
down
(
&
mts_list_semaphore
);
while
(
mts_list
)
{
/* keep track of where the next one is */
next
=
mts_list
->
next
;
mts_remove_nolock
(
mts_list
);
/* advance the list pointer */
mts_list
=
next
;
}
up
(
&
mts_list_semaphore
);
}
module_init
(
microtek_drv_init
);
...
...
drivers/usb/image/microtek.h
View file @
a98b28b1
...
...
@@ -38,9 +38,6 @@ struct mts_desc {
u8
ep_image
;
struct
Scsi_Host
*
host
;
Scsi_Host_Template
ctempl
;
int
host_number
;
struct
semaphore
lock
;
struct
urb
*
urb
;
...
...
drivers/usb/storage/scsiglue.c
View file @
a98b28b1
...
...
@@ -171,9 +171,11 @@ static int usb_storage_queuecommand( Scsi_Cmnd *srb , void (*done)(Scsi_Cmnd *))
/* This is always called with scsi_lock(srb->host) held */
static
int
usb_storage_command_abort
(
Scsi_Cmnd
*
srb
)
{
struct
us_data
*
us
=
(
struct
us_data
*
)
srb
->
device
->
host
->
hostdata
[
0
];
struct
Scsi_Host
*
host
=
srb
->
device
->
host
;
struct
us_data
*
us
=
(
struct
us_data
*
)
host
->
hostdata
[
0
];
int
state
=
atomic_read
(
&
us
->
sm_state
);
US_DEBUGP
(
"
command_abort() called
\n
"
);
US_DEBUGP
(
"
%s called
\n
"
,
__FUNCTION__
);
/* Is this command still active? */
if
(
us
->
srb
!=
srb
)
{
...
...
@@ -181,7 +183,31 @@ static int usb_storage_command_abort( Scsi_Cmnd *srb )
return
FAILED
;
}
return
usb_stor_abort_transport
(
us
);
/* Normally the current state is RUNNING. If the control thread
* hasn't even started processing this command, the state will be
* IDLE. Anything else is a bug. */
if
(
state
!=
US_STATE_RUNNING
&&
state
!=
US_STATE_IDLE
)
{
printk
(
KERN_ERR
USB_STORAGE
"Error in %s: "
"invalid state %d
\n
"
,
__FUNCTION__
,
state
);
return
FAILED
;
}
/* Set state to ABORTING, set the ABORTING bit, and release the lock */
atomic_set
(
&
us
->
sm_state
,
US_STATE_ABORTING
);
set_bit
(
US_FLIDX_ABORTING
,
&
us
->
flags
);
scsi_unlock
(
host
);
/* If the state was RUNNING, stop an ongoing USB transfer */
if
(
state
==
US_STATE_RUNNING
)
usb_stor_stop_transport
(
us
);
/* Wait for the aborted command to finish */
wait_for_completion
(
&
us
->
notify
);
/* Reacquire the lock and allow USB transfers to resume */
scsi_lock
(
host
);
clear_bit
(
US_FLIDX_ABORTING
,
&
us
->
flags
);
return
SUCCESS
;
}
/* This invokes the transport reset mechanism to reset the state of the
...
...
drivers/usb/storage/transport.c
View file @
a98b28b1
...
...
@@ -69,32 +69,35 @@
* as those occurring during device-specific initialization, must be handled
* by a separate code path.)
*
* The abort function first sets the machine state, then atomically
* tests-and-clears the CAN_CANCEL bit in us->flags to see if the current_urb
* needs to be aborted.
* The abort function (usb_storage_command_abort() in scsiglue.c) first
* sets the machine state and the ABORTING bit in us->flags to prevent
* new URBs from being submitted. It then calls usb_stor_stop_transport()
* below, which atomically tests-and-clears the URB_ACTIVE bit in us->flags
* to see if the current_urb needs to be stopped. Likewise, the SG_ACTIVE
* bit is tested to see if the current_sg scatter-gather request needs to be
* stopped.
*
* The submit function first verifies that the submission completed without
* errors, and only then sets the CAN_CANCEL bit. This prevents the abort
* function from trying to cancel the URB while the submit call is underway.
* Next, the submit function must test the state to see if we got aborted
* before the submission or before setting the CAN_CANCEL bit. If so, it's
* essential to abort the URB if it hasn't been cancelled already (i.e.,
* if the CAN_CANCEL bit is still set). Either way, the function must then
* wait for the URB to finish. Note that because the URB_ASYNC_UNLINK flag
* is set, the URB can still be in progress even after a call to
* usb_unlink_urb() returns.
* When a disconnect occurs, the DISCONNECTING bit in us->flags is set to
* prevent new URBs from being submitted, and usb_stor_stop_transport() is
* called to stop any ongoing requests.
*
* (It's also permissible, but not necessary, to test the state -before-
* submitting the URB. Doing so would prevent an unnecessary submission if
* the transaction had already been aborted, but this is very unlikely to
* happen, because the abort would have to have been requested during actual
* kernel processing rather than during an I/O delay.)
* The submit function first verifies that the submitting is allowed
* (neither ABORTING nor DISCONNECTING bits are set) and that the submit
* completes without errors, and only then sets the URB_ACTIVE bit. This
* prevents the stop_transport() function from trying to cancel the URB
* while the submit call is underway. Next, the submit function must test
* the flags to see if an abort or disconnect occurred during the submission
* or before the URB_ACTIVE bit was set. If so, it's essential to cancel
* the URB if it hasn't been cancelled already (i.e., if the URB_ACTIVE bit
* is still set). Either way, the function must then wait for the URB to
* finish. Note that because the URB_ASYNC_UNLINK flag is set, the URB can
* still be in progress even after a call to usb_unlink_urb() returns.
*
* The idea is that (1) once the
state is changed to ABORTING, either the
*
aborting function or the submitting function is guaranteed to call
*
usb_unlink_urb() for an active URB, and (2) test_and_clear_bit() prevents
*
usb_unlink_urb() from being called more than once or from being called
* during usb_submit_urb().
* The idea is that (1) once the
ABORTING or DISCONNECTING bit is set,
*
either the stop_transport() function or the submitting function
*
is guaranteed to call usb_unlink_urb() for an active URB,
*
and (2) test_and_clear_bit() prevents usb_unlink_urb() from being
*
called more than once or from being called
during usb_submit_urb().
*/
/* This is the completion handler which will wake us up when an URB
...
...
@@ -118,6 +121,10 @@ static int usb_stor_msg_common(struct us_data *us)
struct
completion
urb_done
;
int
status
;
/* don't submit URBS during abort/disconnect processing */
if
(
us
->
flags
&
DONT_SUBMIT
)
return
-
ECONNRESET
;
/* set up data structures for the wakeup system */
init_completion
(
&
urb_done
);
...
...
@@ -137,13 +144,13 @@ static int usb_stor_msg_common(struct us_data *us)
/* since the URB has been submitted successfully, it's now okay
* to cancel it */
set_bit
(
US_FLIDX_
CAN_CANCEL
,
&
us
->
flags
);
set_bit
(
US_FLIDX_
URB_ACTIVE
,
&
us
->
flags
);
/*
has the current command been aborted
? */
if
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_ABORTING
)
{
/*
did an abort/disconnect occur during the submission
? */
if
(
us
->
flags
&
DONT_SUBMIT
)
{
/* cancel the URB, if it hasn't been cancelled already */
if
(
test_and_clear_bit
(
US_FLIDX_
CAN_CANCEL
,
&
us
->
flags
))
{
if
(
test_and_clear_bit
(
US_FLIDX_
URB_ACTIVE
,
&
us
->
flags
))
{
US_DEBUGP
(
"-- cancelling URB
\n
"
);
usb_unlink_urb
(
us
->
current_urb
);
}
...
...
@@ -151,7 +158,7 @@ static int usb_stor_msg_common(struct us_data *us)
/* wait for the completion of the URB */
wait_for_completion
(
&
urb_done
);
clear_bit
(
US_FLIDX_
CAN_CANCEL
,
&
us
->
flags
);
clear_bit
(
US_FLIDX_
URB_ACTIVE
,
&
us
->
flags
);
/* return the URB status */
return
us
->
current_urb
->
status
;
...
...
@@ -185,53 +192,6 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
return
status
;
}
/* This is our function to emulate usb_bulk_msg() with enough control
* to make aborts/resets/timeouts work
*/
int
usb_stor_bulk_msg
(
struct
us_data
*
us
,
void
*
data
,
unsigned
int
pipe
,
unsigned
int
len
,
unsigned
int
*
act_len
)
{
int
status
;
/* fill and submit the URB */
usb_fill_bulk_urb
(
us
->
current_urb
,
us
->
pusb_dev
,
pipe
,
data
,
len
,
usb_stor_blocking_completion
,
NULL
);
status
=
usb_stor_msg_common
(
us
);
/* store the actual length of the data transferred */
*
act_len
=
us
->
current_urb
->
actual_length
;
return
status
;
}
/* This is our function to submit interrupt URBs with enough control
* to make aborts/resets/timeouts work
*
* This routine always uses us->recv_intr_pipe as the pipe and
* us->ep_bInterval as the interrupt interval.
*/
int
usb_stor_interrupt_msg
(
struct
us_data
*
us
,
void
*
data
,
unsigned
int
len
,
unsigned
int
*
act_len
)
{
unsigned
int
pipe
=
us
->
recv_intr_pipe
;
unsigned
int
maxp
;
int
status
;
/* calculate the max packet size */
maxp
=
usb_maxpacket
(
us
->
pusb_dev
,
pipe
,
usb_pipeout
(
pipe
));
if
(
maxp
>
len
)
maxp
=
len
;
/* fill and submit the URB */
usb_fill_int_urb
(
us
->
current_urb
,
us
->
pusb_dev
,
pipe
,
data
,
maxp
,
usb_stor_blocking_completion
,
NULL
,
us
->
ep_bInterval
);
status
=
usb_stor_msg_common
(
us
);
/* store the actual length of the data transferred */
*
act_len
=
us
->
current_urb
->
actual_length
;
return
status
;
}
/* This is a version of usb_clear_halt() that doesn't read the status from
* the device -- this is because some devices crash their internal firmware
* when the status is requested after a halt.
...
...
@@ -275,12 +235,12 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
* Interpret the results of a URB transfer
*
* This function prints appropriate debugging messages, clears halts on
*
bulk
endpoints, and translates the status to the corresponding
*
non-control
endpoints, and translates the status to the corresponding
* USB_STOR_XFER_xxx return code.
*/
static
int
interpret_urb_result
(
struct
us_data
*
us
,
unsigned
int
pipe
,
unsigned
int
length
,
int
result
,
unsigned
int
partial
)
{
unsigned
int
length
,
int
result
,
unsigned
int
partial
)
{
US_DEBUGP
(
"Status code %d; transferred %u/%u
\n
"
,
result
,
partial
,
length
);
switch
(
result
)
{
...
...
@@ -333,95 +293,109 @@ static int interpret_urb_result(struct us_data *us, unsigned int pipe,
}
/*
* Transfer one control message
*
* This function does basically the same thing as usb_stor_control_msg()
* above, except that return codes are USB_STOR_XFER_xxx rather than the
* urb status or transfer length.
* Transfer one control message, without timeouts, but allowing early
* termination. Return codes are USB_STOR_XFER_xxx.
*/
int
usb_stor_ctrl_transfer
(
struct
us_data
*
us
,
unsigned
int
pipe
,
u8
request
,
u8
requesttype
,
u16
value
,
u16
index
,
void
*
data
,
u16
size
)
{
void
*
data
,
u16
size
)
{
int
result
;
unsigned
int
partial
=
0
;
US_DEBUGP
(
"usb_stor_ctrl_transfer(): rq=%02x rqtype=%02x "
"value=%04x index=%02x len=%u
\n
"
,
request
,
requesttype
,
value
,
index
,
size
);
result
=
usb_stor_control_msg
(
us
,
pipe
,
request
,
requesttype
,
value
,
index
,
data
,
size
);
US_DEBUGP
(
"%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u
\n
"
,
__FUNCTION__
,
request
,
requesttype
,
value
,
index
,
size
);
if
(
result
>
0
)
{
/* Separate out the amount transferred */
partial
=
result
;
result
=
0
;
}
return
interpret_urb_result
(
us
,
pipe
,
size
,
result
,
partial
);
/* fill in the devrequest structure */
us
->
dr
->
bRequestType
=
requesttype
;
us
->
dr
->
bRequest
=
request
;
us
->
dr
->
wValue
=
cpu_to_le16
(
value
);
us
->
dr
->
wIndex
=
cpu_to_le16
(
index
);
us
->
dr
->
wLength
=
cpu_to_le16
(
size
);
/* fill and submit the URB */
usb_fill_control_urb
(
us
->
current_urb
,
us
->
pusb_dev
,
pipe
,
(
unsigned
char
*
)
us
->
dr
,
data
,
size
,
usb_stor_blocking_completion
,
NULL
);
result
=
usb_stor_msg_common
(
us
);
return
interpret_urb_result
(
us
,
pipe
,
size
,
result
,
us
->
current_urb
->
actual_length
);
}
/*
* Receive one buffer via interrupt transfer
* Receive one interrupt buffer, without timeouts, but allowing early
* termination. Return codes are USB_STOR_XFER_xxx.
*
* This function does basically the same thing as usb_stor_interrupt_msg()
* above, except that return codes are USB_STOR_XFER_xxx rather than the
* urb status.
* This routine always uses us->recv_intr_pipe as the pipe and
* us->ep_bInterval as the interrupt interval.
*/
int
usb_stor_intr_transfer
(
struct
us_data
*
us
,
void
*
buf
,
unsigned
int
length
,
unsigned
int
*
act_len
)
int
usb_stor_intr_transfer
(
struct
us_data
*
us
,
void
*
buf
,
unsigned
int
length
)
{
int
result
;
unsigned
int
partial
;
unsigned
int
pipe
=
us
->
recv_intr_pipe
;
unsigned
int
maxp
;
/* transfer the data */
US_DEBUGP
(
"usb_stor_intr_transfer(): xfer %u bytes
\n
"
,
length
);
result
=
usb_stor_interrupt_msg
(
us
,
buf
,
length
,
&
partial
);
if
(
act_len
)
*
act_len
=
partial
;
US_DEBUGP
(
"%s: xfer %u bytes
\n
"
,
__FUNCTION__
,
length
);
/* calculate the max packet size */
maxp
=
usb_maxpacket
(
us
->
pusb_dev
,
pipe
,
usb_pipeout
(
pipe
));
if
(
maxp
>
length
)
maxp
=
length
;
/* fill and submit the URB */
usb_fill_int_urb
(
us
->
current_urb
,
us
->
pusb_dev
,
pipe
,
buf
,
maxp
,
usb_stor_blocking_completion
,
NULL
,
us
->
ep_bInterval
);
result
=
usb_stor_msg_common
(
us
);
return
interpret_urb_result
(
us
,
us
->
recv_intr_pipe
,
length
,
result
,
partial
);
return
interpret_urb_result
(
us
,
pipe
,
length
,
result
,
us
->
current_urb
->
actual_length
);
}
/*
* Transfer one buffer via bulk transfer
*
* This function does basically the same thing as usb_stor_bulk_msg()
* above, except that:
*
* 1. If the bulk pipe stalls during the transfer, the halt is
* automatically cleared;
* 2. Return codes are USB_STOR_XFER_xxx rather than the
* urb status or transfer length.
* Transfer one buffer via bulk pipe, without timeouts, but allowing early
* termination. Return codes are USB_STOR_XFER_xxx. If the bulk pipe
* stalls during the transfer, the halt is automatically cleared.
*/
int
usb_stor_bulk_transfer_buf
(
struct
us_data
*
us
,
unsigned
int
pipe
,
void
*
buf
,
unsigned
int
length
,
unsigned
int
*
act_len
)
{
int
result
;
unsigned
int
partial
;
/* transfer the data */
US_DEBUGP
(
"usb_stor_bulk_transfer_buf(): xfer %u bytes
\n
"
,
length
);
result
=
usb_stor_bulk_msg
(
us
,
buf
,
pipe
,
length
,
&
partial
);
US_DEBUGP
(
"%s: xfer %u bytes
\n
"
,
__FUNCTION__
,
length
);
/* fill and submit the URB */
usb_fill_bulk_urb
(
us
->
current_urb
,
us
->
pusb_dev
,
pipe
,
buf
,
length
,
usb_stor_blocking_completion
,
NULL
);
result
=
usb_stor_msg_common
(
us
);
/* store the actual length of the data transferred */
if
(
act_len
)
*
act_len
=
partial
;
return
interpret_urb_result
(
us
,
pipe
,
length
,
result
,
partial
);
*
act_len
=
us
->
current_urb
->
actual_length
;
return
interpret_urb_result
(
us
,
pipe
,
length
,
result
,
us
->
current_urb
->
actual_length
);
}
/*
* Transfer a scatter-gather list via bulk transfer
*
* This function does basically the same thing as usb_stor_bulk_transfer_buf()
* above, but it uses the usbcore scatter-gather
primitives
* above, but it uses the usbcore scatter-gather
library.
*/
int
usb_stor_bulk_transfer_sglist
(
struct
us_data
*
us
,
unsigned
int
pipe
,
struct
scatterlist
*
sg
,
int
num_sg
,
unsigned
int
length
,
unsigned
int
*
act_len
)
{
int
result
;
unsigned
int
partial
;
/* don't submit s-g requests during abort/disconnect processing */
if
(
us
->
flags
&
DONT_SUBMIT
)
return
USB_STOR_XFER_ERROR
;
/* initialize the scatter-gather request block */
US_DEBUGP
(
"
usb_stor_bulk_transfer_sglist(): xfer %u bytes, "
"%d entries
\n
"
,
length
,
num_sg
);
US_DEBUGP
(
"
%s: xfer %u bytes, %d entries
\n
"
,
__FUNCTION__
,
length
,
num_sg
);
result
=
usb_sg_init
(
us
->
current_sg
,
us
->
pusb_dev
,
pipe
,
0
,
sg
,
num_sg
,
length
,
SLAB_NOIO
);
if
(
result
)
{
...
...
@@ -431,13 +405,13 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
/* since the block has been initialized successfully, it's now
* okay to cancel it */
set_bit
(
US_FLIDX_
CANCEL_SG
,
&
us
->
flags
);
set_bit
(
US_FLIDX_
SG_ACTIVE
,
&
us
->
flags
);
/*
has the current command been aborted
? */
if
(
atomic_read
(
&
us
->
sm_state
)
==
US_STATE_ABORTING
)
{
/*
did an abort/disconnect occur during the submission
? */
if
(
us
->
flags
&
DONT_SUBMIT
)
{
/* cancel the request, if it hasn't been cancelled already */
if
(
test_and_clear_bit
(
US_FLIDX_
CANCEL_SG
,
&
us
->
flags
))
{
if
(
test_and_clear_bit
(
US_FLIDX_
SG_ACTIVE
,
&
us
->
flags
))
{
US_DEBUGP
(
"-- cancelling sg request
\n
"
);
usb_sg_cancel
(
us
->
current_sg
);
}
...
...
@@ -445,13 +419,13 @@ int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
/* wait for the completion of the transfer */
usb_sg_wait
(
us
->
current_sg
);
clear_bit
(
US_FLIDX_
CANCEL_SG
,
&
us
->
flags
);
clear_bit
(
US_FLIDX_
SG_ACTIVE
,
&
us
->
flags
);
result
=
us
->
current_sg
->
status
;
partial
=
us
->
current_sg
->
bytes
;
if
(
act_len
)
*
act_len
=
partial
;
return
interpret_urb_result
(
us
,
pipe
,
length
,
result
,
partial
);
*
act_len
=
us
->
current_sg
->
bytes
;
return
interpret_urb_result
(
us
,
pipe
,
length
,
result
,
us
->
current_sg
->
bytes
);
}
/*
...
...
@@ -693,56 +667,32 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
Handle_Abort:
srb
->
result
=
DID_ABORT
<<
16
;
if
(
us
->
protocol
==
US_PR_BULK
)
{
/* permit the reset transfer to take place */
clear_bit
(
US_FLIDX_ABORTING
,
&
us
->
flags
);
us
->
transport_reset
(
us
);
}
}
/* Abort the currently running scsi command or device reset.
* This must be called with scsi_lock(us->srb->host) held */
int
usb_stor_abort_transport
(
struct
us_data
*
us
)
/* Stop the current URB transfer */
void
usb_stor_stop_transport
(
struct
us_data
*
us
)
{
struct
Scsi_Host
*
host
;
int
state
=
atomic_read
(
&
us
->
sm_state
);
US_DEBUGP
(
"usb_stor_abort_transport called
\n
"
);
/* Normally the current state is RUNNING. If the control thread
* hasn't even started processing this command, the state will be
* IDLE. Anything else is a bug. */
if
(
state
!=
US_STATE_RUNNING
&&
state
!=
US_STATE_IDLE
)
{
printk
(
KERN_ERR
USB_STORAGE
"Error in %s: "
"invalid state %d
\n
"
,
__FUNCTION__
,
state
);
return
FAILED
;
}
/* set state to abort and release the lock */
atomic_set
(
&
us
->
sm_state
,
US_STATE_ABORTING
);
host
=
us
->
srb
->
device
->
host
;
scsi_unlock
(
host
);
US_DEBUGP
(
"%s called
\n
"
,
__FUNCTION__
);
/* If the state machine is blocked waiting for an URB,
* let's wake it up */
/* If we have an URB pending, cancel it. The test_and_clear_bit()
* call guarantees that if a URB has just been submitted, it
* won't be cancelled more than once. */
if
(
test_and_clear_bit
(
US_FLIDX_CAN_CANCEL
,
&
us
->
flags
))
{
* let's wake it up. The test_and_clear_bit() call
* guarantees that if a URB has just been submitted,
* it won't be cancelled more than once. */
if
(
test_and_clear_bit
(
US_FLIDX_URB_ACTIVE
,
&
us
->
flags
))
{
US_DEBUGP
(
"-- cancelling URB
\n
"
);
usb_unlink_urb
(
us
->
current_urb
);
}
/* If we are waiting for a scatter-gather operation, cancel it. */
if
(
test_and_clear_bit
(
US_FLIDX_
CANCEL_SG
,
&
us
->
flags
))
{
if
(
test_and_clear_bit
(
US_FLIDX_
SG_ACTIVE
,
&
us
->
flags
))
{
US_DEBUGP
(
"-- cancelling sg request
\n
"
);
usb_sg_cancel
(
us
->
current_sg
);
}
/* Wait for the aborted command to finish */
wait_for_completion
(
&
us
->
notify
);
/* Reacquire the lock: note that us->srb is now NULL */
scsi_lock
(
host
);
return
SUCCESS
;
}
/*
...
...
@@ -788,8 +738,7 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
}
/* STATUS STAGE */
result
=
usb_stor_intr_transfer
(
us
,
us
->
irqdata
,
sizeof
(
us
->
irqdata
),
NULL
);
result
=
usb_stor_intr_transfer
(
us
,
us
->
irqdata
,
sizeof
(
us
->
irqdata
));
US_DEBUGP
(
"Got interrupt data (0x%x, 0x%x)
\n
"
,
us
->
irqdata
[
0
],
us
->
irqdata
[
1
]);
if
(
result
!=
USB_STOR_XFER_GOOD
)
...
...
drivers/usb/storage/transport.h
View file @
a98b28b1
...
...
@@ -156,22 +156,18 @@ extern int usb_stor_Bulk_max_lun(struct us_data*);
extern
int
usb_stor_Bulk_reset
(
struct
us_data
*
);
extern
void
usb_stor_invoke_transport
(
Scsi_Cmnd
*
,
struct
us_data
*
);
extern
int
usb_stor_abort
_transport
(
struct
us_data
*
);
extern
void
usb_stor_stop
_transport
(
struct
us_data
*
);
extern
int
usb_stor_bulk_msg
(
struct
us_data
*
us
,
void
*
data
,
unsigned
int
pipe
,
unsigned
int
len
,
unsigned
int
*
act_len
);
extern
int
usb_stor_control_msg
(
struct
us_data
*
us
,
unsigned
int
pipe
,
u8
request
,
u8
requesttype
,
u16
value
,
u16
index
,
void
*
data
,
u16
size
);
extern
int
usb_stor_interrupt_msg
(
struct
us_data
*
us
,
void
*
data
,
unsigned
int
len
,
unsigned
int
*
act_len
);
extern
int
usb_stor_clear_halt
(
struct
us_data
*
,
unsigned
int
pipe
);
extern
int
usb_stor_ctrl_transfer
(
struct
us_data
*
us
,
unsigned
int
pipe
,
u8
request
,
u8
requesttype
,
u16
value
,
u16
index
,
void
*
data
,
u16
size
);
extern
int
usb_stor_intr_transfer
(
struct
us_data
*
us
,
void
*
buf
,
unsigned
int
length
,
unsigned
int
*
act_len
);
unsigned
int
length
);
extern
int
usb_stor_bulk_transfer_buf
(
struct
us_data
*
us
,
unsigned
int
pipe
,
void
*
buf
,
unsigned
int
length
,
unsigned
int
*
act_len
);
extern
int
usb_stor_bulk_transfer_sglist
(
struct
us_data
*
us
,
unsigned
int
pipe
,
...
...
drivers/usb/storage/unusual_devs.h
View file @
a98b28b1
...
...
@@ -314,32 +314,17 @@ UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200,
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/
UNUSUAL_DEV
(
0x0a17
,
0x0004
,
0x1000
,
0x1000
,
"ASAHI PENTAX"
,
"PENTAX OPTIO 430"
,
US_SC_8070
,
US_PR_CBI
,
NULL
,
US_FL_FIX_INQUIRY
),
/* This Pentax still camera is not conformant
* to the USB storage specification: -
* - It does not like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
* Tested on Rev. 10.00 (0x1000)
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/
UNUSUAL_DEV
(
0x0a17
,
0x0004
,
0x1000
,
0x1000
,
"ASAHI PENTAX"
,
"PENTAX OPTIO 430"
,
"Pentax"
,
"Optio 2/3/400"
,
US_SC_8070
,
US_PR_CBI
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Pentax Optio S digital camera
* submitted by Stefan M. Brandl <smb@smbnet.de>
*/
UNUSUAL_DEV
(
0x0a17
,
0x0006
,
0x0000
,
0xffff
,
/* Submitted by Per Winkvist <per.winkvist@uk.com> */
UNUSUAL_DEV
(
0x0a17
,
0x006
,
0x1000
,
0x9009
,
"Pentax"
,
"Optio S"
,
US_SC_8070
,
US_PR_CB
,
NULL
,
US_FL_MODE_XLATE
|
US_FL_FIX_INQUIRY
),
US_SC_8070
,
US_PR_CBI
,
NULL
,
US_FL_FIX_INQUIRY
),
#ifdef CONFIG_USB_STORAGE_ISD200
UNUSUAL_DEV
(
0x05ab
,
0x0031
,
0x0100
,
0x0110
,
...
...
@@ -639,26 +624,6 @@ UNUSUAL_DEV( 0x1065, 0x2136, 0x0000, 0x0001,
US_SC_SCSI
,
US_PR_BULK
,
NULL
,
US_FL_MODE_XLATE
|
US_FL_START_STOP
|
US_FL_FIX_INQUIRY
),
/* This Pentax still camera is not conformant
* to the USB storage specification: -
* - It does not like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
* Tested on Rev. 10.00 (0x1000)
* Submitted by James Courtier-Dutton <James@superbug.demon.co.uk>
*/
UNUSUAL_DEV
(
0x0a17
,
0x0004
,
0x1000
,
0x1000
,
"Pentax"
,
"Optio 2/3/400"
,
US_SC_8070
,
US_PR_CBI
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Submitted by Per Winkvist <per.winkvist@uk.com> */
UNUSUAL_DEV
(
0x0a17
,
0x006
,
0x1000
,
0x9009
,
"Pentax"
,
"Optio S"
,
US_SC_8070
,
US_PR_CBI
,
NULL
,
US_FL_FIX_INQUIRY
),
/* Submitted by Brian Hall <brihall@pcisys.net>
* Needed for START_STOP flag */
UNUSUAL_DEV
(
0x0c76
,
0x0003
,
0x0100
,
0x0100
,
...
...
drivers/usb/storage/usb.c
View file @
a98b28b1
...
...
@@ -887,11 +887,8 @@ static int storage_probe(struct usb_interface *intf,
/* set the hostdata to prepare for scanning */
us
->
host
->
hostdata
[
0
]
=
(
unsigned
long
)
us
;
/* associate this host with our interface */
scsi_set_device
(
us
->
host
,
&
intf
->
dev
);
/* now add the host */
result
=
scsi_add_host
(
us
->
host
,
NULL
);
result
=
scsi_add_host
(
us
->
host
,
&
intf
->
dev
);
if
(
result
)
{
printk
(
KERN_WARNING
USB_STORAGE
"Unable to add the scsi host
\n
"
);
...
...
@@ -942,16 +939,13 @@ static void storage_disconnect(struct usb_interface *intf)
sdev
->
online
=
0
;
scsi_unlock
(
us
->
host
);
/* prevent new USB transfers and stop the current command */
set_bit
(
US_FLIDX_DISCONNECTING
,
&
us
->
flags
);
usb_stor_stop_transport
(
us
);
/* lock device access -- no need to unlock, as we're going away */
down
(
&
(
us
->
dev_semaphore
));
/* Complete all pending commands with * cmd->result = DID_ERROR << 16.
* Since we only queue one command at a time, this is pretty easy. */
if
(
us
->
srb
)
{
us
->
srb
->
result
=
DID_ERROR
<<
16
;
us
->
srb
->
scsi_done
(
us
->
srb
);
}
/* TODO: somehow, wait for the device to
* be 'idle' (tasklet completion) */
...
...
drivers/usb/storage/usb.h
View file @
a98b28b1
...
...
@@ -67,7 +67,7 @@ struct us_unusual_dev {
unsigned
int
flags
;
};
/* Flag definitions */
/* Flag definitions
: these entries are static
*/
#define US_FL_SINGLE_LUN 0x00000001
/* allow access to only LUN 0 */
#define US_FL_MODE_XLATE 0x00000002
/* translate _6 to _10 commands for
Win/MacOS compatibility */
...
...
@@ -77,8 +77,13 @@ struct us_unusual_dev {
#define US_FL_FIX_INQUIRY 0x00000040
/* INQUIRY response needs fixing */
#define US_FL_FIX_CAPACITY 0x00000080
/* READ CAPACITY response too big */
#define US_FLIDX_CAN_CANCEL 18
/* 0x00040000 okay to cancel current_urb? */
#define US_FLIDX_CANCEL_SG 19
/* 0x00080000 okay to cancel current_sg? */
/* Dynamic flag definitions: used in set_bit() etc. */
#define US_FLIDX_URB_ACTIVE 18
/* 0x00040000 current_urb is in use */
#define US_FLIDX_SG_ACTIVE 19
/* 0x00080000 current_sg is in use */
#define US_FLIDX_ABORTING 20
/* 0x00100000 abort is in progress */
#define US_FLIDX_DISCONNECTING 21
/* 0x00200000 disconnect in progress */
#define DONT_SUBMIT ((1UL << US_FLIDX_ABORTING) || \
(1UL << US_FLIDX_DISCONNECTING))
/* processing state machine states */
...
...
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