Commit 40aafff3 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleed-2.5

into kroah.com:/home/greg/linux/BK/gregkh-2.5
parents 4a07c099 cdbe443d
...@@ -59,6 +59,3 @@ obj-$(CONFIG_USB_TEST) += misc/ ...@@ -59,6 +59,3 @@ obj-$(CONFIG_USB_TEST) += misc/
obj-$(CONFIG_USB_TIGL) += misc/ obj-$(CONFIG_USB_TIGL) += misc/
obj-$(CONFIG_USB_USS720) += misc/ obj-$(CONFIG_USB_USS720) += misc/
obj-$(CONFIG_USB_NET2280) += gadget/
obj-$(CONFIG_USB_ZERO) += gadget/
obj-$(CONFIG_USB_ETH) += gadget/
...@@ -756,7 +756,7 @@ static int usb_hub_port_reset(struct usb_device *hub, int port, ...@@ -756,7 +756,7 @@ static int usb_hub_port_reset(struct usb_device *hub, int port,
return -1; return -1;
} }
void usb_hub_port_disable(struct usb_device *hub, int port) int usb_hub_port_disable(struct usb_device *hub, int port)
{ {
int ret; int ret;
...@@ -764,6 +764,8 @@ void usb_hub_port_disable(struct usb_device *hub, int port) ...@@ -764,6 +764,8 @@ void usb_hub_port_disable(struct usb_device *hub, int port)
if (ret) if (ret)
dev_err(hubdev(hub), "cannot disable port %d (err = %d)\n", dev_err(hubdev(hub), "cannot disable port %d (err = %d)\n",
port + 1, ret); port + 1, ret);
return ret;
} }
/* USB 2.0 spec, 7.1.7.3 / fig 7-29: /* USB 2.0 spec, 7.1.7.3 / fig 7-29:
......
...@@ -731,6 +731,70 @@ static void usb_release_dev(struct device *dev) ...@@ -731,6 +731,70 @@ static void usb_release_dev(struct device *dev)
} }
static struct usb_device *match_device(struct usb_device *dev,
u16 vendor_id, u16 product_id)
{
struct usb_device *ret_dev = NULL;
int child;
dbg("looking at vendor %d, product %d",
dev->descriptor.idVendor,
dev->descriptor.idProduct);
/* see if this device matches */
if ((dev->descriptor.idVendor == vendor_id) &&
(dev->descriptor.idProduct == product_id)) {
dbg ("found the device!");
ret_dev = usb_get_dev(dev);
goto exit;
}
/* look through all of the children of this device */
for (child = 0; child < dev->maxchild; ++child) {
if (dev->children[child]) {
ret_dev = match_device(dev->children[child],
vendor_id, product_id);
if (ret_dev)
goto exit;
}
}
exit:
return ret_dev;
}
/**
* usb_find_device - find a specific usb device in the system
* @vendor_id: the vendor id of the device to find
* @product_id: the product id of the device to find
*
* Returns a pointer to a struct usb_device if such a specified usb
* device is present in the system currently. The usage count of the
* device will be incremented if a device is found. Make sure to call
* usb_put_dev() when the caller is finished with the device.
*
* If a device with the specified vendor and product id is not found,
* NULL is returned.
*/
struct usb_device *usb_find_device(u16 vendor_id, u16 product_id)
{
struct list_head *buslist;
struct usb_bus *bus;
struct usb_device *dev = NULL;
down(&usb_bus_list_lock);
for (buslist = usb_bus_list.next;
buslist != &usb_bus_list;
buslist = buslist->next) {
bus = container_of(buslist, struct usb_bus, bus_list);
dev = match_device(bus->root_hub, vendor_id, product_id);
if (dev)
goto exit;
}
exit:
up(&usb_bus_list_lock);
return dev;
}
/** /**
* usb_get_current_frame_number - return current bus frame number * usb_get_current_frame_number - return current bus frame number
* @dev: the device whose bus is being queried * @dev: the device whose bus is being queried
...@@ -1510,6 +1574,7 @@ EXPORT_SYMBOL(usb_disconnect); ...@@ -1510,6 +1574,7 @@ EXPORT_SYMBOL(usb_disconnect);
EXPORT_SYMBOL(__usb_get_extra_descriptor); EXPORT_SYMBOL(__usb_get_extra_descriptor);
EXPORT_SYMBOL(usb_find_device);
EXPORT_SYMBOL(usb_get_current_frame_number); EXPORT_SYMBOL(usb_get_current_frame_number);
EXPORT_SYMBOL (usb_buffer_alloc); EXPORT_SYMBOL (usb_buffer_alloc);
......
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
* *
* Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee). * Based upon mouse.c (Brad Keryan) and printer.c (Michael Gee).
* *
* Changelog:
* 30/05/2003 replaced lock/unlock kernel with up/down
* Daniele Bellucci bellucda@tiscali.it
* */ * */
#include <linux/module.h> #include <linux/module.h>
...@@ -75,17 +78,17 @@ static int open_rio(struct inode *inode, struct file *file) ...@@ -75,17 +78,17 @@ static int open_rio(struct inode *inode, struct file *file)
{ {
struct rio_usb_data *rio = &rio_instance; struct rio_usb_data *rio = &rio_instance;
lock_kernel(); down(&(rio->lock));
if (rio->isopen || !rio->present) { if (rio->isopen || !rio->present) {
unlock_kernel(); up(&(rio->lock));
return -EBUSY; return -EBUSY;
} }
rio->isopen = 1; rio->isopen = 1;
init_waitqueue_head(&rio->wait_q); init_waitqueue_head(&rio->wait_q);
unlock_kernel(); up(&(rio->lock));
info("Rio opened."); info("Rio opened.");
...@@ -460,7 +463,6 @@ static int probe_rio(struct usb_interface *intf, ...@@ -460,7 +463,6 @@ static int probe_rio(struct usb_interface *intf,
return -ENOMEM; return -ENOMEM;
} }
rio->present = 1;
rio->rio_dev = dev; rio->rio_dev = dev;
if (!(rio->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) { if (!(rio->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
...@@ -481,6 +483,8 @@ static int probe_rio(struct usb_interface *intf, ...@@ -481,6 +483,8 @@ static int probe_rio(struct usb_interface *intf,
init_MUTEX(&(rio->lock)); init_MUTEX(&(rio->lock));
usb_set_intfdata (intf, rio); usb_set_intfdata (intf, rio);
rio->present = 1;
return 0; return 0;
} }
...@@ -525,7 +529,7 @@ static struct usb_driver rio_driver = { ...@@ -525,7 +529,7 @@ static struct usb_driver rio_driver = {
.id_table = rio_table, .id_table = rio_table,
}; };
int usb_rio_init(void) static int __init usb_rio_init(void)
{ {
if (usb_register(&rio_driver) < 0) if (usb_register(&rio_driver) < 0)
return -1; return -1;
...@@ -536,7 +540,7 @@ int usb_rio_init(void) ...@@ -536,7 +540,7 @@ int usb_rio_init(void)
} }
void usb_rio_cleanup(void) static void __exit usb_rio_cleanup(void)
{ {
struct rio_usb_data *rio = &rio_instance; struct rio_usb_data *rio = &rio_instance;
......
...@@ -351,6 +351,7 @@ config USB_SERIAL_KOBIL_SCT ...@@ -351,6 +351,7 @@ config USB_SERIAL_KOBIL_SCT
- USB TWIN - USB TWIN
- KAAN Standard Plus - KAAN Standard Plus
- KAAN SIM
- SecOVID Reader Plus - SecOVID Reader Plus
- B1 Professional - B1 Professional
- KAAN Professional - KAAN Professional
......
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
* Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus * Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus
* (Adapter K), B1 Professional and KAAN Professional (Adapter B) * (Adapter K), B1 Professional and KAAN Professional (Adapter B)
* *
* TODO: High baudrates * (28/05/2003) tw
* Add support for KAAN SIM
* *
* (12/09/2002) tw * (12/09/2002) tw
* Adapted to 2.5. * Adapted to 2.5.
...@@ -58,7 +59,7 @@ ...@@ -58,7 +59,7 @@
#include "usb-serial.h" #include "usb-serial.h"
/* Version Information */ /* Version Information */
#define DRIVER_VERSION "12/09/2002" #define DRIVER_VERSION "28/05/2003"
#define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com" #define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com"
#define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)" #define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)"
...@@ -66,6 +67,7 @@ ...@@ -66,6 +67,7 @@
#define KOBIL_ADAPTER_B_PRODUCT_ID 0x2011 #define KOBIL_ADAPTER_B_PRODUCT_ID 0x2011
#define KOBIL_ADAPTER_K_PRODUCT_ID 0x2012 #define KOBIL_ADAPTER_K_PRODUCT_ID 0x2012
#define KOBIL_USBTWIN_PRODUCT_ID 0x0078 #define KOBIL_USBTWIN_PRODUCT_ID 0x0078
#define KOBIL_KAAN_SIM_PRODUCT_ID 0x0081
#define KOBIL_TIMEOUT 500 #define KOBIL_TIMEOUT 500
#define KOBIL_BUF_LENGTH 300 #define KOBIL_BUF_LENGTH 300
...@@ -92,12 +94,22 @@ static struct usb_device_id id_table [] = { ...@@ -92,12 +94,22 @@ static struct usb_device_id id_table [] = {
{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_B_PRODUCT_ID) }, { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_B_PRODUCT_ID) },
{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_K_PRODUCT_ID) }, { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_ADAPTER_K_PRODUCT_ID) },
{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_USBTWIN_PRODUCT_ID) }, { USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_USBTWIN_PRODUCT_ID) },
{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_KAAN_SIM_PRODUCT_ID) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
MODULE_DEVICE_TABLE (usb, id_table); MODULE_DEVICE_TABLE (usb, id_table);
static struct usb_driver kobil_driver = {
.owner = THIS_MODULE,
.name = "kobil",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
};
struct usb_serial_device_type kobil_device = { struct usb_serial_device_type kobil_device = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "KOBIL USB smart card terminal", .name = "KOBIL USB smart card terminal",
...@@ -161,6 +173,9 @@ static int kobil_startup (struct usb_serial *serial) ...@@ -161,6 +173,9 @@ static int kobil_startup (struct usb_serial *serial)
case KOBIL_USBTWIN_PRODUCT_ID: case KOBIL_USBTWIN_PRODUCT_ID:
printk(KERN_DEBUG "KOBIL USBTWIN detected\n"); printk(KERN_DEBUG "KOBIL USBTWIN detected\n");
break; break;
case KOBIL_KAAN_SIM_PRODUCT_ID:
printk(KERN_DEBUG "KOBIL KAAN SIM detected\n");
break;
} }
usb_set_serial_port_data(serial->port, priv); usb_set_serial_port_data(serial->port, priv);
...@@ -353,7 +368,7 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs) ...@@ -353,7 +368,7 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
struct usb_serial_port *port = (struct usb_serial_port *) purb->context; struct usb_serial_port *port = (struct usb_serial_port *) purb->context;
struct tty_struct *tty; struct tty_struct *tty;
unsigned char *data = purb->transfer_buffer; unsigned char *data = purb->transfer_buffer;
char *dbg_data; // char *dbg_data;
dbg("%s - port %d", __FUNCTION__, port->number); dbg("%s - port %d", __FUNCTION__, port->number);
...@@ -366,16 +381,18 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs) ...@@ -366,16 +381,18 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
if (purb->actual_length) { if (purb->actual_length) {
// BEGIN DEBUG // BEGIN DEBUG
dbg_data = (unsigned char *) kmalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); /*
if (! dbg_data) { dbg_data = (unsigned char *) kmalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL);
return; if (! dbg_data) {
} return;
memset(dbg_data, 0, (3 * purb->actual_length + 10)); }
for (i = 0; i < purb->actual_length; i++) { memset(dbg_data, 0, (3 * purb->actual_length + 10));
sprintf(dbg_data +3*i, "%02X ", data[i]); for (i = 0; i < purb->actual_length; i++) {
} sprintf(dbg_data +3*i, "%02X ", data[i]);
dbg(" <-- %s", dbg_data ); }
kfree(dbg_data); dbg(" <-- %s", dbg_data );
kfree(dbg_data);
*/
// END DEBUG // END DEBUG
for (i = 0; i < purb->actual_length; ++i) { for (i = 0; i < purb->actual_length; ++i) {
...@@ -438,7 +455,7 @@ static int kobil_write (struct usb_serial_port *port, int from_user, ...@@ -438,7 +455,7 @@ static int kobil_write (struct usb_serial_port *port, int from_user,
priv->filled = priv->filled + count; priv->filled = priv->filled + count;
// only send complete block. TWIN and adapter K use the same protocol. // only send complete block. TWIN, KAAN SIM and adapter K use the same protocol.
if ( ((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) || if ( ((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) ||
((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4))) ) { ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4))) ) {
...@@ -503,7 +520,7 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file) ...@@ -503,7 +520,7 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
int transfer_buffer_length = 8; int transfer_buffer_length = 8;
priv = usb_get_serial_port_data(port); priv = usb_get_serial_port_data(port);
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) { if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
// This device doesn't support ioctl calls // This device doesn't support ioctl calls
return -EINVAL; return -EINVAL;
} }
...@@ -549,7 +566,7 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file, ...@@ -549,7 +566,7 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
int transfer_buffer_length = 8; int transfer_buffer_length = 8;
priv = usb_get_serial_port_data(port); priv = usb_get_serial_port_data(port);
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) { if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
// This device doesn't support ioctl calls // This device doesn't support ioctl calls
return -EINVAL; return -EINVAL;
} }
...@@ -616,7 +633,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, ...@@ -616,7 +633,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
char *settings; char *settings;
priv = usb_get_serial_port_data(port); priv = usb_get_serial_port_data(port);
if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) { if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
// This device doesn't support ioctl calls // This device doesn't support ioctl calls
return 0; return 0;
} }
...@@ -727,6 +744,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, ...@@ -727,6 +744,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
static int __init kobil_init (void) static int __init kobil_init (void)
{ {
usb_serial_register (&kobil_device); usb_serial_register (&kobil_device);
usb_register (&kobil_driver);
info(DRIVER_VERSION " " DRIVER_AUTHOR); info(DRIVER_VERSION " " DRIVER_AUTHOR);
info(DRIVER_DESC); info(DRIVER_DESC);
...@@ -737,6 +755,7 @@ static int __init kobil_init (void) ...@@ -737,6 +755,7 @@ static int __init kobil_init (void)
static void __exit kobil_exit (void) static void __exit kobil_exit (void)
{ {
usb_deregister (&kobil_driver);
usb_serial_deregister (&kobil_device); usb_serial_deregister (&kobil_device);
} }
......
...@@ -670,7 +670,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us) ...@@ -670,7 +670,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
srb->result = SUCCESS; srb->result = SUCCESS;
} else { } else {
info->sense_key = UNIT_ATTENTION; info->sense_key = UNIT_ATTENTION;
srb->result = CHECK_CONDITION << 1; srb->result = SAM_STAT_CHECK_CONDITION;
} }
return rc; return rc;
} }
......
...@@ -399,7 +399,7 @@ freecom_init (struct us_data *us) ...@@ -399,7 +399,7 @@ freecom_init (struct us_data *us)
} }
} }
result = usb_control_msg(us->pusb_dev, us->recv_ctrl_pipe, result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ); 0x4c, 0xc0, 0x4346, 0x0, buffer, 0x20, 3*HZ);
buffer[32] = '\0'; buffer[32] = '\0';
US_DEBUGP("String returned from FC init is: %s\n", buffer); US_DEBUGP("String returned from FC init is: %s\n", buffer);
...@@ -411,7 +411,7 @@ freecom_init (struct us_data *us) ...@@ -411,7 +411,7 @@ freecom_init (struct us_data *us)
*/ */
/* send reset */ /* send reset */
result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe, result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ); 0x4d, 0x40, 0x24d8, 0x0, NULL, 0x0, 3*HZ);
US_DEBUGP("result from activate reset is %d\n", result); US_DEBUGP("result from activate reset is %d\n", result);
...@@ -419,7 +419,7 @@ freecom_init (struct us_data *us) ...@@ -419,7 +419,7 @@ freecom_init (struct us_data *us)
mdelay(250); mdelay(250);
/* clear reset */ /* clear reset */
result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe, result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ); 0x4d, 0x40, 0x24f8, 0x0, NULL, 0x0, 3*HZ);
US_DEBUGP("result from clear reset is %d\n", result); US_DEBUGP("result from clear reset is %d\n", result);
......
...@@ -50,7 +50,7 @@ int usb_stor_euscsi_init(struct us_data *us) ...@@ -50,7 +50,7 @@ int usb_stor_euscsi_init(struct us_data *us)
int result; int result;
US_DEBUGP("Attempting to init eUSCSI bridge...\n"); US_DEBUGP("Attempting to init eUSCSI bridge...\n");
result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe, result = usb_stor_control_msg(us, us->send_ctrl_pipe,
0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR, 0x0C, USB_RECIP_INTERFACE | USB_TYPE_VENDOR,
0x01, 0x0, &data, 0x1, 5*HZ); 0x01, 0x0, &data, 0x1, 5*HZ);
US_DEBUGP("-- result is %d\n", result); US_DEBUGP("-- result is %d\n", result);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/config.h> #include <linux/config.h>
#include "usb.h" #include "usb.h"
#include "transport.h"
/* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target /* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target
* mode */ * mode */
......
...@@ -558,7 +558,7 @@ void isd200_invoke_transport( struct us_data *us, ...@@ -558,7 +558,7 @@ void isd200_invoke_transport( struct us_data *us,
case USB_STOR_TRANSPORT_GOOD: case USB_STOR_TRANSPORT_GOOD:
/* Indicate a good result */ /* Indicate a good result */
srb->result = GOOD << 1; srb->result = SAM_STAT_GOOD;
break; break;
case USB_STOR_TRANSPORT_FAILED: case USB_STOR_TRANSPORT_FAILED:
...@@ -598,11 +598,11 @@ void isd200_invoke_transport( struct us_data *us, ...@@ -598,11 +598,11 @@ void isd200_invoke_transport( struct us_data *us,
} }
if (result == ISD200_GOOD) { if (result == ISD200_GOOD) {
isd200_build_sense(us, srb); isd200_build_sense(us, srb);
srb->result = CHECK_CONDITION << 1; srb->result = SAM_STAT_CHECK_CONDITION;
/* If things are really okay, then let's show that */ /* If things are really okay, then let's show that */
if ((srb->sense_buffer[2] & 0xf) == 0x0) if ((srb->sense_buffer[2] & 0xf) == 0x0)
srb->result = GOOD << 1; srb->result = SAM_STAT_GOOD;
} else } else
srb->result = DID_ERROR << 16; srb->result = DID_ERROR << 16;
} }
...@@ -611,7 +611,7 @@ void isd200_invoke_transport( struct us_data *us, ...@@ -611,7 +611,7 @@ void isd200_invoke_transport( struct us_data *us,
* condition, show that in the result code * condition, show that in the result code
*/ */
if (transferStatus == USB_STOR_TRANSPORT_FAILED) if (transferStatus == USB_STOR_TRANSPORT_FAILED)
srb->result = CHECK_CONDITION << 1; srb->result = SAM_STAT_CHECK_CONDITION;
} }
#ifdef CONFIG_USB_STORAGE_DEBUG #ifdef CONFIG_USB_STORAGE_DEBUG
...@@ -1185,7 +1185,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1185,7 +1185,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
/* copy InquiryData */ /* copy InquiryData */
isd200_data_copy(srb, (char *) &info->InquiryData, srb->request_bufflen); isd200_data_copy(srb, (char *) &info->InquiryData, srb->request_bufflen);
srb->result = GOOD << 1; srb->result = SAM_STAT_GOOD;
sendToTransport = FALSE; sendToTransport = FALSE;
break; break;
...@@ -1205,7 +1205,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1205,7 +1205,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = 0; srb->request_bufflen = 0;
} else { } else {
US_DEBUGP(" Media Status not supported, just report okay\n"); US_DEBUGP(" Media Status not supported, just report okay\n");
srb->result = GOOD << 1; srb->result = SAM_STAT_GOOD;
sendToTransport = FALSE; sendToTransport = FALSE;
} }
break; break;
...@@ -1226,7 +1226,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1226,7 +1226,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = 0; srb->request_bufflen = 0;
} else { } else {
US_DEBUGP(" Media Status not supported, just report okay\n"); US_DEBUGP(" Media Status not supported, just report okay\n");
srb->result = GOOD << 1; srb->result = SAM_STAT_GOOD;
sendToTransport = FALSE; sendToTransport = FALSE;
} }
break; break;
...@@ -1252,7 +1252,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1252,7 +1252,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = sizeof(struct read_capacity_data); srb->request_bufflen = sizeof(struct read_capacity_data);
isd200_data_copy(srb, (char *) &readCapacityData, srb->request_bufflen); isd200_data_copy(srb, (char *) &readCapacityData, srb->request_bufflen);
srb->result = GOOD << 1; srb->result = SAM_STAT_GOOD;
sendToTransport = FALSE; sendToTransport = FALSE;
} }
break; break;
...@@ -1336,7 +1336,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1336,7 +1336,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = 0; srb->request_bufflen = 0;
} else { } else {
US_DEBUGP(" Not removeable media, just report okay\n"); US_DEBUGP(" Not removeable media, just report okay\n");
srb->result = GOOD << 1; srb->result = SAM_STAT_GOOD;
sendToTransport = FALSE; sendToTransport = FALSE;
} }
break; break;
...@@ -1365,7 +1365,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us, ...@@ -1365,7 +1365,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = 0; srb->request_bufflen = 0;
} else { } else {
US_DEBUGP(" Nothing to do, just report okay\n"); US_DEBUGP(" Nothing to do, just report okay\n");
srb->result = GOOD << 1; srb->result = SAM_STAT_GOOD;
sendToTransport = FALSE; sendToTransport = FALSE;
} }
break; break;
......
...@@ -611,7 +611,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us) ...@@ -611,7 +611,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
srb->result = SUCCESS; srb->result = SUCCESS;
} else { } else {
info->sense_key = UNIT_ATTENTION; info->sense_key = UNIT_ATTENTION;
srb->result = CHECK_CONDITION << 1; srb->result = SAM_STAT_CHECK_CONDITION;
} }
return rc; return rc;
} }
......
...@@ -137,8 +137,7 @@ void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us) ...@@ -137,8 +137,7 @@ void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */ /* send the command to the transport layer */
usb_stor_invoke_transport(srb, us); usb_stor_invoke_transport(srb, us);
if (srb->result == GOOD << 1) { if (srb->result == SAM_STAT_GOOD) {
/* fix the INQUIRY data if necessary */ /* fix the INQUIRY data if necessary */
fix_inquiry_data(srb); fix_inquiry_data(srb);
} }
...@@ -210,7 +209,7 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us) ...@@ -210,7 +209,7 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */ /* send the command to the transport layer */
usb_stor_invoke_transport(srb, us); usb_stor_invoke_transport(srb, us);
if (srb->result == GOOD << 1) { if (srb->result == SAM_STAT_GOOD) {
/* Fix the MODE_SENSE data if we translated the command */ /* Fix the MODE_SENSE data if we translated the command */
if (old_cmnd == MODE_SENSE) if (old_cmnd == MODE_SENSE)
...@@ -307,7 +306,7 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us) ...@@ -307,7 +306,7 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */ /* send the command to the transport layer */
usb_stor_invoke_transport(srb, us); usb_stor_invoke_transport(srb, us);
if (srb->result == GOOD << 1) { if (srb->result == SAM_STAT_GOOD) {
/* Fix the MODE_SENSE data if we translated the command */ /* Fix the MODE_SENSE data if we translated the command */
if (old_cmnd == MODE_SENSE) if (old_cmnd == MODE_SENSE)
...@@ -376,7 +375,7 @@ void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us) ...@@ -376,7 +375,7 @@ void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */ /* send the command to the transport layer */
usb_stor_invoke_transport(srb, us); usb_stor_invoke_transport(srb, us);
if (srb->result == GOOD << 1) { if (srb->result == SAM_STAT_GOOD) {
/* Fix the MODE_SENSE data if we translated the command */ /* Fix the MODE_SENSE data if we translated the command */
if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SENSE)) if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SENSE))
......
...@@ -219,7 +219,7 @@ static int usb_storage_device_reset( Scsi_Cmnd *srb ) ...@@ -219,7 +219,7 @@ static int usb_storage_device_reset( Scsi_Cmnd *srb )
int state = atomic_read(&us->sm_state); int state = atomic_read(&us->sm_state);
int result; int result;
US_DEBUGP("device_reset() called\n" ); US_DEBUGP("%s called\n", __FUNCTION__);
if (state != US_STATE_IDLE) { if (state != US_STATE_IDLE) {
printk(KERN_ERR USB_STORAGE "Error in %s: " printk(KERN_ERR USB_STORAGE "Error in %s: "
"invalid state %d\n", __FUNCTION__, state); "invalid state %d\n", __FUNCTION__, state);
...@@ -245,39 +245,49 @@ static int usb_storage_device_reset( Scsi_Cmnd *srb ) ...@@ -245,39 +245,49 @@ static int usb_storage_device_reset( Scsi_Cmnd *srb )
return result; return result;
} }
/* This resets the device port */ /* This resets the device's USB port. */
/* It refuses to work if there's more than one interface in /* It refuses to work if there's more than one interface in
this device, so that other users are not affected. */ * the device, so that other users are not affected. */
/* This is always called with scsi_lock(srb->host) held */ /* This is always called with scsi_lock(srb->host) held */
static int usb_storage_bus_reset( Scsi_Cmnd *srb ) static int usb_storage_bus_reset( Scsi_Cmnd *srb )
{ {
struct us_data *us; struct us_data *us = (struct us_data *)srb->device->host->hostdata[0];
int state = atomic_read(&us->sm_state);
int result; int result;
/* we use the usb_reset_device() function to handle this for us */ US_DEBUGP("%s called\n", __FUNCTION__);
US_DEBUGP("bus_reset() called\n"); if (state != US_STATE_IDLE) {
printk(KERN_ERR USB_STORAGE "Error in %s: "
"invalid state %d\n", __FUNCTION__, state);
return FAILED;
}
/* set the state and release the lock */
atomic_set(&us->sm_state, US_STATE_RESETTING);
scsi_unlock(srb->device->host); scsi_unlock(srb->device->host);
us = (struct us_data *)srb->device->host->hostdata[0];
/* The USB subsystem doesn't handle synchronisation between /* The USB subsystem doesn't handle synchronisation between
a device's several drivers. Therefore we reset only devices a device's several drivers. Therefore we reset only devices
with one interface which we of course own. with just one interface, which we of course own.
*/ */
//FIXME: needs locking against config changes //FIXME: needs locking against config changes
if ( us->pusb_dev->actconfig->desc.bNumInterfaces == 1) { if (us->pusb_dev->actconfig->desc.bNumInterfaces == 1) {
/* attempt to reset the port */
/* lock the device and attempt to reset the port */
down(&(us->dev_semaphore));
result = usb_reset_device(us->pusb_dev); result = usb_reset_device(us->pusb_dev);
up(&(us->dev_semaphore));
US_DEBUGP("usb_reset_device returns %d\n", result); US_DEBUGP("usb_reset_device returns %d\n", result);
} else { } else {
result = -EBUSY; result = -EBUSY;
US_DEBUGP("cannot reset a multiinterface device. failing to reset.\n"); US_DEBUGP("Refusing to reset a multi-interface device\n");
} }
US_DEBUGP("bus_reset() complete\n"); /* lock access to the state and clear it */
scsi_lock(srb->device->host); scsi_lock(srb->device->host);
atomic_set(&us->sm_state, US_STATE_IDLE);
return result < 0 ? FAILED : SUCCESS; return result < 0 ? FAILED : SUCCESS;
} }
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
* below, which atomically tests-and-clears the URB_ACTIVE bit in us->flags * 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 * 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 * bit is tested to see if the current_sg scatter-gather request needs to be
* stopped. * stopped. The timeout callback routine does much the same thing.
* *
* When a disconnect occurs, the DISCONNECTING bit in us->flags is set to * 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 * prevent new URBs from being submitted, and usb_stor_stop_transport() is
...@@ -109,6 +109,19 @@ static void usb_stor_blocking_completion(struct urb *urb, struct pt_regs *regs) ...@@ -109,6 +109,19 @@ static void usb_stor_blocking_completion(struct urb *urb, struct pt_regs *regs)
complete(urb_done_ptr); complete(urb_done_ptr);
} }
/* This is the timeout handler which will cancel an URB when its timeout
* expires.
*/
static void timeout_handler(unsigned long us_)
{
struct us_data *us = (struct us_data *) us_;
if (test_and_clear_bit(US_FLIDX_URB_ACTIVE, &us->flags)) {
US_DEBUGP("Timeout -- cancelling URB\n");
usb_unlink_urb(us->current_urb);
}
}
/* This is the common part of the URB message submission code /* This is the common part of the URB message submission code
* *
...@@ -116,9 +129,10 @@ static void usb_stor_blocking_completion(struct urb *urb, struct pt_regs *regs) ...@@ -116,9 +129,10 @@ static void usb_stor_blocking_completion(struct urb *urb, struct pt_regs *regs)
* command _must_ pass through this function (or something like it) for the * command _must_ pass through this function (or something like it) for the
* abort mechanisms to work properly. * abort mechanisms to work properly.
*/ */
static int usb_stor_msg_common(struct us_data *us) static int usb_stor_msg_common(struct us_data *us, int timeout)
{ {
struct completion urb_done; struct completion urb_done;
struct timer_list to_timer;
int status; int status;
/* don't submit URBS during abort/disconnect processing */ /* don't submit URBS during abort/disconnect processing */
...@@ -155,24 +169,42 @@ static int usb_stor_msg_common(struct us_data *us) ...@@ -155,24 +169,42 @@ static int usb_stor_msg_common(struct us_data *us)
usb_unlink_urb(us->current_urb); usb_unlink_urb(us->current_urb);
} }
} }
/* submit the timeout timer, if a timeout was requested */
if (timeout > 0) {
init_timer(&to_timer);
to_timer.expires = jiffies + timeout;
to_timer.function = timeout_handler;
to_timer.data = (unsigned long) us;
add_timer(&to_timer);
}
/* wait for the completion of the URB */ /* wait for the completion of the URB */
wait_for_completion(&urb_done); wait_for_completion(&urb_done);
clear_bit(US_FLIDX_URB_ACTIVE, &us->flags); clear_bit(US_FLIDX_URB_ACTIVE, &us->flags);
/* clean up the timeout timer */
if (timeout > 0)
del_timer_sync(&to_timer);
/* return the URB status */ /* return the URB status */
return us->current_urb->status; return us->current_urb->status;
} }
/* This is our function to emulate usb_control_msg() with enough control /*
* to make aborts/resets/timeouts work * Transfer one control message, with timeouts, and allowing early
* termination. Return codes are usual -Exxx, *not* USB_STOR_XFER_xxx.
*/ */
int usb_stor_control_msg(struct us_data *us, unsigned int pipe, int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index, u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size) void *data, u16 size, int timeout)
{ {
int status; int status;
US_DEBUGP("%s: rq=%02x rqtype=%02x value=%04x index=%02x len=%u\n",
__FUNCTION__, request, requesttype,
value, index, size);
/* fill in the devrequest structure */ /* fill in the devrequest structure */
us->dr->bRequestType = requesttype; us->dr->bRequestType = requesttype;
us->dr->bRequest = request; us->dr->bRequest = request;
...@@ -184,7 +216,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe, ...@@ -184,7 +216,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
(unsigned char*) us->dr, data, size, (unsigned char*) us->dr, data, size,
usb_stor_blocking_completion, NULL); usb_stor_blocking_completion, NULL);
status = usb_stor_msg_common(us); status = usb_stor_msg_common(us, timeout);
/* return the actual length of the data transferred if no error */ /* return the actual length of the data transferred if no error */
if (status == 0) if (status == 0)
...@@ -192,9 +224,9 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe, ...@@ -192,9 +224,9 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
return status; return status;
} }
/* This is a version of usb_clear_halt() that doesn't read the status from /* This is a version of usb_clear_halt() that allows early termination and
* the device -- this is because some devices crash their internal firmware * doesn't read the status from the device -- this is because some devices
* when the status is requested after a halt. * crash their internal firmware when the status is requested after a halt.
* *
* A definitive list of these 'bad' devices is too difficult to maintain or * A definitive list of these 'bad' devices is too difficult to maintain or
* make complete enough to be useful. This problem was first observed on the * make complete enough to be useful. This problem was first observed on the
...@@ -214,12 +246,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) ...@@ -214,12 +246,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
result = usb_stor_control_msg(us, us->send_ctrl_pipe, result = usb_stor_control_msg(us, us->send_ctrl_pipe,
USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
endp, NULL, 0); /* note: no 3*HZ timeout */ endp, NULL, 0, 3*HZ);
US_DEBUGP("usb_stor_clear_halt: result=%d\n", result);
/* this is a failure case */
if (result < 0)
return result;
/* reset the toggles and endpoint flags */ /* reset the toggles and endpoint flags */
usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe), usb_endpoint_running(us->pusb_dev, usb_pipeendpoint(pipe),
...@@ -227,7 +254,8 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) ...@@ -227,7 +254,8 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe)
usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe), usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
usb_pipeout(pipe), 0); usb_pipeout(pipe), 0);
return 0; US_DEBUGP("%s: result = %d\n", __FUNCTION__, result);
return result;
} }
...@@ -317,7 +345,7 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe, ...@@ -317,7 +345,7 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe, usb_fill_control_urb(us->current_urb, us->pusb_dev, pipe,
(unsigned char*) us->dr, data, size, (unsigned char*) us->dr, data, size,
usb_stor_blocking_completion, NULL); usb_stor_blocking_completion, NULL);
result = usb_stor_msg_common(us); result = usb_stor_msg_common(us, 0);
return interpret_urb_result(us, pipe, size, result, return interpret_urb_result(us, pipe, size, result,
us->current_urb->actual_length); us->current_urb->actual_length);
...@@ -347,7 +375,7 @@ int usb_stor_intr_transfer(struct us_data *us, void *buf, unsigned int length) ...@@ -347,7 +375,7 @@ int usb_stor_intr_transfer(struct us_data *us, void *buf, unsigned int length)
usb_fill_int_urb(us->current_urb, us->pusb_dev, pipe, buf, usb_fill_int_urb(us->current_urb, us->pusb_dev, pipe, buf,
maxp, usb_stor_blocking_completion, NULL, maxp, usb_stor_blocking_completion, NULL,
us->ep_bInterval); us->ep_bInterval);
result = usb_stor_msg_common(us); result = usb_stor_msg_common(us, 0);
return interpret_urb_result(us, pipe, length, result, return interpret_urb_result(us, pipe, length, result,
us->current_urb->actual_length); us->current_urb->actual_length);
...@@ -368,7 +396,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, ...@@ -368,7 +396,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
/* fill and submit the URB */ /* fill and submit the URB */
usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length, usb_fill_bulk_urb(us->current_urb, us->pusb_dev, pipe, buf, length,
usb_stor_blocking_completion, NULL); usb_stor_blocking_completion, NULL);
result = usb_stor_msg_common(us); result = usb_stor_msg_common(us, 0);
/* store the actual length of the data transferred */ /* store the actual length of the data transferred */
if (act_len) if (act_len)
...@@ -490,7 +518,6 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -490,7 +518,6 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
} }
/* if there is a transport error, reset and don't auto-sense */ /* if there is a transport error, reset and don't auto-sense */
/* What if we want to abort during the reset? */
if (result == USB_STOR_TRANSPORT_ERROR) { if (result == USB_STOR_TRANSPORT_ERROR) {
US_DEBUGP("-- transport indicates error, resetting\n"); US_DEBUGP("-- transport indicates error, resetting\n");
us->transport_reset(us); us->transport_reset(us);
...@@ -559,6 +586,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -559,6 +586,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
unsigned char old_sc_data_direction; unsigned char old_sc_data_direction;
unsigned char old_cmd_len; unsigned char old_cmd_len;
unsigned char old_cmnd[MAX_COMMAND_SIZE]; unsigned char old_cmnd[MAX_COMMAND_SIZE];
unsigned long old_serial_number;
US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
...@@ -594,6 +622,10 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -594,6 +622,10 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
old_sg = srb->use_sg; old_sg = srb->use_sg;
srb->use_sg = 0; srb->use_sg = 0;
/* change the serial number -- toggle the high bit*/
old_serial_number = srb->serial_number;
srb->serial_number ^= 0x80000000;
/* issue the auto-sense command */ /* issue the auto-sense command */
temp_result = us->transport(us->srb, us); temp_result = us->transport(us->srb, us);
...@@ -601,6 +633,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -601,6 +633,7 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
srb->request_buffer = old_request_buffer; srb->request_buffer = old_request_buffer;
srb->request_bufflen = old_request_bufflen; srb->request_bufflen = old_request_bufflen;
srb->use_sg = old_sg; srb->use_sg = old_sg;
srb->serial_number = old_serial_number;
srb->sc_data_direction = old_sc_data_direction; srb->sc_data_direction = old_sc_data_direction;
srb->cmd_len = old_cmd_len; srb->cmd_len = old_cmd_len;
memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
...@@ -616,10 +649,8 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -616,10 +649,8 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
* multi-target device, since failure of an * multi-target device, since failure of an
* auto-sense is perfectly valid * auto-sense is perfectly valid
*/ */
if (!(us->flags & US_FL_SCM_MULT_TARG)) { if (!(us->flags & US_FL_SCM_MULT_TARG))
/* What if we try to abort during the reset? */
us->transport_reset(us); us->transport_reset(us);
}
srb->result = DID_ERROR << 16; srb->result = DID_ERROR << 16;
return; return;
} }
...@@ -638,19 +669,19 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us) ...@@ -638,19 +669,19 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
#endif #endif
/* set the result so the higher layers expect this data */ /* set the result so the higher layers expect this data */
srb->result = CHECK_CONDITION << 1; srb->result = SAM_STAT_CHECK_CONDITION;
/* If things are really okay, then let's show that */ /* If things are really okay, then let's show that */
if ((srb->sense_buffer[2] & 0xf) == 0x0) if ((srb->sense_buffer[2] & 0xf) == 0x0)
srb->result = GOOD << 1; srb->result = SAM_STAT_GOOD;
} else /* if (need_auto_sense) */ } else /* if (need_auto_sense) */
srb->result = GOOD << 1; srb->result = SAM_STAT_GOOD;
/* Regardless of auto-sense, if we _know_ we have an error /* Regardless of auto-sense, if we _know_ we have an error
* condition, show that in the result code * condition, show that in the result code
*/ */
if (result == USB_STOR_TRANSPORT_FAILED) if (result == USB_STOR_TRANSPORT_FAILED)
srb->result = CHECK_CONDITION << 1; srb->result = SAM_STAT_CHECK_CONDITION;
/* If we think we're good, then make sure the sense data shows it. /* If we think we're good, then make sure the sense data shows it.
* This is necessary because the auto-sense for some devices always * This is necessary because the auto-sense for some devices always
...@@ -844,11 +875,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us) ...@@ -844,11 +875,8 @@ int usb_stor_Bulk_max_lun(struct us_data *us)
unsigned char data; unsigned char data;
int result; int result;
/* Issue the command -- use usb_control_msg() because this is /* issue the command */
* not a scsi queued-command. Also note that at this point the result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
* cached pipe values have not yet been stored. */
result = usb_control_msg(us->pusb_dev,
usb_rcvctrlpipe(us->pusb_dev, 0),
US_BULK_GET_MAX_LUN, US_BULK_GET_MAX_LUN,
USB_DIR_IN | USB_TYPE_CLASS | USB_DIR_IN | USB_TYPE_CLASS |
USB_RECIP_INTERFACE, USB_RECIP_INTERFACE,
...@@ -982,43 +1010,40 @@ static int usb_stor_reset_common(struct us_data *us, ...@@ -982,43 +1010,40 @@ static int usb_stor_reset_common(struct us_data *us,
u16 value, u16 index, void *data, u16 size) u16 value, u16 index, void *data, u16 size)
{ {
int result; int result;
int result2;
/* A 20-second timeout may seem rather long, but a LaCie /* A 20-second timeout may seem rather long, but a LaCie
* StudioDrive USB2 device takes 16+ seconds to get going * StudioDrive USB2 device takes 16+ seconds to get going
* following a powerup or USB attach event. */ * following a powerup or USB attach event. */
/* Use usb_control_msg() because this is not a queued-command */ result = usb_stor_control_msg(us, us->send_ctrl_pipe,
result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
request, requesttype, value, index, data, size, request, requesttype, value, index, data, size,
20*HZ); 20*HZ);
if (result < 0) if (result < 0) {
goto Done; US_DEBUGP("Soft reset failed: %d\n", result);
return FAILED;
}
/* long wait for reset */ /* long wait for reset, so unlock to allow disconnects */
up(&us->dev_semaphore);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ*6); schedule_timeout(HZ*6);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
down(&us->dev_semaphore);
/* Use usb_clear_halt() because this is not a queued-command */
US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n"); US_DEBUGP("Soft reset: clearing bulk-in endpoint halt\n");
result = usb_clear_halt(us->pusb_dev, us->recv_bulk_pipe); result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
if (result < 0)
goto Done;
US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n"); US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n");
result = usb_clear_halt(us->pusb_dev, us->send_bulk_pipe); result2 = usb_stor_clear_halt(us, us->send_bulk_pipe);
Done:
/* return a result code based on the result of the control message */ /* return a result code based on the result of the control message */
if (result < 0) { if (result < 0 || result2 < 0) {
US_DEBUGP("Soft reset failed: %d\n", result); US_DEBUGP("Soft reset failed\n");
result = FAILED; return FAILED;
} else {
US_DEBUGP("Soft reset done\n");
result = SUCCESS;
} }
return result; US_DEBUGP("Soft reset done\n");
return SUCCESS;
} }
/* This issues a CB[I] Reset to the device in question /* This issues a CB[I] Reset to the device in question
......
...@@ -160,9 +160,9 @@ extern void usb_stor_stop_transport(struct us_data*); ...@@ -160,9 +160,9 @@ extern void usb_stor_stop_transport(struct us_data*);
extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe, extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index, u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size); void *data, u16 size, int timeout);
extern int usb_stor_clear_halt(struct us_data *us, unsigned int pipe);
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, extern int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe,
u8 request, u8 requesttype, u16 value, u16 index, u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size); void *data, u16 size);
......
...@@ -374,7 +374,7 @@ static int usb_stor_control_thread(void * __us) ...@@ -374,7 +374,7 @@ static int usb_stor_control_thread(void * __us)
memcpy(us->srb->sense_buffer, memcpy(us->srb->sense_buffer,
usb_stor_sense_invalidCDB, usb_stor_sense_invalidCDB,
sizeof(usb_stor_sense_invalidCDB)); sizeof(usb_stor_sense_invalidCDB));
us->srb->result = CHECK_CONDITION << 1; us->srb->result = SAM_STAT_CHECK_CONDITION;
} }
/* Handle those devices which need us to fake /* Handle those devices which need us to fake
...@@ -387,7 +387,7 @@ static int usb_stor_control_thread(void * __us) ...@@ -387,7 +387,7 @@ static int usb_stor_control_thread(void * __us)
US_DEBUGP("Faking INQUIRY command\n"); US_DEBUGP("Faking INQUIRY command\n");
fill_inquiry_response(us, data_ptr, 36); fill_inquiry_response(us, data_ptr, 36);
us->srb->result = GOOD << 1; us->srb->result = SAM_STAT_GOOD;
} }
/* we've got a command, let's do it! */ /* we've got a command, let's do it! */
...@@ -412,9 +412,11 @@ static int usb_stor_control_thread(void * __us) ...@@ -412,9 +412,11 @@ static int usb_stor_control_thread(void * __us)
US_DEBUGP("scsi command aborted\n"); US_DEBUGP("scsi command aborted\n");
} }
/* in case an abort request was received after the command /* If an abort request was received we need to signal that
* completed, we must use a separate test to see whether * the abort has finished. The proper test for this is
* we need to signal that the abort has finished */ * sm_state == US_STATE_ABORTING, not srb->result == DID_ABORT,
* because an abort request might be received after all the
* USB processing was complete. */
if (atomic_read(&us->sm_state) == US_STATE_ABORTING) if (atomic_read(&us->sm_state) == US_STATE_ABORTING)
complete(&(us->notify)); complete(&(us->notify));
...@@ -715,7 +717,6 @@ static int storage_probe(struct usb_interface *intf, ...@@ -715,7 +717,6 @@ static int storage_probe(struct usb_interface *intf,
us->transport_name = "Bulk"; us->transport_name = "Bulk";
us->transport = usb_stor_Bulk_transport; us->transport = usb_stor_Bulk_transport;
us->transport_reset = usb_stor_Bulk_reset; us->transport_reset = usb_stor_Bulk_reset;
us->max_lun = usb_stor_Bulk_max_lun(us);
break; break;
#ifdef CONFIG_USB_STORAGE_HP8200e #ifdef CONFIG_USB_STORAGE_HP8200e
...@@ -842,6 +843,10 @@ static int storage_probe(struct usb_interface *intf, ...@@ -842,6 +843,10 @@ static int storage_probe(struct usb_interface *intf,
if (usb_stor_allocate_urbs(us)) if (usb_stor_allocate_urbs(us))
goto BadDevice; goto BadDevice;
/* For bulk-only devices, determine the max LUN value */
if (us->protocol == US_PR_BULK)
us->max_lun = usb_stor_Bulk_max_lun(us);
/* /*
* Since this is a new device, we need to generate a scsi * Since this is a new device, we need to generate a scsi
* host definition, and register with the higher SCSI layers * host definition, and register with the higher SCSI layers
......
...@@ -82,7 +82,7 @@ struct us_unusual_dev { ...@@ -82,7 +82,7 @@ struct us_unusual_dev {
#define US_FLIDX_SG_ACTIVE 19 /* 0x00080000 current_sg 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_ABORTING 20 /* 0x00100000 abort is in progress */
#define US_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect in progress */ #define US_FLIDX_DISCONNECTING 21 /* 0x00200000 disconnect in progress */
#define DONT_SUBMIT ((1UL << US_FLIDX_ABORTING) || \ #define DONT_SUBMIT ((1UL << US_FLIDX_ABORTING) | \
(1UL << US_FLIDX_DISCONNECTING)) (1UL << US_FLIDX_DISCONNECTING))
......
...@@ -278,6 +278,8 @@ extern void usb_put_dev(struct usb_device *dev); ...@@ -278,6 +278,8 @@ extern void usb_put_dev(struct usb_device *dev);
/* mostly for devices emulating SCSI over USB */ /* mostly for devices emulating SCSI over USB */
extern int usb_reset_device(struct usb_device *dev); extern int usb_reset_device(struct usb_device *dev);
extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
/* for drivers using iso endpoints */ /* for drivers using iso endpoints */
extern int usb_get_current_frame_number (struct usb_device *usb_dev); extern int usb_get_current_frame_number (struct usb_device *usb_dev);
......
...@@ -33,7 +33,7 @@ config SECURITY_CAPABILITIES ...@@ -33,7 +33,7 @@ config SECURITY_CAPABILITIES
config SECURITY_ROOTPLUG config SECURITY_ROOTPLUG
tristate "Root Plug Support" tristate "Root Plug Support"
depends on SECURITY!=n depends on USB && SECURITY!=n
help help
This is a sample LSM module that should only be used as such. This is a sample LSM module that should only be used as such.
It prevents any programs running with egid == 0 if a specific It prevents any programs running with egid == 0 if a specific
......
...@@ -54,7 +54,7 @@ MODULE_PARM_DESC(debug, "Debug enabled or not"); ...@@ -54,7 +54,7 @@ MODULE_PARM_DESC(debug, "Debug enabled or not");
#define MY_NAME "root_plug" #define MY_NAME "root_plug"
#endif #endif
#define dbg(fmt, arg...) \ #define root_dbg(fmt, arg...) \
do { \ do { \
if (debug) \ if (debug) \
printk(KERN_DEBUG "%s: %s: " fmt , \ printk(KERN_DEBUG "%s: %s: " fmt , \
...@@ -62,70 +62,21 @@ MODULE_PARM_DESC(debug, "Debug enabled or not"); ...@@ -62,70 +62,21 @@ MODULE_PARM_DESC(debug, "Debug enabled or not");
## arg); \ ## arg); \
} while (0) } while (0)
extern struct list_head usb_bus_list;
extern struct semaphore usb_bus_list_lock;
static int match_device (struct usb_device *dev)
{
int retval = -ENODEV;
int child;
dbg ("looking at vendor %d, product %d\n",
dev->descriptor.idVendor,
dev->descriptor.idProduct);
/* see if this device matches */
if ((dev->descriptor.idVendor == vendor_id) &&
(dev->descriptor.idProduct == product_id)) {
dbg ("found the device!\n");
retval = 0;
goto exit;
}
/* look through all of the children of this device */
for (child = 0; child < dev->maxchild; ++child) {
if (dev->children[child]) {
retval = match_device (dev->children[child]);
if (retval == 0)
goto exit;
}
}
exit:
return retval;
}
static int find_usb_device (void)
{
struct list_head *buslist;
struct usb_bus *bus;
int retval = -ENODEV;
down (&usb_bus_list_lock);
for (buslist = usb_bus_list.next;
buslist != &usb_bus_list;
buslist = buslist->next) {
bus = container_of (buslist, struct usb_bus, bus_list);
retval = match_device(bus->root_hub);
if (retval == 0)
goto exit;
}
exit:
up (&usb_bus_list_lock);
return retval;
}
static int rootplug_bprm_check_security (struct linux_binprm *bprm) static int rootplug_bprm_check_security (struct linux_binprm *bprm)
{ {
dbg ("file %s, e_uid = %d, e_gid = %d\n", struct usb_device *dev;
bprm->filename, bprm->e_uid, bprm->e_gid);
root_dbg("file %s, e_uid = %d, e_gid = %d\n",
bprm->filename, bprm->e_uid, bprm->e_gid);
if (bprm->e_gid == 0) { if (bprm->e_gid == 0) {
if (find_usb_device() != 0) { dev = usb_find_device(vendor_id, product_id);
dbg ("e_gid = 0, and device not found, " if (!dev) {
"task not allowed to run...\n"); root_dbg("e_gid = 0, and device not found, "
"task not allowed to run...\n");
return -EPERM; return -EPERM;
} }
usb_put_dev(dev);
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment