Re: [usb-storage] Re: RFC drivers/usb/storage/libusual

From: Pete Zaitcev
Date: Sat Oct 08 2005 - 02:39:02 EST


On Fri, 7 Oct 2005 10:41:14 -0400 (EDT), Alan Stern <stern@xxxxxxxxxxxxxxxxxxx> wrote:

> > --- linux-2.6.14-rc2/drivers/usb/storage/usb.h 2005-09-24 20:32:56.000000000 -0700
> > +++ linux-2.6.14-rc2-wip/drivers/usb/storage/usb.h 2005-10-06 21:37:10.000000000 -0700
> ...
> > -/* 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 */

> I would prefer to keep these definitions in the usb-storage driver. They
> refer to dynamic aspects of an individual device, not static blacklist or
> ID-matching for all devices of a particular type. As such, they are of no
> interest to ub or libusual.

OK

> > + * Observe that usb-storage blatantly mixes set_bit() and normal
> > + * shift and mask operations on flags, which is strictly illegal.
> > + * And it probably even works for all flags except GO_SLOW and NO_WP_DETECT.

> Once the device is running, the shift/mask operations are used _only_ for
> reading, never for writing.

OK

How about now?

---

diff -urpN -X dontdiff linux-2.6.14-rc3/drivers/block/Kconfig linux-2.6.14-rc3-wip/drivers/block/Kconfig
--- linux-2.6.14-rc3/drivers/block/Kconfig 2005-10-07 21:27:50.000000000 -0700
+++ linux-2.6.14-rc3-wip/drivers/block/Kconfig 2005-10-07 23:36:31.000000000 -0700
@@ -358,7 +358,8 @@ config BLK_DEV_UB
This driver supports certain USB attached storage devices
such as flash keys.

- Warning: Enabling this cripples the usb-storage driver.
+ If you enable this driver, it is recommended to avoid conflicts
+ with usb-storage by enabling USB_LIBUSUAL.

If unsure, say N.

diff -urpN -X dontdiff linux-2.6.14-rc3/drivers/block/ub.c linux-2.6.14-rc3-wip/drivers/block/ub.c
--- linux-2.6.14-rc3/drivers/block/ub.c 2005-10-07 21:27:51.000000000 -0700
+++ linux-2.6.14-rc3-wip/drivers/block/ub.c 2005-10-07 23:38:59.000000000 -0700
@@ -29,6 +29,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
+#include <linux/usb_usual.h>
#include <linux/blkdev.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/timer.h>
@@ -110,11 +111,13 @@
* Definitions which have to be scattered once we understand the layout better.
*/

+#if 0 /* Subclass and protocol are in usb_usual.h now. */
/* Transport (despite PR in the name) */
#define US_PR_BULK 0x50 /* bulk only */

/* Protocol */
#define US_SC_SCSI 0x06 /* Transparent */
+#endif

/*
* This many LUNs per USB device.
@@ -422,13 +425,18 @@ static int ub_probe_lun(struct ub_dev *s

/*
*/
+#ifdef CONFIG_USB_LIBUSUAL
+
+#define ub_usb_ids storage_usb_ids
+#else
+
static struct usb_device_id ub_usb_ids[] = {
- // { USB_DEVICE_VER(0x0781, 0x0002, 0x0009, 0x0009) }, /* SDDR-31 */
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
{ }
};

MODULE_DEVICE_TABLE(usb, ub_usb_ids);
+#endif /* CONFIG_USB_LIBUSUAL */

/*
* Find me a way to identify "next free minor" for add_disk(),
@@ -2172,6 +2180,9 @@ static int ub_probe(struct usb_interface
int rc;
int i;

+ if (USB_US_TYPE(dev_id->driver_info) != USB_US_TYPE_UB)
+ return -ENXIO;
+
rc = -ENOMEM;
if ((sc = kmalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL)
goto err_core;
@@ -2472,6 +2483,8 @@ static int __init ub_init(void)
{
int rc;

+ usb_usual_set_present(USB_US_TYPE_UB, 1);
+
if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)
goto err_regblkdev;
devfs_mk_dir(DEVFS_NAME);
@@ -2485,6 +2498,7 @@ err_register:
devfs_remove(DEVFS_NAME);
unregister_blkdev(UB_MAJOR, DRV_NAME);
err_regblkdev:
+ usb_usual_set_present(USB_US_TYPE_UB, 0);
return rc;
}

@@ -2494,6 +2508,7 @@ static void __exit ub_exit(void)

devfs_remove(DEVFS_NAME);
unregister_blkdev(UB_MAJOR, DRV_NAME);
+ usb_usual_set_present(USB_US_TYPE_UB, 0);
}

module_init(ub_init);
diff -urpN -X dontdiff linux-2.6.14-rc3/drivers/usb/storage/Kconfig linux-2.6.14-rc3-wip/drivers/usb/storage/Kconfig
--- linux-2.6.14-rc3/drivers/usb/storage/Kconfig 2005-10-07 21:28:13.000000000 -0700
+++ linux-2.6.14-rc3-wip/drivers/usb/storage/Kconfig 2005-10-07 23:36:31.000000000 -0700
@@ -123,3 +123,17 @@ config USB_STORAGE_ONETOUCH
hard drive's as an input device. An action can be associated with
this input in any keybinding software. (e.g. gnome's keyboard short-
cuts)
+
+config USB_LIBUSUAL
+ bool "The shared table of common (or usual) storage devices"
+ depends on USB
+ help
+ This module contains a table of common (or usual) devices
+ for usb-storage and ub drivers, and allows to switch binding
+ of these devices without rebuilding modules.
+
+ Typical syntax of /etc/modprobe.conf is:
+
+ options libusual bias="ub"
+
+ If unsure, say N.
diff -urpN -X dontdiff linux-2.6.14-rc3/drivers/usb/storage/libusual.c linux-2.6.14-rc3-wip/drivers/usb/storage/libusual.c
--- linux-2.6.14-rc3/drivers/usb/storage/libusual.c 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.14-rc3-wip/drivers/usb/storage/libusual.c 2005-10-07 23:36:31.000000000 -0700
@@ -0,0 +1,257 @@
+/*
+ * libusual
+ *
+ * The libusual contains the table of devices common for ub and usb-storage.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb_usual.h>
+#include <linux/vmalloc.h>
+
+/*
+ */
+#define USU_MOD_FL_THREAD 1 /* Thread is running */
+#define USU_MOD_FL_PRESENT 2 /* The module is loaded */
+
+struct mod_status {
+ unsigned long fls;
+};
+
+static struct mod_status stat[3];
+static DEFINE_SPINLOCK(usu_lock);
+
+/*
+ */
+#define USB_US_DEFAULT_BIAS USB_US_TYPE_STOR
+
+#define BIAS_NAME_SIZE (sizeof("usb-storage"))
+static char bias[BIAS_NAME_SIZE];
+static const char *bias_names[3] = { "none", "usb-storage", "ub" };
+
+static DECLARE_MUTEX_LOCKED(usu_init_notify);
+static DECLARE_COMPLETION(usu_end_notify);
+static atomic_t total_threads = ATOMIC_INIT(0);
+
+static int usu_probe_thread(void *arg);
+static void bias_storage_ids(int to_bias);
+static int parse_bias(const char *bias_s);
+
+/*
+ * The UNUSUAL_DEV_FL is a version of UNUSUAL_DEV for "flags-only"
+ * devices which only need an entry in usb_device_id array.
+ * It keeps arguments for vendor and product names because
+ * they are valuable comments, even though they are not used by the code.
+ */
+
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+ vendorName, productName,useProtocol, useTransport, \
+ initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
+ .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+#define USUAL_DEV(useProto, useTrans, useType) \
+{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+ .driver_info = ((useType)<<24) }
+
+struct usb_device_id storage_usb_ids [] = {
+# include "unusual_devs.h"
+ { } /* Terminating entry */
+};
+
+#undef USUAL_DEV
+#undef UNUSUAL_DEV
+
+MODULE_DEVICE_TABLE(usb, storage_usb_ids);
+EXPORT_SYMBOL(storage_usb_ids);
+
+/*
+ * @present: boolean, module is present
+ */
+void usb_usual_set_present(int type, int present)
+{
+ struct mod_status *st;
+ unsigned long flags;
+
+ if (type <= 0 || type >= 3)
+ return;
+ st = &stat[type];
+ spin_lock_irqsave(&usu_lock, flags);
+ st->fls &= ~USU_MOD_FL_PRESENT;
+ st->fls |= present * USU_MOD_FL_PRESENT;
+ spin_unlock_irqrestore(&usu_lock, flags);
+}
+EXPORT_SYMBOL(usb_usual_set_present);
+
+/*
+ */
+static int usu_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ int type = USB_US_TYPE(id->driver_info);
+ int rc;
+ unsigned long flags;
+
+ if (type == 0)
+ return -ENXIO;
+
+ spin_lock_irqsave(&usu_lock, flags);
+ if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) {
+ spin_unlock_irqrestore(&usu_lock, flags);
+ return -ENXIO;
+ }
+ stat[type].fls |= USU_MOD_FL_THREAD;
+ spin_unlock_irqrestore(&usu_lock, flags);
+
+ rc = kernel_thread(usu_probe_thread, (void*)type, CLONE_VM);
+ if (rc < 0) {
+ printk(KERN_WARNING "libusual: "
+ "Unable to start the thread for %s: %d\n",
+ bias_names[type], rc);
+ spin_lock_irqsave(&usu_lock, flags);
+ stat[type].fls &= ~USU_MOD_FL_THREAD;
+ spin_unlock_irqrestore(&usu_lock, flags);
+ return rc; /* Not being -ENXIO causes a message printed */
+ }
+ atomic_inc(&total_threads);
+
+ return -ENXIO;
+}
+
+static void usu_disconnect(struct usb_interface *intf)
+{
+ ; /* We should not be here. */
+}
+
+static struct usb_driver usu_driver = {
+ .owner = THIS_MODULE,
+ .name = "libusual",
+ .probe = usu_probe,
+ .disconnect = usu_disconnect,
+ .id_table = storage_usb_ids,
+};
+
+/*
+ * A whole new thread for a purpose of request_module seems quite stupid.
+ * The request_module forks once inside again. However, if we attempt
+ * to load a storage module from our own modprobe thread, that module
+ * references our symbols, which cannot be resolved until our module is
+ * initialized. I wish there was a way to wait for the end of initialization.
+ * The module notifier reports MODULE_STATE_COMING only.
+ * So, we wait until module->init ends as the next best thing.
+ */
+static int usu_probe_thread(void *arg)
+{
+ int type = (unsigned long) arg;
+ struct mod_status *st = &stat[type];
+ int rc;
+ unsigned long flags;
+
+ daemonize("libusual_%d", type); /* "usb-storage" is kinda too long */
+
+ /* A completion does not work here because it's counted. */
+ down(&usu_init_notify);
+ up(&usu_init_notify);
+
+ rc = request_module(bias_names[type]);
+/* P3 */ printk("request_module(%s) ended with %d\n", bias_names[type], rc);
+
+ spin_lock_irqsave(&usu_lock, flags);
+ if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) {
+ /*
+ * This should not happen, but let us keep tabs on it.
+ */
+ printk(KERN_NOTICE "libusual: "
+ "modprobe for %s succeeded, but module is not present\n",
+ bias_names[type]);
+ }
+ st->fls &= ~USU_MOD_FL_THREAD;
+ spin_unlock_irqrestore(&usu_lock, flags);
+ complete_and_exit(&usu_end_notify, 0);
+}
+
+/*
+ */
+static void bias_storage_ids(int to_bias)
+{
+ struct usb_device_id *id;
+
+ for (id = storage_usb_ids;
+ id->idVendor || id->bDeviceClass || id->bInterfaceClass ||
+ id->driver_info;
+ id++) {
+ if (USB_US_TYPE(id->driver_info) == 0) {
+ id->driver_info |= to_bias << 24;
+ }
+ }
+}
+
+/*
+ */
+static int __init usb_usual_init(void)
+{
+ int usb_usual_bias;
+ int rc;
+
+ bias[BIAS_NAME_SIZE-1] = 0;
+ usb_usual_bias = parse_bias(bias);
+ bias_storage_ids(usb_usual_bias);
+
+ if ((rc = usb_register(&usu_driver)) != 0) {
+ up(&usu_init_notify);
+ return rc;
+ }
+ up(&usu_init_notify);
+ return 0;
+}
+
+static void __exit usb_usual_exit(void)
+{
+ /*
+ * We do not check for any drivers present, because
+ * they keep us pinned with symbol references.
+ */
+
+ usb_deregister(&usu_driver);
+
+ while (atomic_read(&total_threads) > 0) {
+ wait_for_completion(&usu_end_notify);
+ atomic_dec(&total_threads);
+ }
+}
+
+/*
+ * Validate and accept the bias parameter.
+ * Maybe make an sysfs method later. XXX
+ */
+static int parse_bias(const char *bias_s)
+{
+ int i;
+ int bias_n = 0;
+
+ if (bias_s[0] == 0 || bias_s[0] == ' ') {
+ bias_n = USB_US_DEFAULT_BIAS;
+ } else {
+ for (i = 1; i < 3; i++) {
+ if (strcmp(bias_s, bias_names[i]) == 0) {
+ bias_n = i;
+ break;
+ }
+ }
+ if (bias_n == 0) {
+ bias_n = USB_US_DEFAULT_BIAS;
+ printk(KERN_INFO
+ "libusual: unknown bias \"%s\", using \"%s\"\n",
+ bias_s, bias_names[bias_n]);
+ }
+ }
+ return bias_n;
+}
+
+module_init(usb_usual_init);
+module_exit(usb_usual_exit);
+
+module_param_string(bias, bias, BIAS_NAME_SIZE, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(bias, "Bias to usb-storage or ub");
+
+MODULE_LICENSE("GPL");
diff -urpN -X dontdiff linux-2.6.14-rc3/drivers/usb/storage/Makefile linux-2.6.14-rc3-wip/drivers/usb/storage/Makefile
--- linux-2.6.14-rc3/drivers/usb/storage/Makefile 2005-10-07 21:28:13.000000000 -0700
+++ linux-2.6.14-rc3-wip/drivers/usb/storage/Makefile 2005-10-07 23:36:31.000000000 -0700
@@ -22,3 +22,7 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_ONE

usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \
initializers.o $(usb-storage-obj-y)
+
+ifneq ($(CONFIG_USB_LIBUSUAL),)
+ obj-$(CONFIG_USB) += libusual.o
+endif
diff -urpN -X dontdiff linux-2.6.14-rc3/drivers/usb/storage/protocol.h linux-2.6.14-rc3-wip/drivers/usb/storage/protocol.h
--- linux-2.6.14-rc3/drivers/usb/storage/protocol.h 2005-06-17 12:48:29.000000000 -0700
+++ linux-2.6.14-rc3-wip/drivers/usb/storage/protocol.h 2005-10-07 23:36:31.000000000 -0700
@@ -41,20 +41,6 @@
#ifndef _PROTOCOL_H_
#define _PROTOCOL_H_

-/* Sub Classes */
-
-#define US_SC_RBC 0x01 /* Typically, flash devices */
-#define US_SC_8020 0x02 /* CD-ROM */
-#define US_SC_QIC 0x03 /* QIC-157 Tapes */
-#define US_SC_UFI 0x04 /* Floppy */
-#define US_SC_8070 0x05 /* Removable media */
-#define US_SC_SCSI 0x06 /* Transparent */
-#define US_SC_ISD200 0x07 /* ISD200 ATA */
-#define US_SC_MIN US_SC_RBC
-#define US_SC_MAX US_SC_ISD200
-
-#define US_SC_DEVICE 0xff /* Use device's value */
-
/* Protocol handling routines */
extern void usb_stor_ATAPI_command(struct scsi_cmnd*, struct us_data*);
extern void usb_stor_qic157_command(struct scsi_cmnd*, struct us_data*);
diff -urpN -X dontdiff linux-2.6.14-rc3/drivers/usb/storage/transport.h linux-2.6.14-rc3-wip/drivers/usb/storage/transport.h
--- linux-2.6.14-rc3/drivers/usb/storage/transport.h 2005-09-13 01:06:21.000000000 -0700
+++ linux-2.6.14-rc3-wip/drivers/usb/storage/transport.h 2005-10-07 23:36:31.000000000 -0700
@@ -44,36 +44,6 @@
#include <linux/config.h>
#include <linux/blkdev.h>

-/* Protocols */
-
-#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */
-#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */
-#define US_PR_BULK 0x50 /* bulk only */
-#ifdef CONFIG_USB_STORAGE_USBAT
-#define US_PR_SCM_ATAPI 0x80 /* SCM-ATAPI bridge */
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR09
-#define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */
-#endif
-#ifdef CONFIG_USB_STORAGE_SDDR55
-#define US_PR_SDDR55 0x82 /* SDDR-55 (made up) */
-#endif
-#define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */
-
-#ifdef CONFIG_USB_STORAGE_FREECOM
-#define US_PR_FREECOM 0xf1 /* Freecom */
-#endif
-
-#ifdef CONFIG_USB_STORAGE_DATAFAB
-#define US_PR_DATAFAB 0xf2 /* Datafab chipsets */
-#endif
-
-#ifdef CONFIG_USB_STORAGE_JUMPSHOT
-#define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */
-#endif
-
-#define US_PR_DEVICE 0xff /* Use device's value */
-
/*
* Bulk only data structures
*/
diff -urpN -X dontdiff linux-2.6.14-rc3/drivers/usb/storage/unusual_devs.h linux-2.6.14-rc3-wip/drivers/usb/storage/unusual_devs.h
--- linux-2.6.14-rc3/drivers/usb/storage/unusual_devs.h 2005-10-07 21:28:14.000000000 -0700
+++ linux-2.6.14-rc3-wip/drivers/usb/storage/unusual_devs.h 2005-10-07 23:36:31.000000000 -0700
@@ -1093,3 +1093,27 @@ UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x
US_SC_SCSI, US_PR_SDDR55, NULL,
US_FL_SINGLE_LUN),
#endif
+
+/* Control/Bulk transport for all SubClass values */
+USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_QIC, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_UFI, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8070, US_PR_CB, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_SCSI, US_PR_CB, USB_US_TYPE_STOR),
+
+/* Control/Bulk/Interrupt transport for all SubClass values */
+USUAL_DEV(US_SC_RBC, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8020, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_QIC, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_UFI, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8070, US_PR_CBI, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_SCSI, US_PR_CBI, USB_US_TYPE_STOR),
+
+/* Bulk-only transport for all SubClass values */
+USUAL_DEV(US_SC_RBC, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8020, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_QIC, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_UFI, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_8070, US_PR_BULK, USB_US_TYPE_STOR),
+USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0),
diff -urpN -X dontdiff linux-2.6.14-rc3/drivers/usb/storage/usb.c linux-2.6.14-rc3-wip/drivers/usb/storage/usb.c
--- linux-2.6.14-rc3/drivers/usb/storage/usb.c 2005-10-07 21:28:14.000000000 -0700
+++ linux-2.6.14-rc3-wip/drivers/usb/storage/usb.c 2005-10-07 23:36:31.000000000 -0700
@@ -116,49 +116,33 @@ static int storage_probe(struct usb_inte

static void storage_disconnect(struct usb_interface *iface);

-/* The entries in this table, except for final ones here
- * (USB_MASS_STORAGE_CLASS and the empty entry), correspond,
- * line for line with the entries of us_unsuaul_dev_list[].
+/*
+ * The entries in this table correspond, line for line,
+ * with the entries of us_unusual_dev_list[].
*/
+#ifndef CONFIG_USB_LIBUSUAL

#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
vendorName, productName,useProtocol, useTransport, \
initFunction, flags) \
-{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax) }
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \
+ .driver_info = (flags)|(USB_US_TYPE_STOR<<24) }
+
+#define USUAL_DEV(useProto, useTrans, useType) \
+{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \
+ .driver_info = (USB_US_TYPE_STOR<<24) }

static struct usb_device_id storage_usb_ids [] = {

# include "unusual_devs.h"
#undef UNUSUAL_DEV
- /* Control/Bulk transport for all SubClass values */
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CB) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CB) },
-
- /* Control/Bulk/Interrupt transport for all SubClass values */
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_CBI) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_CBI) },
-
- /* Bulk-only transport for all SubClass values */
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_RBC, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8020, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },
- { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
-
+#undef USUAL_DEV
/* Terminating entry */
{ }
};

MODULE_DEVICE_TABLE (usb, storage_usb_ids);
+#endif /* CONFIG_USB_LIBUSUAL */

/* This is the list of devices we recognize, along with their flag data */

@@ -171,7 +155,6 @@ MODULE_DEVICE_TABLE (usb, storage_usb_id
* are free to use as many characters as you like.
*/

-#undef UNUSUAL_DEV
#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \
vendor_name, product_name, use_protocol, use_transport, \
init_function, Flags) \
@@ -181,53 +164,18 @@ MODULE_DEVICE_TABLE (usb, storage_usb_id
.useProtocol = use_protocol, \
.useTransport = use_transport, \
.initFunction = init_function, \
- .flags = Flags, \
+}
+
+#define USUAL_DEV(use_protocol, use_transport, use_type) \
+{ \
+ .useProtocol = use_protocol, \
+ .useTransport = use_transport, \
}

static struct us_unusual_dev us_unusual_dev_list[] = {
# include "unusual_devs.h"
# undef UNUSUAL_DEV
- /* Control/Bulk transport for all SubClass values */
- { .useProtocol = US_SC_RBC,
- .useTransport = US_PR_CB},
- { .useProtocol = US_SC_8020,
- .useTransport = US_PR_CB},
- { .useProtocol = US_SC_QIC,
- .useTransport = US_PR_CB},
- { .useProtocol = US_SC_UFI,
- .useTransport = US_PR_CB},
- { .useProtocol = US_SC_8070,
- .useTransport = US_PR_CB},
- { .useProtocol = US_SC_SCSI,
- .useTransport = US_PR_CB},
-
- /* Control/Bulk/Interrupt transport for all SubClass values */
- { .useProtocol = US_SC_RBC,
- .useTransport = US_PR_CBI},
- { .useProtocol = US_SC_8020,
- .useTransport = US_PR_CBI},
- { .useProtocol = US_SC_QIC,
- .useTransport = US_PR_CBI},
- { .useProtocol = US_SC_UFI,
- .useTransport = US_PR_CBI},
- { .useProtocol = US_SC_8070,
- .useTransport = US_PR_CBI},
- { .useProtocol = US_SC_SCSI,
- .useTransport = US_PR_CBI},
-
- /* Bulk-only transport for all SubClass values */
- { .useProtocol = US_SC_RBC,
- .useTransport = US_PR_BULK},
- { .useProtocol = US_SC_8020,
- .useTransport = US_PR_BULK},
- { .useProtocol = US_SC_QIC,
- .useTransport = US_PR_BULK},
- { .useProtocol = US_SC_UFI,
- .useTransport = US_PR_BULK},
- { .useProtocol = US_SC_8070,
- .useTransport = US_PR_BULK},
- { .useProtocol = US_SC_SCSI,
- .useTransport = US_PR_BULK},
+# undef USUAL_DEV

/* Terminating entry */
{ NULL }
@@ -469,15 +417,21 @@ static int associate_dev(struct us_data
}
return 0;
}
+
+/* Find an unusual_dev descriptor (always succeeds in the current code) */
+static struct us_unusual_dev *find_unusual_entry(const struct usb_device_id *id)
+{
+ const int id_index = id - storage_usb_ids;
+ return &us_unusual_dev_list[id_index];
+}

/* Get the unusual_devs entries and the string descriptors */
-static void get_device_info(struct us_data *us, int id_index)
+static void get_device_info(struct us_data *us, const struct usb_device_id *id)
{
struct usb_device *dev = us->pusb_dev;
struct usb_interface_descriptor *idesc =
&us->pusb_intf->cur_altsetting->desc;
- struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
- struct usb_device_id *id = &storage_usb_ids[id_index];
+ struct us_unusual_dev *unusual_dev = find_unusual_entry(id);

/* Store the entries */
us->unusual_dev = unusual_dev;
@@ -487,7 +441,7 @@ static void get_device_info(struct us_da
us->protocol = (unusual_dev->useTransport == US_PR_DEVICE) ?
idesc->bInterfaceProtocol :
unusual_dev->useTransport;
- us->flags = unusual_dev->flags;
+ us->flags = id->driver_info;

/*
* This flag is only needed when we're in high-speed, so let's
@@ -515,7 +469,7 @@ static void get_device_info(struct us_da
if (unusual_dev->useTransport != US_PR_DEVICE &&
us->protocol == idesc->bInterfaceProtocol)
msg += 2;
- if (msg >= 0 && !(unusual_dev->flags & US_FL_NEED_OVERRIDE))
+ if (msg >= 0 && !(us->flags & US_FL_NEED_OVERRIDE))
printk(KERN_NOTICE USB_STORAGE "This device "
"(%04x,%04x,%04x S %02x P %02x)"
" has %s in unusual_devs.h\n"
@@ -921,9 +875,11 @@ static int storage_probe(struct usb_inte
{
struct Scsi_Host *host;
struct us_data *us;
- const int id_index = id - storage_usb_ids;
int result;

+ if (USB_US_TYPE(id->driver_info) != USB_US_TYPE_STOR)
+ return -ENXIO;
+
US_DEBUGP("USB Mass Storage device detected\n");

/*
@@ -956,7 +912,7 @@ static int storage_probe(struct usb_inte
* of the match from the usb_device_id table, so we can find the
* corresponding entry in the private table.
*/
- get_device_info(us, id_index);
+ get_device_info(us, id);

#ifdef CONFIG_USB_STORAGE_SDDR09
if (us->protocol == US_PR_EUSB_SDDR09 ||
@@ -1043,10 +999,14 @@ static int __init usb_stor_init(void)
int retval;
printk(KERN_INFO "Initializing USB Mass Storage driver...\n");

+ usb_usual_set_present(USB_US_TYPE_STOR, 1);
+
/* register the driver, return usb_register return code if error */
retval = usb_register(&usb_storage_driver);
if (retval == 0)
printk(KERN_INFO "USB Mass Storage support registered.\n");
+ else
+ usb_usual_set_present(USB_US_TYPE_STOR, 0);

return retval;
}
@@ -1071,6 +1031,8 @@ static void __exit usb_stor_exit(void)
wait_for_completion(&threads_gone);
atomic_dec(&total_threads);
}
+
+ usb_usual_set_present(USB_US_TYPE_STOR, 0);
}

module_init(usb_stor_init);
diff -urpN -X dontdiff linux-2.6.14-rc3/drivers/usb/storage/usb.h linux-2.6.14-rc3-wip/drivers/usb/storage/usb.h
--- linux-2.6.14-rc3/drivers/usb/storage/usb.h 2005-10-07 21:28:14.000000000 -0700
+++ linux-2.6.14-rc3-wip/drivers/usb/storage/usb.h 2005-10-08 00:08:51.000000000 -0700
@@ -45,6 +45,7 @@
#define _USB_H_

#include <linux/usb.h>
+#include <linux/usb_usual.h>
#include <linux/blkdev.h>
#include <linux/smp_lock.h>
#include <linux/completion.h>
@@ -63,38 +64,8 @@ struct us_unusual_dev {
__u8 useProtocol;
__u8 useTransport;
int (*initFunction)(struct us_data *);
- unsigned int flags;
};

-/*
- * Static flag definitions. We use this roundabout technique so that the
- * proc_info() routine can automatically display a message for each flag.
- */
-#define US_DO_ALL_FLAGS \
- US_FLAG(SINGLE_LUN, 0x00000001) \
- /* allow access to only LUN 0 */ \
- US_FLAG(NEED_OVERRIDE, 0x00000002) \
- /* unusual_devs entry is necessary */ \
- US_FLAG(SCM_MULT_TARG, 0x00000004) \
- /* supports multiple targets */ \
- US_FLAG(FIX_INQUIRY, 0x00000008) \
- /* INQUIRY response needs faking */ \
- US_FLAG(FIX_CAPACITY, 0x00000010) \
- /* READ CAPACITY response too big */ \
- US_FLAG(IGNORE_RESIDUE, 0x00000020) \
- /* reported residue is wrong */ \
- US_FLAG(BULK32, 0x00000040) \
- /* Uses 32-byte CBW length */ \
- US_FLAG(NOT_LOCKABLE, 0x00000080) \
- /* PREVENT/ALLOW not supported */ \
- US_FLAG(GO_SLOW, 0x00000100) \
- /* Need delay after Command phase */ \
- US_FLAG(NO_WP_DETECT, 0x00000200) \
- /* Don't check for write-protect */ \
-
-#define US_FLAG(name, value) US_FL_##name = value ,
-enum { US_DO_ALL_FLAGS };
-#undef US_FLAG

/* Dynamic flag definitions: used in set_bit() etc. */
#define US_FLIDX_URB_ACTIVE 18 /* 0x00040000 current_urb is in use */
diff -urpN -X dontdiff linux-2.6.14-rc3/include/linux/usb_usual.h linux-2.6.14-rc3-wip/include/linux/usb_usual.h
--- linux-2.6.14-rc3/include/linux/usb_usual.h 1969-12-31 16:00:00.000000000 -0800
+++ linux-2.6.14-rc3-wip/include/linux/usb_usual.h 2005-10-08 00:10:07.000000000 -0700
@@ -0,0 +1,118 @@
+/*
+ * Interface to the libusual.
+ *
+ * Copyright (c) 2005 Pete Zaitcev <zaitcev@xxxxxxxxxx>
+ * Copyright (c) 1999-2002 Matthew Dharm (mdharm-usb@xxxxxxxxxxxxxxxxxx)
+ * Copyright (c) 1999 Michael Gee (michael@xxxxxxxxxxxxxxxxx)
+ */
+
+#ifndef __LINUX_USB_USUAL_H
+#define __LINUX_USB_USUAL_H
+
+#include <linux/config.h>
+
+/* We should do this for cleanliness... But other usb_foo.h do not do this. */
+/* #include <linux/usb.h> */
+
+/*
+ * The flags field, which we store in usb_device_id.driver_info.
+ * It is compatible with the old usb-storage flags in lower 24 bits.
+ */
+
+/*
+ * Static flag definitions. We use this roundabout technique so that the
+ * proc_info() routine can automatically display a message for each flag.
+ */
+#define US_DO_ALL_FLAGS \
+ US_FLAG(SINGLE_LUN, 0x00000001) \
+ /* allow access to only LUN 0 */ \
+ US_FLAG(NEED_OVERRIDE, 0x00000002) \
+ /* unusual_devs entry is necessary */ \
+ US_FLAG(SCM_MULT_TARG, 0x00000004) \
+ /* supports multiple targets */ \
+ US_FLAG(FIX_INQUIRY, 0x00000008) \
+ /* INQUIRY response needs faking */ \
+ US_FLAG(FIX_CAPACITY, 0x00000010) \
+ /* READ CAPACITY response too big */ \
+ US_FLAG(IGNORE_RESIDUE, 0x00000020) \
+ /* reported residue is wrong */ \
+ US_FLAG(BULK32, 0x00000040) \
+ /* Uses 32-byte CBW length */ \
+ US_FLAG(NOT_LOCKABLE, 0x00000080) \
+ /* PREVENT/ALLOW not supported */ \
+ US_FLAG(GO_SLOW, 0x00000100) \
+ /* Need delay after Command phase */ \
+ US_FLAG(NO_WP_DETECT, 0x00000200) \
+ /* Don't check for write-protect */ \
+
+#define US_FLAG(name, value) US_FL_##name = value ,
+enum { US_DO_ALL_FLAGS };
+#undef US_FLAG
+
+/*
+ * The bias field for libusual and friends.
+ */
+#define USB_US_TYPE_NONE 0
+#define USB_US_TYPE_STOR 1
+#define USB_US_TYPE_UB 2
+
+#define USB_US_TYPE(flags) (((flags) >> 24) & 0xFF)
+
+/*
+ * This is probably not the best place to keep these constants, conceptually.
+ * But it's the only header included into all places which need them.
+ */
+
+/* Sub Classes */
+
+#define US_SC_RBC 0x01 /* Typically, flash devices */
+#define US_SC_8020 0x02 /* CD-ROM */
+#define US_SC_QIC 0x03 /* QIC-157 Tapes */
+#define US_SC_UFI 0x04 /* Floppy */
+#define US_SC_8070 0x05 /* Removable media */
+#define US_SC_SCSI 0x06 /* Transparent */
+#define US_SC_ISD200 0x07 /* ISD200 ATA */
+#define US_SC_MIN US_SC_RBC
+#define US_SC_MAX US_SC_ISD200
+
+#define US_SC_DEVICE 0xff /* Use device's value */
+
+/* Protocols */
+
+#define US_PR_CBI 0x00 /* Control/Bulk/Interrupt */
+#define US_PR_CB 0x01 /* Control/Bulk w/o interrupt */
+#define US_PR_BULK 0x50 /* bulk only */
+#ifdef CONFIG_USB_STORAGE_USBAT
+#define US_PR_SCM_ATAPI 0x80 /* SCM-ATAPI bridge */
+#endif
+#ifdef CONFIG_USB_STORAGE_SDDR09
+#define US_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */
+#endif
+#ifdef CONFIG_USB_STORAGE_SDDR55
+#define US_PR_SDDR55 0x82 /* SDDR-55 (made up) */
+#endif
+#define US_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */
+#ifdef CONFIG_USB_STORAGE_FREECOM
+#define US_PR_FREECOM 0xf1 /* Freecom */
+#endif
+#ifdef CONFIG_USB_STORAGE_DATAFAB
+#define US_PR_DATAFAB 0xf2 /* Datafab chipsets */
+#endif
+#ifdef CONFIG_USB_STORAGE_JUMPSHOT
+#define US_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */
+#endif
+
+#define US_PR_DEVICE 0xff /* Use device's value */
+
+/*
+ */
+#ifdef CONFIG_USB_LIBUSUAL
+
+extern struct usb_device_id storage_usb_ids[];
+extern void usb_usual_set_present(int type, int present);
+#else
+
+#define usb_usual_set_present(t,p) do { } while(0)
+#endif /* CONFIG_USB_LIBUSUAL */
+
+#endif /* __LINUX_USB_USUAL_H */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/