On Fri, 7 Oct 2005 10:41:14 -0400 (EDT), Alan Stern <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]>
+ * Copyright (c) 1999-2002 Matthew Dharm ([EMAIL PROTECTED])
+ * Copyright (c) 1999 Michael Gee ([EMAIL PROTECTED])
+ */
+
+#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 */


-------------------------------------------------------
This SF.Net email is sponsored by:
Power Architecture Resource Center: Free content, downloads, discussions,
and more. http://solutions.newsforge.com/ibmarch.tmpl
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to