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/
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/
......@@ -756,7 +756,7 @@ static int usb_hub_port_reset(struct usb_device *hub, int port,
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;
......@@ -764,6 +764,8 @@ void usb_hub_port_disable(struct usb_device *hub, int port)
if (ret)
dev_err(hubdev(hub), "cannot disable port %d (err = %d)\n",
port + 1, ret);
return ret;
}
/* USB 2.0 spec, 7.1.7.3 / fig 7-29:
......
......@@ -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
* @dev: the device whose bus is being queried
......@@ -1510,6 +1574,7 @@ EXPORT_SYMBOL(usb_disconnect);
EXPORT_SYMBOL(__usb_get_extra_descriptor);
EXPORT_SYMBOL(usb_find_device);
EXPORT_SYMBOL(usb_get_current_frame_number);
EXPORT_SYMBOL (usb_buffer_alloc);
......
......@@ -23,6 +23,9 @@
*
* 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>
......@@ -75,17 +78,17 @@ static int open_rio(struct inode *inode, struct file *file)
{
struct rio_usb_data *rio = &rio_instance;
lock_kernel();
down(&(rio->lock));
if (rio->isopen || !rio->present) {
unlock_kernel();
up(&(rio->lock));
return -EBUSY;
}
rio->isopen = 1;
init_waitqueue_head(&rio->wait_q);
unlock_kernel();
up(&(rio->lock));
info("Rio opened.");
......@@ -460,7 +463,6 @@ static int probe_rio(struct usb_interface *intf,
return -ENOMEM;
}
rio->present = 1;
rio->rio_dev = dev;
if (!(rio->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
......@@ -481,6 +483,8 @@ static int probe_rio(struct usb_interface *intf,
init_MUTEX(&(rio->lock));
usb_set_intfdata (intf, rio);
rio->present = 1;
return 0;
}
......@@ -525,7 +529,7 @@ static struct usb_driver rio_driver = {
.id_table = rio_table,
};
int usb_rio_init(void)
static int __init usb_rio_init(void)
{
if (usb_register(&rio_driver) < 0)
return -1;
......@@ -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;
......
......@@ -351,6 +351,7 @@ config USB_SERIAL_KOBIL_SCT
- USB TWIN
- KAAN Standard Plus
- KAAN SIM
- SecOVID Reader Plus
- B1 Professional
- KAAN Professional
......
......@@ -21,7 +21,8 @@
* Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus
* (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
* Adapted to 2.5.
......@@ -58,7 +59,7 @@
#include "usb-serial.h"
/* 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_DESC "KOBIL USB Smart Card Terminal Driver (experimental)"
......@@ -66,6 +67,7 @@
#define KOBIL_ADAPTER_B_PRODUCT_ID 0x2011
#define KOBIL_ADAPTER_K_PRODUCT_ID 0x2012
#define KOBIL_USBTWIN_PRODUCT_ID 0x0078
#define KOBIL_KAAN_SIM_PRODUCT_ID 0x0081
#define KOBIL_TIMEOUT 500
#define KOBIL_BUF_LENGTH 300
......@@ -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_K_PRODUCT_ID) },
{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_USBTWIN_PRODUCT_ID) },
{ USB_DEVICE(KOBIL_VENDOR_ID, KOBIL_KAAN_SIM_PRODUCT_ID) },
{ } /* Terminating entry */
};
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 = {
.owner = THIS_MODULE,
.name = "KOBIL USB smart card terminal",
......@@ -161,6 +173,9 @@ static int kobil_startup (struct usb_serial *serial)
case KOBIL_USBTWIN_PRODUCT_ID:
printk(KERN_DEBUG "KOBIL USBTWIN detected\n");
break;
case KOBIL_KAAN_SIM_PRODUCT_ID:
printk(KERN_DEBUG "KOBIL KAAN SIM detected\n");
break;
}
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)
struct usb_serial_port *port = (struct usb_serial_port *) purb->context;
struct tty_struct *tty;
unsigned char *data = purb->transfer_buffer;
char *dbg_data;
// char *dbg_data;
dbg("%s - port %d", __FUNCTION__, port->number);
......@@ -366,6 +381,7 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
if (purb->actual_length) {
// BEGIN DEBUG
/*
dbg_data = (unsigned char *) kmalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL);
if (! dbg_data) {
return;
......@@ -376,6 +392,7 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs)
}
dbg(" <-- %s", dbg_data );
kfree(dbg_data);
*/
// END DEBUG
for (i = 0; i < purb->actual_length; ++i) {
......@@ -438,7 +455,7 @@ static int kobil_write (struct usb_serial_port *port, int from_user,
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))) ||
((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)
int transfer_buffer_length = 8;
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
return -EINVAL;
}
......@@ -549,7 +566,7 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file,
int transfer_buffer_length = 8;
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
return -EINVAL;
}
......@@ -616,7 +633,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
char *settings;
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
return 0;
}
......@@ -727,6 +744,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file,
static int __init kobil_init (void)
{
usb_serial_register (&kobil_device);
usb_register (&kobil_driver);
info(DRIVER_VERSION " " DRIVER_AUTHOR);
info(DRIVER_DESC);
......@@ -737,6 +755,7 @@ static int __init kobil_init (void)
static void __exit kobil_exit (void)
{
usb_deregister (&kobil_driver);
usb_serial_deregister (&kobil_device);
}
......
......@@ -670,7 +670,7 @@ int datafab_transport(Scsi_Cmnd * srb, struct us_data *us)
srb->result = SUCCESS;
} else {
info->sense_key = UNIT_ATTENTION;
srb->result = CHECK_CONDITION << 1;
srb->result = SAM_STAT_CHECK_CONDITION;
}
return rc;
}
......
......@@ -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);
buffer[32] = '\0';
US_DEBUGP("String returned from FC init is: %s\n", buffer);
......@@ -411,7 +411,7 @@ freecom_init (struct us_data *us)
*/
/* 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);
US_DEBUGP("result from activate reset is %d\n", result);
......@@ -419,7 +419,7 @@ freecom_init (struct us_data *us)
mdelay(250);
/* 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);
US_DEBUGP("result from clear reset is %d\n", result);
......
......@@ -50,7 +50,7 @@ int usb_stor_euscsi_init(struct us_data *us)
int result;
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,
0x01, 0x0, &data, 0x1, 5*HZ);
US_DEBUGP("-- result is %d\n", result);
......
......@@ -39,6 +39,7 @@
#include <linux/config.h>
#include "usb.h"
#include "transport.h"
/* This places the Shuttle/SCM USB<->SCSI bridge devices in multi-target
* mode */
......
......@@ -558,7 +558,7 @@ void isd200_invoke_transport( struct us_data *us,
case USB_STOR_TRANSPORT_GOOD:
/* Indicate a good result */
srb->result = GOOD << 1;
srb->result = SAM_STAT_GOOD;
break;
case USB_STOR_TRANSPORT_FAILED:
......@@ -598,11 +598,11 @@ void isd200_invoke_transport( struct us_data *us,
}
if (result == ISD200_GOOD) {
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 ((srb->sense_buffer[2] & 0xf) == 0x0)
srb->result = GOOD << 1;
srb->result = SAM_STAT_GOOD;
} else
srb->result = DID_ERROR << 16;
}
......@@ -611,7 +611,7 @@ void isd200_invoke_transport( struct us_data *us,
* condition, show that in the result code
*/
if (transferStatus == USB_STOR_TRANSPORT_FAILED)
srb->result = CHECK_CONDITION << 1;
srb->result = SAM_STAT_CHECK_CONDITION;
}
#ifdef CONFIG_USB_STORAGE_DEBUG
......@@ -1185,7 +1185,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
/* copy InquiryData */
isd200_data_copy(srb, (char *) &info->InquiryData, srb->request_bufflen);
srb->result = GOOD << 1;
srb->result = SAM_STAT_GOOD;
sendToTransport = FALSE;
break;
......@@ -1205,7 +1205,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = 0;
} else {
US_DEBUGP(" Media Status not supported, just report okay\n");
srb->result = GOOD << 1;
srb->result = SAM_STAT_GOOD;
sendToTransport = FALSE;
}
break;
......@@ -1226,7 +1226,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = 0;
} else {
US_DEBUGP(" Media Status not supported, just report okay\n");
srb->result = GOOD << 1;
srb->result = SAM_STAT_GOOD;
sendToTransport = FALSE;
}
break;
......@@ -1252,7 +1252,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = sizeof(struct read_capacity_data);
isd200_data_copy(srb, (char *) &readCapacityData, srb->request_bufflen);
srb->result = GOOD << 1;
srb->result = SAM_STAT_GOOD;
sendToTransport = FALSE;
}
break;
......@@ -1336,7 +1336,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = 0;
} else {
US_DEBUGP(" Not removeable media, just report okay\n");
srb->result = GOOD << 1;
srb->result = SAM_STAT_GOOD;
sendToTransport = FALSE;
}
break;
......@@ -1365,7 +1365,7 @@ int isd200_scsi_to_ata(Scsi_Cmnd *srb, struct us_data *us,
srb->request_bufflen = 0;
} else {
US_DEBUGP(" Nothing to do, just report okay\n");
srb->result = GOOD << 1;
srb->result = SAM_STAT_GOOD;
sendToTransport = FALSE;
}
break;
......
......@@ -611,7 +611,7 @@ int jumpshot_transport(Scsi_Cmnd * srb, struct us_data *us)
srb->result = SUCCESS;
} else {
info->sense_key = UNIT_ATTENTION;
srb->result = CHECK_CONDITION << 1;
srb->result = SAM_STAT_CHECK_CONDITION;
}
return rc;
}
......
......@@ -137,8 +137,7 @@ void usb_stor_qic157_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
usb_stor_invoke_transport(srb, us);
if (srb->result == GOOD << 1) {
if (srb->result == SAM_STAT_GOOD) {
/* fix the INQUIRY data if necessary */
fix_inquiry_data(srb);
}
......@@ -210,7 +209,7 @@ void usb_stor_ATAPI_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
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 */
if (old_cmnd == MODE_SENSE)
......@@ -307,7 +306,7 @@ void usb_stor_ufi_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
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 */
if (old_cmnd == MODE_SENSE)
......@@ -376,7 +375,7 @@ void usb_stor_transparent_scsi_command(Scsi_Cmnd *srb, struct us_data *us)
/* send the command to the transport layer */
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 */
if ((us->flags & US_FL_MODE_XLATE) && (old_cmnd == MODE_SENSE))
......
......@@ -219,7 +219,7 @@ static int usb_storage_device_reset( Scsi_Cmnd *srb )
int state = atomic_read(&us->sm_state);
int result;
US_DEBUGP("device_reset() called\n" );
US_DEBUGP("%s called\n", __FUNCTION__);
if (state != US_STATE_IDLE) {
printk(KERN_ERR USB_STORAGE "Error in %s: "
"invalid state %d\n", __FUNCTION__, state);
......@@ -245,39 +245,49 @@ static int usb_storage_device_reset( Scsi_Cmnd *srb )
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
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 */
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;
/* we use the usb_reset_device() function to handle this for us */
US_DEBUGP("bus_reset() called\n");
US_DEBUGP("%s called\n", __FUNCTION__);
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);
us = (struct us_data *)srb->device->host->hostdata[0];
/* The USB subsystem doesn't handle synchronisation between
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
if ( us->pusb_dev->actconfig->desc.bNumInterfaces == 1) {
/* attempt to reset the port */
if (us->pusb_dev->actconfig->desc.bNumInterfaces == 1) {
/* lock the device and attempt to reset the port */
down(&(us->dev_semaphore));
result = usb_reset_device(us->pusb_dev);
up(&(us->dev_semaphore));
US_DEBUGP("usb_reset_device returns %d\n", result);
} else {
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);
atomic_set(&us->sm_state, US_STATE_IDLE);
return result < 0 ? FAILED : SUCCESS;
}
......
......@@ -75,7 +75,7 @@
* 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.
* stopped. The timeout callback routine does much the same thing.
*
* 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
......@@ -110,15 +110,29 @@ static void usb_stor_blocking_completion(struct urb *urb, struct pt_regs *regs)
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
*
* All URBs from the usb-storage driver involved in handling a queued scsi
* command _must_ pass through this function (or something like it) for the
* 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 timer_list to_timer;
int status;
/* don't submit URBS during abort/disconnect processing */
......@@ -156,23 +170,41 @@ static int usb_stor_msg_common(struct us_data *us)
}
}
/* 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_completion(&urb_done);
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 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,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size)
void *data, u16 size, int timeout)
{
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 */
us->dr->bRequestType = requesttype;
us->dr->bRequest = request;
......@@ -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,
(unsigned char*) us->dr, data, size,
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 */
if (status == 0)
......@@ -192,9 +224,9 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
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.
/* This is a version of usb_clear_halt() that allows early termination and
* 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.
*
* 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
......@@ -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,
USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
endp, NULL, 0); /* note: no 3*HZ timeout */
US_DEBUGP("usb_stor_clear_halt: result=%d\n", result);
/* this is a failure case */
if (result < 0)
return result;
endp, NULL, 0, 3*HZ);
/* reset the toggles and endpoint flags */
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)
usb_settoggle(us->pusb_dev, usb_pipeendpoint(pipe),
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,
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);
result = usb_stor_msg_common(us, 0);
return interpret_urb_result(us, pipe, size, result,
us->current_urb->actual_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,
maxp, usb_stor_blocking_completion, NULL,
us->ep_bInterval);
result = usb_stor_msg_common(us);
result = usb_stor_msg_common(us, 0);
return interpret_urb_result(us, pipe, length, result,
us->current_urb->actual_length);
......@@ -368,7 +396,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe,
/* 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);
result = usb_stor_msg_common(us, 0);
/* store the actual length of the data transferred */
if (act_len)
......@@ -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 */
/* What if we want to abort during the reset? */
if (result == USB_STOR_TRANSPORT_ERROR) {
US_DEBUGP("-- transport indicates error, resetting\n");
us->transport_reset(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_cmd_len;
unsigned char old_cmnd[MAX_COMMAND_SIZE];
unsigned long old_serial_number;
US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
......@@ -594,6 +622,10 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
old_sg = srb->use_sg;
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 */
temp_result = us->transport(us->srb, 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_bufflen = old_request_bufflen;
srb->use_sg = old_sg;
srb->serial_number = old_serial_number;
srb->sc_data_direction = old_sc_data_direction;
srb->cmd_len = old_cmd_len;
memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
......@@ -616,10 +649,8 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
* multi-target device, since failure of an
* auto-sense is perfectly valid
*/
if (!(us->flags & US_FL_SCM_MULT_TARG)) {
/* What if we try to abort during the reset? */
if (!(us->flags & US_FL_SCM_MULT_TARG))
us->transport_reset(us);
}
srb->result = DID_ERROR << 16;
return;
}
......@@ -638,19 +669,19 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
#endif
/* 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 ((srb->sense_buffer[2] & 0xf) == 0x0)
srb->result = GOOD << 1;
srb->result = SAM_STAT_GOOD;
} 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
* condition, show that in the result code
*/
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.
* 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)
unsigned char data;
int result;
/* Issue the command -- use usb_control_msg() because this is
* not a scsi queued-command. Also note that at this point the
* cached pipe values have not yet been stored. */
result = usb_control_msg(us->pusb_dev,
usb_rcvctrlpipe(us->pusb_dev, 0),
/* issue the command */
result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
US_BULK_GET_MAX_LUN,
USB_DIR_IN | USB_TYPE_CLASS |
USB_RECIP_INTERFACE,
......@@ -982,43 +1010,40 @@ static int usb_stor_reset_common(struct us_data *us,
u16 value, u16 index, void *data, u16 size)
{
int result;
int result2;
/* A 20-second timeout may seem rather long, but a LaCie
* StudioDrive USB2 device takes 16+ seconds to get going
* following a powerup or USB attach event. */
/* Use usb_control_msg() because this is not a queued-command */
result = usb_control_msg(us->pusb_dev, us->send_ctrl_pipe,
result = usb_stor_control_msg(us, us->send_ctrl_pipe,
request, requesttype, value, index, data, size,
20*HZ);
if (result < 0)
goto Done;
if (result < 0) {
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);
schedule_timeout(HZ*6);
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");
result = usb_clear_halt(us->pusb_dev, us->recv_bulk_pipe);
if (result < 0)
goto Done;
result = usb_stor_clear_halt(us, us->recv_bulk_pipe);
US_DEBUGP("Soft reset: clearing bulk-out endpoint halt\n");
result = usb_clear_halt(us->pusb_dev, us->send_bulk_pipe);
Done:
result2 = usb_stor_clear_halt(us, us->send_bulk_pipe);
/* return a result code based on the result of the control message */
if (result < 0) {
US_DEBUGP("Soft reset failed: %d\n", result);
result = FAILED;
} else {
US_DEBUGP("Soft reset done\n");
result = SUCCESS;
if (result < 0 || result2 < 0) {
US_DEBUGP("Soft reset failed\n");
return FAILED;
}
return result;
US_DEBUGP("Soft reset done\n");
return SUCCESS;
}
/* This issues a CB[I] Reset to the device in question
......
......@@ -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,
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,
u8 request, u8 requesttype, u16 value, u16 index,
void *data, u16 size);
......
......@@ -374,7 +374,7 @@ static int usb_stor_control_thread(void * __us)
memcpy(us->srb->sense_buffer,
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
......@@ -387,7 +387,7 @@ static int usb_stor_control_thread(void * __us)
US_DEBUGP("Faking INQUIRY command\n");
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! */
......@@ -412,9 +412,11 @@ static int usb_stor_control_thread(void * __us)
US_DEBUGP("scsi command aborted\n");
}
/* in case an abort request was received after the command
* completed, we must use a separate test to see whether
* we need to signal that the abort has finished */
/* If an abort request was received we need to signal that
* the abort has finished. The proper test for this is
* 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)
complete(&(us->notify));
......@@ -715,7 +717,6 @@ static int storage_probe(struct usb_interface *intf,
us->transport_name = "Bulk";
us->transport = usb_stor_Bulk_transport;
us->transport_reset = usb_stor_Bulk_reset;
us->max_lun = usb_stor_Bulk_max_lun(us);
break;
#ifdef CONFIG_USB_STORAGE_HP8200e
......@@ -842,6 +843,10 @@ static int storage_probe(struct usb_interface *intf,
if (usb_stor_allocate_urbs(us))
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
* host definition, and register with the higher SCSI layers
......
......@@ -82,7 +82,7 @@ struct us_unusual_dev {
#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) || \
#define DONT_SUBMIT ((1UL << US_FLIDX_ABORTING) | \
(1UL << US_FLIDX_DISCONNECTING))
......
......@@ -278,6 +278,8 @@ extern void usb_put_dev(struct usb_device *dev);
/* mostly for devices emulating SCSI over USB */
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 */
extern int usb_get_current_frame_number (struct usb_device *usb_dev);
......
......@@ -33,7 +33,7 @@ config SECURITY_CAPABILITIES
config SECURITY_ROOTPLUG
tristate "Root Plug Support"
depends on SECURITY!=n
depends on USB && SECURITY!=n
help
This is a sample LSM module that should only be used as such.
It prevents any programs running with egid == 0 if a specific
......
......@@ -54,7 +54,7 @@ MODULE_PARM_DESC(debug, "Debug enabled or not");
#define MY_NAME "root_plug"
#endif
#define dbg(fmt, arg...) \
#define root_dbg(fmt, arg...) \
do { \
if (debug) \
printk(KERN_DEBUG "%s: %s: " fmt , \
......@@ -62,70 +62,21 @@ MODULE_PARM_DESC(debug, "Debug enabled or not");
## arg); \
} 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)
{
dbg ("file %s, e_uid = %d, e_gid = %d\n",
struct usb_device *dev;
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 (find_usb_device() != 0) {
dbg ("e_gid = 0, and device not found, "
dev = usb_find_device(vendor_id, product_id);
if (!dev) {
root_dbg("e_gid = 0, and device not found, "
"task not allowed to run...\n");
return -EPERM;
}
usb_put_dev(dev);
}
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